annot-server/static/js/libs-annotviz.js
author ymh <ymh.work@gmail.com>
Thu, 22 Jan 2015 11:01:26 +0100
changeset 116 61d4a6610ba4
parent 108 082b64a5c699
child 130 0a2b4991d48c
permissions -rw-r--r--
change category by keyword
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
108
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({"lodash":[function(require,module,exports){
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
(function (global){
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
/**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
 * @license
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
 * Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
 * Build: `lodash modern -o ./dist/lodash.js`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
 * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
 * Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
 * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
 * Available under MIT license <http://lodash.com/license>
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
 */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
;(function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
  /** Used as a safe reference for `undefined` in pre ES5 environments */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
  var undefined;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
  /** Used to pool arrays and objects used internally */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
  var arrayPool = [],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
      objectPool = [];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
  /** Used to generate unique IDs */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
  var idCounter = 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
  /** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
  var keyPrefix = +new Date + '';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
  /** Used as the size when optimizations are enabled for large arrays */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
  var largeArraySize = 75;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
  /** Used as the max size of the `arrayPool` and `objectPool` */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
  var maxPoolSize = 40;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
  /** Used to detect and test whitespace */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
  var whitespace = (
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
    // whitespace
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
    ' \t\x0B\f\xA0\ufeff' +
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
    // line terminators
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
    '\n\r\u2028\u2029' +
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
    // unicode category "Zs" space separators
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
    '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
  );
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
  /** Used to match empty string literals in compiled template source */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
  var reEmptyStringLeading = /\b__p \+= '';/g,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
      reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
      reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
  /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
   * Used to match ES6 template delimiters
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
   * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
   */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
  var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
  /** Used to match regexp flags from their coerced string values */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
  var reFlags = /\w*$/;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
  /** Used to detected named functions */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
  var reFuncName = /^\s*function[ \n\r\t]+\w/;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
  /** Used to match "interpolate" template delimiters */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
  var reInterpolate = /<%=([\s\S]+?)%>/g;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
  /** Used to match leading whitespace and zeros to be removed */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
  var reLeadingSpacesAndZeros = RegExp('^[' + whitespace + ']*0+(?=.$)');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
  /** Used to ensure capturing order of template delimiters */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
  var reNoMatch = /($^)/;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
  /** Used to detect functions containing a `this` reference */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
  var reThis = /\bthis\b/;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
  /** Used to match unescaped characters in compiled string literals */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
  var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
  /** Used to assign default `context` object properties */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
  var contextProps = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
    'Array', 'Boolean', 'Date', 'Function', 'Math', 'Number', 'Object',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
    'RegExp', 'String', '_', 'attachEvent', 'clearTimeout', 'isFinite', 'isNaN',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
    'parseInt', 'setTimeout'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
  ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
  /** Used to make template sourceURLs easier to identify */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
  var templateCounter = 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
  /** `Object#toString` result shortcuts */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
  var argsClass = '[object Arguments]',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
      arrayClass = '[object Array]',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
      boolClass = '[object Boolean]',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
      dateClass = '[object Date]',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
      funcClass = '[object Function]',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
      numberClass = '[object Number]',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
      objectClass = '[object Object]',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
      regexpClass = '[object RegExp]',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
      stringClass = '[object String]';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
  /** Used to identify object classifications that `_.clone` supports */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
  var cloneableClasses = {};
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
  cloneableClasses[funcClass] = false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
  cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
  cloneableClasses[boolClass] = cloneableClasses[dateClass] =
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
  cloneableClasses[numberClass] = cloneableClasses[objectClass] =
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
  cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
  /** Used as an internal `_.debounce` options object */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   107
  var debounceOptions = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   108
    'leading': false,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
    'maxWait': 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
    'trailing': false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
  };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
  /** Used as the property descriptor for `__bindData__` */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   114
  var descriptor = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   115
    'configurable': false,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   116
    'enumerable': false,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   117
    'value': null,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   118
    'writable': false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   119
  };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   120
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   121
  /** Used to determine if values are of the language type Object */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   122
  var objectTypes = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   123
    'boolean': false,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   124
    'function': true,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   125
    'object': true,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   126
    'number': false,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   127
    'string': false,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   128
    'undefined': false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   129
  };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   130
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   131
  /** Used to escape characters for inclusion in compiled string literals */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   132
  var stringEscapes = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   133
    '\\': '\\',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   134
    "'": "'",
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   135
    '\n': 'n',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   136
    '\r': 'r',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   137
    '\t': 't',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   138
    '\u2028': 'u2028',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   139
    '\u2029': 'u2029'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   140
  };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   141
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   142
  /** Used as a reference to the global object */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   143
  var root = (objectTypes[typeof window] && window) || this;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   144
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   145
  /** Detect free variable `exports` */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   146
  var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   147
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   148
  /** Detect free variable `module` */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   149
  var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   150
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   151
  /** Detect the popular CommonJS extension `module.exports` */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   152
  var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   153
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   154
  /** Detect free variable `global` from Node.js or Browserified code and use it as `root` */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   155
  var freeGlobal = objectTypes[typeof global] && global;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   156
  if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   157
    root = freeGlobal;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   158
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   159
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   160
  /*--------------------------------------------------------------------------*/
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   161
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   162
  /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   163
   * The base implementation of `_.indexOf` without support for binary searches
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   164
   * or `fromIndex` constraints.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   165
   *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   166
   * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   167
   * @param {Array} array The array to search.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   168
   * @param {*} value The value to search for.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   169
   * @param {number} [fromIndex=0] The index to search from.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   170
   * @returns {number} Returns the index of the matched value or `-1`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   171
   */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   172
  function baseIndexOf(array, value, fromIndex) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   173
    var index = (fromIndex || 0) - 1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   174
        length = array ? array.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   175
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   176
    while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   177
      if (array[index] === value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   178
        return index;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   179
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   180
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   181
    return -1;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   182
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   183
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   184
  /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   185
   * An implementation of `_.contains` for cache objects that mimics the return
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   186
   * signature of `_.indexOf` by returning `0` if the value is found, else `-1`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   187
   *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   188
   * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   189
   * @param {Object} cache The cache object to inspect.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   190
   * @param {*} value The value to search for.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   191
   * @returns {number} Returns `0` if `value` is found, else `-1`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   192
   */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   193
  function cacheIndexOf(cache, value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   194
    var type = typeof value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   195
    cache = cache.cache;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   196
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   197
    if (type == 'boolean' || value == null) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   198
      return cache[value] ? 0 : -1;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   199
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   200
    if (type != 'number' && type != 'string') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   201
      type = 'object';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   202
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   203
    var key = type == 'number' ? value : keyPrefix + value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   204
    cache = (cache = cache[type]) && cache[key];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   205
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   206
    return type == 'object'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   207
      ? (cache && baseIndexOf(cache, value) > -1 ? 0 : -1)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   208
      : (cache ? 0 : -1);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   209
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   210
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   211
  /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   212
   * Adds a given value to the corresponding cache object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   213
   *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   214
   * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   215
   * @param {*} value The value to add to the cache.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   216
   */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   217
  function cachePush(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   218
    var cache = this.cache,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   219
        type = typeof value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   220
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   221
    if (type == 'boolean' || value == null) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   222
      cache[value] = true;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   223
    } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   224
      if (type != 'number' && type != 'string') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   225
        type = 'object';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   226
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   227
      var key = type == 'number' ? value : keyPrefix + value,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   228
          typeCache = cache[type] || (cache[type] = {});
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   229
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   230
      if (type == 'object') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   231
        (typeCache[key] || (typeCache[key] = [])).push(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   232
      } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   233
        typeCache[key] = true;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   234
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   235
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   236
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   237
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   238
  /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   239
   * Used by `_.max` and `_.min` as the default callback when a given
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   240
   * collection is a string value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   241
   *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   242
   * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   243
   * @param {string} value The character to inspect.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   244
   * @returns {number} Returns the code unit of given character.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   245
   */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   246
  function charAtCallback(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   247
    return value.charCodeAt(0);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   248
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   249
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   250
  /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   251
   * Used by `sortBy` to compare transformed `collection` elements, stable sorting
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   252
   * them in ascending order.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   253
   *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   254
   * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   255
   * @param {Object} a The object to compare to `b`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   256
   * @param {Object} b The object to compare to `a`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   257
   * @returns {number} Returns the sort order indicator of `1` or `-1`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   258
   */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   259
  function compareAscending(a, b) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   260
    var ac = a.criteria,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   261
        bc = b.criteria,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   262
        index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   263
        length = ac.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   264
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   265
    while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   266
      var value = ac[index],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   267
          other = bc[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   268
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   269
      if (value !== other) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   270
        if (value > other || typeof value == 'undefined') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   271
          return 1;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   272
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   273
        if (value < other || typeof other == 'undefined') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   274
          return -1;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   275
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   276
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   277
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   278
    // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   279
    // that causes it, under certain circumstances, to return the same value for
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   280
    // `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   281
    //
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   282
    // This also ensures a stable sort in V8 and other engines.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   283
    // See http://code.google.com/p/v8/issues/detail?id=90
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   284
    return a.index - b.index;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   285
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   286
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   287
  /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   288
   * Creates a cache object to optimize linear searches of large arrays.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   289
   *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   290
   * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   291
   * @param {Array} [array=[]] The array to search.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   292
   * @returns {null|Object} Returns the cache object or `null` if caching should not be used.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   293
   */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   294
  function createCache(array) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   295
    var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   296
        length = array.length,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   297
        first = array[0],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   298
        mid = array[(length / 2) | 0],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   299
        last = array[length - 1];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   300
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   301
    if (first && typeof first == 'object' &&
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   302
        mid && typeof mid == 'object' && last && typeof last == 'object') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   303
      return false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   304
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   305
    var cache = getObject();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   306
    cache['false'] = cache['null'] = cache['true'] = cache['undefined'] = false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   307
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   308
    var result = getObject();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   309
    result.array = array;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   310
    result.cache = cache;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   311
    result.push = cachePush;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   312
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   313
    while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   314
      result.push(array[index]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   315
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   316
    return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   317
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   318
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   319
  /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   320
   * Used by `template` to escape characters for inclusion in compiled
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   321
   * string literals.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   322
   *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   323
   * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   324
   * @param {string} match The matched character to escape.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   325
   * @returns {string} Returns the escaped character.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   326
   */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   327
  function escapeStringChar(match) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   328
    return '\\' + stringEscapes[match];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   329
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   330
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   331
  /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   332
   * Gets an array from the array pool or creates a new one if the pool is empty.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   333
   *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   334
   * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   335
   * @returns {Array} The array from the pool.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   336
   */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   337
  function getArray() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   338
    return arrayPool.pop() || [];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   339
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   340
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   341
  /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   342
   * Gets an object from the object pool or creates a new one if the pool is empty.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   343
   *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   344
   * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   345
   * @returns {Object} The object from the pool.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   346
   */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   347
  function getObject() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   348
    return objectPool.pop() || {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   349
      'array': null,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   350
      'cache': null,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   351
      'criteria': null,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   352
      'false': false,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   353
      'index': 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   354
      'null': false,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   355
      'number': null,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   356
      'object': null,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   357
      'push': null,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   358
      'string': null,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   359
      'true': false,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   360
      'undefined': false,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   361
      'value': null
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   362
    };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   363
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   364
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   365
  /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   366
   * Releases the given array back to the array pool.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   367
   *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   368
   * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   369
   * @param {Array} [array] The array to release.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   370
   */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   371
  function releaseArray(array) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   372
    array.length = 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   373
    if (arrayPool.length < maxPoolSize) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   374
      arrayPool.push(array);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   375
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   376
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   377
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   378
  /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   379
   * Releases the given object back to the object pool.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   380
   *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   381
   * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   382
   * @param {Object} [object] The object to release.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   383
   */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   384
  function releaseObject(object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   385
    var cache = object.cache;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   386
    if (cache) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   387
      releaseObject(cache);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   388
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   389
    object.array = object.cache = object.criteria = object.object = object.number = object.string = object.value = null;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   390
    if (objectPool.length < maxPoolSize) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   391
      objectPool.push(object);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   392
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   393
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   394
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   395
  /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   396
   * Slices the `collection` from the `start` index up to, but not including,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   397
   * the `end` index.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   398
   *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   399
   * Note: This function is used instead of `Array#slice` to support node lists
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   400
   * in IE < 9 and to ensure dense arrays are returned.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   401
   *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   402
   * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   403
   * @param {Array|Object|string} collection The collection to slice.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   404
   * @param {number} start The start index.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   405
   * @param {number} end The end index.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   406
   * @returns {Array} Returns the new array.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   407
   */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   408
  function slice(array, start, end) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   409
    start || (start = 0);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   410
    if (typeof end == 'undefined') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   411
      end = array ? array.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   412
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   413
    var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   414
        length = end - start || 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   415
        result = Array(length < 0 ? 0 : length);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   416
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   417
    while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   418
      result[index] = array[start + index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   419
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   420
    return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   421
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   422
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   423
  /*--------------------------------------------------------------------------*/
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   424
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   425
  /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   426
   * Create a new `lodash` function using the given context object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   427
   *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   428
   * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   429
   * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   430
   * @category Utilities
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   431
   * @param {Object} [context=root] The context object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   432
   * @returns {Function} Returns the `lodash` function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   433
   */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   434
  function runInContext(context) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   435
    // Avoid issues with some ES3 environments that attempt to use values, named
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   436
    // after built-in constructors like `Object`, for the creation of literals.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   437
    // ES5 clears this up by stating that literals must use built-in constructors.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   438
    // See http://es5.github.io/#x11.1.5.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   439
    context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   440
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   441
    /** Native constructor references */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   442
    var Array = context.Array,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   443
        Boolean = context.Boolean,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   444
        Date = context.Date,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   445
        Function = context.Function,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   446
        Math = context.Math,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   447
        Number = context.Number,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   448
        Object = context.Object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   449
        RegExp = context.RegExp,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   450
        String = context.String,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   451
        TypeError = context.TypeError;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   452
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   453
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   454
     * Used for `Array` method references.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   455
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   456
     * Normally `Array.prototype` would suffice, however, using an array literal
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   457
     * avoids issues in Narwhal.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   458
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   459
    var arrayRef = [];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   460
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   461
    /** Used for native method references */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   462
    var objectProto = Object.prototype;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   463
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   464
    /** Used to restore the original `_` reference in `noConflict` */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   465
    var oldDash = context._;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   466
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   467
    /** Used to resolve the internal [[Class]] of values */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   468
    var toString = objectProto.toString;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   469
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   470
    /** Used to detect if a method is native */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   471
    var reNative = RegExp('^' +
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   472
      String(toString)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   473
        .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   474
        .replace(/toString| for [^\]]+/g, '.*?') + '$'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   475
    );
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   476
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   477
    /** Native method shortcuts */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   478
    var ceil = Math.ceil,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   479
        clearTimeout = context.clearTimeout,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   480
        floor = Math.floor,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   481
        fnToString = Function.prototype.toString,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   482
        getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   483
        hasOwnProperty = objectProto.hasOwnProperty,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   484
        push = arrayRef.push,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   485
        setTimeout = context.setTimeout,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   486
        splice = arrayRef.splice,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   487
        unshift = arrayRef.unshift;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   488
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   489
    /** Used to set meta data on functions */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   490
    var defineProperty = (function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   491
      // IE 8 only accepts DOM elements
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   492
      try {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   493
        var o = {},
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   494
            func = isNative(func = Object.defineProperty) && func,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   495
            result = func(o, o, o) && func;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   496
      } catch(e) { }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   497
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   498
    }());
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   499
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   500
    /* Native method shortcuts for methods with the same name as other `lodash` methods */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   501
    var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   502
        nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   503
        nativeIsFinite = context.isFinite,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   504
        nativeIsNaN = context.isNaN,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   505
        nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   506
        nativeMax = Math.max,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   507
        nativeMin = Math.min,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   508
        nativeParseInt = context.parseInt,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   509
        nativeRandom = Math.random;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   510
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   511
    /** Used to lookup a built-in constructor by [[Class]] */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   512
    var ctorByClass = {};
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   513
    ctorByClass[arrayClass] = Array;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   514
    ctorByClass[boolClass] = Boolean;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   515
    ctorByClass[dateClass] = Date;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   516
    ctorByClass[funcClass] = Function;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   517
    ctorByClass[objectClass] = Object;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   518
    ctorByClass[numberClass] = Number;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   519
    ctorByClass[regexpClass] = RegExp;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   520
    ctorByClass[stringClass] = String;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   521
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   522
    /*--------------------------------------------------------------------------*/
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   523
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   524
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   525
     * Creates a `lodash` object which wraps the given value to enable intuitive
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   526
     * method chaining.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   527
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   528
     * In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   529
     * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   530
     * and `unshift`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   531
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   532
     * Chaining is supported in custom builds as long as the `value` method is
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   533
     * implicitly or explicitly included in the build.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   534
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   535
     * The chainable wrapper functions are:
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   536
     * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   537
     * `compose`, `concat`, `countBy`, `create`, `createCallback`, `curry`,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   538
     * `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   539
     * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   540
     * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   541
     * `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   542
     * `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `pull`, `push`,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   543
     * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   544
     * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   545
     * `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   546
     * and `zip`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   547
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   548
     * The non-chainable wrapper functions are:
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   549
     * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   550
     * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `has`, `identity`,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   551
     * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   552
     * `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   553
     * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   554
     * `lastIndexOf`, `mixin`, `noConflict`, `parseInt`, `pop`, `random`, `reduce`,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   555
     * `reduceRight`, `result`, `shift`, `size`, `some`, `sortedIndex`, `runInContext`,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   556
     * `template`, `unescape`, `uniqueId`, and `value`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   557
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   558
     * The wrapper functions `first` and `last` return wrapped values when `n` is
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   559
     * provided, otherwise they return unwrapped values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   560
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   561
     * Explicit chaining can be enabled by using the `_.chain` method.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   562
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   563
     * @name _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   564
     * @constructor
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   565
     * @category Chaining
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   566
     * @param {*} value The value to wrap in a `lodash` instance.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   567
     * @returns {Object} Returns a `lodash` instance.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   568
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   569
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   570
     * var wrapped = _([1, 2, 3]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   571
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   572
     * // returns an unwrapped value
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   573
     * wrapped.reduce(function(sum, num) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   574
     *   return sum + num;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   575
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   576
     * // => 6
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   577
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   578
     * // returns a wrapped value
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   579
     * var squares = wrapped.map(function(num) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   580
     *   return num * num;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   581
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   582
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   583
     * _.isArray(squares);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   584
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   585
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   586
     * _.isArray(squares.value());
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   587
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   588
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   589
    function lodash(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   590
      // don't wrap if already wrapped, even if wrapped by a different `lodash` constructor
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   591
      return (value && typeof value == 'object' && !isArray(value) && hasOwnProperty.call(value, '__wrapped__'))
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   592
       ? value
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   593
       : new lodashWrapper(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   594
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   595
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   596
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   597
     * A fast path for creating `lodash` wrapper objects.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   598
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   599
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   600
     * @param {*} value The value to wrap in a `lodash` instance.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   601
     * @param {boolean} chainAll A flag to enable chaining for all methods
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   602
     * @returns {Object} Returns a `lodash` instance.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   603
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   604
    function lodashWrapper(value, chainAll) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   605
      this.__chain__ = !!chainAll;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   606
      this.__wrapped__ = value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   607
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   608
    // ensure `new lodashWrapper` is an instance of `lodash`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   609
    lodashWrapper.prototype = lodash.prototype;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   610
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   611
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   612
     * An object used to flag environments features.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   613
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   614
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   615
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   616
     * @type Object
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   617
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   618
    var support = lodash.support = {};
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   619
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   620
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   621
     * Detect if functions can be decompiled by `Function#toString`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   622
     * (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   623
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   624
     * @memberOf _.support
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   625
     * @type boolean
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   626
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   627
    support.funcDecomp = !isNative(context.WinRTError) && reThis.test(runInContext);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   628
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   629
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   630
     * Detect if `Function#name` is supported (all but IE).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   631
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   632
     * @memberOf _.support
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   633
     * @type boolean
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   634
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   635
    support.funcNames = typeof Function.name == 'string';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   636
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   637
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   638
     * By default, the template delimiters used by Lo-Dash are similar to those in
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   639
     * embedded Ruby (ERB). Change the following template settings to use alternative
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   640
     * delimiters.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   641
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   642
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   643
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   644
     * @type Object
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   645
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   646
    lodash.templateSettings = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   647
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   648
      /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   649
       * Used to detect `data` property values to be HTML-escaped.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   650
       *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   651
       * @memberOf _.templateSettings
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   652
       * @type RegExp
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   653
       */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   654
      'escape': /<%-([\s\S]+?)%>/g,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   655
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   656
      /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   657
       * Used to detect code to be evaluated.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   658
       *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   659
       * @memberOf _.templateSettings
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   660
       * @type RegExp
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   661
       */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   662
      'evaluate': /<%([\s\S]+?)%>/g,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   663
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   664
      /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   665
       * Used to detect `data` property values to inject.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   666
       *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   667
       * @memberOf _.templateSettings
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   668
       * @type RegExp
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   669
       */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   670
      'interpolate': reInterpolate,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   671
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   672
      /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   673
       * Used to reference the data object in the template text.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   674
       *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   675
       * @memberOf _.templateSettings
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   676
       * @type string
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   677
       */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   678
      'variable': '',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   679
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   680
      /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   681
       * Used to import variables into the compiled template.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   682
       *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   683
       * @memberOf _.templateSettings
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   684
       * @type Object
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   685
       */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   686
      'imports': {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   687
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   688
        /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   689
         * A reference to the `lodash` function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   690
         *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   691
         * @memberOf _.templateSettings.imports
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   692
         * @type Function
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   693
         */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   694
        '_': lodash
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   695
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   696
    };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   697
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   698
    /*--------------------------------------------------------------------------*/
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   699
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   700
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   701
     * The base implementation of `_.bind` that creates the bound function and
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   702
     * sets its meta data.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   703
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   704
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   705
     * @param {Array} bindData The bind data array.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   706
     * @returns {Function} Returns the new bound function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   707
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   708
    function baseBind(bindData) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   709
      var func = bindData[0],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   710
          partialArgs = bindData[2],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   711
          thisArg = bindData[4];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   712
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   713
      function bound() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   714
        // `Function#bind` spec
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   715
        // http://es5.github.io/#x15.3.4.5
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   716
        if (partialArgs) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   717
          // avoid `arguments` object deoptimizations by using `slice` instead
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   718
          // of `Array.prototype.slice.call` and not assigning `arguments` to a
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   719
          // variable as a ternary expression
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   720
          var args = slice(partialArgs);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   721
          push.apply(args, arguments);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   722
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   723
        // mimic the constructor's `return` behavior
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   724
        // http://es5.github.io/#x13.2.2
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   725
        if (this instanceof bound) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   726
          // ensure `new bound` is an instance of `func`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   727
          var thisBinding = baseCreate(func.prototype),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   728
              result = func.apply(thisBinding, args || arguments);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   729
          return isObject(result) ? result : thisBinding;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   730
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   731
        return func.apply(thisArg, args || arguments);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   732
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   733
      setBindData(bound, bindData);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   734
      return bound;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   735
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   736
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   737
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   738
     * The base implementation of `_.clone` without argument juggling or support
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   739
     * for `thisArg` binding.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   740
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   741
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   742
     * @param {*} value The value to clone.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   743
     * @param {boolean} [isDeep=false] Specify a deep clone.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   744
     * @param {Function} [callback] The function to customize cloning values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   745
     * @param {Array} [stackA=[]] Tracks traversed source objects.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   746
     * @param {Array} [stackB=[]] Associates clones with source counterparts.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   747
     * @returns {*} Returns the cloned value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   748
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   749
    function baseClone(value, isDeep, callback, stackA, stackB) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   750
      if (callback) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   751
        var result = callback(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   752
        if (typeof result != 'undefined') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   753
          return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   754
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   755
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   756
      // inspect [[Class]]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   757
      var isObj = isObject(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   758
      if (isObj) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   759
        var className = toString.call(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   760
        if (!cloneableClasses[className]) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   761
          return value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   762
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   763
        var ctor = ctorByClass[className];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   764
        switch (className) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   765
          case boolClass:
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   766
          case dateClass:
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   767
            return new ctor(+value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   768
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   769
          case numberClass:
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   770
          case stringClass:
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   771
            return new ctor(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   772
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   773
          case regexpClass:
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   774
            result = ctor(value.source, reFlags.exec(value));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   775
            result.lastIndex = value.lastIndex;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   776
            return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   777
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   778
      } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   779
        return value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   780
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   781
      var isArr = isArray(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   782
      if (isDeep) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   783
        // check for circular references and return corresponding clone
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   784
        var initedStack = !stackA;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   785
        stackA || (stackA = getArray());
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   786
        stackB || (stackB = getArray());
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   787
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   788
        var length = stackA.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   789
        while (length--) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   790
          if (stackA[length] == value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   791
            return stackB[length];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   792
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   793
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   794
        result = isArr ? ctor(value.length) : {};
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   795
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   796
      else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   797
        result = isArr ? slice(value) : assign({}, value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   798
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   799
      // add array properties assigned by `RegExp#exec`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   800
      if (isArr) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   801
        if (hasOwnProperty.call(value, 'index')) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   802
          result.index = value.index;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   803
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   804
        if (hasOwnProperty.call(value, 'input')) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   805
          result.input = value.input;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   806
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   807
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   808
      // exit for shallow clone
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   809
      if (!isDeep) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   810
        return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   811
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   812
      // add the source value to the stack of traversed objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   813
      // and associate it with its clone
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   814
      stackA.push(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   815
      stackB.push(result);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   816
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   817
      // recursively populate clone (susceptible to call stack limits)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   818
      (isArr ? forEach : forOwn)(value, function(objValue, key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   819
        result[key] = baseClone(objValue, isDeep, callback, stackA, stackB);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   820
      });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   821
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   822
      if (initedStack) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   823
        releaseArray(stackA);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   824
        releaseArray(stackB);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   825
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   826
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   827
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   828
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   829
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   830
     * The base implementation of `_.create` without support for assigning
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   831
     * properties to the created object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   832
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   833
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   834
     * @param {Object} prototype The object to inherit from.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   835
     * @returns {Object} Returns the new object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   836
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   837
    function baseCreate(prototype, properties) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   838
      return isObject(prototype) ? nativeCreate(prototype) : {};
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   839
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   840
    // fallback for browsers without `Object.create`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   841
    if (!nativeCreate) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   842
      baseCreate = (function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   843
        function Object() {}
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   844
        return function(prototype) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   845
          if (isObject(prototype)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   846
            Object.prototype = prototype;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   847
            var result = new Object;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   848
            Object.prototype = null;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   849
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   850
          return result || context.Object();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   851
        };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   852
      }());
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   853
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   854
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   855
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   856
     * The base implementation of `_.createCallback` without support for creating
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   857
     * "_.pluck" or "_.where" style callbacks.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   858
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   859
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   860
     * @param {*} [func=identity] The value to convert to a callback.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   861
     * @param {*} [thisArg] The `this` binding of the created callback.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   862
     * @param {number} [argCount] The number of arguments the callback accepts.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   863
     * @returns {Function} Returns a callback function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   864
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   865
    function baseCreateCallback(func, thisArg, argCount) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   866
      if (typeof func != 'function') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   867
        return identity;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   868
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   869
      // exit early for no `thisArg` or already bound by `Function#bind`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   870
      if (typeof thisArg == 'undefined' || !('prototype' in func)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   871
        return func;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   872
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   873
      var bindData = func.__bindData__;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   874
      if (typeof bindData == 'undefined') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   875
        if (support.funcNames) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   876
          bindData = !func.name;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   877
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   878
        bindData = bindData || !support.funcDecomp;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   879
        if (!bindData) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   880
          var source = fnToString.call(func);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   881
          if (!support.funcNames) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   882
            bindData = !reFuncName.test(source);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   883
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   884
          if (!bindData) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   885
            // checks if `func` references the `this` keyword and stores the result
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   886
            bindData = reThis.test(source);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   887
            setBindData(func, bindData);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   888
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   889
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   890
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   891
      // exit early if there are no `this` references or `func` is bound
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   892
      if (bindData === false || (bindData !== true && bindData[1] & 1)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   893
        return func;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   894
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   895
      switch (argCount) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   896
        case 1: return function(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   897
          return func.call(thisArg, value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   898
        };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   899
        case 2: return function(a, b) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   900
          return func.call(thisArg, a, b);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   901
        };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   902
        case 3: return function(value, index, collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   903
          return func.call(thisArg, value, index, collection);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   904
        };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   905
        case 4: return function(accumulator, value, index, collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   906
          return func.call(thisArg, accumulator, value, index, collection);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   907
        };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   908
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   909
      return bind(func, thisArg);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   910
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   911
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   912
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   913
     * The base implementation of `createWrapper` that creates the wrapper and
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   914
     * sets its meta data.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   915
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   916
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   917
     * @param {Array} bindData The bind data array.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   918
     * @returns {Function} Returns the new function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   919
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   920
    function baseCreateWrapper(bindData) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   921
      var func = bindData[0],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   922
          bitmask = bindData[1],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   923
          partialArgs = bindData[2],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   924
          partialRightArgs = bindData[3],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   925
          thisArg = bindData[4],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   926
          arity = bindData[5];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   927
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   928
      var isBind = bitmask & 1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   929
          isBindKey = bitmask & 2,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   930
          isCurry = bitmask & 4,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   931
          isCurryBound = bitmask & 8,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   932
          key = func;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   933
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   934
      function bound() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   935
        var thisBinding = isBind ? thisArg : this;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   936
        if (partialArgs) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   937
          var args = slice(partialArgs);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   938
          push.apply(args, arguments);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   939
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   940
        if (partialRightArgs || isCurry) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   941
          args || (args = slice(arguments));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   942
          if (partialRightArgs) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   943
            push.apply(args, partialRightArgs);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   944
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   945
          if (isCurry && args.length < arity) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   946
            bitmask |= 16 & ~32;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   947
            return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   948
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   949
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   950
        args || (args = arguments);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   951
        if (isBindKey) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   952
          func = thisBinding[key];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   953
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   954
        if (this instanceof bound) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   955
          thisBinding = baseCreate(func.prototype);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   956
          var result = func.apply(thisBinding, args);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   957
          return isObject(result) ? result : thisBinding;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   958
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   959
        return func.apply(thisBinding, args);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   960
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   961
      setBindData(bound, bindData);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   962
      return bound;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   963
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   964
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   965
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   966
     * The base implementation of `_.difference` that accepts a single array
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   967
     * of values to exclude.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   968
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   969
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   970
     * @param {Array} array The array to process.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   971
     * @param {Array} [values] The array of values to exclude.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   972
     * @returns {Array} Returns a new array of filtered values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   973
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   974
    function baseDifference(array, values) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   975
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   976
          indexOf = getIndexOf(),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   977
          length = array ? array.length : 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   978
          isLarge = length >= largeArraySize && indexOf === baseIndexOf,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   979
          result = [];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   980
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   981
      if (isLarge) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   982
        var cache = createCache(values);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   983
        if (cache) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   984
          indexOf = cacheIndexOf;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   985
          values = cache;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   986
        } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   987
          isLarge = false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   988
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   989
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   990
      while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   991
        var value = array[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   992
        if (indexOf(values, value) < 0) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   993
          result.push(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   994
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   995
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   996
      if (isLarge) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   997
        releaseObject(values);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   998
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
   999
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1000
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1001
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1002
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1003
     * The base implementation of `_.flatten` without support for callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1004
     * shorthands or `thisArg` binding.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1005
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1006
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1007
     * @param {Array} array The array to flatten.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1008
     * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1009
     * @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1010
     * @param {number} [fromIndex=0] The index to start from.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1011
     * @returns {Array} Returns a new flattened array.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1012
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1013
    function baseFlatten(array, isShallow, isStrict, fromIndex) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1014
      var index = (fromIndex || 0) - 1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1015
          length = array ? array.length : 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1016
          result = [];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1017
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1018
      while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1019
        var value = array[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1020
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1021
        if (value && typeof value == 'object' && typeof value.length == 'number'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1022
            && (isArray(value) || isArguments(value))) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1023
          // recursively flatten arrays (susceptible to call stack limits)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1024
          if (!isShallow) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1025
            value = baseFlatten(value, isShallow, isStrict);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1026
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1027
          var valIndex = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1028
              valLength = value.length,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1029
              resIndex = result.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1030
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1031
          result.length += valLength;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1032
          while (++valIndex < valLength) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1033
            result[resIndex++] = value[valIndex];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1034
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1035
        } else if (!isStrict) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1036
          result.push(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1037
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1038
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1039
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1040
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1041
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1042
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1043
     * The base implementation of `_.isEqual`, without support for `thisArg` binding,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1044
     * that allows partial "_.where" style comparisons.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1045
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1046
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1047
     * @param {*} a The value to compare.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1048
     * @param {*} b The other value to compare.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1049
     * @param {Function} [callback] The function to customize comparing values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1050
     * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1051
     * @param {Array} [stackA=[]] Tracks traversed `a` objects.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1052
     * @param {Array} [stackB=[]] Tracks traversed `b` objects.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1053
     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1054
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1055
    function baseIsEqual(a, b, callback, isWhere, stackA, stackB) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1056
      // used to indicate that when comparing objects, `a` has at least the properties of `b`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1057
      if (callback) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1058
        var result = callback(a, b);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1059
        if (typeof result != 'undefined') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1060
          return !!result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1061
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1062
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1063
      // exit early for identical values
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1064
      if (a === b) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1065
        // treat `+0` vs. `-0` as not equal
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1066
        return a !== 0 || (1 / a == 1 / b);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1067
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1068
      var type = typeof a,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1069
          otherType = typeof b;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1070
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1071
      // exit early for unlike primitive values
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1072
      if (a === a &&
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1073
          !(a && objectTypes[type]) &&
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1074
          !(b && objectTypes[otherType])) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1075
        return false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1076
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1077
      // exit early for `null` and `undefined` avoiding ES3's Function#call behavior
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1078
      // http://es5.github.io/#x15.3.4.4
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1079
      if (a == null || b == null) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1080
        return a === b;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1081
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1082
      // compare [[Class]] names
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1083
      var className = toString.call(a),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1084
          otherClass = toString.call(b);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1085
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1086
      if (className == argsClass) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1087
        className = objectClass;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1088
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1089
      if (otherClass == argsClass) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1090
        otherClass = objectClass;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1091
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1092
      if (className != otherClass) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1093
        return false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1094
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1095
      switch (className) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1096
        case boolClass:
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1097
        case dateClass:
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1098
          // coerce dates and booleans to numbers, dates to milliseconds and booleans
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1099
          // to `1` or `0` treating invalid dates coerced to `NaN` as not equal
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1100
          return +a == +b;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1101
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1102
        case numberClass:
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1103
          // treat `NaN` vs. `NaN` as equal
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1104
          return (a != +a)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1105
            ? b != +b
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1106
            // but treat `+0` vs. `-0` as not equal
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1107
            : (a == 0 ? (1 / a == 1 / b) : a == +b);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1108
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1109
        case regexpClass:
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1110
        case stringClass:
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1111
          // coerce regexes to strings (http://es5.github.io/#x15.10.6.4)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1112
          // treat string primitives and their corresponding object instances as equal
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1113
          return a == String(b);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1114
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1115
      var isArr = className == arrayClass;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1116
      if (!isArr) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1117
        // unwrap any `lodash` wrapped values
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1118
        var aWrapped = hasOwnProperty.call(a, '__wrapped__'),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1119
            bWrapped = hasOwnProperty.call(b, '__wrapped__');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1120
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1121
        if (aWrapped || bWrapped) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1122
          return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1123
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1124
        // exit for functions and DOM nodes
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1125
        if (className != objectClass) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1126
          return false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1127
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1128
        // in older versions of Opera, `arguments` objects have `Array` constructors
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1129
        var ctorA = a.constructor,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1130
            ctorB = b.constructor;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1131
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1132
        // non `Object` object instances with different constructors are not equal
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1133
        if (ctorA != ctorB &&
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1134
              !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) &&
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1135
              ('constructor' in a && 'constructor' in b)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1136
            ) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1137
          return false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1138
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1139
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1140
      // assume cyclic structures are equal
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1141
      // the algorithm for detecting cyclic structures is adapted from ES 5.1
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1142
      // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1143
      var initedStack = !stackA;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1144
      stackA || (stackA = getArray());
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1145
      stackB || (stackB = getArray());
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1146
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1147
      var length = stackA.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1148
      while (length--) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1149
        if (stackA[length] == a) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1150
          return stackB[length] == b;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1151
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1152
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1153
      var size = 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1154
      result = true;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1155
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1156
      // add `a` and `b` to the stack of traversed objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1157
      stackA.push(a);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1158
      stackB.push(b);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1159
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1160
      // recursively compare objects and arrays (susceptible to call stack limits)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1161
      if (isArr) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1162
        // compare lengths to determine if a deep comparison is necessary
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1163
        length = a.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1164
        size = b.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1165
        result = size == length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1166
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1167
        if (result || isWhere) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1168
          // deep compare the contents, ignoring non-numeric properties
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1169
          while (size--) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1170
            var index = length,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1171
                value = b[size];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1172
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1173
            if (isWhere) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1174
              while (index--) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1175
                if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1176
                  break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1177
                }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1178
              }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1179
            } else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1180
              break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1181
            }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1182
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1183
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1184
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1185
      else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1186
        // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1187
        // which, in this case, is more costly
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1188
        forIn(b, function(value, key, b) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1189
          if (hasOwnProperty.call(b, key)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1190
            // count the number of properties.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1191
            size++;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1192
            // deep compare each property value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1193
            return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1194
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1195
        });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1196
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1197
        if (result && !isWhere) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1198
          // ensure both objects have the same number of properties
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1199
          forIn(a, function(value, key, a) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1200
            if (hasOwnProperty.call(a, key)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1201
              // `size` will be `-1` if `a` has more properties than `b`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1202
              return (result = --size > -1);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1203
            }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1204
          });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1205
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1206
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1207
      stackA.pop();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1208
      stackB.pop();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1209
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1210
      if (initedStack) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1211
        releaseArray(stackA);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1212
        releaseArray(stackB);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1213
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1214
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1215
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1216
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1217
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1218
     * The base implementation of `_.merge` without argument juggling or support
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1219
     * for `thisArg` binding.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1220
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1221
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1222
     * @param {Object} object The destination object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1223
     * @param {Object} source The source object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1224
     * @param {Function} [callback] The function to customize merging properties.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1225
     * @param {Array} [stackA=[]] Tracks traversed source objects.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1226
     * @param {Array} [stackB=[]] Associates values with source counterparts.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1227
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1228
    function baseMerge(object, source, callback, stackA, stackB) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1229
      (isArray(source) ? forEach : forOwn)(source, function(source, key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1230
        var found,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1231
            isArr,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1232
            result = source,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1233
            value = object[key];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1234
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1235
        if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1236
          // avoid merging previously merged cyclic sources
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1237
          var stackLength = stackA.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1238
          while (stackLength--) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1239
            if ((found = stackA[stackLength] == source)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1240
              value = stackB[stackLength];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1241
              break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1242
            }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1243
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1244
          if (!found) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1245
            var isShallow;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1246
            if (callback) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1247
              result = callback(value, source);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1248
              if ((isShallow = typeof result != 'undefined')) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1249
                value = result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1250
              }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1251
            }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1252
            if (!isShallow) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1253
              value = isArr
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1254
                ? (isArray(value) ? value : [])
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1255
                : (isPlainObject(value) ? value : {});
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1256
            }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1257
            // add `source` and associated `value` to the stack of traversed objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1258
            stackA.push(source);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1259
            stackB.push(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1260
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1261
            // recursively merge objects and arrays (susceptible to call stack limits)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1262
            if (!isShallow) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1263
              baseMerge(value, source, callback, stackA, stackB);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1264
            }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1265
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1266
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1267
        else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1268
          if (callback) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1269
            result = callback(value, source);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1270
            if (typeof result == 'undefined') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1271
              result = source;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1272
            }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1273
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1274
          if (typeof result != 'undefined') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1275
            value = result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1276
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1277
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1278
        object[key] = value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1279
      });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1280
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1281
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1282
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1283
     * The base implementation of `_.random` without argument juggling or support
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1284
     * for returning floating-point numbers.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1285
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1286
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1287
     * @param {number} min The minimum possible value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1288
     * @param {number} max The maximum possible value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1289
     * @returns {number} Returns a random number.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1290
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1291
    function baseRandom(min, max) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1292
      return min + floor(nativeRandom() * (max - min + 1));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1293
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1294
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1295
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1296
     * The base implementation of `_.uniq` without support for callback shorthands
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1297
     * or `thisArg` binding.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1298
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1299
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1300
     * @param {Array} array The array to process.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1301
     * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1302
     * @param {Function} [callback] The function called per iteration.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1303
     * @returns {Array} Returns a duplicate-value-free array.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1304
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1305
    function baseUniq(array, isSorted, callback) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1306
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1307
          indexOf = getIndexOf(),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1308
          length = array ? array.length : 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1309
          result = [];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1310
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1311
      var isLarge = !isSorted && length >= largeArraySize && indexOf === baseIndexOf,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1312
          seen = (callback || isLarge) ? getArray() : result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1313
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1314
      if (isLarge) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1315
        var cache = createCache(seen);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1316
        indexOf = cacheIndexOf;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1317
        seen = cache;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1318
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1319
      while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1320
        var value = array[index],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1321
            computed = callback ? callback(value, index, array) : value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1322
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1323
        if (isSorted
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1324
              ? !index || seen[seen.length - 1] !== computed
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1325
              : indexOf(seen, computed) < 0
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1326
            ) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1327
          if (callback || isLarge) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1328
            seen.push(computed);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1329
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1330
          result.push(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1331
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1332
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1333
      if (isLarge) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1334
        releaseArray(seen.array);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1335
        releaseObject(seen);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1336
      } else if (callback) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1337
        releaseArray(seen);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1338
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1339
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1340
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1341
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1342
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1343
     * Creates a function that aggregates a collection, creating an object composed
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1344
     * of keys generated from the results of running each element of the collection
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1345
     * through a callback. The given `setter` function sets the keys and values
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1346
     * of the composed object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1347
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1348
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1349
     * @param {Function} setter The setter function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1350
     * @returns {Function} Returns the new aggregator function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1351
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1352
    function createAggregator(setter) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1353
      return function(collection, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1354
        var result = {};
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1355
        callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1356
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1357
        var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1358
            length = collection ? collection.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1359
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1360
        if (typeof length == 'number') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1361
          while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1362
            var value = collection[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1363
            setter(result, value, callback(value, index, collection), collection);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1364
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1365
        } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1366
          forOwn(collection, function(value, key, collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1367
            setter(result, value, callback(value, key, collection), collection);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1368
          });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1369
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1370
        return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1371
      };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1372
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1373
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1374
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1375
     * Creates a function that, when called, either curries or invokes `func`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1376
     * with an optional `this` binding and partially applied arguments.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1377
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1378
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1379
     * @param {Function|string} func The function or method name to reference.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1380
     * @param {number} bitmask The bitmask of method flags to compose.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1381
     *  The bitmask may be composed of the following flags:
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1382
     *  1 - `_.bind`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1383
     *  2 - `_.bindKey`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1384
     *  4 - `_.curry`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1385
     *  8 - `_.curry` (bound)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1386
     *  16 - `_.partial`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1387
     *  32 - `_.partialRight`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1388
     * @param {Array} [partialArgs] An array of arguments to prepend to those
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1389
     *  provided to the new function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1390
     * @param {Array} [partialRightArgs] An array of arguments to append to those
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1391
     *  provided to the new function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1392
     * @param {*} [thisArg] The `this` binding of `func`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1393
     * @param {number} [arity] The arity of `func`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1394
     * @returns {Function} Returns the new function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1395
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1396
    function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1397
      var isBind = bitmask & 1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1398
          isBindKey = bitmask & 2,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1399
          isCurry = bitmask & 4,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1400
          isCurryBound = bitmask & 8,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1401
          isPartial = bitmask & 16,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1402
          isPartialRight = bitmask & 32;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1403
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1404
      if (!isBindKey && !isFunction(func)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1405
        throw new TypeError;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1406
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1407
      if (isPartial && !partialArgs.length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1408
        bitmask &= ~16;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1409
        isPartial = partialArgs = false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1410
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1411
      if (isPartialRight && !partialRightArgs.length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1412
        bitmask &= ~32;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1413
        isPartialRight = partialRightArgs = false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1414
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1415
      var bindData = func && func.__bindData__;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1416
      if (bindData && bindData !== true) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1417
        // clone `bindData`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1418
        bindData = slice(bindData);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1419
        if (bindData[2]) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1420
          bindData[2] = slice(bindData[2]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1421
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1422
        if (bindData[3]) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1423
          bindData[3] = slice(bindData[3]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1424
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1425
        // set `thisBinding` is not previously bound
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1426
        if (isBind && !(bindData[1] & 1)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1427
          bindData[4] = thisArg;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1428
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1429
        // set if previously bound but not currently (subsequent curried functions)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1430
        if (!isBind && bindData[1] & 1) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1431
          bitmask |= 8;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1432
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1433
        // set curried arity if not yet set
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1434
        if (isCurry && !(bindData[1] & 4)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1435
          bindData[5] = arity;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1436
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1437
        // append partial left arguments
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1438
        if (isPartial) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1439
          push.apply(bindData[2] || (bindData[2] = []), partialArgs);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1440
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1441
        // append partial right arguments
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1442
        if (isPartialRight) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1443
          unshift.apply(bindData[3] || (bindData[3] = []), partialRightArgs);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1444
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1445
        // merge flags
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1446
        bindData[1] |= bitmask;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1447
        return createWrapper.apply(null, bindData);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1448
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1449
      // fast path for `_.bind`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1450
      var creater = (bitmask == 1 || bitmask === 17) ? baseBind : baseCreateWrapper;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1451
      return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1452
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1453
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1454
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1455
     * Used by `escape` to convert characters to HTML entities.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1456
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1457
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1458
     * @param {string} match The matched character to escape.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1459
     * @returns {string} Returns the escaped character.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1460
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1461
    function escapeHtmlChar(match) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1462
      return htmlEscapes[match];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1463
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1464
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1465
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1466
     * Gets the appropriate "indexOf" function. If the `_.indexOf` method is
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1467
     * customized, this method returns the custom method, otherwise it returns
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1468
     * the `baseIndexOf` function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1469
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1470
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1471
     * @returns {Function} Returns the "indexOf" function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1472
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1473
    function getIndexOf() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1474
      var result = (result = lodash.indexOf) === indexOf ? baseIndexOf : result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1475
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1476
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1477
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1478
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1479
     * Checks if `value` is a native function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1480
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1481
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1482
     * @param {*} value The value to check.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1483
     * @returns {boolean} Returns `true` if the `value` is a native function, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1484
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1485
    function isNative(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1486
      return typeof value == 'function' && reNative.test(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1487
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1488
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1489
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1490
     * Sets `this` binding data on a given function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1491
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1492
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1493
     * @param {Function} func The function to set data on.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1494
     * @param {Array} value The data array to set.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1495
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1496
    var setBindData = !defineProperty ? noop : function(func, value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1497
      descriptor.value = value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1498
      defineProperty(func, '__bindData__', descriptor);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1499
    };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1500
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1501
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1502
     * A fallback implementation of `isPlainObject` which checks if a given value
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1503
     * is an object created by the `Object` constructor, assuming objects created
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1504
     * by the `Object` constructor have no inherited enumerable properties and that
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1505
     * there are no `Object.prototype` extensions.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1506
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1507
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1508
     * @param {*} value The value to check.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1509
     * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1510
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1511
    function shimIsPlainObject(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1512
      var ctor,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1513
          result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1514
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1515
      // avoid non Object objects, `arguments` objects, and DOM elements
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1516
      if (!(value && toString.call(value) == objectClass) ||
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1517
          (ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor))) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1518
        return false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1519
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1520
      // In most environments an object's own properties are iterated before
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1521
      // its inherited properties. If the last iterated property is an object's
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1522
      // own property then there are no inherited enumerable properties.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1523
      forIn(value, function(value, key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1524
        result = key;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1525
      });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1526
      return typeof result == 'undefined' || hasOwnProperty.call(value, result);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1527
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1528
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1529
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1530
     * Used by `unescape` to convert HTML entities to characters.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1531
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1532
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1533
     * @param {string} match The matched character to unescape.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1534
     * @returns {string} Returns the unescaped character.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1535
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1536
    function unescapeHtmlChar(match) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1537
      return htmlUnescapes[match];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1538
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1539
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1540
    /*--------------------------------------------------------------------------*/
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1541
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1542
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1543
     * Checks if `value` is an `arguments` object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1544
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1545
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1546
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1547
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1548
     * @param {*} value The value to check.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1549
     * @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1550
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1551
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1552
     * (function() { return _.isArguments(arguments); })(1, 2, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1553
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1554
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1555
     * _.isArguments([1, 2, 3]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1556
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1557
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1558
    function isArguments(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1559
      return value && typeof value == 'object' && typeof value.length == 'number' &&
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1560
        toString.call(value) == argsClass || false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1561
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1562
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1563
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1564
     * Checks if `value` is an array.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1565
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1566
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1567
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1568
     * @type Function
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1569
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1570
     * @param {*} value The value to check.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1571
     * @returns {boolean} Returns `true` if the `value` is an array, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1572
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1573
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1574
     * (function() { return _.isArray(arguments); })();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1575
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1576
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1577
     * _.isArray([1, 2, 3]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1578
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1579
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1580
    var isArray = nativeIsArray || function(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1581
      return value && typeof value == 'object' && typeof value.length == 'number' &&
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1582
        toString.call(value) == arrayClass || false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1583
    };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1584
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1585
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1586
     * A fallback implementation of `Object.keys` which produces an array of the
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1587
     * given object's own enumerable property names.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1588
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1589
     * @private
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1590
     * @type Function
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1591
     * @param {Object} object The object to inspect.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1592
     * @returns {Array} Returns an array of property names.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1593
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1594
    var shimKeys = function(object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1595
      var index, iterable = object, result = [];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1596
      if (!iterable) return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1597
      if (!(objectTypes[typeof object])) return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1598
        for (index in iterable) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1599
          if (hasOwnProperty.call(iterable, index)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1600
            result.push(index);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1601
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1602
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1603
      return result
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1604
    };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1605
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1606
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1607
     * Creates an array composed of the own enumerable property names of an object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1608
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1609
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1610
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1611
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1612
     * @param {Object} object The object to inspect.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1613
     * @returns {Array} Returns an array of property names.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1614
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1615
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1616
     * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1617
     * // => ['one', 'two', 'three'] (property order is not guaranteed across environments)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1618
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1619
    var keys = !nativeKeys ? shimKeys : function(object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1620
      if (!isObject(object)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1621
        return [];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1622
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1623
      return nativeKeys(object);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1624
    };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1625
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1626
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1627
     * Used to convert characters to HTML entities:
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1628
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1629
     * Though the `>` character is escaped for symmetry, characters like `>` and `/`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1630
     * don't require escaping in HTML and have no special meaning unless they're part
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1631
     * of a tag or an unquoted attribute value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1632
     * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1633
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1634
    var htmlEscapes = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1635
      '&': '&amp;',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1636
      '<': '&lt;',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1637
      '>': '&gt;',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1638
      '"': '&quot;',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1639
      "'": '&#39;'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1640
    };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1641
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1642
    /** Used to convert HTML entities to characters */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1643
    var htmlUnescapes = invert(htmlEscapes);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1644
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1645
    /** Used to match HTML entities and HTML characters */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1646
    var reEscapedHtml = RegExp('(' + keys(htmlUnescapes).join('|') + ')', 'g'),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1647
        reUnescapedHtml = RegExp('[' + keys(htmlEscapes).join('') + ']', 'g');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1648
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1649
    /*--------------------------------------------------------------------------*/
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1650
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1651
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1652
     * Assigns own enumerable properties of source object(s) to the destination
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1653
     * object. Subsequent sources will overwrite property assignments of previous
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1654
     * sources. If a callback is provided it will be executed to produce the
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1655
     * assigned values. The callback is bound to `thisArg` and invoked with two
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1656
     * arguments; (objectValue, sourceValue).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1657
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1658
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1659
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1660
     * @type Function
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1661
     * @alias extend
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1662
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1663
     * @param {Object} object The destination object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1664
     * @param {...Object} [source] The source objects.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1665
     * @param {Function} [callback] The function to customize assigning values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1666
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1667
     * @returns {Object} Returns the destination object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1668
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1669
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1670
     * _.assign({ 'name': 'fred' }, { 'employer': 'slate' });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1671
     * // => { 'name': 'fred', 'employer': 'slate' }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1672
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1673
     * var defaults = _.partialRight(_.assign, function(a, b) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1674
     *   return typeof a == 'undefined' ? b : a;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1675
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1676
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1677
     * var object = { 'name': 'barney' };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1678
     * defaults(object, { 'name': 'fred', 'employer': 'slate' });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1679
     * // => { 'name': 'barney', 'employer': 'slate' }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1680
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1681
    var assign = function(object, source, guard) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1682
      var index, iterable = object, result = iterable;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1683
      if (!iterable) return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1684
      var args = arguments,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1685
          argsIndex = 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1686
          argsLength = typeof guard == 'number' ? 2 : args.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1687
      if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1688
        var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1689
      } else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1690
        callback = args[--argsLength];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1691
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1692
      while (++argsIndex < argsLength) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1693
        iterable = args[argsIndex];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1694
        if (iterable && objectTypes[typeof iterable]) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1695
        var ownIndex = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1696
            ownProps = objectTypes[typeof iterable] && keys(iterable),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1697
            length = ownProps ? ownProps.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1698
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1699
        while (++ownIndex < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1700
          index = ownProps[ownIndex];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1701
          result[index] = callback ? callback(result[index], iterable[index]) : iterable[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1702
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1703
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1704
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1705
      return result
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1706
    };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1707
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1708
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1709
     * Creates a clone of `value`. If `isDeep` is `true` nested objects will also
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1710
     * be cloned, otherwise they will be assigned by reference. If a callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1711
     * is provided it will be executed to produce the cloned values. If the
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1712
     * callback returns `undefined` cloning will be handled by the method instead.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1713
     * The callback is bound to `thisArg` and invoked with one argument; (value).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1714
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1715
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1716
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1717
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1718
     * @param {*} value The value to clone.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1719
     * @param {boolean} [isDeep=false] Specify a deep clone.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1720
     * @param {Function} [callback] The function to customize cloning values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1721
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1722
     * @returns {*} Returns the cloned value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1723
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1724
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1725
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1726
     *   { 'name': 'barney', 'age': 36 },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1727
     *   { 'name': 'fred',   'age': 40 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1728
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1729
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1730
     * var shallow = _.clone(characters);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1731
     * shallow[0] === characters[0];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1732
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1733
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1734
     * var deep = _.clone(characters, true);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1735
     * deep[0] === characters[0];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1736
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1737
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1738
     * _.mixin({
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1739
     *   'clone': _.partialRight(_.clone, function(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1740
     *     return _.isElement(value) ? value.cloneNode(false) : undefined;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1741
     *   })
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1742
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1743
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1744
     * var clone = _.clone(document.body);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1745
     * clone.childNodes.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1746
     * // => 0
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1747
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1748
    function clone(value, isDeep, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1749
      // allows working with "Collections" methods without using their `index`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1750
      // and `collection` arguments for `isDeep` and `callback`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1751
      if (typeof isDeep != 'boolean' && isDeep != null) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1752
        thisArg = callback;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1753
        callback = isDeep;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1754
        isDeep = false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1755
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1756
      return baseClone(value, isDeep, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1757
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1758
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1759
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1760
     * Creates a deep clone of `value`. If a callback is provided it will be
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1761
     * executed to produce the cloned values. If the callback returns `undefined`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1762
     * cloning will be handled by the method instead. The callback is bound to
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1763
     * `thisArg` and invoked with one argument; (value).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1764
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1765
     * Note: This method is loosely based on the structured clone algorithm. Functions
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1766
     * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1767
     * objects created by constructors other than `Object` are cloned to plain `Object` objects.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1768
     * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1769
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1770
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1771
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1772
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1773
     * @param {*} value The value to deep clone.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1774
     * @param {Function} [callback] The function to customize cloning values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1775
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1776
     * @returns {*} Returns the deep cloned value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1777
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1778
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1779
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1780
     *   { 'name': 'barney', 'age': 36 },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1781
     *   { 'name': 'fred',   'age': 40 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1782
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1783
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1784
     * var deep = _.cloneDeep(characters);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1785
     * deep[0] === characters[0];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1786
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1787
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1788
     * var view = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1789
     *   'label': 'docs',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1790
     *   'node': element
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1791
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1792
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1793
     * var clone = _.cloneDeep(view, function(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1794
     *   return _.isElement(value) ? value.cloneNode(true) : undefined;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1795
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1796
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1797
     * clone.node == view.node;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1798
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1799
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1800
    function cloneDeep(value, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1801
      return baseClone(value, true, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1802
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1803
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1804
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1805
     * Creates an object that inherits from the given `prototype` object. If a
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1806
     * `properties` object is provided its own enumerable properties are assigned
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1807
     * to the created object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1808
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1809
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1810
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1811
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1812
     * @param {Object} prototype The object to inherit from.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1813
     * @param {Object} [properties] The properties to assign to the object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1814
     * @returns {Object} Returns the new object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1815
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1816
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1817
     * function Shape() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1818
     *   this.x = 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1819
     *   this.y = 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1820
     * }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1821
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1822
     * function Circle() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1823
     *   Shape.call(this);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1824
     * }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1825
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1826
     * Circle.prototype = _.create(Shape.prototype, { 'constructor': Circle });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1827
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1828
     * var circle = new Circle;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1829
     * circle instanceof Circle;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1830
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1831
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1832
     * circle instanceof Shape;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1833
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1834
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1835
    function create(prototype, properties) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1836
      var result = baseCreate(prototype);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1837
      return properties ? assign(result, properties) : result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1838
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1839
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1840
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1841
     * Assigns own enumerable properties of source object(s) to the destination
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1842
     * object for all destination properties that resolve to `undefined`. Once a
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1843
     * property is set, additional defaults of the same property will be ignored.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1844
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1845
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1846
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1847
     * @type Function
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1848
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1849
     * @param {Object} object The destination object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1850
     * @param {...Object} [source] The source objects.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1851
     * @param- {Object} [guard] Allows working with `_.reduce` without using its
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1852
     *  `key` and `object` arguments as sources.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1853
     * @returns {Object} Returns the destination object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1854
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1855
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1856
     * var object = { 'name': 'barney' };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1857
     * _.defaults(object, { 'name': 'fred', 'employer': 'slate' });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1858
     * // => { 'name': 'barney', 'employer': 'slate' }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1859
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1860
    var defaults = function(object, source, guard) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1861
      var index, iterable = object, result = iterable;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1862
      if (!iterable) return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1863
      var args = arguments,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1864
          argsIndex = 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1865
          argsLength = typeof guard == 'number' ? 2 : args.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1866
      while (++argsIndex < argsLength) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1867
        iterable = args[argsIndex];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1868
        if (iterable && objectTypes[typeof iterable]) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1869
        var ownIndex = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1870
            ownProps = objectTypes[typeof iterable] && keys(iterable),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1871
            length = ownProps ? ownProps.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1872
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1873
        while (++ownIndex < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1874
          index = ownProps[ownIndex];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1875
          if (typeof result[index] == 'undefined') result[index] = iterable[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1876
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1877
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1878
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1879
      return result
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1880
    };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1881
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1882
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1883
     * This method is like `_.findIndex` except that it returns the key of the
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1884
     * first element that passes the callback check, instead of the element itself.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1885
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1886
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1887
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1888
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1889
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1890
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1891
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1892
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1893
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1894
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1895
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1896
     * @param {Object} object The object to search.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1897
     * @param {Function|Object|string} [callback=identity] The function called per
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1898
     *  iteration. If a property name or object is provided it will be used to
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1899
     *  create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1900
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1901
     * @returns {string|undefined} Returns the key of the found element, else `undefined`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1902
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1903
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1904
     * var characters = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1905
     *   'barney': {  'age': 36, 'blocked': false },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1906
     *   'fred': {    'age': 40, 'blocked': true },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1907
     *   'pebbles': { 'age': 1,  'blocked': false }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1908
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1909
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1910
     * _.findKey(characters, function(chr) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1911
     *   return chr.age < 40;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1912
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1913
     * // => 'barney' (property order is not guaranteed across environments)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1914
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1915
     * // using "_.where" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1916
     * _.findKey(characters, { 'age': 1 });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1917
     * // => 'pebbles'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1918
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1919
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1920
     * _.findKey(characters, 'blocked');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1921
     * // => 'fred'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1922
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1923
    function findKey(object, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1924
      var result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1925
      callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1926
      forOwn(object, function(value, key, object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1927
        if (callback(value, key, object)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1928
          result = key;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1929
          return false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1930
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1931
      });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1932
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1933
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1934
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1935
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1936
     * This method is like `_.findKey` except that it iterates over elements
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1937
     * of a `collection` in the opposite order.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1938
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1939
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1940
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1941
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1942
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1943
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1944
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1945
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1946
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1947
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1948
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1949
     * @param {Object} object The object to search.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1950
     * @param {Function|Object|string} [callback=identity] The function called per
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1951
     *  iteration. If a property name or object is provided it will be used to
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1952
     *  create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1953
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1954
     * @returns {string|undefined} Returns the key of the found element, else `undefined`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1955
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1956
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1957
     * var characters = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1958
     *   'barney': {  'age': 36, 'blocked': true },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1959
     *   'fred': {    'age': 40, 'blocked': false },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1960
     *   'pebbles': { 'age': 1,  'blocked': true }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1961
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1962
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1963
     * _.findLastKey(characters, function(chr) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1964
     *   return chr.age < 40;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1965
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1966
     * // => returns `pebbles`, assuming `_.findKey` returns `barney`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1967
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1968
     * // using "_.where" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1969
     * _.findLastKey(characters, { 'age': 40 });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1970
     * // => 'fred'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1971
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1972
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1973
     * _.findLastKey(characters, 'blocked');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1974
     * // => 'pebbles'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1975
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1976
    function findLastKey(object, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1977
      var result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1978
      callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1979
      forOwnRight(object, function(value, key, object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1980
        if (callback(value, key, object)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1981
          result = key;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1982
          return false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1983
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1984
      });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1985
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1986
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1987
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1988
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1989
     * Iterates over own and inherited enumerable properties of an object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1990
     * executing the callback for each property. The callback is bound to `thisArg`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1991
     * and invoked with three arguments; (value, key, object). Callbacks may exit
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1992
     * iteration early by explicitly returning `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1993
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1994
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1995
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1996
     * @type Function
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1997
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1998
     * @param {Object} object The object to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  1999
     * @param {Function} [callback=identity] The function called per iteration.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2000
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2001
     * @returns {Object} Returns `object`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2002
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2003
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2004
     * function Shape() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2005
     *   this.x = 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2006
     *   this.y = 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2007
     * }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2008
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2009
     * Shape.prototype.move = function(x, y) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2010
     *   this.x += x;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2011
     *   this.y += y;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2012
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2013
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2014
     * _.forIn(new Shape, function(value, key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2015
     *   console.log(key);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2016
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2017
     * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2018
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2019
    var forIn = function(collection, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2020
      var index, iterable = collection, result = iterable;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2021
      if (!iterable) return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2022
      if (!objectTypes[typeof iterable]) return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2023
      callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2024
        for (index in iterable) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2025
          if (callback(iterable[index], index, collection) === false) return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2026
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2027
      return result
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2028
    };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2029
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2030
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2031
     * This method is like `_.forIn` except that it iterates over elements
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2032
     * of a `collection` in the opposite order.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2033
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2034
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2035
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2036
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2037
     * @param {Object} object The object to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2038
     * @param {Function} [callback=identity] The function called per iteration.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2039
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2040
     * @returns {Object} Returns `object`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2041
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2042
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2043
     * function Shape() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2044
     *   this.x = 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2045
     *   this.y = 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2046
     * }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2047
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2048
     * Shape.prototype.move = function(x, y) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2049
     *   this.x += x;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2050
     *   this.y += y;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2051
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2052
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2053
     * _.forInRight(new Shape, function(value, key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2054
     *   console.log(key);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2055
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2056
     * // => logs 'move', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'move'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2057
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2058
    function forInRight(object, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2059
      var pairs = [];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2060
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2061
      forIn(object, function(value, key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2062
        pairs.push(key, value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2063
      });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2064
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2065
      var length = pairs.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2066
      callback = baseCreateCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2067
      while (length--) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2068
        if (callback(pairs[length--], pairs[length], object) === false) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2069
          break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2070
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2071
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2072
      return object;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2073
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2074
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2075
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2076
     * Iterates over own enumerable properties of an object, executing the callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2077
     * for each property. The callback is bound to `thisArg` and invoked with three
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2078
     * arguments; (value, key, object). Callbacks may exit iteration early by
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2079
     * explicitly returning `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2080
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2081
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2082
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2083
     * @type Function
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2084
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2085
     * @param {Object} object The object to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2086
     * @param {Function} [callback=identity] The function called per iteration.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2087
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2088
     * @returns {Object} Returns `object`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2089
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2090
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2091
     * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2092
     *   console.log(key);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2093
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2094
     * // => logs '0', '1', and 'length' (property order is not guaranteed across environments)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2095
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2096
    var forOwn = function(collection, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2097
      var index, iterable = collection, result = iterable;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2098
      if (!iterable) return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2099
      if (!objectTypes[typeof iterable]) return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2100
      callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2101
        var ownIndex = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2102
            ownProps = objectTypes[typeof iterable] && keys(iterable),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2103
            length = ownProps ? ownProps.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2104
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2105
        while (++ownIndex < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2106
          index = ownProps[ownIndex];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2107
          if (callback(iterable[index], index, collection) === false) return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2108
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2109
      return result
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2110
    };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2111
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2112
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2113
     * This method is like `_.forOwn` except that it iterates over elements
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2114
     * of a `collection` in the opposite order.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2115
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2116
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2117
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2118
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2119
     * @param {Object} object The object to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2120
     * @param {Function} [callback=identity] The function called per iteration.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2121
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2122
     * @returns {Object} Returns `object`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2123
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2124
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2125
     * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2126
     *   console.log(key);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2127
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2128
     * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2129
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2130
    function forOwnRight(object, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2131
      var props = keys(object),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2132
          length = props.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2133
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2134
      callback = baseCreateCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2135
      while (length--) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2136
        var key = props[length];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2137
        if (callback(object[key], key, object) === false) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2138
          break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2139
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2140
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2141
      return object;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2142
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2143
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2144
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2145
     * Creates a sorted array of property names of all enumerable properties,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2146
     * own and inherited, of `object` that have function values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2147
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2148
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2149
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2150
     * @alias methods
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2151
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2152
     * @param {Object} object The object to inspect.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2153
     * @returns {Array} Returns an array of property names that have function values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2154
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2155
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2156
     * _.functions(_);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2157
     * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2158
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2159
    function functions(object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2160
      var result = [];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2161
      forIn(object, function(value, key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2162
        if (isFunction(value)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2163
          result.push(key);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2164
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2165
      });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2166
      return result.sort();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2167
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2168
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2169
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2170
     * Checks if the specified property name exists as a direct property of `object`,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2171
     * instead of an inherited property.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2172
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2173
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2174
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2175
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2176
     * @param {Object} object The object to inspect.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2177
     * @param {string} key The name of the property to check.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2178
     * @returns {boolean} Returns `true` if key is a direct property, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2179
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2180
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2181
     * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2182
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2183
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2184
    function has(object, key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2185
      return object ? hasOwnProperty.call(object, key) : false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2186
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2187
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2188
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2189
     * Creates an object composed of the inverted keys and values of the given object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2190
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2191
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2192
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2193
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2194
     * @param {Object} object The object to invert.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2195
     * @returns {Object} Returns the created inverted object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2196
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2197
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2198
     * _.invert({ 'first': 'fred', 'second': 'barney' });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2199
     * // => { 'fred': 'first', 'barney': 'second' }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2200
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2201
    function invert(object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2202
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2203
          props = keys(object),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2204
          length = props.length,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2205
          result = {};
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2206
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2207
      while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2208
        var key = props[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2209
        result[object[key]] = key;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2210
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2211
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2212
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2213
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2214
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2215
     * Checks if `value` is a boolean value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2216
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2217
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2218
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2219
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2220
     * @param {*} value The value to check.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2221
     * @returns {boolean} Returns `true` if the `value` is a boolean value, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2222
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2223
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2224
     * _.isBoolean(null);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2225
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2226
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2227
    function isBoolean(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2228
      return value === true || value === false ||
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2229
        value && typeof value == 'object' && toString.call(value) == boolClass || false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2230
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2231
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2232
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2233
     * Checks if `value` is a date.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2234
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2235
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2236
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2237
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2238
     * @param {*} value The value to check.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2239
     * @returns {boolean} Returns `true` if the `value` is a date, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2240
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2241
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2242
     * _.isDate(new Date);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2243
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2244
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2245
    function isDate(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2246
      return value && typeof value == 'object' && toString.call(value) == dateClass || false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2247
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2248
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2249
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2250
     * Checks if `value` is a DOM element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2251
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2252
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2253
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2254
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2255
     * @param {*} value The value to check.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2256
     * @returns {boolean} Returns `true` if the `value` is a DOM element, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2257
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2258
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2259
     * _.isElement(document.body);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2260
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2261
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2262
    function isElement(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2263
      return value && value.nodeType === 1 || false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2264
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2265
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2266
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2267
     * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2268
     * length of `0` and objects with no own enumerable properties are considered
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2269
     * "empty".
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2270
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2271
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2272
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2273
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2274
     * @param {Array|Object|string} value The value to inspect.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2275
     * @returns {boolean} Returns `true` if the `value` is empty, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2276
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2277
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2278
     * _.isEmpty([1, 2, 3]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2279
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2280
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2281
     * _.isEmpty({});
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2282
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2283
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2284
     * _.isEmpty('');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2285
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2286
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2287
    function isEmpty(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2288
      var result = true;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2289
      if (!value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2290
        return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2291
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2292
      var className = toString.call(value),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2293
          length = value.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2294
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2295
      if ((className == arrayClass || className == stringClass || className == argsClass ) ||
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2296
          (className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2297
        return !length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2298
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2299
      forOwn(value, function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2300
        return (result = false);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2301
      });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2302
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2303
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2304
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2305
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2306
     * Performs a deep comparison between two values to determine if they are
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2307
     * equivalent to each other. If a callback is provided it will be executed
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2308
     * to compare values. If the callback returns `undefined` comparisons will
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2309
     * be handled by the method instead. The callback is bound to `thisArg` and
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2310
     * invoked with two arguments; (a, b).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2311
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2312
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2313
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2314
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2315
     * @param {*} a The value to compare.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2316
     * @param {*} b The other value to compare.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2317
     * @param {Function} [callback] The function to customize comparing values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2318
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2319
     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2320
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2321
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2322
     * var object = { 'name': 'fred' };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2323
     * var copy = { 'name': 'fred' };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2324
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2325
     * object == copy;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2326
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2327
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2328
     * _.isEqual(object, copy);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2329
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2330
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2331
     * var words = ['hello', 'goodbye'];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2332
     * var otherWords = ['hi', 'goodbye'];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2333
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2334
     * _.isEqual(words, otherWords, function(a, b) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2335
     *   var reGreet = /^(?:hello|hi)$/i,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2336
     *       aGreet = _.isString(a) && reGreet.test(a),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2337
     *       bGreet = _.isString(b) && reGreet.test(b);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2338
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2339
     *   return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2340
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2341
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2342
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2343
    function isEqual(a, b, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2344
      return baseIsEqual(a, b, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2345
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2346
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2347
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2348
     * Checks if `value` is, or can be coerced to, a finite number.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2349
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2350
     * Note: This is not the same as native `isFinite` which will return true for
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2351
     * booleans and empty strings. See http://es5.github.io/#x15.1.2.5.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2352
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2353
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2354
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2355
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2356
     * @param {*} value The value to check.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2357
     * @returns {boolean} Returns `true` if the `value` is finite, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2358
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2359
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2360
     * _.isFinite(-101);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2361
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2362
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2363
     * _.isFinite('10');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2364
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2365
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2366
     * _.isFinite(true);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2367
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2368
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2369
     * _.isFinite('');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2370
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2371
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2372
     * _.isFinite(Infinity);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2373
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2374
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2375
    function isFinite(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2376
      return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2377
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2378
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2379
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2380
     * Checks if `value` is a function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2381
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2382
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2383
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2384
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2385
     * @param {*} value The value to check.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2386
     * @returns {boolean} Returns `true` if the `value` is a function, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2387
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2388
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2389
     * _.isFunction(_);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2390
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2391
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2392
    function isFunction(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2393
      return typeof value == 'function';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2394
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2395
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2396
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2397
     * Checks if `value` is the language type of Object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2398
     * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2399
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2400
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2401
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2402
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2403
     * @param {*} value The value to check.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2404
     * @returns {boolean} Returns `true` if the `value` is an object, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2405
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2406
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2407
     * _.isObject({});
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2408
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2409
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2410
     * _.isObject([1, 2, 3]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2411
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2412
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2413
     * _.isObject(1);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2414
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2415
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2416
    function isObject(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2417
      // check if the value is the ECMAScript language type of Object
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2418
      // http://es5.github.io/#x8
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2419
      // and avoid a V8 bug
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2420
      // http://code.google.com/p/v8/issues/detail?id=2291
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2421
      return !!(value && objectTypes[typeof value]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2422
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2423
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2424
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2425
     * Checks if `value` is `NaN`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2426
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2427
     * Note: This is not the same as native `isNaN` which will return `true` for
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2428
     * `undefined` and other non-numeric values. See http://es5.github.io/#x15.1.2.4.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2429
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2430
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2431
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2432
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2433
     * @param {*} value The value to check.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2434
     * @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2435
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2436
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2437
     * _.isNaN(NaN);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2438
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2439
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2440
     * _.isNaN(new Number(NaN));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2441
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2442
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2443
     * isNaN(undefined);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2444
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2445
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2446
     * _.isNaN(undefined);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2447
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2448
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2449
    function isNaN(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2450
      // `NaN` as a primitive is the only value that is not equal to itself
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2451
      // (perform the [[Class]] check first to avoid errors with some host objects in IE)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2452
      return isNumber(value) && value != +value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2453
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2454
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2455
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2456
     * Checks if `value` is `null`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2457
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2458
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2459
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2460
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2461
     * @param {*} value The value to check.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2462
     * @returns {boolean} Returns `true` if the `value` is `null`, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2463
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2464
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2465
     * _.isNull(null);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2466
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2467
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2468
     * _.isNull(undefined);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2469
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2470
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2471
    function isNull(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2472
      return value === null;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2473
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2474
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2475
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2476
     * Checks if `value` is a number.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2477
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2478
     * Note: `NaN` is considered a number. See http://es5.github.io/#x8.5.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2479
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2480
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2481
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2482
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2483
     * @param {*} value The value to check.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2484
     * @returns {boolean} Returns `true` if the `value` is a number, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2485
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2486
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2487
     * _.isNumber(8.4 * 5);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2488
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2489
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2490
    function isNumber(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2491
      return typeof value == 'number' ||
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2492
        value && typeof value == 'object' && toString.call(value) == numberClass || false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2493
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2494
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2495
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2496
     * Checks if `value` is an object created by the `Object` constructor.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2497
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2498
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2499
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2500
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2501
     * @param {*} value The value to check.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2502
     * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2503
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2504
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2505
     * function Shape() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2506
     *   this.x = 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2507
     *   this.y = 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2508
     * }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2509
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2510
     * _.isPlainObject(new Shape);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2511
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2512
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2513
     * _.isPlainObject([1, 2, 3]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2514
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2515
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2516
     * _.isPlainObject({ 'x': 0, 'y': 0 });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2517
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2518
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2519
    var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2520
      if (!(value && toString.call(value) == objectClass)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2521
        return false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2522
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2523
      var valueOf = value.valueOf,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2524
          objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2525
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2526
      return objProto
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2527
        ? (value == objProto || getPrototypeOf(value) == objProto)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2528
        : shimIsPlainObject(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2529
    };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2530
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2531
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2532
     * Checks if `value` is a regular expression.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2533
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2534
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2535
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2536
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2537
     * @param {*} value The value to check.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2538
     * @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2539
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2540
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2541
     * _.isRegExp(/fred/);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2542
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2543
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2544
    function isRegExp(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2545
      return value && typeof value == 'object' && toString.call(value) == regexpClass || false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2546
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2547
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2548
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2549
     * Checks if `value` is a string.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2550
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2551
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2552
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2553
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2554
     * @param {*} value The value to check.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2555
     * @returns {boolean} Returns `true` if the `value` is a string, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2556
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2557
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2558
     * _.isString('fred');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2559
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2560
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2561
    function isString(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2562
      return typeof value == 'string' ||
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2563
        value && typeof value == 'object' && toString.call(value) == stringClass || false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2564
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2565
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2566
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2567
     * Checks if `value` is `undefined`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2568
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2569
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2570
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2571
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2572
     * @param {*} value The value to check.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2573
     * @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2574
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2575
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2576
     * _.isUndefined(void 0);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2577
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2578
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2579
    function isUndefined(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2580
      return typeof value == 'undefined';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2581
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2582
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2583
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2584
     * Creates an object with the same keys as `object` and values generated by
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2585
     * running each own enumerable property of `object` through the callback.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2586
     * The callback is bound to `thisArg` and invoked with three arguments;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2587
     * (value, key, object).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2588
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2589
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2590
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2591
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2592
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2593
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2594
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2595
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2596
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2597
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2598
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2599
     * @param {Object} object The object to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2600
     * @param {Function|Object|string} [callback=identity] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2601
     *  per iteration. If a property name or object is provided it will be used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2602
     *  to create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2603
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2604
     * @returns {Array} Returns a new object with values of the results of each `callback` execution.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2605
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2606
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2607
     * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2608
     * // => { 'a': 3, 'b': 6, 'c': 9 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2609
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2610
     * var characters = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2611
     *   'fred': { 'name': 'fred', 'age': 40 },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2612
     *   'pebbles': { 'name': 'pebbles', 'age': 1 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2613
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2614
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2615
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2616
     * _.mapValues(characters, 'age');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2617
     * // => { 'fred': 40, 'pebbles': 1 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2618
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2619
    function mapValues(object, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2620
      var result = {};
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2621
      callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2622
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2623
      forOwn(object, function(value, key, object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2624
        result[key] = callback(value, key, object);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2625
      });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2626
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2627
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2628
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2629
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2630
     * Recursively merges own enumerable properties of the source object(s), that
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2631
     * don't resolve to `undefined` into the destination object. Subsequent sources
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2632
     * will overwrite property assignments of previous sources. If a callback is
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2633
     * provided it will be executed to produce the merged values of the destination
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2634
     * and source properties. If the callback returns `undefined` merging will
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2635
     * be handled by the method instead. The callback is bound to `thisArg` and
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2636
     * invoked with two arguments; (objectValue, sourceValue).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2637
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2638
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2639
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2640
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2641
     * @param {Object} object The destination object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2642
     * @param {...Object} [source] The source objects.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2643
     * @param {Function} [callback] The function to customize merging properties.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2644
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2645
     * @returns {Object} Returns the destination object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2646
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2647
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2648
     * var names = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2649
     *   'characters': [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2650
     *     { 'name': 'barney' },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2651
     *     { 'name': 'fred' }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2652
     *   ]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2653
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2654
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2655
     * var ages = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2656
     *   'characters': [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2657
     *     { 'age': 36 },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2658
     *     { 'age': 40 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2659
     *   ]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2660
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2661
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2662
     * _.merge(names, ages);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2663
     * // => { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2664
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2665
     * var food = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2666
     *   'fruits': ['apple'],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2667
     *   'vegetables': ['beet']
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2668
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2669
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2670
     * var otherFood = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2671
     *   'fruits': ['banana'],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2672
     *   'vegetables': ['carrot']
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2673
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2674
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2675
     * _.merge(food, otherFood, function(a, b) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2676
     *   return _.isArray(a) ? a.concat(b) : undefined;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2677
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2678
     * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2679
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2680
    function merge(object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2681
      var args = arguments,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2682
          length = 2;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2683
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2684
      if (!isObject(object)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2685
        return object;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2686
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2687
      // allows working with `_.reduce` and `_.reduceRight` without using
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2688
      // their `index` and `collection` arguments
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2689
      if (typeof args[2] != 'number') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2690
        length = args.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2691
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2692
      if (length > 3 && typeof args[length - 2] == 'function') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2693
        var callback = baseCreateCallback(args[--length - 1], args[length--], 2);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2694
      } else if (length > 2 && typeof args[length - 1] == 'function') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2695
        callback = args[--length];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2696
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2697
      var sources = slice(arguments, 1, length),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2698
          index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2699
          stackA = getArray(),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2700
          stackB = getArray();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2701
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2702
      while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2703
        baseMerge(object, sources[index], callback, stackA, stackB);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2704
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2705
      releaseArray(stackA);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2706
      releaseArray(stackB);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2707
      return object;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2708
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2709
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2710
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2711
     * Creates a shallow clone of `object` excluding the specified properties.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2712
     * Property names may be specified as individual arguments or as arrays of
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2713
     * property names. If a callback is provided it will be executed for each
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2714
     * property of `object` omitting the properties the callback returns truey
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2715
     * for. The callback is bound to `thisArg` and invoked with three arguments;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2716
     * (value, key, object).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2717
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2718
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2719
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2720
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2721
     * @param {Object} object The source object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2722
     * @param {Function|...string|string[]} [callback] The properties to omit or the
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2723
     *  function called per iteration.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2724
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2725
     * @returns {Object} Returns an object without the omitted properties.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2726
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2727
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2728
     * _.omit({ 'name': 'fred', 'age': 40 }, 'age');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2729
     * // => { 'name': 'fred' }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2730
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2731
     * _.omit({ 'name': 'fred', 'age': 40 }, function(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2732
     *   return typeof value == 'number';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2733
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2734
     * // => { 'name': 'fred' }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2735
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2736
    function omit(object, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2737
      var result = {};
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2738
      if (typeof callback != 'function') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2739
        var props = [];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2740
        forIn(object, function(value, key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2741
          props.push(key);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2742
        });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2743
        props = baseDifference(props, baseFlatten(arguments, true, false, 1));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2744
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2745
        var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2746
            length = props.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2747
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2748
        while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2749
          var key = props[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2750
          result[key] = object[key];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2751
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2752
      } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2753
        callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2754
        forIn(object, function(value, key, object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2755
          if (!callback(value, key, object)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2756
            result[key] = value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2757
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2758
        });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2759
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2760
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2761
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2762
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2763
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2764
     * Creates a two dimensional array of an object's key-value pairs,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2765
     * i.e. `[[key1, value1], [key2, value2]]`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2766
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2767
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2768
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2769
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2770
     * @param {Object} object The object to inspect.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2771
     * @returns {Array} Returns new array of key-value pairs.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2772
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2773
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2774
     * _.pairs({ 'barney': 36, 'fred': 40 });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2775
     * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2776
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2777
    function pairs(object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2778
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2779
          props = keys(object),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2780
          length = props.length,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2781
          result = Array(length);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2782
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2783
      while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2784
        var key = props[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2785
        result[index] = [key, object[key]];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2786
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2787
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2788
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2789
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2790
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2791
     * Creates a shallow clone of `object` composed of the specified properties.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2792
     * Property names may be specified as individual arguments or as arrays of
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2793
     * property names. If a callback is provided it will be executed for each
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2794
     * property of `object` picking the properties the callback returns truey
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2795
     * for. The callback is bound to `thisArg` and invoked with three arguments;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2796
     * (value, key, object).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2797
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2798
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2799
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2800
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2801
     * @param {Object} object The source object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2802
     * @param {Function|...string|string[]} [callback] The function called per
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2803
     *  iteration or property names to pick, specified as individual property
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2804
     *  names or arrays of property names.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2805
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2806
     * @returns {Object} Returns an object composed of the picked properties.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2807
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2808
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2809
     * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2810
     * // => { 'name': 'fred' }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2811
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2812
     * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2813
     *   return key.charAt(0) != '_';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2814
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2815
     * // => { 'name': 'fred' }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2816
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2817
    function pick(object, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2818
      var result = {};
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2819
      if (typeof callback != 'function') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2820
        var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2821
            props = baseFlatten(arguments, true, false, 1),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2822
            length = isObject(object) ? props.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2823
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2824
        while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2825
          var key = props[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2826
          if (key in object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2827
            result[key] = object[key];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2828
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2829
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2830
      } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2831
        callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2832
        forIn(object, function(value, key, object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2833
          if (callback(value, key, object)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2834
            result[key] = value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2835
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2836
        });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2837
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2838
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2839
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2840
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2841
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2842
     * An alternative to `_.reduce` this method transforms `object` to a new
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2843
     * `accumulator` object which is the result of running each of its own
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2844
     * enumerable properties through a callback, with each callback execution
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2845
     * potentially mutating the `accumulator` object. The callback is bound to
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2846
     * `thisArg` and invoked with four arguments; (accumulator, value, key, object).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2847
     * Callbacks may exit iteration early by explicitly returning `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2848
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2849
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2850
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2851
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2852
     * @param {Array|Object} object The object to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2853
     * @param {Function} [callback=identity] The function called per iteration.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2854
     * @param {*} [accumulator] The custom accumulator value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2855
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2856
     * @returns {*} Returns the accumulated value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2857
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2858
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2859
     * var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(result, num) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2860
     *   num *= num;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2861
     *   if (num % 2) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2862
     *     return result.push(num) < 3;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2863
     *   }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2864
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2865
     * // => [1, 9, 25]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2866
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2867
     * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2868
     *   result[key] = num * 3;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2869
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2870
     * // => { 'a': 3, 'b': 6, 'c': 9 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2871
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2872
    function transform(object, callback, accumulator, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2873
      var isArr = isArray(object);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2874
      if (accumulator == null) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2875
        if (isArr) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2876
          accumulator = [];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2877
        } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2878
          var ctor = object && object.constructor,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2879
              proto = ctor && ctor.prototype;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2880
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2881
          accumulator = baseCreate(proto);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2882
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2883
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2884
      if (callback) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2885
        callback = lodash.createCallback(callback, thisArg, 4);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2886
        (isArr ? forEach : forOwn)(object, function(value, index, object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2887
          return callback(accumulator, value, index, object);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2888
        });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2889
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2890
      return accumulator;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2891
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2892
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2893
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2894
     * Creates an array composed of the own enumerable property values of `object`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2895
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2896
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2897
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2898
     * @category Objects
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2899
     * @param {Object} object The object to inspect.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2900
     * @returns {Array} Returns an array of property values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2901
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2902
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2903
     * _.values({ 'one': 1, 'two': 2, 'three': 3 });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2904
     * // => [1, 2, 3] (property order is not guaranteed across environments)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2905
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2906
    function values(object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2907
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2908
          props = keys(object),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2909
          length = props.length,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2910
          result = Array(length);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2911
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2912
      while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2913
        result[index] = object[props[index]];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2914
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2915
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2916
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2917
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2918
    /*--------------------------------------------------------------------------*/
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2919
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2920
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2921
     * Creates an array of elements from the specified indexes, or keys, of the
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2922
     * `collection`. Indexes may be specified as individual arguments or as arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2923
     * of indexes.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2924
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2925
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2926
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2927
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2928
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2929
     * @param {...(number|number[]|string|string[])} [index] The indexes of `collection`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2930
     *   to retrieve, specified as individual indexes or arrays of indexes.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2931
     * @returns {Array} Returns a new array of elements corresponding to the
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2932
     *  provided indexes.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2933
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2934
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2935
     * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2936
     * // => ['a', 'c', 'e']
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2937
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2938
     * _.at(['fred', 'barney', 'pebbles'], 0, 2);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2939
     * // => ['fred', 'pebbles']
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2940
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2941
    function at(collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2942
      var args = arguments,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2943
          index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2944
          props = baseFlatten(args, true, false, 1),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2945
          length = (args[2] && args[2][args[1]] === collection) ? 1 : props.length,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2946
          result = Array(length);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2947
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2948
      while(++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2949
        result[index] = collection[props[index]];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2950
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2951
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2952
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2953
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2954
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2955
     * Checks if a given value is present in a collection using strict equality
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2956
     * for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2957
     * offset from the end of the collection.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2958
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2959
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2960
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2961
     * @alias include
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2962
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2963
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2964
     * @param {*} target The value to check for.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2965
     * @param {number} [fromIndex=0] The index to search from.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2966
     * @returns {boolean} Returns `true` if the `target` element is found, else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2967
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2968
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2969
     * _.contains([1, 2, 3], 1);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2970
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2971
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2972
     * _.contains([1, 2, 3], 1, 2);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2973
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2974
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2975
     * _.contains({ 'name': 'fred', 'age': 40 }, 'fred');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2976
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2977
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2978
     * _.contains('pebbles', 'eb');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2979
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2980
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2981
    function contains(collection, target, fromIndex) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2982
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2983
          indexOf = getIndexOf(),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2984
          length = collection ? collection.length : 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2985
          result = false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2986
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2987
      fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2988
      if (isArray(collection)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2989
        result = indexOf(collection, target, fromIndex) > -1;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2990
      } else if (typeof length == 'number') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2991
        result = (isString(collection) ? collection.indexOf(target, fromIndex) : indexOf(collection, target, fromIndex)) > -1;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2992
      } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2993
        forOwn(collection, function(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2994
          if (++index >= fromIndex) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2995
            return !(result = value === target);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2996
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2997
        });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2998
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  2999
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3000
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3001
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3002
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3003
     * Creates an object composed of keys generated from the results of running
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3004
     * each element of `collection` through the callback. The corresponding value
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3005
     * of each key is the number of times the key was returned by the callback.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3006
     * The callback is bound to `thisArg` and invoked with three arguments;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3007
     * (value, index|key, collection).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3008
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3009
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3010
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3011
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3012
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3013
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3014
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3015
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3016
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3017
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3018
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3019
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3020
     * @param {Function|Object|string} [callback=identity] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3021
     *  per iteration. If a property name or object is provided it will be used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3022
     *  to create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3023
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3024
     * @returns {Object} Returns the composed aggregate object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3025
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3026
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3027
     * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3028
     * // => { '4': 1, '6': 2 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3029
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3030
     * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3031
     * // => { '4': 1, '6': 2 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3032
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3033
     * _.countBy(['one', 'two', 'three'], 'length');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3034
     * // => { '3': 2, '5': 1 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3035
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3036
    var countBy = createAggregator(function(result, value, key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3037
      (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3038
    });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3039
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3040
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3041
     * Checks if the given callback returns truey value for **all** elements of
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3042
     * a collection. The callback is bound to `thisArg` and invoked with three
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3043
     * arguments; (value, index|key, collection).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3044
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3045
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3046
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3047
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3048
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3049
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3050
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3051
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3052
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3053
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3054
     * @alias all
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3055
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3056
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3057
     * @param {Function|Object|string} [callback=identity] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3058
     *  per iteration. If a property name or object is provided it will be used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3059
     *  to create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3060
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3061
     * @returns {boolean} Returns `true` if all elements passed the callback check,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3062
     *  else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3063
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3064
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3065
     * _.every([true, 1, null, 'yes']);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3066
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3067
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3068
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3069
     *   { 'name': 'barney', 'age': 36 },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3070
     *   { 'name': 'fred',   'age': 40 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3071
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3072
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3073
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3074
     * _.every(characters, 'age');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3075
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3076
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3077
     * // using "_.where" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3078
     * _.every(characters, { 'age': 36 });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3079
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3080
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3081
    function every(collection, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3082
      var result = true;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3083
      callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3084
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3085
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3086
          length = collection ? collection.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3087
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3088
      if (typeof length == 'number') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3089
        while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3090
          if (!(result = !!callback(collection[index], index, collection))) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3091
            break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3092
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3093
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3094
      } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3095
        forOwn(collection, function(value, index, collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3096
          return (result = !!callback(value, index, collection));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3097
        });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3098
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3099
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3100
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3101
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3102
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3103
     * Iterates over elements of a collection, returning an array of all elements
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3104
     * the callback returns truey for. The callback is bound to `thisArg` and
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3105
     * invoked with three arguments; (value, index|key, collection).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3106
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3107
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3108
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3109
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3110
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3111
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3112
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3113
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3114
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3115
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3116
     * @alias select
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3117
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3118
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3119
     * @param {Function|Object|string} [callback=identity] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3120
     *  per iteration. If a property name or object is provided it will be used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3121
     *  to create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3122
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3123
     * @returns {Array} Returns a new array of elements that passed the callback check.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3124
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3125
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3126
     * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3127
     * // => [2, 4, 6]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3128
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3129
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3130
     *   { 'name': 'barney', 'age': 36, 'blocked': false },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3131
     *   { 'name': 'fred',   'age': 40, 'blocked': true }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3132
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3133
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3134
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3135
     * _.filter(characters, 'blocked');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3136
     * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3137
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3138
     * // using "_.where" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3139
     * _.filter(characters, { 'age': 36 });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3140
     * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3141
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3142
    function filter(collection, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3143
      var result = [];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3144
      callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3145
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3146
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3147
          length = collection ? collection.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3148
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3149
      if (typeof length == 'number') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3150
        while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3151
          var value = collection[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3152
          if (callback(value, index, collection)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3153
            result.push(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3154
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3155
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3156
      } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3157
        forOwn(collection, function(value, index, collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3158
          if (callback(value, index, collection)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3159
            result.push(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3160
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3161
        });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3162
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3163
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3164
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3165
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3166
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3167
     * Iterates over elements of a collection, returning the first element that
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3168
     * the callback returns truey for. The callback is bound to `thisArg` and
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3169
     * invoked with three arguments; (value, index|key, collection).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3170
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3171
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3172
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3173
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3174
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3175
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3176
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3177
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3178
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3179
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3180
     * @alias detect, findWhere
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3181
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3182
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3183
     * @param {Function|Object|string} [callback=identity] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3184
     *  per iteration. If a property name or object is provided it will be used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3185
     *  to create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3186
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3187
     * @returns {*} Returns the found element, else `undefined`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3188
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3189
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3190
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3191
     *   { 'name': 'barney',  'age': 36, 'blocked': false },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3192
     *   { 'name': 'fred',    'age': 40, 'blocked': true },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3193
     *   { 'name': 'pebbles', 'age': 1,  'blocked': false }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3194
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3195
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3196
     * _.find(characters, function(chr) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3197
     *   return chr.age < 40;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3198
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3199
     * // => { 'name': 'barney', 'age': 36, 'blocked': false }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3200
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3201
     * // using "_.where" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3202
     * _.find(characters, { 'age': 1 });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3203
     * // =>  { 'name': 'pebbles', 'age': 1, 'blocked': false }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3204
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3205
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3206
     * _.find(characters, 'blocked');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3207
     * // => { 'name': 'fred', 'age': 40, 'blocked': true }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3208
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3209
    function find(collection, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3210
      callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3211
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3212
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3213
          length = collection ? collection.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3214
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3215
      if (typeof length == 'number') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3216
        while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3217
          var value = collection[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3218
          if (callback(value, index, collection)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3219
            return value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3220
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3221
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3222
      } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3223
        var result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3224
        forOwn(collection, function(value, index, collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3225
          if (callback(value, index, collection)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3226
            result = value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3227
            return false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3228
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3229
        });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3230
        return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3231
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3232
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3233
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3234
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3235
     * This method is like `_.find` except that it iterates over elements
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3236
     * of a `collection` from right to left.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3237
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3238
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3239
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3240
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3241
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3242
     * @param {Function|Object|string} [callback=identity] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3243
     *  per iteration. If a property name or object is provided it will be used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3244
     *  to create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3245
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3246
     * @returns {*} Returns the found element, else `undefined`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3247
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3248
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3249
     * _.findLast([1, 2, 3, 4], function(num) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3250
     *   return num % 2 == 1;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3251
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3252
     * // => 3
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3253
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3254
    function findLast(collection, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3255
      var result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3256
      callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3257
      forEachRight(collection, function(value, index, collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3258
        if (callback(value, index, collection)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3259
          result = value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3260
          return false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3261
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3262
      });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3263
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3264
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3265
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3266
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3267
     * Iterates over elements of a collection, executing the callback for each
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3268
     * element. The callback is bound to `thisArg` and invoked with three arguments;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3269
     * (value, index|key, collection). Callbacks may exit iteration early by
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3270
     * explicitly returning `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3271
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3272
     * Note: As with other "Collections" methods, objects with a `length` property
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3273
     * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3274
     * may be used for object iteration.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3275
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3276
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3277
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3278
     * @alias each
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3279
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3280
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3281
     * @param {Function} [callback=identity] The function called per iteration.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3282
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3283
     * @returns {Array|Object|string} Returns `collection`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3284
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3285
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3286
     * _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(',');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3287
     * // => logs each number and returns '1,2,3'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3288
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3289
     * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3290
     * // => logs each number and returns the object (property order is not guaranteed across environments)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3291
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3292
    function forEach(collection, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3293
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3294
          length = collection ? collection.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3295
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3296
      callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3297
      if (typeof length == 'number') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3298
        while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3299
          if (callback(collection[index], index, collection) === false) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3300
            break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3301
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3302
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3303
      } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3304
        forOwn(collection, callback);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3305
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3306
      return collection;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3307
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3308
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3309
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3310
     * This method is like `_.forEach` except that it iterates over elements
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3311
     * of a `collection` from right to left.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3312
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3313
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3314
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3315
     * @alias eachRight
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3316
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3317
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3318
     * @param {Function} [callback=identity] The function called per iteration.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3319
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3320
     * @returns {Array|Object|string} Returns `collection`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3321
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3322
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3323
     * _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(',');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3324
     * // => logs each number from right to left and returns '3,2,1'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3325
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3326
    function forEachRight(collection, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3327
      var length = collection ? collection.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3328
      callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3329
      if (typeof length == 'number') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3330
        while (length--) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3331
          if (callback(collection[length], length, collection) === false) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3332
            break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3333
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3334
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3335
      } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3336
        var props = keys(collection);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3337
        length = props.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3338
        forOwn(collection, function(value, key, collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3339
          key = props ? props[--length] : --length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3340
          return callback(collection[key], key, collection);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3341
        });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3342
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3343
      return collection;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3344
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3345
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3346
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3347
     * Creates an object composed of keys generated from the results of running
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3348
     * each element of a collection through the callback. The corresponding value
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3349
     * of each key is an array of the elements responsible for generating the key.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3350
     * The callback is bound to `thisArg` and invoked with three arguments;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3351
     * (value, index|key, collection).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3352
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3353
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3354
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3355
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3356
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3357
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3358
     * else `false`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3359
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3360
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3361
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3362
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3363
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3364
     * @param {Function|Object|string} [callback=identity] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3365
     *  per iteration. If a property name or object is provided it will be used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3366
     *  to create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3367
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3368
     * @returns {Object} Returns the composed aggregate object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3369
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3370
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3371
     * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3372
     * // => { '4': [4.2], '6': [6.1, 6.4] }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3373
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3374
     * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3375
     * // => { '4': [4.2], '6': [6.1, 6.4] }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3376
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3377
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3378
     * _.groupBy(['one', 'two', 'three'], 'length');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3379
     * // => { '3': ['one', 'two'], '5': ['three'] }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3380
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3381
    var groupBy = createAggregator(function(result, value, key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3382
      (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3383
    });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3384
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3385
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3386
     * Creates an object composed of keys generated from the results of running
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3387
     * each element of the collection through the given callback. The corresponding
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3388
     * value of each key is the last element responsible for generating the key.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3389
     * The callback is bound to `thisArg` and invoked with three arguments;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3390
     * (value, index|key, collection).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3391
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3392
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3393
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3394
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3395
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3396
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3397
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3398
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3399
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3400
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3401
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3402
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3403
     * @param {Function|Object|string} [callback=identity] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3404
     *  per iteration. If a property name or object is provided it will be used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3405
     *  to create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3406
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3407
     * @returns {Object} Returns the composed aggregate object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3408
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3409
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3410
     * var keys = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3411
     *   { 'dir': 'left', 'code': 97 },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3412
     *   { 'dir': 'right', 'code': 100 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3413
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3414
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3415
     * _.indexBy(keys, 'dir');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3416
     * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3417
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3418
     * _.indexBy(keys, function(key) { return String.fromCharCode(key.code); });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3419
     * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3420
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3421
     * _.indexBy(characters, function(key) { this.fromCharCode(key.code); }, String);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3422
     * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3423
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3424
    var indexBy = createAggregator(function(result, value, key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3425
      result[key] = value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3426
    });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3427
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3428
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3429
     * Invokes the method named by `methodName` on each element in the `collection`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3430
     * returning an array of the results of each invoked method. Additional arguments
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3431
     * will be provided to each invoked method. If `methodName` is a function it
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3432
     * will be invoked for, and `this` bound to, each element in the `collection`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3433
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3434
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3435
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3436
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3437
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3438
     * @param {Function|string} methodName The name of the method to invoke or
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3439
     *  the function invoked per iteration.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3440
     * @param {...*} [arg] Arguments to invoke the method with.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3441
     * @returns {Array} Returns a new array of the results of each invoked method.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3442
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3443
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3444
     * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3445
     * // => [[1, 5, 7], [1, 2, 3]]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3446
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3447
     * _.invoke([123, 456], String.prototype.split, '');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3448
     * // => [['1', '2', '3'], ['4', '5', '6']]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3449
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3450
    function invoke(collection, methodName) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3451
      var args = slice(arguments, 2),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3452
          index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3453
          isFunc = typeof methodName == 'function',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3454
          length = collection ? collection.length : 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3455
          result = Array(typeof length == 'number' ? length : 0);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3456
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3457
      forEach(collection, function(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3458
        result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3459
      });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3460
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3461
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3462
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3463
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3464
     * Creates an array of values by running each element in the collection
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3465
     * through the callback. The callback is bound to `thisArg` and invoked with
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3466
     * three arguments; (value, index|key, collection).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3467
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3468
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3469
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3470
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3471
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3472
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3473
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3474
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3475
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3476
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3477
     * @alias collect
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3478
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3479
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3480
     * @param {Function|Object|string} [callback=identity] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3481
     *  per iteration. If a property name or object is provided it will be used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3482
     *  to create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3483
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3484
     * @returns {Array} Returns a new array of the results of each `callback` execution.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3485
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3486
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3487
     * _.map([1, 2, 3], function(num) { return num * 3; });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3488
     * // => [3, 6, 9]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3489
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3490
     * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3491
     * // => [3, 6, 9] (property order is not guaranteed across environments)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3492
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3493
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3494
     *   { 'name': 'barney', 'age': 36 },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3495
     *   { 'name': 'fred',   'age': 40 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3496
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3497
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3498
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3499
     * _.map(characters, 'name');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3500
     * // => ['barney', 'fred']
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3501
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3502
    function map(collection, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3503
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3504
          length = collection ? collection.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3505
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3506
      callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3507
      if (typeof length == 'number') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3508
        var result = Array(length);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3509
        while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3510
          result[index] = callback(collection[index], index, collection);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3511
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3512
      } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3513
        result = [];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3514
        forOwn(collection, function(value, key, collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3515
          result[++index] = callback(value, key, collection);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3516
        });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3517
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3518
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3519
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3520
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3521
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3522
     * Retrieves the maximum value of a collection. If the collection is empty or
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3523
     * falsey `-Infinity` is returned. If a callback is provided it will be executed
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3524
     * for each value in the collection to generate the criterion by which the value
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3525
     * is ranked. The callback is bound to `thisArg` and invoked with three
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3526
     * arguments; (value, index, collection).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3527
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3528
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3529
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3530
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3531
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3532
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3533
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3534
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3535
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3536
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3537
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3538
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3539
     * @param {Function|Object|string} [callback=identity] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3540
     *  per iteration. If a property name or object is provided it will be used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3541
     *  to create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3542
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3543
     * @returns {*} Returns the maximum value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3544
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3545
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3546
     * _.max([4, 2, 8, 6]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3547
     * // => 8
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3548
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3549
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3550
     *   { 'name': 'barney', 'age': 36 },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3551
     *   { 'name': 'fred',   'age': 40 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3552
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3553
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3554
     * _.max(characters, function(chr) { return chr.age; });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3555
     * // => { 'name': 'fred', 'age': 40 };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3556
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3557
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3558
     * _.max(characters, 'age');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3559
     * // => { 'name': 'fred', 'age': 40 };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3560
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3561
    function max(collection, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3562
      var computed = -Infinity,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3563
          result = computed;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3564
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3565
      // allows working with functions like `_.map` without using
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3566
      // their `index` argument as a callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3567
      if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3568
        callback = null;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3569
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3570
      if (callback == null && isArray(collection)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3571
        var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3572
            length = collection.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3573
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3574
        while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3575
          var value = collection[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3576
          if (value > result) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3577
            result = value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3578
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3579
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3580
      } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3581
        callback = (callback == null && isString(collection))
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3582
          ? charAtCallback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3583
          : lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3584
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3585
        forEach(collection, function(value, index, collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3586
          var current = callback(value, index, collection);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3587
          if (current > computed) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3588
            computed = current;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3589
            result = value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3590
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3591
        });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3592
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3593
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3594
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3595
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3596
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3597
     * Retrieves the minimum value of a collection. If the collection is empty or
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3598
     * falsey `Infinity` is returned. If a callback is provided it will be executed
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3599
     * for each value in the collection to generate the criterion by which the value
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3600
     * is ranked. The callback is bound to `thisArg` and invoked with three
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3601
     * arguments; (value, index, collection).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3602
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3603
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3604
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3605
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3606
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3607
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3608
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3609
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3610
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3611
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3612
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3613
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3614
     * @param {Function|Object|string} [callback=identity] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3615
     *  per iteration. If a property name or object is provided it will be used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3616
     *  to create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3617
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3618
     * @returns {*} Returns the minimum value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3619
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3620
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3621
     * _.min([4, 2, 8, 6]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3622
     * // => 2
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3623
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3624
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3625
     *   { 'name': 'barney', 'age': 36 },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3626
     *   { 'name': 'fred',   'age': 40 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3627
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3628
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3629
     * _.min(characters, function(chr) { return chr.age; });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3630
     * // => { 'name': 'barney', 'age': 36 };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3631
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3632
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3633
     * _.min(characters, 'age');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3634
     * // => { 'name': 'barney', 'age': 36 };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3635
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3636
    function min(collection, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3637
      var computed = Infinity,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3638
          result = computed;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3639
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3640
      // allows working with functions like `_.map` without using
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3641
      // their `index` argument as a callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3642
      if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3643
        callback = null;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3644
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3645
      if (callback == null && isArray(collection)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3646
        var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3647
            length = collection.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3648
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3649
        while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3650
          var value = collection[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3651
          if (value < result) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3652
            result = value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3653
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3654
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3655
      } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3656
        callback = (callback == null && isString(collection))
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3657
          ? charAtCallback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3658
          : lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3659
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3660
        forEach(collection, function(value, index, collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3661
          var current = callback(value, index, collection);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3662
          if (current < computed) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3663
            computed = current;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3664
            result = value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3665
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3666
        });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3667
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3668
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3669
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3670
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3671
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3672
     * Retrieves the value of a specified property from all elements in the collection.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3673
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3674
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3675
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3676
     * @type Function
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3677
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3678
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3679
     * @param {string} property The name of the property to pluck.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3680
     * @returns {Array} Returns a new array of property values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3681
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3682
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3683
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3684
     *   { 'name': 'barney', 'age': 36 },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3685
     *   { 'name': 'fred',   'age': 40 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3686
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3687
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3688
     * _.pluck(characters, 'name');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3689
     * // => ['barney', 'fred']
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3690
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3691
    var pluck = map;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3692
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3693
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3694
     * Reduces a collection to a value which is the accumulated result of running
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3695
     * each element in the collection through the callback, where each successive
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3696
     * callback execution consumes the return value of the previous execution. If
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3697
     * `accumulator` is not provided the first element of the collection will be
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3698
     * used as the initial `accumulator` value. The callback is bound to `thisArg`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3699
     * and invoked with four arguments; (accumulator, value, index|key, collection).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3700
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3701
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3702
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3703
     * @alias foldl, inject
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3704
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3705
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3706
     * @param {Function} [callback=identity] The function called per iteration.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3707
     * @param {*} [accumulator] Initial value of the accumulator.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3708
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3709
     * @returns {*} Returns the accumulated value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3710
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3711
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3712
     * var sum = _.reduce([1, 2, 3], function(sum, num) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3713
     *   return sum + num;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3714
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3715
     * // => 6
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3716
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3717
     * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3718
     *   result[key] = num * 3;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3719
     *   return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3720
     * }, {});
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3721
     * // => { 'a': 3, 'b': 6, 'c': 9 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3722
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3723
    function reduce(collection, callback, accumulator, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3724
      if (!collection) return accumulator;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3725
      var noaccum = arguments.length < 3;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3726
      callback = lodash.createCallback(callback, thisArg, 4);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3727
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3728
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3729
          length = collection.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3730
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3731
      if (typeof length == 'number') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3732
        if (noaccum) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3733
          accumulator = collection[++index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3734
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3735
        while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3736
          accumulator = callback(accumulator, collection[index], index, collection);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3737
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3738
      } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3739
        forOwn(collection, function(value, index, collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3740
          accumulator = noaccum
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3741
            ? (noaccum = false, value)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3742
            : callback(accumulator, value, index, collection)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3743
        });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3744
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3745
      return accumulator;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3746
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3747
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3748
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3749
     * This method is like `_.reduce` except that it iterates over elements
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3750
     * of a `collection` from right to left.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3751
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3752
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3753
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3754
     * @alias foldr
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3755
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3756
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3757
     * @param {Function} [callback=identity] The function called per iteration.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3758
     * @param {*} [accumulator] Initial value of the accumulator.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3759
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3760
     * @returns {*} Returns the accumulated value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3761
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3762
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3763
     * var list = [[0, 1], [2, 3], [4, 5]];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3764
     * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3765
     * // => [4, 5, 2, 3, 0, 1]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3766
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3767
    function reduceRight(collection, callback, accumulator, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3768
      var noaccum = arguments.length < 3;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3769
      callback = lodash.createCallback(callback, thisArg, 4);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3770
      forEachRight(collection, function(value, index, collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3771
        accumulator = noaccum
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3772
          ? (noaccum = false, value)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3773
          : callback(accumulator, value, index, collection);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3774
      });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3775
      return accumulator;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3776
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3777
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3778
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3779
     * The opposite of `_.filter` this method returns the elements of a
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3780
     * collection that the callback does **not** return truey for.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3781
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3782
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3783
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3784
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3785
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3786
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3787
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3788
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3789
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3790
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3791
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3792
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3793
     * @param {Function|Object|string} [callback=identity] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3794
     *  per iteration. If a property name or object is provided it will be used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3795
     *  to create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3796
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3797
     * @returns {Array} Returns a new array of elements that failed the callback check.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3798
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3799
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3800
     * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3801
     * // => [1, 3, 5]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3802
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3803
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3804
     *   { 'name': 'barney', 'age': 36, 'blocked': false },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3805
     *   { 'name': 'fred',   'age': 40, 'blocked': true }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3806
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3807
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3808
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3809
     * _.reject(characters, 'blocked');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3810
     * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3811
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3812
     * // using "_.where" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3813
     * _.reject(characters, { 'age': 36 });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3814
     * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3815
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3816
    function reject(collection, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3817
      callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3818
      return filter(collection, function(value, index, collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3819
        return !callback(value, index, collection);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3820
      });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3821
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3822
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3823
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3824
     * Retrieves a random element or `n` random elements from a collection.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3825
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3826
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3827
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3828
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3829
     * @param {Array|Object|string} collection The collection to sample.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3830
     * @param {number} [n] The number of elements to sample.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3831
     * @param- {Object} [guard] Allows working with functions like `_.map`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3832
     *  without using their `index` arguments as `n`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3833
     * @returns {Array} Returns the random sample(s) of `collection`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3834
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3835
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3836
     * _.sample([1, 2, 3, 4]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3837
     * // => 2
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3838
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3839
     * _.sample([1, 2, 3, 4], 2);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3840
     * // => [3, 1]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3841
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3842
    function sample(collection, n, guard) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3843
      if (collection && typeof collection.length != 'number') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3844
        collection = values(collection);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3845
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3846
      if (n == null || guard) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3847
        return collection ? collection[baseRandom(0, collection.length - 1)] : undefined;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3848
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3849
      var result = shuffle(collection);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3850
      result.length = nativeMin(nativeMax(0, n), result.length);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3851
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3852
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3853
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3854
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3855
     * Creates an array of shuffled values, using a version of the Fisher-Yates
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3856
     * shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3857
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3858
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3859
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3860
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3861
     * @param {Array|Object|string} collection The collection to shuffle.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3862
     * @returns {Array} Returns a new shuffled collection.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3863
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3864
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3865
     * _.shuffle([1, 2, 3, 4, 5, 6]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3866
     * // => [4, 1, 6, 3, 5, 2]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3867
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3868
    function shuffle(collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3869
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3870
          length = collection ? collection.length : 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3871
          result = Array(typeof length == 'number' ? length : 0);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3872
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3873
      forEach(collection, function(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3874
        var rand = baseRandom(0, ++index);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3875
        result[index] = result[rand];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3876
        result[rand] = value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3877
      });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3878
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3879
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3880
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3881
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3882
     * Gets the size of the `collection` by returning `collection.length` for arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3883
     * and array-like objects or the number of own enumerable properties for objects.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3884
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3885
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3886
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3887
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3888
     * @param {Array|Object|string} collection The collection to inspect.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3889
     * @returns {number} Returns `collection.length` or number of own enumerable properties.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3890
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3891
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3892
     * _.size([1, 2]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3893
     * // => 2
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3894
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3895
     * _.size({ 'one': 1, 'two': 2, 'three': 3 });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3896
     * // => 3
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3897
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3898
     * _.size('pebbles');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3899
     * // => 7
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3900
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3901
    function size(collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3902
      var length = collection ? collection.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3903
      return typeof length == 'number' ? length : keys(collection).length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3904
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3905
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3906
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3907
     * Checks if the callback returns a truey value for **any** element of a
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3908
     * collection. The function returns as soon as it finds a passing value and
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3909
     * does not iterate over the entire collection. The callback is bound to
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3910
     * `thisArg` and invoked with three arguments; (value, index|key, collection).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3911
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3912
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3913
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3914
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3915
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3916
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3917
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3918
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3919
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3920
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3921
     * @alias any
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3922
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3923
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3924
     * @param {Function|Object|string} [callback=identity] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3925
     *  per iteration. If a property name or object is provided it will be used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3926
     *  to create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3927
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3928
     * @returns {boolean} Returns `true` if any element passed the callback check,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3929
     *  else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3930
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3931
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3932
     * _.some([null, 0, 'yes', false], Boolean);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3933
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3934
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3935
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3936
     *   { 'name': 'barney', 'age': 36, 'blocked': false },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3937
     *   { 'name': 'fred',   'age': 40, 'blocked': true }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3938
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3939
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3940
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3941
     * _.some(characters, 'blocked');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3942
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3943
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3944
     * // using "_.where" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3945
     * _.some(characters, { 'age': 1 });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3946
     * // => false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3947
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3948
    function some(collection, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3949
      var result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3950
      callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3951
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3952
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3953
          length = collection ? collection.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3954
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3955
      if (typeof length == 'number') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3956
        while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3957
          if ((result = callback(collection[index], index, collection))) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3958
            break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3959
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3960
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3961
      } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3962
        forOwn(collection, function(value, index, collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3963
          return !(result = callback(value, index, collection));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3964
        });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3965
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3966
      return !!result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3967
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3968
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3969
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3970
     * Creates an array of elements, sorted in ascending order by the results of
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3971
     * running each element in a collection through the callback. This method
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3972
     * performs a stable sort, that is, it will preserve the original sort order
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3973
     * of equal elements. The callback is bound to `thisArg` and invoked with
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3974
     * three arguments; (value, index|key, collection).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3975
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3976
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3977
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3978
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3979
     * If an array of property names is provided for `callback` the collection
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3980
     * will be sorted by each property value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3981
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3982
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3983
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3984
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3985
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3986
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3987
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3988
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3989
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3990
     * @param {Array|Function|Object|string} [callback=identity] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3991
     *  per iteration. If a property name or object is provided it will be used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3992
     *  to create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3993
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3994
     * @returns {Array} Returns a new array of sorted elements.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3995
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3996
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3997
     * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3998
     * // => [3, 1, 2]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  3999
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4000
     * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4001
     * // => [3, 1, 2]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4002
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4003
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4004
     *   { 'name': 'barney',  'age': 36 },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4005
     *   { 'name': 'fred',    'age': 40 },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4006
     *   { 'name': 'barney',  'age': 26 },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4007
     *   { 'name': 'fred',    'age': 30 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4008
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4009
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4010
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4011
     * _.map(_.sortBy(characters, 'age'), _.values);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4012
     * // => [['barney', 26], ['fred', 30], ['barney', 36], ['fred', 40]]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4013
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4014
     * // sorting by multiple properties
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4015
     * _.map(_.sortBy(characters, ['name', 'age']), _.values);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4016
     * // = > [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4017
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4018
    function sortBy(collection, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4019
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4020
          isArr = isArray(callback),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4021
          length = collection ? collection.length : 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4022
          result = Array(typeof length == 'number' ? length : 0);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4023
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4024
      if (!isArr) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4025
        callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4026
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4027
      forEach(collection, function(value, key, collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4028
        var object = result[++index] = getObject();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4029
        if (isArr) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4030
          object.criteria = map(callback, function(key) { return value[key]; });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4031
        } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4032
          (object.criteria = getArray())[0] = callback(value, key, collection);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4033
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4034
        object.index = index;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4035
        object.value = value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4036
      });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4037
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4038
      length = result.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4039
      result.sort(compareAscending);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4040
      while (length--) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4041
        var object = result[length];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4042
        result[length] = object.value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4043
        if (!isArr) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4044
          releaseArray(object.criteria);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4045
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4046
        releaseObject(object);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4047
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4048
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4049
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4050
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4051
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4052
     * Converts the `collection` to an array.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4053
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4054
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4055
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4056
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4057
     * @param {Array|Object|string} collection The collection to convert.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4058
     * @returns {Array} Returns the new converted array.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4059
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4060
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4061
     * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4062
     * // => [2, 3, 4]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4063
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4064
    function toArray(collection) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4065
      if (collection && typeof collection.length == 'number') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4066
        return slice(collection);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4067
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4068
      return values(collection);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4069
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4070
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4071
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4072
     * Performs a deep comparison of each element in a `collection` to the given
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4073
     * `properties` object, returning an array of all elements that have equivalent
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4074
     * property values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4075
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4076
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4077
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4078
     * @type Function
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4079
     * @category Collections
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4080
     * @param {Array|Object|string} collection The collection to iterate over.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4081
     * @param {Object} props The object of property values to filter by.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4082
     * @returns {Array} Returns a new array of elements that have the given properties.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4083
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4084
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4085
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4086
     *   { 'name': 'barney', 'age': 36, 'pets': ['hoppy'] },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4087
     *   { 'name': 'fred',   'age': 40, 'pets': ['baby puss', 'dino'] }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4088
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4089
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4090
     * _.where(characters, { 'age': 36 });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4091
     * // => [{ 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4092
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4093
     * _.where(characters, { 'pets': ['dino'] });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4094
     * // => [{ 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4095
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4096
    var where = filter;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4097
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4098
    /*--------------------------------------------------------------------------*/
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4099
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4100
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4101
     * Creates an array with all falsey values removed. The values `false`, `null`,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4102
     * `0`, `""`, `undefined`, and `NaN` are all falsey.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4103
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4104
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4105
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4106
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4107
     * @param {Array} array The array to compact.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4108
     * @returns {Array} Returns a new array of filtered values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4109
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4110
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4111
     * _.compact([0, 1, false, 2, '', 3]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4112
     * // => [1, 2, 3]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4113
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4114
    function compact(array) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4115
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4116
          length = array ? array.length : 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4117
          result = [];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4118
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4119
      while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4120
        var value = array[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4121
        if (value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4122
          result.push(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4123
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4124
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4125
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4126
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4127
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4128
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4129
     * Creates an array excluding all values of the provided arrays using strict
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4130
     * equality for comparisons, i.e. `===`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4131
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4132
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4133
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4134
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4135
     * @param {Array} array The array to process.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4136
     * @param {...Array} [values] The arrays of values to exclude.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4137
     * @returns {Array} Returns a new array of filtered values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4138
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4139
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4140
     * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4141
     * // => [1, 3, 4]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4142
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4143
    function difference(array) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4144
      return baseDifference(array, baseFlatten(arguments, true, true, 1));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4145
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4146
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4147
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4148
     * This method is like `_.find` except that it returns the index of the first
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4149
     * element that passes the callback check, instead of the element itself.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4150
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4151
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4152
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4153
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4154
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4155
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4156
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4157
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4158
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4159
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4160
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4161
     * @param {Array} array The array to search.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4162
     * @param {Function|Object|string} [callback=identity] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4163
     *  per iteration. If a property name or object is provided it will be used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4164
     *  to create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4165
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4166
     * @returns {number} Returns the index of the found element, else `-1`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4167
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4168
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4169
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4170
     *   { 'name': 'barney',  'age': 36, 'blocked': false },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4171
     *   { 'name': 'fred',    'age': 40, 'blocked': true },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4172
     *   { 'name': 'pebbles', 'age': 1,  'blocked': false }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4173
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4174
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4175
     * _.findIndex(characters, function(chr) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4176
     *   return chr.age < 20;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4177
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4178
     * // => 2
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4179
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4180
     * // using "_.where" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4181
     * _.findIndex(characters, { 'age': 36 });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4182
     * // => 0
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4183
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4184
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4185
     * _.findIndex(characters, 'blocked');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4186
     * // => 1
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4187
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4188
    function findIndex(array, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4189
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4190
          length = array ? array.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4191
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4192
      callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4193
      while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4194
        if (callback(array[index], index, array)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4195
          return index;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4196
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4197
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4198
      return -1;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4199
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4200
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4201
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4202
     * This method is like `_.findIndex` except that it iterates over elements
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4203
     * of a `collection` from right to left.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4204
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4205
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4206
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4207
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4208
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4209
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4210
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4211
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4212
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4213
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4214
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4215
     * @param {Array} array The array to search.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4216
     * @param {Function|Object|string} [callback=identity] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4217
     *  per iteration. If a property name or object is provided it will be used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4218
     *  to create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4219
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4220
     * @returns {number} Returns the index of the found element, else `-1`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4221
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4222
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4223
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4224
     *   { 'name': 'barney',  'age': 36, 'blocked': true },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4225
     *   { 'name': 'fred',    'age': 40, 'blocked': false },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4226
     *   { 'name': 'pebbles', 'age': 1,  'blocked': true }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4227
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4228
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4229
     * _.findLastIndex(characters, function(chr) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4230
     *   return chr.age > 30;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4231
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4232
     * // => 1
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4233
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4234
     * // using "_.where" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4235
     * _.findLastIndex(characters, { 'age': 36 });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4236
     * // => 0
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4237
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4238
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4239
     * _.findLastIndex(characters, 'blocked');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4240
     * // => 2
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4241
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4242
    function findLastIndex(array, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4243
      var length = array ? array.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4244
      callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4245
      while (length--) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4246
        if (callback(array[length], length, array)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4247
          return length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4248
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4249
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4250
      return -1;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4251
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4252
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4253
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4254
     * Gets the first element or first `n` elements of an array. If a callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4255
     * is provided elements at the beginning of the array are returned as long
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4256
     * as the callback returns truey. The callback is bound to `thisArg` and
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4257
     * invoked with three arguments; (value, index, array).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4258
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4259
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4260
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4261
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4262
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4263
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4264
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4265
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4266
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4267
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4268
     * @alias head, take
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4269
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4270
     * @param {Array} array The array to query.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4271
     * @param {Function|Object|number|string} [callback] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4272
     *  per element or the number of elements to return. If a property name or
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4273
     *  object is provided it will be used to create a "_.pluck" or "_.where"
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4274
     *  style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4275
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4276
     * @returns {*} Returns the first element(s) of `array`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4277
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4278
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4279
     * _.first([1, 2, 3]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4280
     * // => 1
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4281
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4282
     * _.first([1, 2, 3], 2);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4283
     * // => [1, 2]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4284
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4285
     * _.first([1, 2, 3], function(num) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4286
     *   return num < 3;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4287
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4288
     * // => [1, 2]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4289
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4290
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4291
     *   { 'name': 'barney',  'blocked': true,  'employer': 'slate' },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4292
     *   { 'name': 'fred',    'blocked': false, 'employer': 'slate' },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4293
     *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4294
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4295
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4296
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4297
     * _.first(characters, 'blocked');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4298
     * // => [{ 'name': 'barney', 'blocked': true, 'employer': 'slate' }]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4299
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4300
     * // using "_.where" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4301
     * _.pluck(_.first(characters, { 'employer': 'slate' }), 'name');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4302
     * // => ['barney', 'fred']
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4303
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4304
    function first(array, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4305
      var n = 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4306
          length = array ? array.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4307
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4308
      if (typeof callback != 'number' && callback != null) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4309
        var index = -1;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4310
        callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4311
        while (++index < length && callback(array[index], index, array)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4312
          n++;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4313
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4314
      } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4315
        n = callback;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4316
        if (n == null || thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4317
          return array ? array[0] : undefined;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4318
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4319
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4320
      return slice(array, 0, nativeMin(nativeMax(0, n), length));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4321
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4322
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4323
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4324
     * Flattens a nested array (the nesting can be to any depth). If `isShallow`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4325
     * is truey, the array will only be flattened a single level. If a callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4326
     * is provided each element of the array is passed through the callback before
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4327
     * flattening. The callback is bound to `thisArg` and invoked with three
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4328
     * arguments; (value, index, array).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4329
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4330
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4331
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4332
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4333
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4334
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4335
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4336
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4337
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4338
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4339
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4340
     * @param {Array} array The array to flatten.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4341
     * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4342
     * @param {Function|Object|string} [callback=identity] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4343
     *  per iteration. If a property name or object is provided it will be used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4344
     *  to create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4345
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4346
     * @returns {Array} Returns a new flattened array.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4347
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4348
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4349
     * _.flatten([1, [2], [3, [[4]]]]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4350
     * // => [1, 2, 3, 4];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4351
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4352
     * _.flatten([1, [2], [3, [[4]]]], true);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4353
     * // => [1, 2, 3, [[4]]];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4354
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4355
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4356
     *   { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4357
     *   { 'name': 'fred',   'age': 40, 'pets': ['baby puss', 'dino'] }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4358
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4359
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4360
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4361
     * _.flatten(characters, 'pets');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4362
     * // => ['hoppy', 'baby puss', 'dino']
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4363
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4364
    function flatten(array, isShallow, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4365
      // juggle arguments
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4366
      if (typeof isShallow != 'boolean' && isShallow != null) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4367
        thisArg = callback;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4368
        callback = (typeof isShallow != 'function' && thisArg && thisArg[isShallow] === array) ? null : isShallow;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4369
        isShallow = false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4370
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4371
      if (callback != null) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4372
        array = map(array, callback, thisArg);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4373
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4374
      return baseFlatten(array, isShallow);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4375
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4376
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4377
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4378
     * Gets the index at which the first occurrence of `value` is found using
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4379
     * strict equality for comparisons, i.e. `===`. If the array is already sorted
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4380
     * providing `true` for `fromIndex` will run a faster binary search.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4381
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4382
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4383
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4384
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4385
     * @param {Array} array The array to search.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4386
     * @param {*} value The value to search for.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4387
     * @param {boolean|number} [fromIndex=0] The index to search from or `true`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4388
     *  to perform a binary search on a sorted array.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4389
     * @returns {number} Returns the index of the matched value or `-1`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4390
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4391
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4392
     * _.indexOf([1, 2, 3, 1, 2, 3], 2);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4393
     * // => 1
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4394
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4395
     * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4396
     * // => 4
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4397
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4398
     * _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4399
     * // => 2
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4400
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4401
    function indexOf(array, value, fromIndex) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4402
      if (typeof fromIndex == 'number') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4403
        var length = array ? array.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4404
        fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4405
      } else if (fromIndex) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4406
        var index = sortedIndex(array, value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4407
        return array[index] === value ? index : -1;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4408
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4409
      return baseIndexOf(array, value, fromIndex);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4410
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4411
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4412
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4413
     * Gets all but the last element or last `n` elements of an array. If a
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4414
     * callback is provided elements at the end of the array are excluded from
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4415
     * the result as long as the callback returns truey. The callback is bound
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4416
     * to `thisArg` and invoked with three arguments; (value, index, array).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4417
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4418
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4419
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4420
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4421
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4422
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4423
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4424
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4425
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4426
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4427
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4428
     * @param {Array} array The array to query.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4429
     * @param {Function|Object|number|string} [callback=1] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4430
     *  per element or the number of elements to exclude. If a property name or
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4431
     *  object is provided it will be used to create a "_.pluck" or "_.where"
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4432
     *  style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4433
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4434
     * @returns {Array} Returns a slice of `array`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4435
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4436
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4437
     * _.initial([1, 2, 3]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4438
     * // => [1, 2]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4439
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4440
     * _.initial([1, 2, 3], 2);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4441
     * // => [1]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4442
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4443
     * _.initial([1, 2, 3], function(num) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4444
     *   return num > 1;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4445
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4446
     * // => [1]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4447
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4448
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4449
     *   { 'name': 'barney',  'blocked': false, 'employer': 'slate' },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4450
     *   { 'name': 'fred',    'blocked': true,  'employer': 'slate' },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4451
     *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4452
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4453
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4454
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4455
     * _.initial(characters, 'blocked');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4456
     * // => [{ 'name': 'barney',  'blocked': false, 'employer': 'slate' }]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4457
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4458
     * // using "_.where" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4459
     * _.pluck(_.initial(characters, { 'employer': 'na' }), 'name');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4460
     * // => ['barney', 'fred']
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4461
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4462
    function initial(array, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4463
      var n = 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4464
          length = array ? array.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4465
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4466
      if (typeof callback != 'number' && callback != null) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4467
        var index = length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4468
        callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4469
        while (index-- && callback(array[index], index, array)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4470
          n++;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4471
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4472
      } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4473
        n = (callback == null || thisArg) ? 1 : callback || n;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4474
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4475
      return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4476
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4477
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4478
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4479
     * Creates an array of unique values present in all provided arrays using
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4480
     * strict equality for comparisons, i.e. `===`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4481
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4482
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4483
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4484
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4485
     * @param {...Array} [array] The arrays to inspect.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4486
     * @returns {Array} Returns an array of shared values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4487
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4488
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4489
     * _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4490
     * // => [1, 2]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4491
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4492
    function intersection() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4493
      var args = [],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4494
          argsIndex = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4495
          argsLength = arguments.length,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4496
          caches = getArray(),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4497
          indexOf = getIndexOf(),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4498
          trustIndexOf = indexOf === baseIndexOf,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4499
          seen = getArray();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4500
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4501
      while (++argsIndex < argsLength) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4502
        var value = arguments[argsIndex];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4503
        if (isArray(value) || isArguments(value)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4504
          args.push(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4505
          caches.push(trustIndexOf && value.length >= largeArraySize &&
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4506
            createCache(argsIndex ? args[argsIndex] : seen));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4507
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4508
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4509
      var array = args[0],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4510
          index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4511
          length = array ? array.length : 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4512
          result = [];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4513
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4514
      outer:
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4515
      while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4516
        var cache = caches[0];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4517
        value = array[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4518
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4519
        if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4520
          argsIndex = argsLength;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4521
          (cache || seen).push(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4522
          while (--argsIndex) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4523
            cache = caches[argsIndex];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4524
            if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4525
              continue outer;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4526
            }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4527
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4528
          result.push(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4529
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4530
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4531
      while (argsLength--) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4532
        cache = caches[argsLength];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4533
        if (cache) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4534
          releaseObject(cache);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4535
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4536
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4537
      releaseArray(caches);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4538
      releaseArray(seen);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4539
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4540
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4541
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4542
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4543
     * Gets the last element or last `n` elements of an array. If a callback is
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4544
     * provided elements at the end of the array are returned as long as the
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4545
     * callback returns truey. The callback is bound to `thisArg` and invoked
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4546
     * with three arguments; (value, index, array).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4547
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4548
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4549
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4550
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4551
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4552
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4553
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4554
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4555
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4556
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4557
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4558
     * @param {Array} array The array to query.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4559
     * @param {Function|Object|number|string} [callback] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4560
     *  per element or the number of elements to return. If a property name or
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4561
     *  object is provided it will be used to create a "_.pluck" or "_.where"
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4562
     *  style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4563
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4564
     * @returns {*} Returns the last element(s) of `array`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4565
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4566
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4567
     * _.last([1, 2, 3]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4568
     * // => 3
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4569
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4570
     * _.last([1, 2, 3], 2);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4571
     * // => [2, 3]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4572
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4573
     * _.last([1, 2, 3], function(num) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4574
     *   return num > 1;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4575
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4576
     * // => [2, 3]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4577
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4578
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4579
     *   { 'name': 'barney',  'blocked': false, 'employer': 'slate' },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4580
     *   { 'name': 'fred',    'blocked': true,  'employer': 'slate' },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4581
     *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4582
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4583
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4584
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4585
     * _.pluck(_.last(characters, 'blocked'), 'name');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4586
     * // => ['fred', 'pebbles']
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4587
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4588
     * // using "_.where" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4589
     * _.last(characters, { 'employer': 'na' });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4590
     * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4591
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4592
    function last(array, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4593
      var n = 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4594
          length = array ? array.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4595
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4596
      if (typeof callback != 'number' && callback != null) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4597
        var index = length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4598
        callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4599
        while (index-- && callback(array[index], index, array)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4600
          n++;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4601
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4602
      } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4603
        n = callback;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4604
        if (n == null || thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4605
          return array ? array[length - 1] : undefined;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4606
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4607
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4608
      return slice(array, nativeMax(0, length - n));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4609
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4610
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4611
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4612
     * Gets the index at which the last occurrence of `value` is found using strict
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4613
     * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4614
     * as the offset from the end of the collection.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4615
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4616
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4617
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4618
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4619
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4620
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4621
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4622
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4623
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4624
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4625
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4626
     * @param {Array} array The array to search.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4627
     * @param {*} value The value to search for.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4628
     * @param {number} [fromIndex=array.length-1] The index to search from.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4629
     * @returns {number} Returns the index of the matched value or `-1`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4630
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4631
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4632
     * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4633
     * // => 4
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4634
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4635
     * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4636
     * // => 1
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4637
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4638
    function lastIndexOf(array, value, fromIndex) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4639
      var index = array ? array.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4640
      if (typeof fromIndex == 'number') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4641
        index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4642
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4643
      while (index--) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4644
        if (array[index] === value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4645
          return index;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4646
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4647
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4648
      return -1;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4649
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4650
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4651
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4652
     * Removes all provided values from the given array using strict equality for
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4653
     * comparisons, i.e. `===`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4654
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4655
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4656
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4657
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4658
     * @param {Array} array The array to modify.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4659
     * @param {...*} [value] The values to remove.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4660
     * @returns {Array} Returns `array`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4661
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4662
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4663
     * var array = [1, 2, 3, 1, 2, 3];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4664
     * _.pull(array, 2, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4665
     * console.log(array);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4666
     * // => [1, 1]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4667
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4668
    function pull(array) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4669
      var args = arguments,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4670
          argsIndex = 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4671
          argsLength = args.length,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4672
          length = array ? array.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4673
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4674
      while (++argsIndex < argsLength) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4675
        var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4676
            value = args[argsIndex];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4677
        while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4678
          if (array[index] === value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4679
            splice.call(array, index--, 1);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4680
            length--;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4681
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4682
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4683
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4684
      return array;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4685
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4686
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4687
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4688
     * Creates an array of numbers (positive and/or negative) progressing from
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4689
     * `start` up to but not including `end`. If `start` is less than `stop` a
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4690
     * zero-length range is created unless a negative `step` is specified.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4691
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4692
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4693
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4694
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4695
     * @param {number} [start=0] The start of the range.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4696
     * @param {number} end The end of the range.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4697
     * @param {number} [step=1] The value to increment or decrement by.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4698
     * @returns {Array} Returns a new range array.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4699
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4700
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4701
     * _.range(4);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4702
     * // => [0, 1, 2, 3]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4703
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4704
     * _.range(1, 5);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4705
     * // => [1, 2, 3, 4]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4706
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4707
     * _.range(0, 20, 5);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4708
     * // => [0, 5, 10, 15]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4709
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4710
     * _.range(0, -4, -1);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4711
     * // => [0, -1, -2, -3]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4712
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4713
     * _.range(1, 4, 0);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4714
     * // => [1, 1, 1]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4715
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4716
     * _.range(0);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4717
     * // => []
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4718
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4719
    function range(start, end, step) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4720
      start = +start || 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4721
      step = typeof step == 'number' ? step : (+step || 1);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4722
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4723
      if (end == null) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4724
        end = start;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4725
        start = 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4726
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4727
      // use `Array(length)` so engines like Chakra and V8 avoid slower modes
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4728
      // http://youtu.be/XAqIpGU8ZZk#t=17m25s
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4729
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4730
          length = nativeMax(0, ceil((end - start) / (step || 1))),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4731
          result = Array(length);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4732
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4733
      while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4734
        result[index] = start;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4735
        start += step;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4736
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4737
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4738
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4739
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4740
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4741
     * Removes all elements from an array that the callback returns truey for
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4742
     * and returns an array of removed elements. The callback is bound to `thisArg`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4743
     * and invoked with three arguments; (value, index, array).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4744
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4745
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4746
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4747
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4748
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4749
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4750
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4751
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4752
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4753
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4754
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4755
     * @param {Array} array The array to modify.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4756
     * @param {Function|Object|string} [callback=identity] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4757
     *  per iteration. If a property name or object is provided it will be used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4758
     *  to create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4759
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4760
     * @returns {Array} Returns a new array of removed elements.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4761
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4762
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4763
     * var array = [1, 2, 3, 4, 5, 6];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4764
     * var evens = _.remove(array, function(num) { return num % 2 == 0; });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4765
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4766
     * console.log(array);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4767
     * // => [1, 3, 5]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4768
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4769
     * console.log(evens);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4770
     * // => [2, 4, 6]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4771
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4772
    function remove(array, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4773
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4774
          length = array ? array.length : 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4775
          result = [];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4776
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4777
      callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4778
      while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4779
        var value = array[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4780
        if (callback(value, index, array)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4781
          result.push(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4782
          splice.call(array, index--, 1);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4783
          length--;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4784
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4785
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4786
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4787
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4788
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4789
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4790
     * The opposite of `_.initial` this method gets all but the first element or
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4791
     * first `n` elements of an array. If a callback function is provided elements
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4792
     * at the beginning of the array are excluded from the result as long as the
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4793
     * callback returns truey. The callback is bound to `thisArg` and invoked
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4794
     * with three arguments; (value, index, array).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4795
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4796
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4797
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4798
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4799
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4800
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4801
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4802
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4803
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4804
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4805
     * @alias drop, tail
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4806
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4807
     * @param {Array} array The array to query.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4808
     * @param {Function|Object|number|string} [callback=1] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4809
     *  per element or the number of elements to exclude. If a property name or
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4810
     *  object is provided it will be used to create a "_.pluck" or "_.where"
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4811
     *  style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4812
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4813
     * @returns {Array} Returns a slice of `array`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4814
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4815
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4816
     * _.rest([1, 2, 3]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4817
     * // => [2, 3]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4818
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4819
     * _.rest([1, 2, 3], 2);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4820
     * // => [3]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4821
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4822
     * _.rest([1, 2, 3], function(num) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4823
     *   return num < 3;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4824
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4825
     * // => [3]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4826
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4827
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4828
     *   { 'name': 'barney',  'blocked': true,  'employer': 'slate' },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4829
     *   { 'name': 'fred',    'blocked': false,  'employer': 'slate' },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4830
     *   { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4831
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4832
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4833
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4834
     * _.pluck(_.rest(characters, 'blocked'), 'name');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4835
     * // => ['fred', 'pebbles']
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4836
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4837
     * // using "_.where" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4838
     * _.rest(characters, { 'employer': 'slate' });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4839
     * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4840
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4841
    function rest(array, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4842
      if (typeof callback != 'number' && callback != null) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4843
        var n = 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4844
            index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4845
            length = array ? array.length : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4846
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4847
        callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4848
        while (++index < length && callback(array[index], index, array)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4849
          n++;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4850
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4851
      } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4852
        n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4853
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4854
      return slice(array, n);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4855
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4856
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4857
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4858
     * Uses a binary search to determine the smallest index at which a value
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4859
     * should be inserted into a given sorted array in order to maintain the sort
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4860
     * order of the array. If a callback is provided it will be executed for
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4861
     * `value` and each element of `array` to compute their sort ranking. The
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4862
     * callback is bound to `thisArg` and invoked with one argument; (value).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4863
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4864
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4865
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4866
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4867
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4868
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4869
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4870
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4871
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4872
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4873
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4874
     * @param {Array} array The array to inspect.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4875
     * @param {*} value The value to evaluate.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4876
     * @param {Function|Object|string} [callback=identity] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4877
     *  per iteration. If a property name or object is provided it will be used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4878
     *  to create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4879
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4880
     * @returns {number} Returns the index at which `value` should be inserted
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4881
     *  into `array`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4882
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4883
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4884
     * _.sortedIndex([20, 30, 50], 40);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4885
     * // => 2
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4886
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4887
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4888
     * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4889
     * // => 2
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4890
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4891
     * var dict = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4892
     *   'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4893
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4894
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4895
     * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4896
     *   return dict.wordToNumber[word];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4897
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4898
     * // => 2
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4899
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4900
     * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4901
     *   return this.wordToNumber[word];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4902
     * }, dict);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4903
     * // => 2
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4904
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4905
    function sortedIndex(array, value, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4906
      var low = 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4907
          high = array ? array.length : low;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4908
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4909
      // explicitly reference `identity` for better inlining in Firefox
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4910
      callback = callback ? lodash.createCallback(callback, thisArg, 1) : identity;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4911
      value = callback(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4912
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4913
      while (low < high) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4914
        var mid = (low + high) >>> 1;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4915
        (callback(array[mid]) < value)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4916
          ? low = mid + 1
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4917
          : high = mid;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4918
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4919
      return low;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4920
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4921
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4922
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4923
     * Creates an array of unique values, in order, of the provided arrays using
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4924
     * strict equality for comparisons, i.e. `===`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4925
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4926
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4927
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4928
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4929
     * @param {...Array} [array] The arrays to inspect.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4930
     * @returns {Array} Returns an array of combined values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4931
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4932
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4933
     * _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4934
     * // => [1, 2, 3, 5, 4]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4935
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4936
    function union() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4937
      return baseUniq(baseFlatten(arguments, true, true));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4938
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4939
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4940
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4941
     * Creates a duplicate-value-free version of an array using strict equality
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4942
     * for comparisons, i.e. `===`. If the array is sorted, providing
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4943
     * `true` for `isSorted` will use a faster algorithm. If a callback is provided
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4944
     * each element of `array` is passed through the callback before uniqueness
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4945
     * is computed. The callback is bound to `thisArg` and invoked with three
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4946
     * arguments; (value, index, array).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4947
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4948
     * If a property name is provided for `callback` the created "_.pluck" style
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4949
     * callback will return the property value of the given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4950
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4951
     * If an object is provided for `callback` the created "_.where" style callback
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4952
     * will return `true` for elements that have the properties of the given object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4953
     * else `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4954
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4955
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4956
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4957
     * @alias unique
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4958
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4959
     * @param {Array} array The array to process.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4960
     * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4961
     * @param {Function|Object|string} [callback=identity] The function called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4962
     *  per iteration. If a property name or object is provided it will be used
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4963
     *  to create a "_.pluck" or "_.where" style callback, respectively.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4964
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4965
     * @returns {Array} Returns a duplicate-value-free array.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4966
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4967
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4968
     * _.uniq([1, 2, 1, 3, 1]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4969
     * // => [1, 2, 3]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4970
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4971
     * _.uniq([1, 1, 2, 2, 3], true);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4972
     * // => [1, 2, 3]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4973
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4974
     * _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4975
     * // => ['A', 'b', 'C']
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4976
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4977
     * _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4978
     * // => [1, 2.5, 3]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4979
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4980
     * // using "_.pluck" callback shorthand
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4981
     * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4982
     * // => [{ 'x': 1 }, { 'x': 2 }]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4983
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4984
    function uniq(array, isSorted, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4985
      // juggle arguments
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4986
      if (typeof isSorted != 'boolean' && isSorted != null) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4987
        thisArg = callback;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4988
        callback = (typeof isSorted != 'function' && thisArg && thisArg[isSorted] === array) ? null : isSorted;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4989
        isSorted = false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4990
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4991
      if (callback != null) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4992
        callback = lodash.createCallback(callback, thisArg, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4993
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4994
      return baseUniq(array, isSorted, callback);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4995
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4996
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4997
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4998
     * Creates an array excluding all provided values using strict equality for
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  4999
     * comparisons, i.e. `===`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5000
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5001
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5002
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5003
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5004
     * @param {Array} array The array to filter.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5005
     * @param {...*} [value] The values to exclude.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5006
     * @returns {Array} Returns a new array of filtered values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5007
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5008
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5009
     * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5010
     * // => [2, 3, 4]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5011
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5012
    function without(array) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5013
      return baseDifference(array, slice(arguments, 1));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5014
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5015
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5016
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5017
     * Creates an array that is the symmetric difference of the provided arrays.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5018
     * See http://en.wikipedia.org/wiki/Symmetric_difference.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5019
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5020
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5021
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5022
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5023
     * @param {...Array} [array] The arrays to inspect.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5024
     * @returns {Array} Returns an array of values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5025
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5026
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5027
     * _.xor([1, 2, 3], [5, 2, 1, 4]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5028
     * // => [3, 5, 4]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5029
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5030
     * _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5031
     * // => [1, 4, 5]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5032
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5033
    function xor() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5034
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5035
          length = arguments.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5036
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5037
      while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5038
        var array = arguments[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5039
        if (isArray(array) || isArguments(array)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5040
          var result = result
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5041
            ? baseUniq(baseDifference(result, array).concat(baseDifference(array, result)))
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5042
            : array;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5043
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5044
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5045
      return result || [];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5046
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5047
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5048
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5049
     * Creates an array of grouped elements, the first of which contains the first
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5050
     * elements of the given arrays, the second of which contains the second
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5051
     * elements of the given arrays, and so on.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5052
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5053
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5054
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5055
     * @alias unzip
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5056
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5057
     * @param {...Array} [array] Arrays to process.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5058
     * @returns {Array} Returns a new array of grouped elements.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5059
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5060
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5061
     * _.zip(['fred', 'barney'], [30, 40], [true, false]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5062
     * // => [['fred', 30, true], ['barney', 40, false]]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5063
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5064
    function zip() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5065
      var array = arguments.length > 1 ? arguments : arguments[0],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5066
          index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5067
          length = array ? max(pluck(array, 'length')) : 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5068
          result = Array(length < 0 ? 0 : length);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5069
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5070
      while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5071
        result[index] = pluck(array, index);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5072
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5073
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5074
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5075
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5076
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5077
     * Creates an object composed from arrays of `keys` and `values`. Provide
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5078
     * either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5079
     * or two arrays, one of `keys` and one of corresponding `values`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5080
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5081
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5082
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5083
     * @alias object
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5084
     * @category Arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5085
     * @param {Array} keys The array of keys.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5086
     * @param {Array} [values=[]] The array of values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5087
     * @returns {Object} Returns an object composed of the given keys and
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5088
     *  corresponding values.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5089
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5090
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5091
     * _.zipObject(['fred', 'barney'], [30, 40]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5092
     * // => { 'fred': 30, 'barney': 40 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5093
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5094
    function zipObject(keys, values) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5095
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5096
          length = keys ? keys.length : 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5097
          result = {};
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5098
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5099
      if (!values && length && !isArray(keys[0])) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5100
        values = [];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5101
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5102
      while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5103
        var key = keys[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5104
        if (values) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5105
          result[key] = values[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5106
        } else if (key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5107
          result[key[0]] = key[1];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5108
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5109
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5110
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5111
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5112
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5113
    /*--------------------------------------------------------------------------*/
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5114
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5115
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5116
     * Creates a function that executes `func`, with  the `this` binding and
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5117
     * arguments of the created function, only after being called `n` times.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5118
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5119
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5120
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5121
     * @category Functions
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5122
     * @param {number} n The number of times the function must be called before
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5123
     *  `func` is executed.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5124
     * @param {Function} func The function to restrict.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5125
     * @returns {Function} Returns the new restricted function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5126
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5127
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5128
     * var saves = ['profile', 'settings'];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5129
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5130
     * var done = _.after(saves.length, function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5131
     *   console.log('Done saving!');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5132
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5133
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5134
     * _.forEach(saves, function(type) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5135
     *   asyncSave({ 'type': type, 'complete': done });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5136
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5137
     * // => logs 'Done saving!', after all saves have completed
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5138
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5139
    function after(n, func) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5140
      if (!isFunction(func)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5141
        throw new TypeError;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5142
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5143
      return function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5144
        if (--n < 1) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5145
          return func.apply(this, arguments);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5146
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5147
      };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5148
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5149
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5150
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5151
     * Creates a function that, when called, invokes `func` with the `this`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5152
     * binding of `thisArg` and prepends any additional `bind` arguments to those
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5153
     * provided to the bound function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5154
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5155
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5156
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5157
     * @category Functions
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5158
     * @param {Function} func The function to bind.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5159
     * @param {*} [thisArg] The `this` binding of `func`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5160
     * @param {...*} [arg] Arguments to be partially applied.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5161
     * @returns {Function} Returns the new bound function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5162
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5163
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5164
     * var func = function(greeting) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5165
     *   return greeting + ' ' + this.name;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5166
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5167
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5168
     * func = _.bind(func, { 'name': 'fred' }, 'hi');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5169
     * func();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5170
     * // => 'hi fred'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5171
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5172
    function bind(func, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5173
      return arguments.length > 2
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5174
        ? createWrapper(func, 17, slice(arguments, 2), null, thisArg)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5175
        : createWrapper(func, 1, null, null, thisArg);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5176
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5177
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5178
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5179
     * Binds methods of an object to the object itself, overwriting the existing
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5180
     * method. Method names may be specified as individual arguments or as arrays
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5181
     * of method names. If no method names are provided all the function properties
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5182
     * of `object` will be bound.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5183
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5184
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5185
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5186
     * @category Functions
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5187
     * @param {Object} object The object to bind and assign the bound methods to.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5188
     * @param {...string} [methodName] The object method names to
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5189
     *  bind, specified as individual method names or arrays of method names.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5190
     * @returns {Object} Returns `object`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5191
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5192
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5193
     * var view = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5194
     *   'label': 'docs',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5195
     *   'onClick': function() { console.log('clicked ' + this.label); }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5196
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5197
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5198
     * _.bindAll(view);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5199
     * jQuery('#docs').on('click', view.onClick);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5200
     * // => logs 'clicked docs', when the button is clicked
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5201
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5202
    function bindAll(object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5203
      var funcs = arguments.length > 1 ? baseFlatten(arguments, true, false, 1) : functions(object),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5204
          index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5205
          length = funcs.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5206
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5207
      while (++index < length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5208
        var key = funcs[index];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5209
        object[key] = createWrapper(object[key], 1, null, null, object);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5210
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5211
      return object;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5212
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5213
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5214
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5215
     * Creates a function that, when called, invokes the method at `object[key]`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5216
     * and prepends any additional `bindKey` arguments to those provided to the bound
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5217
     * function. This method differs from `_.bind` by allowing bound functions to
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5218
     * reference methods that will be redefined or don't yet exist.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5219
     * See http://michaux.ca/articles/lazy-function-definition-pattern.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5220
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5221
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5222
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5223
     * @category Functions
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5224
     * @param {Object} object The object the method belongs to.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5225
     * @param {string} key The key of the method.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5226
     * @param {...*} [arg] Arguments to be partially applied.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5227
     * @returns {Function} Returns the new bound function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5228
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5229
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5230
     * var object = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5231
     *   'name': 'fred',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5232
     *   'greet': function(greeting) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5233
     *     return greeting + ' ' + this.name;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5234
     *   }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5235
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5236
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5237
     * var func = _.bindKey(object, 'greet', 'hi');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5238
     * func();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5239
     * // => 'hi fred'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5240
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5241
     * object.greet = function(greeting) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5242
     *   return greeting + 'ya ' + this.name + '!';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5243
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5244
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5245
     * func();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5246
     * // => 'hiya fred!'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5247
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5248
    function bindKey(object, key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5249
      return arguments.length > 2
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5250
        ? createWrapper(key, 19, slice(arguments, 2), null, object)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5251
        : createWrapper(key, 3, null, null, object);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5252
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5253
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5254
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5255
     * Creates a function that is the composition of the provided functions,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5256
     * where each function consumes the return value of the function that follows.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5257
     * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5258
     * Each function is executed with the `this` binding of the composed function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5259
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5260
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5261
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5262
     * @category Functions
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5263
     * @param {...Function} [func] Functions to compose.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5264
     * @returns {Function} Returns the new composed function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5265
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5266
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5267
     * var realNameMap = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5268
     *   'pebbles': 'penelope'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5269
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5270
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5271
     * var format = function(name) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5272
     *   name = realNameMap[name.toLowerCase()] || name;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5273
     *   return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5274
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5275
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5276
     * var greet = function(formatted) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5277
     *   return 'Hiya ' + formatted + '!';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5278
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5279
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5280
     * var welcome = _.compose(greet, format);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5281
     * welcome('pebbles');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5282
     * // => 'Hiya Penelope!'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5283
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5284
    function compose() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5285
      var funcs = arguments,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5286
          length = funcs.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5287
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5288
      while (length--) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5289
        if (!isFunction(funcs[length])) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5290
          throw new TypeError;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5291
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5292
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5293
      return function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5294
        var args = arguments,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5295
            length = funcs.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5296
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5297
        while (length--) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5298
          args = [funcs[length].apply(this, args)];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5299
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5300
        return args[0];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5301
      };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5302
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5303
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5304
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5305
     * Creates a function which accepts one or more arguments of `func` that when
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5306
     * invoked either executes `func` returning its result, if all `func` arguments
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5307
     * have been provided, or returns a function that accepts one or more of the
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5308
     * remaining `func` arguments, and so on. The arity of `func` can be specified
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5309
     * if `func.length` is not sufficient.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5310
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5311
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5312
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5313
     * @category Functions
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5314
     * @param {Function} func The function to curry.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5315
     * @param {number} [arity=func.length] The arity of `func`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5316
     * @returns {Function} Returns the new curried function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5317
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5318
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5319
     * var curried = _.curry(function(a, b, c) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5320
     *   console.log(a + b + c);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5321
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5322
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5323
     * curried(1)(2)(3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5324
     * // => 6
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5325
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5326
     * curried(1, 2)(3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5327
     * // => 6
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5328
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5329
     * curried(1, 2, 3);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5330
     * // => 6
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5331
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5332
    function curry(func, arity) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5333
      arity = typeof arity == 'number' ? arity : (+arity || func.length);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5334
      return createWrapper(func, 4, null, null, null, arity);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5335
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5336
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5337
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5338
     * Creates a function that will delay the execution of `func` until after
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5339
     * `wait` milliseconds have elapsed since the last time it was invoked.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5340
     * Provide an options object to indicate that `func` should be invoked on
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5341
     * the leading and/or trailing edge of the `wait` timeout. Subsequent calls
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5342
     * to the debounced function will return the result of the last `func` call.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5343
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5344
     * Note: If `leading` and `trailing` options are `true` `func` will be called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5345
     * on the trailing edge of the timeout only if the the debounced function is
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5346
     * invoked more than once during the `wait` timeout.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5347
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5348
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5349
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5350
     * @category Functions
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5351
     * @param {Function} func The function to debounce.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5352
     * @param {number} wait The number of milliseconds to delay.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5353
     * @param {Object} [options] The options object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5354
     * @param {boolean} [options.leading=false] Specify execution on the leading edge of the timeout.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5355
     * @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's called.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5356
     * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5357
     * @returns {Function} Returns the new debounced function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5358
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5359
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5360
     * // avoid costly calculations while the window size is in flux
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5361
     * var lazyLayout = _.debounce(calculateLayout, 150);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5362
     * jQuery(window).on('resize', lazyLayout);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5363
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5364
     * // execute `sendMail` when the click event is fired, debouncing subsequent calls
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5365
     * jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5366
     *   'leading': true,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5367
     *   'trailing': false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5368
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5369
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5370
     * // ensure `batchLog` is executed once after 1 second of debounced calls
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5371
     * var source = new EventSource('/stream');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5372
     * source.addEventListener('message', _.debounce(batchLog, 250, {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5373
     *   'maxWait': 1000
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5374
     * }, false);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5375
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5376
    function debounce(func, wait, options) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5377
      var args,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5378
          maxTimeoutId,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5379
          result,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5380
          stamp,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5381
          thisArg,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5382
          timeoutId,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5383
          trailingCall,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5384
          lastCalled = 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5385
          maxWait = false,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5386
          trailing = true;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5387
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5388
      if (!isFunction(func)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5389
        throw new TypeError;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5390
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5391
      wait = nativeMax(0, wait) || 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5392
      if (options === true) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5393
        var leading = true;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5394
        trailing = false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5395
      } else if (isObject(options)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5396
        leading = options.leading;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5397
        maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5398
        trailing = 'trailing' in options ? options.trailing : trailing;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5399
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5400
      var delayed = function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5401
        var remaining = wait - (now() - stamp);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5402
        if (remaining <= 0) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5403
          if (maxTimeoutId) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5404
            clearTimeout(maxTimeoutId);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5405
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5406
          var isCalled = trailingCall;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5407
          maxTimeoutId = timeoutId = trailingCall = undefined;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5408
          if (isCalled) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5409
            lastCalled = now();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5410
            result = func.apply(thisArg, args);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5411
            if (!timeoutId && !maxTimeoutId) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5412
              args = thisArg = null;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5413
            }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5414
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5415
        } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5416
          timeoutId = setTimeout(delayed, remaining);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5417
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5418
      };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5419
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5420
      var maxDelayed = function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5421
        if (timeoutId) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5422
          clearTimeout(timeoutId);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5423
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5424
        maxTimeoutId = timeoutId = trailingCall = undefined;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5425
        if (trailing || (maxWait !== wait)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5426
          lastCalled = now();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5427
          result = func.apply(thisArg, args);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5428
          if (!timeoutId && !maxTimeoutId) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5429
            args = thisArg = null;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5430
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5431
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5432
      };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5433
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5434
      return function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5435
        args = arguments;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5436
        stamp = now();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5437
        thisArg = this;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5438
        trailingCall = trailing && (timeoutId || !leading);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5439
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5440
        if (maxWait === false) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5441
          var leadingCall = leading && !timeoutId;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5442
        } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5443
          if (!maxTimeoutId && !leading) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5444
            lastCalled = stamp;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5445
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5446
          var remaining = maxWait - (stamp - lastCalled),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5447
              isCalled = remaining <= 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5448
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5449
          if (isCalled) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5450
            if (maxTimeoutId) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5451
              maxTimeoutId = clearTimeout(maxTimeoutId);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5452
            }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5453
            lastCalled = stamp;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5454
            result = func.apply(thisArg, args);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5455
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5456
          else if (!maxTimeoutId) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5457
            maxTimeoutId = setTimeout(maxDelayed, remaining);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5458
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5459
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5460
        if (isCalled && timeoutId) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5461
          timeoutId = clearTimeout(timeoutId);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5462
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5463
        else if (!timeoutId && wait !== maxWait) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5464
          timeoutId = setTimeout(delayed, wait);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5465
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5466
        if (leadingCall) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5467
          isCalled = true;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5468
          result = func.apply(thisArg, args);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5469
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5470
        if (isCalled && !timeoutId && !maxTimeoutId) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5471
          args = thisArg = null;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5472
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5473
        return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5474
      };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5475
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5476
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5477
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5478
     * Defers executing the `func` function until the current call stack has cleared.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5479
     * Additional arguments will be provided to `func` when it is invoked.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5480
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5481
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5482
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5483
     * @category Functions
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5484
     * @param {Function} func The function to defer.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5485
     * @param {...*} [arg] Arguments to invoke the function with.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5486
     * @returns {number} Returns the timer id.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5487
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5488
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5489
     * _.defer(function(text) { console.log(text); }, 'deferred');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5490
     * // logs 'deferred' after one or more milliseconds
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5491
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5492
    function defer(func) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5493
      if (!isFunction(func)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5494
        throw new TypeError;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5495
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5496
      var args = slice(arguments, 1);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5497
      return setTimeout(function() { func.apply(undefined, args); }, 1);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5498
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5499
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5500
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5501
     * Executes the `func` function after `wait` milliseconds. Additional arguments
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5502
     * will be provided to `func` when it is invoked.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5503
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5504
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5505
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5506
     * @category Functions
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5507
     * @param {Function} func The function to delay.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5508
     * @param {number} wait The number of milliseconds to delay execution.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5509
     * @param {...*} [arg] Arguments to invoke the function with.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5510
     * @returns {number} Returns the timer id.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5511
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5512
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5513
     * _.delay(function(text) { console.log(text); }, 1000, 'later');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5514
     * // => logs 'later' after one second
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5515
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5516
    function delay(func, wait) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5517
      if (!isFunction(func)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5518
        throw new TypeError;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5519
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5520
      var args = slice(arguments, 2);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5521
      return setTimeout(function() { func.apply(undefined, args); }, wait);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5522
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5523
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5524
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5525
     * Creates a function that memoizes the result of `func`. If `resolver` is
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5526
     * provided it will be used to determine the cache key for storing the result
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5527
     * based on the arguments provided to the memoized function. By default, the
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5528
     * first argument provided to the memoized function is used as the cache key.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5529
     * The `func` is executed with the `this` binding of the memoized function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5530
     * The result cache is exposed as the `cache` property on the memoized function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5531
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5532
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5533
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5534
     * @category Functions
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5535
     * @param {Function} func The function to have its output memoized.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5536
     * @param {Function} [resolver] A function used to resolve the cache key.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5537
     * @returns {Function} Returns the new memoizing function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5538
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5539
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5540
     * var fibonacci = _.memoize(function(n) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5541
     *   return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5542
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5543
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5544
     * fibonacci(9)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5545
     * // => 34
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5546
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5547
     * var data = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5548
     *   'fred': { 'name': 'fred', 'age': 40 },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5549
     *   'pebbles': { 'name': 'pebbles', 'age': 1 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5550
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5551
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5552
     * // modifying the result cache
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5553
     * var get = _.memoize(function(name) { return data[name]; }, _.identity);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5554
     * get('pebbles');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5555
     * // => { 'name': 'pebbles', 'age': 1 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5556
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5557
     * get.cache.pebbles.name = 'penelope';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5558
     * get('pebbles');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5559
     * // => { 'name': 'penelope', 'age': 1 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5560
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5561
    function memoize(func, resolver) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5562
      if (!isFunction(func)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5563
        throw new TypeError;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5564
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5565
      var memoized = function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5566
        var cache = memoized.cache,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5567
            key = resolver ? resolver.apply(this, arguments) : keyPrefix + arguments[0];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5568
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5569
        return hasOwnProperty.call(cache, key)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5570
          ? cache[key]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5571
          : (cache[key] = func.apply(this, arguments));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5572
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5573
      memoized.cache = {};
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5574
      return memoized;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5575
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5576
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5577
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5578
     * Creates a function that is restricted to execute `func` once. Repeat calls to
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5579
     * the function will return the value of the first call. The `func` is executed
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5580
     * with the `this` binding of the created function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5581
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5582
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5583
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5584
     * @category Functions
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5585
     * @param {Function} func The function to restrict.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5586
     * @returns {Function} Returns the new restricted function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5587
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5588
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5589
     * var initialize = _.once(createApplication);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5590
     * initialize();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5591
     * initialize();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5592
     * // `initialize` executes `createApplication` once
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5593
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5594
    function once(func) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5595
      var ran,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5596
          result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5597
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5598
      if (!isFunction(func)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5599
        throw new TypeError;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5600
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5601
      return function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5602
        if (ran) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5603
          return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5604
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5605
        ran = true;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5606
        result = func.apply(this, arguments);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5607
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5608
        // clear the `func` variable so the function may be garbage collected
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5609
        func = null;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5610
        return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5611
      };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5612
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5613
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5614
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5615
     * Creates a function that, when called, invokes `func` with any additional
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5616
     * `partial` arguments prepended to those provided to the new function. This
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5617
     * method is similar to `_.bind` except it does **not** alter the `this` binding.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5618
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5619
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5620
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5621
     * @category Functions
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5622
     * @param {Function} func The function to partially apply arguments to.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5623
     * @param {...*} [arg] Arguments to be partially applied.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5624
     * @returns {Function} Returns the new partially applied function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5625
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5626
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5627
     * var greet = function(greeting, name) { return greeting + ' ' + name; };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5628
     * var hi = _.partial(greet, 'hi');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5629
     * hi('fred');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5630
     * // => 'hi fred'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5631
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5632
    function partial(func) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5633
      return createWrapper(func, 16, slice(arguments, 1));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5634
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5635
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5636
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5637
     * This method is like `_.partial` except that `partial` arguments are
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5638
     * appended to those provided to the new function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5639
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5640
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5641
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5642
     * @category Functions
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5643
     * @param {Function} func The function to partially apply arguments to.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5644
     * @param {...*} [arg] Arguments to be partially applied.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5645
     * @returns {Function} Returns the new partially applied function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5646
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5647
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5648
     * var defaultsDeep = _.partialRight(_.merge, _.defaults);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5649
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5650
     * var options = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5651
     *   'variable': 'data',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5652
     *   'imports': { 'jq': $ }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5653
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5654
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5655
     * defaultsDeep(options, _.templateSettings);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5656
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5657
     * options.variable
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5658
     * // => 'data'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5659
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5660
     * options.imports
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5661
     * // => { '_': _, 'jq': $ }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5662
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5663
    function partialRight(func) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5664
      return createWrapper(func, 32, null, slice(arguments, 1));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5665
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5666
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5667
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5668
     * Creates a function that, when executed, will only call the `func` function
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5669
     * at most once per every `wait` milliseconds. Provide an options object to
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5670
     * indicate that `func` should be invoked on the leading and/or trailing edge
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5671
     * of the `wait` timeout. Subsequent calls to the throttled function will
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5672
     * return the result of the last `func` call.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5673
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5674
     * Note: If `leading` and `trailing` options are `true` `func` will be called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5675
     * on the trailing edge of the timeout only if the the throttled function is
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5676
     * invoked more than once during the `wait` timeout.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5677
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5678
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5679
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5680
     * @category Functions
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5681
     * @param {Function} func The function to throttle.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5682
     * @param {number} wait The number of milliseconds to throttle executions to.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5683
     * @param {Object} [options] The options object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5684
     * @param {boolean} [options.leading=true] Specify execution on the leading edge of the timeout.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5685
     * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5686
     * @returns {Function} Returns the new throttled function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5687
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5688
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5689
     * // avoid excessively updating the position while scrolling
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5690
     * var throttled = _.throttle(updatePosition, 100);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5691
     * jQuery(window).on('scroll', throttled);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5692
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5693
     * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5694
     * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5695
     *   'trailing': false
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5696
     * }));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5697
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5698
    function throttle(func, wait, options) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5699
      var leading = true,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5700
          trailing = true;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5701
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5702
      if (!isFunction(func)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5703
        throw new TypeError;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5704
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5705
      if (options === false) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5706
        leading = false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5707
      } else if (isObject(options)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5708
        leading = 'leading' in options ? options.leading : leading;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5709
        trailing = 'trailing' in options ? options.trailing : trailing;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5710
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5711
      debounceOptions.leading = leading;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5712
      debounceOptions.maxWait = wait;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5713
      debounceOptions.trailing = trailing;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5714
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5715
      return debounce(func, wait, debounceOptions);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5716
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5717
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5718
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5719
     * Creates a function that provides `value` to the wrapper function as its
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5720
     * first argument. Additional arguments provided to the function are appended
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5721
     * to those provided to the wrapper function. The wrapper is executed with
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5722
     * the `this` binding of the created function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5723
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5724
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5725
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5726
     * @category Functions
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5727
     * @param {*} value The value to wrap.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5728
     * @param {Function} wrapper The wrapper function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5729
     * @returns {Function} Returns the new function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5730
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5731
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5732
     * var p = _.wrap(_.escape, function(func, text) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5733
     *   return '<p>' + func(text) + '</p>';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5734
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5735
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5736
     * p('Fred, Wilma, & Pebbles');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5737
     * // => '<p>Fred, Wilma, &amp; Pebbles</p>'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5738
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5739
    function wrap(value, wrapper) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5740
      return createWrapper(wrapper, 16, [value]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5741
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5742
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5743
    /*--------------------------------------------------------------------------*/
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5744
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5745
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5746
     * Creates a function that returns `value`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5747
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5748
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5749
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5750
     * @category Utilities
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5751
     * @param {*} value The value to return from the new function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5752
     * @returns {Function} Returns the new function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5753
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5754
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5755
     * var object = { 'name': 'fred' };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5756
     * var getter = _.constant(object);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5757
     * getter() === object;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5758
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5759
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5760
    function constant(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5761
      return function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5762
        return value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5763
      };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5764
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5765
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5766
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5767
     * Produces a callback bound to an optional `thisArg`. If `func` is a property
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5768
     * name the created callback will return the property value for a given element.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5769
     * If `func` is an object the created callback will return `true` for elements
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5770
     * that contain the equivalent object properties, otherwise it will return `false`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5771
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5772
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5773
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5774
     * @category Utilities
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5775
     * @param {*} [func=identity] The value to convert to a callback.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5776
     * @param {*} [thisArg] The `this` binding of the created callback.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5777
     * @param {number} [argCount] The number of arguments the callback accepts.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5778
     * @returns {Function} Returns a callback function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5779
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5780
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5781
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5782
     *   { 'name': 'barney', 'age': 36 },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5783
     *   { 'name': 'fred',   'age': 40 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5784
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5785
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5786
     * // wrap to create custom callback shorthands
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5787
     * _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5788
     *   var match = /^(.+?)__([gl]t)(.+)$/.exec(callback);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5789
     *   return !match ? func(callback, thisArg) : function(object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5790
     *     return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5791
     *   };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5792
     * });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5793
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5794
     * _.filter(characters, 'age__gt38');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5795
     * // => [{ 'name': 'fred', 'age': 40 }]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5796
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5797
    function createCallback(func, thisArg, argCount) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5798
      var type = typeof func;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5799
      if (func == null || type == 'function') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5800
        return baseCreateCallback(func, thisArg, argCount);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5801
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5802
      // handle "_.pluck" style callback shorthands
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5803
      if (type != 'object') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5804
        return property(func);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5805
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5806
      var props = keys(func),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5807
          key = props[0],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5808
          a = func[key];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5809
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5810
      // handle "_.where" style callback shorthands
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5811
      if (props.length == 1 && a === a && !isObject(a)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5812
        // fast path the common case of providing an object with a single
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5813
        // property containing a primitive value
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5814
        return function(object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5815
          var b = object[key];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5816
          return a === b && (a !== 0 || (1 / a == 1 / b));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5817
        };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5818
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5819
      return function(object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5820
        var length = props.length,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5821
            result = false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5822
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5823
        while (length--) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5824
          if (!(result = baseIsEqual(object[props[length]], func[props[length]], null, true))) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5825
            break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5826
          }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5827
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5828
        return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5829
      };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5830
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5831
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5832
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5833
     * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5834
     * corresponding HTML entities.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5835
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5836
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5837
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5838
     * @category Utilities
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5839
     * @param {string} string The string to escape.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5840
     * @returns {string} Returns the escaped string.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5841
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5842
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5843
     * _.escape('Fred, Wilma, & Pebbles');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5844
     * // => 'Fred, Wilma, &amp; Pebbles'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5845
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5846
    function escape(string) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5847
      return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5848
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5849
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5850
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5851
     * This method returns the first argument provided to it.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5852
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5853
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5854
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5855
     * @category Utilities
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5856
     * @param {*} value Any value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5857
     * @returns {*} Returns `value`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5858
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5859
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5860
     * var object = { 'name': 'fred' };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5861
     * _.identity(object) === object;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5862
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5863
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5864
    function identity(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5865
      return value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5866
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5867
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5868
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5869
     * Adds function properties of a source object to the destination object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5870
     * If `object` is a function methods will be added to its prototype as well.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5871
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5872
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5873
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5874
     * @category Utilities
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5875
     * @param {Function|Object} [object=lodash] object The destination object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5876
     * @param {Object} source The object of functions to add.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5877
     * @param {Object} [options] The options object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5878
     * @param {boolean} [options.chain=true] Specify whether the functions added are chainable.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5879
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5880
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5881
     * function capitalize(string) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5882
     *   return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5883
     * }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5884
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5885
     * _.mixin({ 'capitalize': capitalize });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5886
     * _.capitalize('fred');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5887
     * // => 'Fred'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5888
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5889
     * _('fred').capitalize().value();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5890
     * // => 'Fred'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5891
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5892
     * _.mixin({ 'capitalize': capitalize }, { 'chain': false });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5893
     * _('fred').capitalize();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5894
     * // => 'Fred'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5895
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5896
    function mixin(object, source, options) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5897
      var chain = true,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5898
          methodNames = source && functions(source);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5899
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5900
      if (!source || (!options && !methodNames.length)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5901
        if (options == null) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5902
          options = source;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5903
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5904
        ctor = lodashWrapper;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5905
        source = object;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5906
        object = lodash;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5907
        methodNames = functions(source);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5908
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5909
      if (options === false) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5910
        chain = false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5911
      } else if (isObject(options) && 'chain' in options) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5912
        chain = options.chain;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5913
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5914
      var ctor = object,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5915
          isFunc = isFunction(ctor);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5916
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5917
      forEach(methodNames, function(methodName) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5918
        var func = object[methodName] = source[methodName];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5919
        if (isFunc) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5920
          ctor.prototype[methodName] = function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5921
            var chainAll = this.__chain__,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5922
                value = this.__wrapped__,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5923
                args = [value];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5924
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5925
            push.apply(args, arguments);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5926
            var result = func.apply(object, args);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5927
            if (chain || chainAll) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5928
              if (value === result && isObject(result)) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5929
                return this;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5930
              }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5931
              result = new ctor(result);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5932
              result.__chain__ = chainAll;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5933
            }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5934
            return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5935
          };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5936
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5937
      });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5938
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5939
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5940
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5941
     * Reverts the '_' variable to its previous value and returns a reference to
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5942
     * the `lodash` function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5943
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5944
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5945
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5946
     * @category Utilities
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5947
     * @returns {Function} Returns the `lodash` function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5948
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5949
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5950
     * var lodash = _.noConflict();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5951
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5952
    function noConflict() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5953
      context._ = oldDash;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5954
      return this;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5955
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5956
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5957
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5958
     * A no-operation function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5959
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5960
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5961
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5962
     * @category Utilities
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5963
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5964
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5965
     * var object = { 'name': 'fred' };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5966
     * _.noop(object) === undefined;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5967
     * // => true
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5968
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5969
    function noop() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5970
      // no operation performed
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5971
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5972
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5973
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5974
     * Gets the number of milliseconds that have elapsed since the Unix epoch
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5975
     * (1 January 1970 00:00:00 UTC).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5976
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5977
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5978
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5979
     * @category Utilities
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5980
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5981
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5982
     * var stamp = _.now();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5983
     * _.defer(function() { console.log(_.now() - stamp); });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5984
     * // => logs the number of milliseconds it took for the deferred function to be called
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5985
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5986
    var now = isNative(now = Date.now) && now || function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5987
      return new Date().getTime();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5988
    };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5989
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5990
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5991
     * Converts the given value into an integer of the specified radix.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5992
     * If `radix` is `undefined` or `0` a `radix` of `10` is used unless the
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5993
     * `value` is a hexadecimal, in which case a `radix` of `16` is used.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5994
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5995
     * Note: This method avoids differences in native ES3 and ES5 `parseInt`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5996
     * implementations. See http://es5.github.io/#E.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5997
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5998
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  5999
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6000
     * @category Utilities
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6001
     * @param {string} value The value to parse.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6002
     * @param {number} [radix] The radix used to interpret the value to parse.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6003
     * @returns {number} Returns the new integer value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6004
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6005
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6006
     * _.parseInt('08');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6007
     * // => 8
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6008
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6009
    var parseInt = nativeParseInt(whitespace + '08') == 8 ? nativeParseInt : function(value, radix) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6010
      // Firefox < 21 and Opera < 15 follow the ES3 specified implementation of `parseInt`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6011
      return nativeParseInt(isString(value) ? value.replace(reLeadingSpacesAndZeros, '') : value, radix || 0);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6012
    };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6013
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6014
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6015
     * Creates a "_.pluck" style function, which returns the `key` value of a
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6016
     * given object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6017
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6018
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6019
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6020
     * @category Utilities
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6021
     * @param {string} key The name of the property to retrieve.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6022
     * @returns {Function} Returns the new function.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6023
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6024
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6025
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6026
     *   { 'name': 'fred',   'age': 40 },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6027
     *   { 'name': 'barney', 'age': 36 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6028
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6029
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6030
     * var getName = _.property('name');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6031
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6032
     * _.map(characters, getName);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6033
     * // => ['barney', 'fred']
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6034
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6035
     * _.sortBy(characters, getName);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6036
     * // => [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred',   'age': 40 }]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6037
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6038
    function property(key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6039
      return function(object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6040
        return object[key];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6041
      };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6042
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6043
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6044
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6045
     * Produces a random number between `min` and `max` (inclusive). If only one
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6046
     * argument is provided a number between `0` and the given number will be
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6047
     * returned. If `floating` is truey or either `min` or `max` are floats a
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6048
     * floating-point number will be returned instead of an integer.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6049
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6050
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6051
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6052
     * @category Utilities
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6053
     * @param {number} [min=0] The minimum possible value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6054
     * @param {number} [max=1] The maximum possible value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6055
     * @param {boolean} [floating=false] Specify returning a floating-point number.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6056
     * @returns {number} Returns a random number.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6057
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6058
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6059
     * _.random(0, 5);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6060
     * // => an integer between 0 and 5
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6061
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6062
     * _.random(5);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6063
     * // => also an integer between 0 and 5
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6064
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6065
     * _.random(5, true);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6066
     * // => a floating-point number between 0 and 5
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6067
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6068
     * _.random(1.2, 5.2);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6069
     * // => a floating-point number between 1.2 and 5.2
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6070
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6071
    function random(min, max, floating) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6072
      var noMin = min == null,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6073
          noMax = max == null;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6074
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6075
      if (floating == null) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6076
        if (typeof min == 'boolean' && noMax) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6077
          floating = min;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6078
          min = 1;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6079
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6080
        else if (!noMax && typeof max == 'boolean') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6081
          floating = max;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6082
          noMax = true;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6083
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6084
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6085
      if (noMin && noMax) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6086
        max = 1;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6087
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6088
      min = +min || 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6089
      if (noMax) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6090
        max = min;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6091
        min = 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6092
      } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6093
        max = +max || 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6094
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6095
      if (floating || min % 1 || max % 1) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6096
        var rand = nativeRandom();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6097
        return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand +'').length - 1)))), max);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6098
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6099
      return baseRandom(min, max);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6100
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6101
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6102
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6103
     * Resolves the value of property `key` on `object`. If `key` is a function
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6104
     * it will be invoked with the `this` binding of `object` and its result returned,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6105
     * else the property value is returned. If `object` is falsey then `undefined`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6106
     * is returned.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6107
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6108
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6109
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6110
     * @category Utilities
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6111
     * @param {Object} object The object to inspect.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6112
     * @param {string} key The name of the property to resolve.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6113
     * @returns {*} Returns the resolved value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6114
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6115
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6116
     * var object = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6117
     *   'cheese': 'crumpets',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6118
     *   'stuff': function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6119
     *     return 'nonsense';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6120
     *   }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6121
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6122
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6123
     * _.result(object, 'cheese');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6124
     * // => 'crumpets'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6125
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6126
     * _.result(object, 'stuff');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6127
     * // => 'nonsense'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6128
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6129
    function result(object, key) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6130
      if (object) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6131
        var value = object[key];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6132
        return isFunction(value) ? object[key]() : value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6133
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6134
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6135
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6136
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6137
     * A micro-templating method that handles arbitrary delimiters, preserves
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6138
     * whitespace, and correctly escapes quotes within interpolated code.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6139
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6140
     * Note: In the development build, `_.template` utilizes sourceURLs for easier
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6141
     * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6142
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6143
     * For more information on precompiling templates see:
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6144
     * http://lodash.com/custom-builds
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6145
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6146
     * For more information on Chrome extension sandboxes see:
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6147
     * http://developer.chrome.com/stable/extensions/sandboxingEval.html
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6148
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6149
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6150
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6151
     * @category Utilities
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6152
     * @param {string} text The template text.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6153
     * @param {Object} data The data object used to populate the text.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6154
     * @param {Object} [options] The options object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6155
     * @param {RegExp} [options.escape] The "escape" delimiter.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6156
     * @param {RegExp} [options.evaluate] The "evaluate" delimiter.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6157
     * @param {Object} [options.imports] An object to import into the template as local variables.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6158
     * @param {RegExp} [options.interpolate] The "interpolate" delimiter.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6159
     * @param {string} [sourceURL] The sourceURL of the template's compiled source.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6160
     * @param {string} [variable] The data object variable name.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6161
     * @returns {Function|string} Returns a compiled function when no `data` object
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6162
     *  is given, else it returns the interpolated text.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6163
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6164
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6165
     * // using the "interpolate" delimiter to create a compiled template
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6166
     * var compiled = _.template('hello <%= name %>');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6167
     * compiled({ 'name': 'fred' });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6168
     * // => 'hello fred'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6169
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6170
     * // using the "escape" delimiter to escape HTML in data property values
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6171
     * _.template('<b><%- value %></b>', { 'value': '<script>' });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6172
     * // => '<b>&lt;script&gt;</b>'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6173
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6174
     * // using the "evaluate" delimiter to generate HTML
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6175
     * var list = '<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6176
     * _.template(list, { 'people': ['fred', 'barney'] });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6177
     * // => '<li>fred</li><li>barney</li>'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6178
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6179
     * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6180
     * _.template('hello ${ name }', { 'name': 'pebbles' });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6181
     * // => 'hello pebbles'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6182
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6183
     * // using the internal `print` function in "evaluate" delimiters
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6184
     * _.template('<% print("hello " + name); %>!', { 'name': 'barney' });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6185
     * // => 'hello barney!'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6186
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6187
     * // using a custom template delimiters
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6188
     * _.templateSettings = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6189
     *   'interpolate': /{{([\s\S]+?)}}/g
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6190
     * };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6191
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6192
     * _.template('hello {{ name }}!', { 'name': 'mustache' });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6193
     * // => 'hello mustache!'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6194
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6195
     * // using the `imports` option to import jQuery
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6196
     * var list = '<% jq.each(people, function(name) { %><li><%- name %></li><% }); %>';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6197
     * _.template(list, { 'people': ['fred', 'barney'] }, { 'imports': { 'jq': jQuery } });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6198
     * // => '<li>fred</li><li>barney</li>'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6199
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6200
     * // using the `sourceURL` option to specify a custom sourceURL for the template
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6201
     * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6202
     * compiled(data);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6203
     * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6204
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6205
     * // using the `variable` option to ensure a with-statement isn't used in the compiled template
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6206
     * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6207
     * compiled.source;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6208
     * // => function(data) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6209
     *   var __t, __p = '', __e = _.escape;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6210
     *   __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6211
     *   return __p;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6212
     * }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6213
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6214
     * // using the `source` property to inline compiled templates for meaningful
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6215
     * // line numbers in error messages and a stack trace
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6216
     * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6217
     *   var JST = {\
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6218
     *     "main": ' + _.template(mainText).source + '\
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6219
     *   };\
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6220
     * ');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6221
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6222
    function template(text, data, options) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6223
      // based on John Resig's `tmpl` implementation
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6224
      // http://ejohn.org/blog/javascript-micro-templating/
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6225
      // and Laura Doktorova's doT.js
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6226
      // https://github.com/olado/doT
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6227
      var settings = lodash.templateSettings;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6228
      text = String(text || '');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6229
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6230
      // avoid missing dependencies when `iteratorTemplate` is not defined
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6231
      options = defaults({}, options, settings);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6232
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6233
      var imports = defaults({}, options.imports, settings.imports),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6234
          importsKeys = keys(imports),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6235
          importsValues = values(imports);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6236
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6237
      var isEvaluating,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6238
          index = 0,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6239
          interpolate = options.interpolate || reNoMatch,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6240
          source = "__p += '";
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6241
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6242
      // compile the regexp to match each delimiter
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6243
      var reDelimiters = RegExp(
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6244
        (options.escape || reNoMatch).source + '|' +
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6245
        interpolate.source + '|' +
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6246
        (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6247
        (options.evaluate || reNoMatch).source + '|$'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6248
      , 'g');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6249
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6250
      text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6251
        interpolateValue || (interpolateValue = esTemplateValue);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6252
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6253
        // escape characters that cannot be included in string literals
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6254
        source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6255
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6256
        // replace delimiters with snippets
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6257
        if (escapeValue) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6258
          source += "' +\n__e(" + escapeValue + ") +\n'";
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6259
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6260
        if (evaluateValue) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6261
          isEvaluating = true;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6262
          source += "';\n" + evaluateValue + ";\n__p += '";
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6263
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6264
        if (interpolateValue) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6265
          source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6266
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6267
        index = offset + match.length;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6268
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6269
        // the JS engine embedded in Adobe products requires returning the `match`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6270
        // string in order to produce the correct `offset` value
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6271
        return match;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6272
      });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6273
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6274
      source += "';\n";
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6275
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6276
      // if `variable` is not specified, wrap a with-statement around the generated
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6277
      // code to add the data object to the top of the scope chain
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6278
      var variable = options.variable,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6279
          hasVariable = variable;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6280
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6281
      if (!hasVariable) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6282
        variable = 'obj';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6283
        source = 'with (' + variable + ') {\n' + source + '\n}\n';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6284
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6285
      // cleanup code by stripping empty strings
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6286
      source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6287
        .replace(reEmptyStringMiddle, '$1')
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6288
        .replace(reEmptyStringTrailing, '$1;');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6289
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6290
      // frame code as the function body
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6291
      source = 'function(' + variable + ') {\n' +
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6292
        (hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6293
        "var __t, __p = '', __e = _.escape" +
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6294
        (isEvaluating
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6295
          ? ', __j = Array.prototype.join;\n' +
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6296
            "function print() { __p += __j.call(arguments, '') }\n"
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6297
          : ';\n'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6298
        ) +
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6299
        source +
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6300
        'return __p\n}';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6301
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6302
      // Use a sourceURL for easier debugging.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6303
      // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6304
      var sourceURL = '\n/*\n//# sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6305
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6306
      try {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6307
        var result = Function(importsKeys, 'return ' + source + sourceURL).apply(undefined, importsValues);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6308
      } catch(e) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6309
        e.source = source;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6310
        throw e;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6311
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6312
      if (data) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6313
        return result(data);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6314
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6315
      // provide the compiled function's source by its `toString` method, in
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6316
      // supported environments, or the `source` property as a convenience for
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6317
      // inlining compiled templates during the build process
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6318
      result.source = source;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6319
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6320
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6321
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6322
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6323
     * Executes the callback `n` times, returning an array of the results
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6324
     * of each callback execution. The callback is bound to `thisArg` and invoked
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6325
     * with one argument; (index).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6326
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6327
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6328
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6329
     * @category Utilities
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6330
     * @param {number} n The number of times to execute the callback.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6331
     * @param {Function} callback The function called per iteration.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6332
     * @param {*} [thisArg] The `this` binding of `callback`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6333
     * @returns {Array} Returns an array of the results of each `callback` execution.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6334
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6335
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6336
     * var diceRolls = _.times(3, _.partial(_.random, 1, 6));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6337
     * // => [3, 6, 4]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6338
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6339
     * _.times(3, function(n) { mage.castSpell(n); });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6340
     * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6341
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6342
     * _.times(3, function(n) { this.cast(n); }, mage);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6343
     * // => also calls `mage.castSpell(n)` three times
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6344
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6345
    function times(n, callback, thisArg) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6346
      n = (n = +n) > -1 ? n : 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6347
      var index = -1,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6348
          result = Array(n);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6349
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6350
      callback = baseCreateCallback(callback, thisArg, 1);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6351
      while (++index < n) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6352
        result[index] = callback(index);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6353
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6354
      return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6355
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6356
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6357
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6358
     * The inverse of `_.escape` this method converts the HTML entities
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6359
     * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6360
     * corresponding characters.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6361
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6362
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6363
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6364
     * @category Utilities
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6365
     * @param {string} string The string to unescape.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6366
     * @returns {string} Returns the unescaped string.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6367
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6368
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6369
     * _.unescape('Fred, Barney &amp; Pebbles');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6370
     * // => 'Fred, Barney & Pebbles'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6371
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6372
    function unescape(string) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6373
      return string == null ? '' : String(string).replace(reEscapedHtml, unescapeHtmlChar);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6374
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6375
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6376
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6377
     * Generates a unique ID. If `prefix` is provided the ID will be appended to it.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6378
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6379
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6380
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6381
     * @category Utilities
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6382
     * @param {string} [prefix] The value to prefix the ID with.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6383
     * @returns {string} Returns the unique ID.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6384
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6385
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6386
     * _.uniqueId('contact_');
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6387
     * // => 'contact_104'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6388
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6389
     * _.uniqueId();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6390
     * // => '105'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6391
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6392
    function uniqueId(prefix) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6393
      var id = ++idCounter;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6394
      return String(prefix == null ? '' : prefix) + id;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6395
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6396
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6397
    /*--------------------------------------------------------------------------*/
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6398
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6399
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6400
     * Creates a `lodash` object that wraps the given value with explicit
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6401
     * method chaining enabled.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6402
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6403
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6404
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6405
     * @category Chaining
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6406
     * @param {*} value The value to wrap.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6407
     * @returns {Object} Returns the wrapper object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6408
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6409
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6410
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6411
     *   { 'name': 'barney',  'age': 36 },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6412
     *   { 'name': 'fred',    'age': 40 },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6413
     *   { 'name': 'pebbles', 'age': 1 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6414
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6415
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6416
     * var youngest = _.chain(characters)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6417
     *     .sortBy('age')
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6418
     *     .map(function(chr) { return chr.name + ' is ' + chr.age; })
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6419
     *     .first()
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6420
     *     .value();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6421
     * // => 'pebbles is 1'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6422
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6423
    function chain(value) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6424
      value = new lodashWrapper(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6425
      value.__chain__ = true;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6426
      return value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6427
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6428
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6429
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6430
     * Invokes `interceptor` with the `value` as the first argument and then
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6431
     * returns `value`. The purpose of this method is to "tap into" a method
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6432
     * chain in order to perform operations on intermediate results within
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6433
     * the chain.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6434
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6435
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6436
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6437
     * @category Chaining
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6438
     * @param {*} value The value to provide to `interceptor`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6439
     * @param {Function} interceptor The function to invoke.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6440
     * @returns {*} Returns `value`.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6441
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6442
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6443
     * _([1, 2, 3, 4])
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6444
     *  .tap(function(array) { array.pop(); })
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6445
     *  .reverse()
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6446
     *  .value();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6447
     * // => [3, 2, 1]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6448
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6449
    function tap(value, interceptor) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6450
      interceptor(value);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6451
      return value;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6452
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6453
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6454
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6455
     * Enables explicit method chaining on the wrapper object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6456
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6457
     * @name chain
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6458
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6459
     * @category Chaining
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6460
     * @returns {*} Returns the wrapper object.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6461
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6462
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6463
     * var characters = [
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6464
     *   { 'name': 'barney', 'age': 36 },
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6465
     *   { 'name': 'fred',   'age': 40 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6466
     * ];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6467
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6468
     * // without explicit chaining
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6469
     * _(characters).first();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6470
     * // => { 'name': 'barney', 'age': 36 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6471
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6472
     * // with explicit chaining
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6473
     * _(characters).chain()
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6474
     *   .first()
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6475
     *   .pick('age')
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6476
     *   .value();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6477
     * // => { 'age': 36 }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6478
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6479
    function wrapperChain() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6480
      this.__chain__ = true;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6481
      return this;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6482
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6483
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6484
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6485
     * Produces the `toString` result of the wrapped value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6486
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6487
     * @name toString
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6488
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6489
     * @category Chaining
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6490
     * @returns {string} Returns the string result.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6491
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6492
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6493
     * _([1, 2, 3]).toString();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6494
     * // => '1,2,3'
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6495
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6496
    function wrapperToString() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6497
      return String(this.__wrapped__);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6498
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6499
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6500
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6501
     * Extracts the wrapped value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6502
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6503
     * @name valueOf
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6504
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6505
     * @alias value
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6506
     * @category Chaining
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6507
     * @returns {*} Returns the wrapped value.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6508
     * @example
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6509
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6510
     * _([1, 2, 3]).valueOf();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6511
     * // => [1, 2, 3]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6512
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6513
    function wrapperValueOf() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6514
      return this.__wrapped__;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6515
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6516
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6517
    /*--------------------------------------------------------------------------*/
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6518
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6519
    // add functions that return wrapped values when chaining
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6520
    lodash.after = after;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6521
    lodash.assign = assign;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6522
    lodash.at = at;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6523
    lodash.bind = bind;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6524
    lodash.bindAll = bindAll;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6525
    lodash.bindKey = bindKey;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6526
    lodash.chain = chain;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6527
    lodash.compact = compact;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6528
    lodash.compose = compose;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6529
    lodash.constant = constant;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6530
    lodash.countBy = countBy;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6531
    lodash.create = create;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6532
    lodash.createCallback = createCallback;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6533
    lodash.curry = curry;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6534
    lodash.debounce = debounce;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6535
    lodash.defaults = defaults;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6536
    lodash.defer = defer;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6537
    lodash.delay = delay;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6538
    lodash.difference = difference;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6539
    lodash.filter = filter;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6540
    lodash.flatten = flatten;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6541
    lodash.forEach = forEach;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6542
    lodash.forEachRight = forEachRight;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6543
    lodash.forIn = forIn;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6544
    lodash.forInRight = forInRight;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6545
    lodash.forOwn = forOwn;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6546
    lodash.forOwnRight = forOwnRight;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6547
    lodash.functions = functions;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6548
    lodash.groupBy = groupBy;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6549
    lodash.indexBy = indexBy;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6550
    lodash.initial = initial;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6551
    lodash.intersection = intersection;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6552
    lodash.invert = invert;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6553
    lodash.invoke = invoke;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6554
    lodash.keys = keys;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6555
    lodash.map = map;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6556
    lodash.mapValues = mapValues;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6557
    lodash.max = max;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6558
    lodash.memoize = memoize;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6559
    lodash.merge = merge;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6560
    lodash.min = min;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6561
    lodash.omit = omit;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6562
    lodash.once = once;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6563
    lodash.pairs = pairs;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6564
    lodash.partial = partial;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6565
    lodash.partialRight = partialRight;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6566
    lodash.pick = pick;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6567
    lodash.pluck = pluck;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6568
    lodash.property = property;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6569
    lodash.pull = pull;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6570
    lodash.range = range;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6571
    lodash.reject = reject;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6572
    lodash.remove = remove;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6573
    lodash.rest = rest;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6574
    lodash.shuffle = shuffle;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6575
    lodash.sortBy = sortBy;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6576
    lodash.tap = tap;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6577
    lodash.throttle = throttle;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6578
    lodash.times = times;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6579
    lodash.toArray = toArray;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6580
    lodash.transform = transform;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6581
    lodash.union = union;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6582
    lodash.uniq = uniq;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6583
    lodash.values = values;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6584
    lodash.where = where;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6585
    lodash.without = without;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6586
    lodash.wrap = wrap;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6587
    lodash.xor = xor;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6588
    lodash.zip = zip;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6589
    lodash.zipObject = zipObject;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6590
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6591
    // add aliases
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6592
    lodash.collect = map;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6593
    lodash.drop = rest;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6594
    lodash.each = forEach;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6595
    lodash.eachRight = forEachRight;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6596
    lodash.extend = assign;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6597
    lodash.methods = functions;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6598
    lodash.object = zipObject;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6599
    lodash.select = filter;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6600
    lodash.tail = rest;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6601
    lodash.unique = uniq;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6602
    lodash.unzip = zip;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6603
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6604
    // add functions to `lodash.prototype`
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6605
    mixin(lodash);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6606
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6607
    /*--------------------------------------------------------------------------*/
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6608
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6609
    // add functions that return unwrapped values when chaining
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6610
    lodash.clone = clone;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6611
    lodash.cloneDeep = cloneDeep;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6612
    lodash.contains = contains;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6613
    lodash.escape = escape;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6614
    lodash.every = every;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6615
    lodash.find = find;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6616
    lodash.findIndex = findIndex;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6617
    lodash.findKey = findKey;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6618
    lodash.findLast = findLast;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6619
    lodash.findLastIndex = findLastIndex;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6620
    lodash.findLastKey = findLastKey;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6621
    lodash.has = has;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6622
    lodash.identity = identity;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6623
    lodash.indexOf = indexOf;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6624
    lodash.isArguments = isArguments;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6625
    lodash.isArray = isArray;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6626
    lodash.isBoolean = isBoolean;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6627
    lodash.isDate = isDate;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6628
    lodash.isElement = isElement;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6629
    lodash.isEmpty = isEmpty;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6630
    lodash.isEqual = isEqual;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6631
    lodash.isFinite = isFinite;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6632
    lodash.isFunction = isFunction;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6633
    lodash.isNaN = isNaN;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6634
    lodash.isNull = isNull;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6635
    lodash.isNumber = isNumber;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6636
    lodash.isObject = isObject;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6637
    lodash.isPlainObject = isPlainObject;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6638
    lodash.isRegExp = isRegExp;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6639
    lodash.isString = isString;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6640
    lodash.isUndefined = isUndefined;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6641
    lodash.lastIndexOf = lastIndexOf;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6642
    lodash.mixin = mixin;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6643
    lodash.noConflict = noConflict;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6644
    lodash.noop = noop;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6645
    lodash.now = now;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6646
    lodash.parseInt = parseInt;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6647
    lodash.random = random;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6648
    lodash.reduce = reduce;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6649
    lodash.reduceRight = reduceRight;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6650
    lodash.result = result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6651
    lodash.runInContext = runInContext;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6652
    lodash.size = size;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6653
    lodash.some = some;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6654
    lodash.sortedIndex = sortedIndex;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6655
    lodash.template = template;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6656
    lodash.unescape = unescape;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6657
    lodash.uniqueId = uniqueId;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6658
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6659
    // add aliases
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6660
    lodash.all = every;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6661
    lodash.any = some;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6662
    lodash.detect = find;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6663
    lodash.findWhere = find;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6664
    lodash.foldl = reduce;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6665
    lodash.foldr = reduceRight;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6666
    lodash.include = contains;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6667
    lodash.inject = reduce;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6668
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6669
    mixin(function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6670
      var source = {}
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6671
      forOwn(lodash, function(func, methodName) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6672
        if (!lodash.prototype[methodName]) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6673
          source[methodName] = func;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6674
        }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6675
      });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6676
      return source;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6677
    }(), false);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6678
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6679
    /*--------------------------------------------------------------------------*/
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6680
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6681
    // add functions capable of returning wrapped and unwrapped values when chaining
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6682
    lodash.first = first;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6683
    lodash.last = last;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6684
    lodash.sample = sample;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6685
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6686
    // add aliases
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6687
    lodash.take = first;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6688
    lodash.head = first;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6689
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6690
    forOwn(lodash, function(func, methodName) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6691
      var callbackable = methodName !== 'sample';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6692
      if (!lodash.prototype[methodName]) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6693
        lodash.prototype[methodName]= function(n, guard) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6694
          var chainAll = this.__chain__,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6695
              result = func(this.__wrapped__, n, guard);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6696
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6697
          return !chainAll && (n == null || (guard && !(callbackable && typeof n == 'function')))
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6698
            ? result
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6699
            : new lodashWrapper(result, chainAll);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6700
        };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6701
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6702
    });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6703
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6704
    /*--------------------------------------------------------------------------*/
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6705
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6706
    /**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6707
     * The semantic version number.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6708
     *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6709
     * @static
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6710
     * @memberOf _
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6711
     * @type string
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6712
     */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6713
    lodash.VERSION = '2.4.1';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6714
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6715
    // add "Chaining" functions to the wrapper
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6716
    lodash.prototype.chain = wrapperChain;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6717
    lodash.prototype.toString = wrapperToString;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6718
    lodash.prototype.value = wrapperValueOf;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6719
    lodash.prototype.valueOf = wrapperValueOf;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6720
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6721
    // add `Array` functions that return unwrapped values
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6722
    forEach(['join', 'pop', 'shift'], function(methodName) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6723
      var func = arrayRef[methodName];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6724
      lodash.prototype[methodName] = function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6725
        var chainAll = this.__chain__,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6726
            result = func.apply(this.__wrapped__, arguments);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6727
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6728
        return chainAll
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6729
          ? new lodashWrapper(result, chainAll)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6730
          : result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6731
      };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6732
    });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6733
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6734
    // add `Array` functions that return the existing wrapped value
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6735
    forEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6736
      var func = arrayRef[methodName];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6737
      lodash.prototype[methodName] = function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6738
        func.apply(this.__wrapped__, arguments);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6739
        return this;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6740
      };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6741
    });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6742
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6743
    // add `Array` functions that return new wrapped values
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6744
    forEach(['concat', 'slice', 'splice'], function(methodName) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6745
      var func = arrayRef[methodName];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6746
      lodash.prototype[methodName] = function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6747
        return new lodashWrapper(func.apply(this.__wrapped__, arguments), this.__chain__);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6748
      };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6749
    });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6750
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6751
    return lodash;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6752
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6753
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6754
  /*--------------------------------------------------------------------------*/
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6755
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6756
  // expose Lo-Dash
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6757
  var _ = runInContext();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6758
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6759
  // some AMD build optimizers like r.js check for condition patterns like the following:
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6760
  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6761
    // Expose Lo-Dash to the global object even when an AMD loader is present in
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6762
    // case Lo-Dash is loaded with a RequireJS shim config.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6763
    // See http://requirejs.org/docs/api.html#config-shim
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6764
    root._ = _;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6765
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6766
    // define as an anonymous module so, through path mapping, it can be
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6767
    // referenced as the "underscore" module
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6768
    define(function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6769
      return _;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6770
    });
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6771
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6772
  // check for `exports` after `define` in case a build optimizer adds an `exports` object
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6773
  else if (freeExports && freeModule) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6774
    // in Node.js or RingoJS
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6775
    if (moduleExports) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6776
      (freeModule.exports = _)._ = _;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6777
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6778
    // in Narwhal or Rhino -require
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6779
    else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6780
      freeExports._ = _;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6781
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6782
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6783
  else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6784
    // in a browser or Rhino
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6785
    root._ = _;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6786
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6787
}.call(this));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6788
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6789
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6790
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6791
},{}],"pixi":[function(require,module,exports){
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6792
/**
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6793
 * @license
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6794
 * pixi.js - v2.2.3
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6795
 * Copyright (c) 2012-2014, Mat Groves
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6796
 * http://goodboydigital.com/
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6797
 *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6798
 * Compiled: 2015-01-06
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6799
 *
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6800
 * pixi.js is licensed under the MIT License.
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6801
 * http://www.opensource.org/licenses/mit-license.php
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6802
 */
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6803
(function(){var a=this,b=b||{};b.WEBGL_RENDERER=0,b.CANVAS_RENDERER=1,b.VERSION="v2.2.3",b.blendModes={NORMAL:0,ADD:1,MULTIPLY:2,SCREEN:3,OVERLAY:4,DARKEN:5,LIGHTEN:6,COLOR_DODGE:7,COLOR_BURN:8,HARD_LIGHT:9,SOFT_LIGHT:10,DIFFERENCE:11,EXCLUSION:12,HUE:13,SATURATION:14,COLOR:15,LUMINOSITY:16},b.scaleModes={DEFAULT:0,LINEAR:0,NEAREST:1},b._UID=0,"undefined"!=typeof Float32Array?(b.Float32Array=Float32Array,b.Uint16Array=Uint16Array,b.Uint32Array=Uint32Array,b.ArrayBuffer=ArrayBuffer):(b.Float32Array=Array,b.Uint16Array=Array),b.INTERACTION_FREQUENCY=30,b.AUTO_PREVENT_DEFAULT=!0,b.PI_2=2*Math.PI,b.RAD_TO_DEG=180/Math.PI,b.DEG_TO_RAD=Math.PI/180,b.RETINA_PREFIX="@2x",b.dontSayHello=!1,b.defaultRenderOptions={view:null,transparent:!1,antialias:!1,preserveDrawingBuffer:!1,resolution:1,clearBeforeRender:!0,autoResize:!1},b.sayHello=function(a){if(!b.dontSayHello){if(navigator.userAgent.toLowerCase().indexOf("chrome")>-1){var c=["%c %c %c Pixi.js "+b.VERSION+" - "+a+"  %c  %c  http://www.pixijs.com/  %c %c ♥%c♥%c♥ ","background: #ff66a5","background: #ff66a5","color: #ff66a5; background: #030307;","background: #ff66a5","background: #ffc3dc","background: #ff66a5","color: #ff2424; background: #fff","color: #ff2424; background: #fff","color: #ff2424; background: #fff"];console.log.apply(console,c)}else window.console&&console.log("Pixi.js "+b.VERSION+" - http://www.pixijs.com/");b.dontSayHello=!0}},b.Point=function(a,b){this.x=a||0,this.y=b||0},b.Point.prototype.clone=function(){return new b.Point(this.x,this.y)},b.Point.prototype.set=function(a,b){this.x=a||0,this.y=b||(0!==b?this.x:0)},b.Point.prototype.constructor=b.Point,b.Rectangle=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},b.Rectangle.prototype.clone=function(){return new b.Rectangle(this.x,this.y,this.width,this.height)},b.Rectangle.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=this.x;if(a>=c&&a<=c+this.width){var d=this.y;if(b>=d&&b<=d+this.height)return!0}return!1},b.Rectangle.prototype.constructor=b.Rectangle,b.EmptyRectangle=new b.Rectangle(0,0,0,0),b.Polygon=function(a){if(a instanceof Array||(a=Array.prototype.slice.call(arguments)),a[0]instanceof b.Point){for(var c=[],d=0,e=a.length;e>d;d++)c.push(a[d].x,a[d].y);a=c}this.closed=!0,this.points=a},b.Polygon.prototype.clone=function(){var a=this.points.slice();return new b.Polygon(a)},b.Polygon.prototype.contains=function(a,b){for(var c=!1,d=this.points.length/2,e=0,f=d-1;d>e;f=e++){var g=this.points[2*e],h=this.points[2*e+1],i=this.points[2*f],j=this.points[2*f+1],k=h>b!=j>b&&(i-g)*(b-h)/(j-h)+g>a;k&&(c=!c)}return c},b.Polygon.prototype.constructor=b.Polygon,b.Circle=function(a,b,c){this.x=a||0,this.y=b||0,this.radius=c||0},b.Circle.prototype.clone=function(){return new b.Circle(this.x,this.y,this.radius)},b.Circle.prototype.contains=function(a,b){if(this.radius<=0)return!1;var c=this.x-a,d=this.y-b,e=this.radius*this.radius;return c*=c,d*=d,e>=c+d},b.Circle.prototype.getBounds=function(){return new b.Rectangle(this.x-this.radius,this.y-this.radius,2*this.radius,2*this.radius)},b.Circle.prototype.constructor=b.Circle,b.Ellipse=function(a,b,c,d){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0},b.Ellipse.prototype.clone=function(){return new b.Ellipse(this.x,this.y,this.width,this.height)},b.Ellipse.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=(a-this.x)/this.width,d=(b-this.y)/this.height;return c*=c,d*=d,1>=c+d},b.Ellipse.prototype.getBounds=function(){return new b.Rectangle(this.x-this.width,this.y-this.height,this.width,this.height)},b.Ellipse.prototype.constructor=b.Ellipse,b.RoundedRectangle=function(a,b,c,d,e){this.x=a||0,this.y=b||0,this.width=c||0,this.height=d||0,this.radius=e||20},b.RoundedRectangle.prototype.clone=function(){return new b.RoundedRectangle(this.x,this.y,this.width,this.height,this.radius)},b.RoundedRectangle.prototype.contains=function(a,b){if(this.width<=0||this.height<=0)return!1;var c=this.x;if(a>=c&&a<=c+this.width){var d=this.y;if(b>=d&&b<=d+this.height)return!0}return!1},b.RoundedRectangle.prototype.constructor=b.RoundedRectangle,b.Matrix=function(){this.a=1,this.b=0,this.c=0,this.d=1,this.tx=0,this.ty=0},b.Matrix.prototype.fromArray=function(a){this.a=a[0],this.b=a[1],this.c=a[3],this.d=a[4],this.tx=a[2],this.ty=a[5]},b.Matrix.prototype.toArray=function(a){this.array||(this.array=new b.Float32Array(9));var c=this.array;return a?(c[0]=this.a,c[1]=this.b,c[2]=0,c[3]=this.c,c[4]=this.d,c[5]=0,c[6]=this.tx,c[7]=this.ty,c[8]=1):(c[0]=this.a,c[1]=this.c,c[2]=this.tx,c[3]=this.b,c[4]=this.d,c[5]=this.ty,c[6]=0,c[7]=0,c[8]=1),c},b.Matrix.prototype.apply=function(a,c){return c=c||new b.Point,c.x=this.a*a.x+this.c*a.y+this.tx,c.y=this.b*a.x+this.d*a.y+this.ty,c},b.Matrix.prototype.applyInverse=function(a,c){c=c||new b.Point;var d=1/(this.a*this.d+this.c*-this.b);return c.x=this.d*d*a.x+-this.c*d*a.y+(this.ty*this.c-this.tx*this.d)*d,c.y=this.a*d*a.y+-this.b*d*a.x+(-this.ty*this.a+this.tx*this.b)*d,c},b.Matrix.prototype.translate=function(a,b){return this.tx+=a,this.ty+=b,this},b.Matrix.prototype.scale=function(a,b){return this.a*=a,this.d*=b,this.c*=a,this.b*=b,this.tx*=a,this.ty*=b,this},b.Matrix.prototype.rotate=function(a){var b=Math.cos(a),c=Math.sin(a),d=this.a,e=this.c,f=this.tx;return this.a=d*b-this.b*c,this.b=d*c+this.b*b,this.c=e*b-this.d*c,this.d=e*c+this.d*b,this.tx=f*b-this.ty*c,this.ty=f*c+this.ty*b,this},b.Matrix.prototype.append=function(a){var b=this.a,c=this.b,d=this.c,e=this.d;return this.a=a.a*b+a.b*d,this.b=a.a*c+a.b*e,this.c=a.c*b+a.d*d,this.d=a.c*c+a.d*e,this.tx=a.tx*b+a.ty*d+this.tx,this.ty=a.tx*c+a.ty*e+this.ty,this},b.Matrix.prototype.identity=function(){return this.a=1,this.b=0,this.c=0,this.d=1,this.tx=0,this.ty=0,this},b.identityMatrix=new b.Matrix,b.DisplayObject=function(){this.position=new b.Point,this.scale=new b.Point(1,1),this.pivot=new b.Point(0,0),this.rotation=0,this.alpha=1,this.visible=!0,this.hitArea=null,this.buttonMode=!1,this.renderable=!1,this.parent=null,this.stage=null,this.worldAlpha=1,this._interactive=!1,this.defaultCursor="pointer",this.worldTransform=new b.Matrix,this._sr=0,this._cr=1,this.filterArea=null,this._bounds=new b.Rectangle(0,0,1,1),this._currentBounds=null,this._mask=null,this._cacheAsBitmap=!1,this._cacheIsDirty=!1},b.DisplayObject.prototype.constructor=b.DisplayObject,Object.defineProperty(b.DisplayObject.prototype,"interactive",{get:function(){return this._interactive},set:function(a){this._interactive=a,this.stage&&(this.stage.dirty=!0)}}),Object.defineProperty(b.DisplayObject.prototype,"worldVisible",{get:function(){var a=this;do{if(!a.visible)return!1;a=a.parent}while(a);return!0}}),Object.defineProperty(b.DisplayObject.prototype,"mask",{get:function(){return this._mask},set:function(a){this._mask&&(this._mask.isMask=!1),this._mask=a,this._mask&&(this._mask.isMask=!0)}}),Object.defineProperty(b.DisplayObject.prototype,"filters",{get:function(){return this._filters},set:function(a){if(a){for(var b=[],c=0;c<a.length;c++)for(var d=a[c].passes,e=0;e<d.length;e++)b.push(d[e]);this._filterBlock={target:this,filterPasses:b}}this._filters=a}}),Object.defineProperty(b.DisplayObject.prototype,"cacheAsBitmap",{get:function(){return this._cacheAsBitmap},set:function(a){this._cacheAsBitmap!==a&&(a?this._generateCachedSprite():this._destroyCachedSprite(),this._cacheAsBitmap=a)}}),b.DisplayObject.prototype.updateTransform=function(){var a,c,d,e,f,g,h=this.parent.worldTransform,i=this.worldTransform;this.rotation%b.PI_2?(this.rotation!==this.rotationCache&&(this.rotationCache=this.rotation,this._sr=Math.sin(this.rotation),this._cr=Math.cos(this.rotation)),a=this._cr*this.scale.x,c=this._sr*this.scale.x,d=-this._sr*this.scale.y,e=this._cr*this.scale.y,f=this.position.x,g=this.position.y,(this.pivot.x||this.pivot.y)&&(f-=this.pivot.x*a+this.pivot.y*d,g-=this.pivot.x*c+this.pivot.y*e),i.a=a*h.a+c*h.c,i.b=a*h.b+c*h.d,i.c=d*h.a+e*h.c,i.d=d*h.b+e*h.d,i.tx=f*h.a+g*h.c+h.tx,i.ty=f*h.b+g*h.d+h.ty):(a=this.scale.x,e=this.scale.y,f=this.position.x-this.pivot.x*a,g=this.position.y-this.pivot.y*e,i.a=a*h.a,i.b=a*h.b,i.c=e*h.c,i.d=e*h.d,i.tx=f*h.a+g*h.c+h.tx,i.ty=f*h.b+g*h.d+h.ty),this.worldAlpha=this.alpha*this.parent.worldAlpha},b.DisplayObject.prototype.displayObjectUpdateTransform=b.DisplayObject.prototype.updateTransform,b.DisplayObject.prototype.getBounds=function(a){return a=a,b.EmptyRectangle},b.DisplayObject.prototype.getLocalBounds=function(){return this.getBounds(b.identityMatrix)},b.DisplayObject.prototype.setStageReference=function(a){this.stage=a,this._interactive&&(this.stage.dirty=!0)},b.DisplayObject.prototype.generateTexture=function(a,c,d){var e=this.getLocalBounds(),f=new b.RenderTexture(0|e.width,0|e.height,d,c,a);return b.DisplayObject._tempMatrix.tx=-e.x,b.DisplayObject._tempMatrix.ty=-e.y,f.render(this,b.DisplayObject._tempMatrix),f},b.DisplayObject.prototype.updateCache=function(){this._generateCachedSprite()},b.DisplayObject.prototype.toGlobal=function(a){return this.displayObjectUpdateTransform(),this.worldTransform.apply(a)},b.DisplayObject.prototype.toLocal=function(a,b){return b&&(a=b.toGlobal(a)),this.displayObjectUpdateTransform(),this.worldTransform.applyInverse(a)},b.DisplayObject.prototype._renderCachedSprite=function(a){this._cachedSprite.worldAlpha=this.worldAlpha,a.gl?b.Sprite.prototype._renderWebGL.call(this._cachedSprite,a):b.Sprite.prototype._renderCanvas.call(this._cachedSprite,a)},b.DisplayObject.prototype._generateCachedSprite=function(){this._cacheAsBitmap=!1;var a=this.getLocalBounds();if(this._cachedSprite)this._cachedSprite.texture.resize(0|a.width,0|a.height);else{var c=new b.RenderTexture(0|a.width,0|a.height);this._cachedSprite=new b.Sprite(c),this._cachedSprite.worldTransform=this.worldTransform}var d=this._filters;this._filters=null,this._cachedSprite.filters=d,b.DisplayObject._tempMatrix.tx=-a.x,b.DisplayObject._tempMatrix.ty=-a.y,this._cachedSprite.texture.render(this,b.DisplayObject._tempMatrix,!0),this._cachedSprite.anchor.x=-(a.x/a.width),this._cachedSprite.anchor.y=-(a.y/a.height),this._filters=d,this._cacheAsBitmap=!0},b.DisplayObject.prototype._destroyCachedSprite=function(){this._cachedSprite&&(this._cachedSprite.texture.destroy(!0),this._cachedSprite=null)},b.DisplayObject.prototype._renderWebGL=function(a){a=a},b.DisplayObject.prototype._renderCanvas=function(a){a=a},b.DisplayObject._tempMatrix=new b.Matrix,Object.defineProperty(b.DisplayObject.prototype,"x",{get:function(){return this.position.x},set:function(a){this.position.x=a}}),Object.defineProperty(b.DisplayObject.prototype,"y",{get:function(){return this.position.y},set:function(a){this.position.y=a}}),b.DisplayObjectContainer=function(){b.DisplayObject.call(this),this.children=[]},b.DisplayObjectContainer.prototype=Object.create(b.DisplayObject.prototype),b.DisplayObjectContainer.prototype.constructor=b.DisplayObjectContainer,Object.defineProperty(b.DisplayObjectContainer.prototype,"width",{get:function(){return this.scale.x*this.getLocalBounds().width},set:function(a){var b=this.getLocalBounds().width;this.scale.x=0!==b?a/b:1,this._width=a}}),Object.defineProperty(b.DisplayObjectContainer.prototype,"height",{get:function(){return this.scale.y*this.getLocalBounds().height},set:function(a){var b=this.getLocalBounds().height;this.scale.y=0!==b?a/b:1,this._height=a}}),b.DisplayObjectContainer.prototype.addChild=function(a){return this.addChildAt(a,this.children.length)},b.DisplayObjectContainer.prototype.addChildAt=function(a,b){if(b>=0&&b<=this.children.length)return a.parent&&a.parent.removeChild(a),a.parent=this,this.children.splice(b,0,a),this.stage&&a.setStageReference(this.stage),a;throw new Error(a+"addChildAt: The index "+b+" supplied is out of bounds "+this.children.length)},b.DisplayObjectContainer.prototype.swapChildren=function(a,b){if(a!==b){var c=this.getChildIndex(a),d=this.getChildIndex(b);if(0>c||0>d)throw new Error("swapChildren: Both the supplied DisplayObjects must be a child of the caller.");this.children[c]=b,this.children[d]=a}},b.DisplayObjectContainer.prototype.getChildIndex=function(a){var b=this.children.indexOf(a);if(-1===b)throw new Error("The supplied DisplayObject must be a child of the caller");return b},b.DisplayObjectContainer.prototype.setChildIndex=function(a,b){if(0>b||b>=this.children.length)throw new Error("The supplied index is out of bounds");var c=this.getChildIndex(a);this.children.splice(c,1),this.children.splice(b,0,a)},b.DisplayObjectContainer.prototype.getChildAt=function(a){if(0>a||a>=this.children.length)throw new Error("getChildAt: Supplied index "+a+" does not exist in the child list, or the supplied DisplayObject must be a child of the caller");return this.children[a]},b.DisplayObjectContainer.prototype.removeChild=function(a){var b=this.children.indexOf(a);if(-1!==b)return this.removeChildAt(b)},b.DisplayObjectContainer.prototype.removeChildAt=function(a){var b=this.getChildAt(a);return this.stage&&b.removeStageReference(),b.parent=void 0,this.children.splice(a,1),b},b.DisplayObjectContainer.prototype.removeChildren=function(a,b){var c=a||0,d="number"==typeof b?b:this.children.length,e=d-c;if(e>0&&d>=e){for(var f=this.children.splice(c,e),g=0;g<f.length;g++){var h=f[g];this.stage&&h.removeStageReference(),h.parent=void 0}return f}if(0===e&&0===this.children.length)return[];throw new Error("removeChildren: Range Error, numeric values are outside the acceptable range")},b.DisplayObjectContainer.prototype.updateTransform=function(){if(this.visible&&(this.displayObjectUpdateTransform(),!this._cacheAsBitmap))for(var a=0,b=this.children.length;b>a;a++)this.children[a].updateTransform()},b.DisplayObjectContainer.prototype.displayObjectContainerUpdateTransform=b.DisplayObjectContainer.prototype.updateTransform,b.DisplayObjectContainer.prototype.getBounds=function(){if(0===this.children.length)return b.EmptyRectangle;for(var a,c,d,e=1/0,f=1/0,g=-1/0,h=-1/0,i=!1,j=0,k=this.children.length;k>j;j++){var l=this.children[j];l.visible&&(i=!0,a=this.children[j].getBounds(),e=e<a.x?e:a.x,f=f<a.y?f:a.y,c=a.width+a.x,d=a.height+a.y,g=g>c?g:c,h=h>d?h:d)}if(!i)return b.EmptyRectangle;var m=this._bounds;return m.x=e,m.y=f,m.width=g-e,m.height=h-f,m},b.DisplayObjectContainer.prototype.getLocalBounds=function(){var a=this.worldTransform;this.worldTransform=b.identityMatrix;for(var c=0,d=this.children.length;d>c;c++)this.children[c].updateTransform();var e=this.getBounds();return this.worldTransform=a,e},b.DisplayObjectContainer.prototype.setStageReference=function(a){this.stage=a,this._interactive&&(this.stage.dirty=!0);for(var b=0,c=this.children.length;c>b;b++){var d=this.children[b];d.setStageReference(a)}},b.DisplayObjectContainer.prototype.removeStageReference=function(){for(var a=0,b=this.children.length;b>a;a++){var c=this.children[a];c.removeStageReference()}this._interactive&&(this.stage.dirty=!0),this.stage=null},b.DisplayObjectContainer.prototype._renderWebGL=function(a){if(this.visible&&!(this.alpha<=0)){if(this._cacheAsBitmap)return void this._renderCachedSprite(a);var b,c;if(this._mask||this._filters){for(this._filters&&(a.spriteBatch.flush(),a.filterManager.pushFilter(this._filterBlock)),this._mask&&(a.spriteBatch.stop(),a.maskManager.pushMask(this.mask,a),a.spriteBatch.start()),b=0,c=this.children.length;c>b;b++)this.children[b]._renderWebGL(a);a.spriteBatch.stop(),this._mask&&a.maskManager.popMask(this._mask,a),this._filters&&a.filterManager.popFilter(),a.spriteBatch.start()}else for(b=0,c=this.children.length;c>b;b++)this.children[b]._renderWebGL(a)}},b.DisplayObjectContainer.prototype._renderCanvas=function(a){if(this.visible!==!1&&0!==this.alpha){if(this._cacheAsBitmap)return void this._renderCachedSprite(a);this._mask&&a.maskManager.pushMask(this._mask,a);for(var b=0,c=this.children.length;c>b;b++){var d=this.children[b];d._renderCanvas(a)}this._mask&&a.maskManager.popMask(a)}},b.Sprite=function(a){b.DisplayObjectContainer.call(this),this.anchor=new b.Point,this.texture=a||b.Texture.emptyTexture,this._width=0,this._height=0,this.tint=16777215,this.blendMode=b.blendModes.NORMAL,this.shader=null,this.texture.baseTexture.hasLoaded?this.onTextureUpdate():this.texture.on("update",this.onTextureUpdate.bind(this)),this.renderable=!0},b.Sprite.prototype=Object.create(b.DisplayObjectContainer.prototype),b.Sprite.prototype.constructor=b.Sprite,Object.defineProperty(b.Sprite.prototype,"width",{get:function(){return this.scale.x*this.texture.frame.width},set:function(a){this.scale.x=a/this.texture.frame.width,this._width=a}}),Object.defineProperty(b.Sprite.prototype,"height",{get:function(){return this.scale.y*this.texture.frame.height},set:function(a){this.scale.y=a/this.texture.frame.height,this._height=a}}),b.Sprite.prototype.setTexture=function(a){this.texture=a,this.cachedTint=16777215},b.Sprite.prototype.onTextureUpdate=function(){this._width&&(this.scale.x=this._width/this.texture.frame.width),this._height&&(this.scale.y=this._height/this.texture.frame.height)},b.Sprite.prototype.getBounds=function(a){var b=this.texture.frame.width,c=this.texture.frame.height,d=b*(1-this.anchor.x),e=b*-this.anchor.x,f=c*(1-this.anchor.y),g=c*-this.anchor.y,h=a||this.worldTransform,i=h.a,j=h.b,k=h.c,l=h.d,m=h.tx,n=h.ty,o=-1/0,p=-1/0,q=1/0,r=1/0;if(0===j&&0===k)0>i&&(i*=-1),0>l&&(l*=-1),q=i*e+m,o=i*d+m,r=l*g+n,p=l*f+n;else{var s=i*e+k*g+m,t=l*g+j*e+n,u=i*d+k*g+m,v=l*g+j*d+n,w=i*d+k*f+m,x=l*f+j*d+n,y=i*e+k*f+m,z=l*f+j*e+n;q=q>s?s:q,q=q>u?u:q,q=q>w?w:q,q=q>y?y:q,r=r>t?t:r,r=r>v?v:r,r=r>x?x:r,r=r>z?z:r,o=s>o?s:o,o=u>o?u:o,o=w>o?w:o,o=y>o?y:o,p=t>p?t:p,p=v>p?v:p,p=x>p?x:p,p=z>p?z:p}var A=this._bounds;return A.x=q,A.width=o-q,A.y=r,A.height=p-r,this._currentBounds=A,A},b.Sprite.prototype._renderWebGL=function(a){if(this.visible&&!(this.alpha<=0)){var b,c;if(this._mask||this._filters){var d=a.spriteBatch;for(this._filters&&(d.flush(),a.filterManager.pushFilter(this._filterBlock)),this._mask&&(d.stop(),a.maskManager.pushMask(this.mask,a),d.start()),d.render(this),b=0,c=this.children.length;c>b;b++)this.children[b]._renderWebGL(a);d.stop(),this._mask&&a.maskManager.popMask(this._mask,a),this._filters&&a.filterManager.popFilter(),d.start()}else for(a.spriteBatch.render(this),b=0,c=this.children.length;c>b;b++)this.children[b]._renderWebGL(a)}},b.Sprite.prototype._renderCanvas=function(a){if(!(this.visible===!1||0===this.alpha||this.texture.crop.width<=0||this.texture.crop.height<=0)){if(this.blendMode!==a.currentBlendMode&&(a.currentBlendMode=this.blendMode,a.context.globalCompositeOperation=b.blendModesCanvas[a.currentBlendMode]),this._mask&&a.maskManager.pushMask(this._mask,a),this.texture.valid){var c=this.texture.baseTexture.resolution/a.resolution;a.context.globalAlpha=this.worldAlpha,a.smoothProperty&&a.scaleMode!==this.texture.baseTexture.scaleMode&&(a.scaleMode=this.texture.baseTexture.scaleMode,a.context[a.smoothProperty]=a.scaleMode===b.scaleModes.LINEAR);var d=this.texture.trim?this.texture.trim.x-this.anchor.x*this.texture.trim.width:this.anchor.x*-this.texture.frame.width,e=this.texture.trim?this.texture.trim.y-this.anchor.y*this.texture.trim.height:this.anchor.y*-this.texture.frame.height;a.roundPixels?(a.context.setTransform(this.worldTransform.a,this.worldTransform.b,this.worldTransform.c,this.worldTransform.d,this.worldTransform.tx*a.resolution|0,this.worldTransform.ty*a.resolution|0),d=0|d,e=0|e):a.context.setTransform(this.worldTransform.a,this.worldTransform.b,this.worldTransform.c,this.worldTransform.d,this.worldTransform.tx*a.resolution,this.worldTransform.ty*a.resolution),16777215!==this.tint?(this.cachedTint!==this.tint&&(this.cachedTint=this.tint,this.tintedTexture=b.CanvasTinter.getTintedTexture(this,this.tint)),a.context.drawImage(this.tintedTexture,0,0,this.texture.crop.width,this.texture.crop.height,d/c,e/c,this.texture.crop.width/c,this.texture.crop.height/c)):a.context.drawImage(this.texture.baseTexture.source,this.texture.crop.x,this.texture.crop.y,this.texture.crop.width,this.texture.crop.height,d/c,e/c,this.texture.crop.width/c,this.texture.crop.height/c)}for(var f=0,g=this.children.length;g>f;f++)this.children[f]._renderCanvas(a);this._mask&&a.maskManager.popMask(a)}},b.Sprite.fromFrame=function(a){var c=b.TextureCache[a];if(!c)throw new Error('The frameId "'+a+'" does not exist in the texture cache'+this);return new b.Sprite(c)},b.Sprite.fromImage=function(a,c,d){var e=b.Texture.fromImage(a,c,d);return new b.Sprite(e)},b.SpriteBatch=function(a){b.DisplayObjectContainer.call(this),this.textureThing=a,this.ready=!1},b.SpriteBatch.prototype=Object.create(b.DisplayObjectContainer.prototype),b.SpriteBatch.prototype.constructor=b.SpriteBatch,b.SpriteBatch.prototype.initWebGL=function(a){this.fastSpriteBatch=new b.WebGLFastSpriteBatch(a),this.ready=!0},b.SpriteBatch.prototype.updateTransform=function(){this.displayObjectUpdateTransform()},b.SpriteBatch.prototype._renderWebGL=function(a){!this.visible||this.alpha<=0||!this.children.length||(this.ready||this.initWebGL(a.gl),a.spriteBatch.stop(),a.shaderManager.setShader(a.shaderManager.fastShader),this.fastSpriteBatch.begin(this,a),this.fastSpriteBatch.render(this),a.spriteBatch.start())},b.SpriteBatch.prototype._renderCanvas=function(a){if(this.visible&&!(this.alpha<=0)&&this.children.length){var b=a.context;b.globalAlpha=this.worldAlpha,this.displayObjectUpdateTransform();for(var c=this.worldTransform,d=!0,e=0;e<this.children.length;e++){var f=this.children[e];if(f.visible){var g=f.texture,h=g.frame;if(b.globalAlpha=this.worldAlpha*f.alpha,f.rotation%(2*Math.PI)===0)d&&(b.setTransform(c.a,c.b,c.c,c.d,c.tx,c.ty),d=!1),b.drawImage(g.baseTexture.source,h.x,h.y,h.width,h.height,f.anchor.x*-h.width*f.scale.x+f.position.x+.5|0,f.anchor.y*-h.height*f.scale.y+f.position.y+.5|0,h.width*f.scale.x,h.height*f.scale.y);else{d||(d=!0),f.displayObjectUpdateTransform();var i=f.worldTransform;a.roundPixels?b.setTransform(i.a,i.b,i.c,i.d,0|i.tx,0|i.ty):b.setTransform(i.a,i.b,i.c,i.d,i.tx,i.ty),b.drawImage(g.baseTexture.source,h.x,h.y,h.width,h.height,f.anchor.x*-h.width+.5|0,f.anchor.y*-h.height+.5|0,h.width,h.height)}}}}},b.MovieClip=function(a){b.Sprite.call(this,a[0]),this.textures=a,this.animationSpeed=1,this.loop=!0,this.onComplete=null,this.currentFrame=0,this.playing=!1},b.MovieClip.prototype=Object.create(b.Sprite.prototype),b.MovieClip.prototype.constructor=b.MovieClip,Object.defineProperty(b.MovieClip.prototype,"totalFrames",{get:function(){return this.textures.length}}),b.MovieClip.prototype.stop=function(){this.playing=!1},b.MovieClip.prototype.play=function(){this.playing=!0},b.MovieClip.prototype.gotoAndStop=function(a){this.playing=!1,this.currentFrame=a;var b=this.currentFrame+.5|0;this.setTexture(this.textures[b%this.textures.length])},b.MovieClip.prototype.gotoAndPlay=function(a){this.currentFrame=a,this.playing=!0},b.MovieClip.prototype.updateTransform=function(){if(this.displayObjectContainerUpdateTransform(),this.playing){this.currentFrame+=this.animationSpeed;var a=this.currentFrame+.5|0;this.currentFrame=this.currentFrame%this.textures.length,this.loop||a<this.textures.length?this.setTexture(this.textures[a%this.textures.length]):a>=this.textures.length&&(this.gotoAndStop(this.textures.length-1),this.onComplete&&this.onComplete())}},b.MovieClip.fromFrames=function(a){for(var c=[],d=0;d<a.length;d++)c.push(new b.Texture.fromFrame(a[d]));return new b.MovieClip(c)},b.MovieClip.fromImages=function(a){for(var c=[],d=0;d<a.length;d++)c.push(new b.Texture.fromImage(a[d]));return new b.MovieClip(c)},b.FilterBlock=function(){this.visible=!0,this.renderable=!0},b.FilterBlock.prototype.constructor=b.FilterBlock,b.Text=function(a,c){this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),this.resolution=1,b.Sprite.call(this,b.Texture.fromCanvas(this.canvas)),this.setText(a),this.setStyle(c)},b.Text.prototype=Object.create(b.Sprite.prototype),b.Text.prototype.constructor=b.Text,Object.defineProperty(b.Text.prototype,"width",{get:function(){return this.dirty&&(this.updateText(),this.dirty=!1),this.scale.x*this.texture.frame.width},set:function(a){this.scale.x=a/this.texture.frame.width,this._width=a}}),Object.defineProperty(b.Text.prototype,"height",{get:function(){return this.dirty&&(this.updateText(),this.dirty=!1),this.scale.y*this.texture.frame.height},set:function(a){this.scale.y=a/this.texture.frame.height,this._height=a}}),b.Text.prototype.setStyle=function(a){a=a||{},a.font=a.font||"bold 20pt Arial",a.fill=a.fill||"black",a.align=a.align||"left",a.stroke=a.stroke||"black",a.strokeThickness=a.strokeThickness||0,a.wordWrap=a.wordWrap||!1,a.wordWrapWidth=a.wordWrapWidth||100,a.dropShadow=a.dropShadow||!1,a.dropShadowAngle=a.dropShadowAngle||Math.PI/6,a.dropShadowDistance=a.dropShadowDistance||4,a.dropShadowColor=a.dropShadowColor||"black",this.style=a,this.dirty=!0},b.Text.prototype.setText=function(a){this.text=a.toString()||" ",this.dirty=!0},b.Text.prototype.updateText=function(){this.texture.baseTexture.resolution=this.resolution,this.context.font=this.style.font;var a=this.text;this.style.wordWrap&&(a=this.wordWrap(this.text));for(var b=a.split(/(?:\r\n|\r|\n)/),c=[],d=0,e=this.determineFontProperties(this.style.font),f=0;f<b.length;f++){var g=this.context.measureText(b[f]).width;c[f]=g,d=Math.max(d,g)}var h=d+this.style.strokeThickness;this.style.dropShadow&&(h+=this.style.dropShadowDistance),this.canvas.width=(h+this.context.lineWidth)*this.resolution;var i=e.fontSize+this.style.strokeThickness,j=i*b.length;this.style.dropShadow&&(j+=this.style.dropShadowDistance),this.canvas.height=j*this.resolution,this.context.scale(this.resolution,this.resolution),navigator.isCocoonJS&&this.context.clearRect(0,0,this.canvas.width,this.canvas.height),this.context.font=this.style.font,this.context.strokeStyle=this.style.stroke,this.context.lineWidth=this.style.strokeThickness,this.context.textBaseline="alphabetic";var k,l;if(this.style.dropShadow){this.context.fillStyle=this.style.dropShadowColor;var m=Math.sin(this.style.dropShadowAngle)*this.style.dropShadowDistance,n=Math.cos(this.style.dropShadowAngle)*this.style.dropShadowDistance;for(f=0;f<b.length;f++)k=this.style.strokeThickness/2,l=this.style.strokeThickness/2+f*i+e.ascent,"right"===this.style.align?k+=d-c[f]:"center"===this.style.align&&(k+=(d-c[f])/2),this.style.fill&&this.context.fillText(b[f],k+m,l+n)}for(this.context.fillStyle=this.style.fill,f=0;f<b.length;f++)k=this.style.strokeThickness/2,l=this.style.strokeThickness/2+f*i+e.ascent,"right"===this.style.align?k+=d-c[f]:"center"===this.style.align&&(k+=(d-c[f])/2),this.style.stroke&&this.style.strokeThickness&&this.context.strokeText(b[f],k,l),this.style.fill&&this.context.fillText(b[f],k,l);this.updateTexture()},b.Text.prototype.updateTexture=function(){this.texture.baseTexture.width=this.canvas.width,this.texture.baseTexture.height=this.canvas.height,this.texture.crop.width=this.texture.frame.width=this.canvas.width,this.texture.crop.height=this.texture.frame.height=this.canvas.height,this._width=this.canvas.width,this._height=this.canvas.height,this.texture.baseTexture.dirty()},b.Text.prototype._renderWebGL=function(a){this.dirty&&(this.resolution=a.resolution,this.updateText(),this.dirty=!1),b.Sprite.prototype._renderWebGL.call(this,a)},b.Text.prototype._renderCanvas=function(a){this.dirty&&(this.resolution=a.resolution,this.updateText(),this.dirty=!1),b.Sprite.prototype._renderCanvas.call(this,a)},b.Text.prototype.determineFontProperties=function(a){var c=b.Text.fontPropertiesCache[a];if(!c){c={};var d=b.Text.fontPropertiesCanvas,e=b.Text.fontPropertiesContext;e.font=a;var f=Math.ceil(e.measureText("|Mq").width),g=Math.ceil(e.measureText("M").width),h=2*g;g=1.4*g|0,d.width=f,d.height=h,e.fillStyle="#f00",e.fillRect(0,0,f,h),e.font=a,e.textBaseline="alphabetic",e.fillStyle="#000",e.fillText("|MÉq",0,g);var i,j,k=e.getImageData(0,0,f,h).data,l=k.length,m=4*f,n=0,o=!1;for(i=0;g>i;i++){for(j=0;m>j;j+=4)if(255!==k[n+j]){o=!0;break}if(o)break;n+=m}for(c.ascent=g-i,n=l-m,o=!1,i=h;i>g;i--){for(j=0;m>j;j+=4)if(255!==k[n+j]){o=!0;break}if(o)break;n-=m}c.descent=i-g,c.descent+=6,c.fontSize=c.ascent+c.descent,b.Text.fontPropertiesCache[a]=c}return c},b.Text.prototype.wordWrap=function(a){for(var b="",c=a.split("\n"),d=0;d<c.length;d++){for(var e=this.style.wordWrapWidth,f=c[d].split(" "),g=0;g<f.length;g++){var h=this.context.measureText(f[g]).width,i=h+this.context.measureText(" ").width;0===g||i>e?(g>0&&(b+="\n"),b+=f[g],e=this.style.wordWrapWidth-h):(e-=i,b+=" "+f[g])}d<c.length-1&&(b+="\n")}return b},b.Text.prototype.getBounds=function(a){return this.dirty&&(this.updateText(),this.dirty=!1),b.Sprite.prototype.getBounds.call(this,a)},b.Text.prototype.destroy=function(a){this.context=null,this.canvas=null,this.texture.destroy(void 0===a?!0:a)},b.Text.fontPropertiesCache={},b.Text.fontPropertiesCanvas=document.createElement("canvas"),b.Text.fontPropertiesContext=b.Text.fontPropertiesCanvas.getContext("2d"),b.BitmapText=function(a,c){b.DisplayObjectContainer.call(this),this.textWidth=0,this.textHeight=0,this._pool=[],this.setText(a),this.setStyle(c),this.updateText(),this.dirty=!1},b.BitmapText.prototype=Object.create(b.DisplayObjectContainer.prototype),b.BitmapText.prototype.constructor=b.BitmapText,b.BitmapText.prototype.setText=function(a){this.text=a||" ",this.dirty=!0},b.BitmapText.prototype.setStyle=function(a){a=a||{},a.align=a.align||"left",this.style=a;var c=a.font.split(" ");this.fontName=c[c.length-1],this.fontSize=c.length>=2?parseInt(c[c.length-2],10):b.BitmapText.fonts[this.fontName].size,this.dirty=!0,this.tint=a.tint},b.BitmapText.prototype.updateText=function(){for(var a=b.BitmapText.fonts[this.fontName],c=new b.Point,d=null,e=[],f=0,g=[],h=0,i=this.fontSize/a.size,j=0;j<this.text.length;j++){var k=this.text.charCodeAt(j);if(/(?:\r\n|\r|\n)/.test(this.text.charAt(j)))g.push(c.x),f=Math.max(f,c.x),h++,c.x=0,c.y+=a.lineHeight,d=null;else{var l=a.chars[k];l&&(d&&l.kerning[d]&&(c.x+=l.kerning[d]),e.push({texture:l.texture,line:h,charCode:k,position:new b.Point(c.x+l.xOffset,c.y+l.yOffset)}),c.x+=l.xAdvance,d=k)}}g.push(c.x),f=Math.max(f,c.x);var m=[];for(j=0;h>=j;j++){var n=0;"right"===this.style.align?n=f-g[j]:"center"===this.style.align&&(n=(f-g[j])/2),m.push(n)}var o=this.children.length,p=e.length,q=this.tint||16777215;for(j=0;p>j;j++){var r=o>j?this.children[j]:this._pool.pop();r?r.setTexture(e[j].texture):r=new b.Sprite(e[j].texture),r.position.x=(e[j].position.x+m[e[j].line])*i,r.position.y=e[j].position.y*i,r.scale.x=r.scale.y=i,r.tint=q,r.parent||this.addChild(r)}for(;this.children.length>p;){var s=this.getChildAt(this.children.length-1);this._pool.push(s),this.removeChild(s)}this.textWidth=f*i,this.textHeight=(c.y+a.lineHeight)*i},b.BitmapText.prototype.updateTransform=function(){this.dirty&&(this.updateText(),this.dirty=!1),b.DisplayObjectContainer.prototype.updateTransform.call(this)},b.BitmapText.fonts={},b.InteractionData=function(){this.global=new b.Point,this.target=null,this.originalEvent=null},b.InteractionData.prototype.getLocalPosition=function(a,c){var d=a.worldTransform,e=this.global,f=d.a,g=d.c,h=d.tx,i=d.b,j=d.d,k=d.ty,l=1/(f*j+g*-i);return c=c||new b.Point,c.x=j*l*e.x+-g*l*e.y+(k*g-h*j)*l,c.y=f*l*e.y+-i*l*e.x+(-k*f+h*i)*l,c},b.InteractionData.prototype.constructor=b.InteractionData,b.InteractionManager=function(a){this.stage=a,this.mouse=new b.InteractionData,this.touches={},this.tempPoint=new b.Point,this.mouseoverEnabled=!0,this.pool=[],this.interactiveItems=[],this.interactionDOMElement=null,this.onMouseMove=this.onMouseMove.bind(this),this.onMouseDown=this.onMouseDown.bind(this),this.onMouseOut=this.onMouseOut.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this.onTouchStart=this.onTouchStart.bind(this),this.onTouchEnd=this.onTouchEnd.bind(this),this.onTouchMove=this.onTouchMove.bind(this),this.last=0,this.currentCursorStyle="inherit",this.mouseOut=!1,this.resolution=1,this._tempPoint=new b.Point},b.InteractionManager.prototype.constructor=b.InteractionManager,b.InteractionManager.prototype.collectInteractiveSprite=function(a,b){for(var c=a.children,d=c.length,e=d-1;e>=0;e--){var f=c[e];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6804
f._interactive?(b.interactiveChildren=!0,this.interactiveItems.push(f),f.children.length>0&&this.collectInteractiveSprite(f,f)):(f.__iParent=null,f.children.length>0&&this.collectInteractiveSprite(f,b))}},b.InteractionManager.prototype.setTarget=function(a){this.target=a,this.resolution=a.resolution,null===this.interactionDOMElement&&this.setTargetDomElement(a.view)},b.InteractionManager.prototype.setTargetDomElement=function(a){this.removeEvents(),window.navigator.msPointerEnabled&&(a.style["-ms-content-zooming"]="none",a.style["-ms-touch-action"]="none"),this.interactionDOMElement=a,a.addEventListener("mousemove",this.onMouseMove,!0),a.addEventListener("mousedown",this.onMouseDown,!0),a.addEventListener("mouseout",this.onMouseOut,!0),a.addEventListener("touchstart",this.onTouchStart,!0),a.addEventListener("touchend",this.onTouchEnd,!0),a.addEventListener("touchmove",this.onTouchMove,!0),window.addEventListener("mouseup",this.onMouseUp,!0)},b.InteractionManager.prototype.removeEvents=function(){this.interactionDOMElement&&(this.interactionDOMElement.style["-ms-content-zooming"]="",this.interactionDOMElement.style["-ms-touch-action"]="",this.interactionDOMElement.removeEventListener("mousemove",this.onMouseMove,!0),this.interactionDOMElement.removeEventListener("mousedown",this.onMouseDown,!0),this.interactionDOMElement.removeEventListener("mouseout",this.onMouseOut,!0),this.interactionDOMElement.removeEventListener("touchstart",this.onTouchStart,!0),this.interactionDOMElement.removeEventListener("touchend",this.onTouchEnd,!0),this.interactionDOMElement.removeEventListener("touchmove",this.onTouchMove,!0),this.interactionDOMElement=null,window.removeEventListener("mouseup",this.onMouseUp,!0))},b.InteractionManager.prototype.update=function(){if(this.target){var a=Date.now(),c=a-this.last;if(c=c*b.INTERACTION_FREQUENCY/1e3,!(1>c)){this.last=a;var d=0;this.dirty&&this.rebuildInteractiveGraph();var e=this.interactiveItems.length,f="inherit",g=!1;for(d=0;e>d;d++){var h=this.interactiveItems[d];h.__hit=this.hitTest(h,this.mouse),this.mouse.target=h,h.__hit&&!g?(h.buttonMode&&(f=h.defaultCursor),h.interactiveChildren||(g=!0),h.__isOver||(h.mouseover&&h.mouseover(this.mouse),h.__isOver=!0)):h.__isOver&&(h.mouseout&&h.mouseout(this.mouse),h.__isOver=!1)}this.currentCursorStyle!==f&&(this.currentCursorStyle=f,this.interactionDOMElement.style.cursor=f)}}},b.InteractionManager.prototype.rebuildInteractiveGraph=function(){this.dirty=!1;for(var a=this.interactiveItems.length,b=0;a>b;b++)this.interactiveItems[b].interactiveChildren=!1;this.interactiveItems=[],this.stage.interactive&&this.interactiveItems.push(this.stage),this.collectInteractiveSprite(this.stage,this.stage)},b.InteractionManager.prototype.onMouseMove=function(a){this.dirty&&this.rebuildInteractiveGraph(),this.mouse.originalEvent=a;var b=this.interactionDOMElement.getBoundingClientRect();this.mouse.global.x=(a.clientX-b.left)*(this.target.width/b.width)/this.resolution,this.mouse.global.y=(a.clientY-b.top)*(this.target.height/b.height)/this.resolution;for(var c=this.interactiveItems.length,d=0;c>d;d++){var e=this.interactiveItems[d];e.mousemove&&e.mousemove(this.mouse)}},b.InteractionManager.prototype.onMouseDown=function(a){this.dirty&&this.rebuildInteractiveGraph(),this.mouse.originalEvent=a,b.AUTO_PREVENT_DEFAULT&&this.mouse.originalEvent.preventDefault();for(var c=this.interactiveItems.length,d=this.mouse.originalEvent,e=2===d.button||3===d.which,f=e?"rightdown":"mousedown",g=e?"rightclick":"click",h=e?"__rightIsDown":"__mouseIsDown",i=e?"__isRightDown":"__isDown",j=0;c>j;j++){var k=this.interactiveItems[j];if((k[f]||k[g])&&(k[h]=!0,k.__hit=this.hitTest(k,this.mouse),k.__hit&&(k[f]&&k[f](this.mouse),k[i]=!0,!k.interactiveChildren)))break}},b.InteractionManager.prototype.onMouseOut=function(a){this.dirty&&this.rebuildInteractiveGraph(),this.mouse.originalEvent=a;var b=this.interactiveItems.length;this.interactionDOMElement.style.cursor="inherit";for(var c=0;b>c;c++){var d=this.interactiveItems[c];d.__isOver&&(this.mouse.target=d,d.mouseout&&d.mouseout(this.mouse),d.__isOver=!1)}this.mouseOut=!0,this.mouse.global.x=-1e4,this.mouse.global.y=-1e4},b.InteractionManager.prototype.onMouseUp=function(a){this.dirty&&this.rebuildInteractiveGraph(),this.mouse.originalEvent=a;for(var b=this.interactiveItems.length,c=!1,d=this.mouse.originalEvent,e=2===d.button||3===d.which,f=e?"rightup":"mouseup",g=e?"rightclick":"click",h=e?"rightupoutside":"mouseupoutside",i=e?"__isRightDown":"__isDown",j=0;b>j;j++){var k=this.interactiveItems[j];(k[g]||k[f]||k[h])&&(k.__hit=this.hitTest(k,this.mouse),k.__hit&&!c?(k[f]&&k[f](this.mouse),k[i]&&k[g]&&k[g](this.mouse),k.interactiveChildren||(c=!0)):k[i]&&k[h]&&k[h](this.mouse),k[i]=!1)}},b.InteractionManager.prototype.hitTest=function(a,c){var d=c.global;if(!a.worldVisible)return!1;a.worldTransform.applyInverse(d,this._tempPoint);var e,f=this._tempPoint.x,g=this._tempPoint.y;if(c.target=a,a.hitArea&&a.hitArea.contains)return a.hitArea.contains(f,g);if(a instanceof b.Sprite){var h,i=a.texture.frame.width,j=a.texture.frame.height,k=-i*a.anchor.x;if(f>k&&k+i>f&&(h=-j*a.anchor.y,g>h&&h+j>g))return!0}else if(a instanceof b.Graphics){var l=a.graphicsData;for(e=0;e<l.length;e++){var m=l[e];if(m.fill&&m.shape&&m.shape.contains(f,g))return!0}}var n=a.children.length;for(e=0;n>e;e++){var o=a.children[e],p=this.hitTest(o,c);if(p)return c.target=a,!0}return!1},b.InteractionManager.prototype.onTouchMove=function(a){this.dirty&&this.rebuildInteractiveGraph();var b,c=this.interactionDOMElement.getBoundingClientRect(),d=a.changedTouches,e=0;for(e=0;e<d.length;e++){var f=d[e];b=this.touches[f.identifier],b.originalEvent=a,b.global.x=(f.clientX-c.left)*(this.target.width/c.width)/this.resolution,b.global.y=(f.clientY-c.top)*(this.target.height/c.height)/this.resolution,!navigator.isCocoonJS||c.left||c.top||a.target.style.width||a.target.style.height||(b.global.x=f.clientX,b.global.y=f.clientY);for(var g=0;g<this.interactiveItems.length;g++){var h=this.interactiveItems[g];h.touchmove&&h.__touchData&&h.__touchData[f.identifier]&&h.touchmove(b)}}},b.InteractionManager.prototype.onTouchStart=function(a){this.dirty&&this.rebuildInteractiveGraph();var c=this.interactionDOMElement.getBoundingClientRect();b.AUTO_PREVENT_DEFAULT&&a.preventDefault();for(var d=a.changedTouches,e=0;e<d.length;e++){var f=d[e],g=this.pool.pop();g||(g=new b.InteractionData),g.originalEvent=a,this.touches[f.identifier]=g,g.global.x=(f.clientX-c.left)*(this.target.width/c.width)/this.resolution,g.global.y=(f.clientY-c.top)*(this.target.height/c.height)/this.resolution,!navigator.isCocoonJS||c.left||c.top||a.target.style.width||a.target.style.height||(g.global.x=f.clientX,g.global.y=f.clientY);for(var h=this.interactiveItems.length,i=0;h>i;i++){var j=this.interactiveItems[i];if((j.touchstart||j.tap)&&(j.__hit=this.hitTest(j,g),j.__hit&&(j.touchstart&&j.touchstart(g),j.__isDown=!0,j.__touchData=j.__touchData||{},j.__touchData[f.identifier]=g,!j.interactiveChildren)))break}}},b.InteractionManager.prototype.onTouchEnd=function(a){this.dirty&&this.rebuildInteractiveGraph();for(var b=this.interactionDOMElement.getBoundingClientRect(),c=a.changedTouches,d=0;d<c.length;d++){var e=c[d],f=this.touches[e.identifier],g=!1;f.global.x=(e.clientX-b.left)*(this.target.width/b.width)/this.resolution,f.global.y=(e.clientY-b.top)*(this.target.height/b.height)/this.resolution,!navigator.isCocoonJS||b.left||b.top||a.target.style.width||a.target.style.height||(f.global.x=e.clientX,f.global.y=e.clientY);for(var h=this.interactiveItems.length,i=0;h>i;i++){var j=this.interactiveItems[i];j.__touchData&&j.__touchData[e.identifier]&&(j.__hit=this.hitTest(j,j.__touchData[e.identifier]),f.originalEvent=a,(j.touchend||j.tap)&&(j.__hit&&!g?(j.touchend&&j.touchend(f),j.__isDown&&j.tap&&j.tap(f),j.interactiveChildren||(g=!0)):j.__isDown&&j.touchendoutside&&j.touchendoutside(f),j.__isDown=!1),j.__touchData[e.identifier]=null)}this.pool.push(f),this.touches[e.identifier]=null}},b.Stage=function(a){b.DisplayObjectContainer.call(this),this.worldTransform=new b.Matrix,this.interactive=!0,this.interactionManager=new b.InteractionManager(this),this.dirty=!0,this.stage=this,this.stage.hitArea=new b.Rectangle(0,0,1e5,1e5),this.setBackgroundColor(a)},b.Stage.prototype=Object.create(b.DisplayObjectContainer.prototype),b.Stage.prototype.constructor=b.Stage,b.Stage.prototype.setInteractionDelegate=function(a){this.interactionManager.setTargetDomElement(a)},b.Stage.prototype.updateTransform=function(){this.worldAlpha=1;for(var a=0,b=this.children.length;b>a;a++)this.children[a].updateTransform();this.dirty&&(this.dirty=!1,this.interactionManager.dirty=!0),this.interactive&&this.interactionManager.update()},b.Stage.prototype.setBackgroundColor=function(a){this.backgroundColor=a||0,this.backgroundColorSplit=b.hex2rgb(this.backgroundColor);var c=this.backgroundColor.toString(16);c="000000".substr(0,6-c.length)+c,this.backgroundColorString="#"+c},b.Stage.prototype.getMousePosition=function(){return this.interactionManager.mouse.global},function(a){for(var b=0,c=["ms","moz","webkit","o"],d=0;d<c.length&&!a.requestAnimationFrame;++d)a.requestAnimationFrame=a[c[d]+"RequestAnimationFrame"],a.cancelAnimationFrame=a[c[d]+"CancelAnimationFrame"]||a[c[d]+"CancelRequestAnimationFrame"];a.requestAnimationFrame||(a.requestAnimationFrame=function(c){var d=(new Date).getTime(),e=Math.max(0,16-(d-b)),f=a.setTimeout(function(){c(d+e)},e);return b=d+e,f}),a.cancelAnimationFrame||(a.cancelAnimationFrame=function(a){clearTimeout(a)}),a.requestAnimFrame=a.requestAnimationFrame}(this),b.hex2rgb=function(a){return[(a>>16&255)/255,(a>>8&255)/255,(255&a)/255]},b.rgb2hex=function(a){return(255*a[0]<<16)+(255*a[1]<<8)+255*a[2]},"function"!=typeof Function.prototype.bind&&(Function.prototype.bind=function(){return function(a){function b(){for(var d=arguments.length,f=new Array(d);d--;)f[d]=arguments[d];return f=e.concat(f),c.apply(this instanceof b?this:a,f)}var c=this,d=arguments.length-1,e=[];if(d>0)for(e.length=d;d--;)e[d]=arguments[d+1];if("function"!=typeof c)throw new TypeError;return b.prototype=function f(a){return a&&(f.prototype=a),this instanceof f?void 0:new f}(c.prototype),b}}()),b.AjaxRequest=function(){var a=["Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.3.0","Microsoft.XMLHTTP"];if(!window.ActiveXObject)return window.XMLHttpRequest?new window.XMLHttpRequest:!1;for(var b=0;b<a.length;b++)try{return new window.ActiveXObject(a[b])}catch(c){}},b.canUseNewCanvasBlendModes=function(){if("undefined"==typeof document)return!1;var a=document.createElement("canvas");a.width=1,a.height=1;var b=a.getContext("2d");return b.fillStyle="#000",b.fillRect(0,0,1,1),b.globalCompositeOperation="multiply",b.fillStyle="#fff",b.fillRect(0,0,1,1),0===b.getImageData(0,0,1,1).data[0]},b.getNextPowerOfTwo=function(a){if(a>0&&0===(a&a-1))return a;for(var b=1;a>b;)b<<=1;return b},b.isPowerOfTwo=function(a,b){return a>0&&0===(a&a-1)&&b>0&&0===(b&b-1)},b.EventTarget={call:function(a){a&&(a=a.prototype||a,b.EventTarget.mixin(a))},mixin:function(a){a.listeners=function(a){return this._listeners=this._listeners||{},this._listeners[a]?this._listeners[a].slice():[]},a.emit=a.dispatchEvent=function(a,c){if(this._listeners=this._listeners||{},"object"==typeof a&&(c=a,a=a.type),c&&c.__isEventObject===!0||(c=new b.Event(this,a,c)),this._listeners&&this._listeners[a]){var d,e=this._listeners[a].slice(0),f=e.length,g=e[0];for(d=0;f>d;g=e[++d])if(g.call(this,c),c.stoppedImmediate)return this;if(c.stopped)return this}return this.parent&&this.parent.emit&&this.parent.emit.call(this.parent,a,c),this},a.on=a.addEventListener=function(a,b){return this._listeners=this._listeners||{},(this._listeners[a]=this._listeners[a]||[]).push(b),this},a.once=function(a,b){function c(){b.apply(d.off(a,c),arguments)}this._listeners=this._listeners||{};var d=this;return c._originalHandler=b,this.on(a,c)},a.off=a.removeEventListener=function(a,b){if(this._listeners=this._listeners||{},!this._listeners[a])return this;for(var c=this._listeners[a],d=b?c.length:0;d-->0;)(c[d]===b||c[d]._originalHandler===b)&&c.splice(d,1);return 0===c.length&&delete this._listeners[a],this},a.removeAllListeners=function(a){return this._listeners=this._listeners||{},this._listeners[a]?(delete this._listeners[a],this):this}}},b.Event=function(a,b,c){this.__isEventObject=!0,this.stopped=!1,this.stoppedImmediate=!1,this.target=a,this.type=b,this.data=c,this.content=c,this.timeStamp=Date.now()},b.Event.prototype.stopPropagation=function(){this.stopped=!0},b.Event.prototype.stopImmediatePropagation=function(){this.stoppedImmediate=!0},b.autoDetectRenderer=function(a,c,d){a||(a=800),c||(c=600);var e=function(){try{var a=document.createElement("canvas");return!!window.WebGLRenderingContext&&(a.getContext("webgl")||a.getContext("experimental-webgl"))}catch(b){return!1}}();return e?new b.WebGLRenderer(a,c,d):new b.CanvasRenderer(a,c,d)},b.autoDetectRecommendedRenderer=function(a,c,d){a||(a=800),c||(c=600);var e=function(){try{var a=document.createElement("canvas");return!!window.WebGLRenderingContext&&(a.getContext("webgl")||a.getContext("experimental-webgl"))}catch(b){return!1}}(),f=/Android/i.test(navigator.userAgent);return e&&!f?new b.WebGLRenderer(a,c,d):new b.CanvasRenderer(a,c,d)},b.PolyK={},b.PolyK.Triangulate=function(a){var c=!0,d=a.length>>1;if(3>d)return[];for(var e=[],f=[],g=0;d>g;g++)f.push(g);g=0;for(var h=d;h>3;){var i=f[(g+0)%h],j=f[(g+1)%h],k=f[(g+2)%h],l=a[2*i],m=a[2*i+1],n=a[2*j],o=a[2*j+1],p=a[2*k],q=a[2*k+1],r=!1;if(b.PolyK._convex(l,m,n,o,p,q,c)){r=!0;for(var s=0;h>s;s++){var t=f[s];if(t!==i&&t!==j&&t!==k&&b.PolyK._PointInTriangle(a[2*t],a[2*t+1],l,m,n,o,p,q)){r=!1;break}}}if(r)e.push(i,j,k),f.splice((g+1)%h,1),h--,g=0;else if(g++>3*h){if(!c)return null;for(e=[],f=[],g=0;d>g;g++)f.push(g);g=0,h=d,c=!1}}return e.push(f[0],f[1],f[2]),e},b.PolyK._PointInTriangle=function(a,b,c,d,e,f,g,h){var i=g-c,j=h-d,k=e-c,l=f-d,m=a-c,n=b-d,o=i*i+j*j,p=i*k+j*l,q=i*m+j*n,r=k*k+l*l,s=k*m+l*n,t=1/(o*r-p*p),u=(r*q-p*s)*t,v=(o*s-p*q)*t;return u>=0&&v>=0&&1>u+v},b.PolyK._convex=function(a,b,c,d,e,f,g){return(b-d)*(e-c)+(c-a)*(f-d)>=0===g},b.initDefaultShaders=function(){},b.CompileVertexShader=function(a,c){return b._CompileShader(a,c,a.VERTEX_SHADER)},b.CompileFragmentShader=function(a,c){return b._CompileShader(a,c,a.FRAGMENT_SHADER)},b._CompileShader=function(a,b,c){var d=b.join("\n"),e=a.createShader(c);return a.shaderSource(e,d),a.compileShader(e),a.getShaderParameter(e,a.COMPILE_STATUS)?e:(window.console.log(a.getShaderInfoLog(e)),null)},b.compileProgram=function(a,c,d){var e=b.CompileFragmentShader(a,d),f=b.CompileVertexShader(a,c),g=a.createProgram();return a.attachShader(g,f),a.attachShader(g,e),a.linkProgram(g),a.getProgramParameter(g,a.LINK_STATUS)||window.console.log("Could not initialise shaders"),g},b.PixiShader=function(a){this._UID=b._UID++,this.gl=a,this.program=null,this.fragmentSrc=["precision lowp float;","varying vec2 vTextureCoord;","varying vec4 vColor;","uniform sampler2D uSampler;","void main(void) {","   gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;","}"],this.textureCount=0,this.firstRun=!0,this.dirty=!0,this.attributes=[],this.init()},b.PixiShader.prototype.constructor=b.PixiShader,b.PixiShader.prototype.init=function(){var a=this.gl,c=b.compileProgram(a,this.vertexSrc||b.PixiShader.defaultVertexSrc,this.fragmentSrc);a.useProgram(c),this.uSampler=a.getUniformLocation(c,"uSampler"),this.projectionVector=a.getUniformLocation(c,"projectionVector"),this.offsetVector=a.getUniformLocation(c,"offsetVector"),this.dimensions=a.getUniformLocation(c,"dimensions"),this.aVertexPosition=a.getAttribLocation(c,"aVertexPosition"),this.aTextureCoord=a.getAttribLocation(c,"aTextureCoord"),this.colorAttribute=a.getAttribLocation(c,"aColor"),-1===this.colorAttribute&&(this.colorAttribute=2),this.attributes=[this.aVertexPosition,this.aTextureCoord,this.colorAttribute];for(var d in this.uniforms)this.uniforms[d].uniformLocation=a.getUniformLocation(c,d);this.initUniforms(),this.program=c},b.PixiShader.prototype.initUniforms=function(){this.textureCount=1;var a,b=this.gl;for(var c in this.uniforms){a=this.uniforms[c];var d=a.type;"sampler2D"===d?(a._init=!1,null!==a.value&&this.initSampler2D(a)):"mat2"===d||"mat3"===d||"mat4"===d?(a.glMatrix=!0,a.glValueLength=1,"mat2"===d?a.glFunc=b.uniformMatrix2fv:"mat3"===d?a.glFunc=b.uniformMatrix3fv:"mat4"===d&&(a.glFunc=b.uniformMatrix4fv)):(a.glFunc=b["uniform"+d],a.glValueLength="2f"===d||"2i"===d?2:"3f"===d||"3i"===d?3:"4f"===d||"4i"===d?4:1)}},b.PixiShader.prototype.initSampler2D=function(a){if(a.value&&a.value.baseTexture&&a.value.baseTexture.hasLoaded){var b=this.gl;if(b.activeTexture(b["TEXTURE"+this.textureCount]),b.bindTexture(b.TEXTURE_2D,a.value.baseTexture._glTextures[b.id]),a.textureData){var c=a.textureData,d=c.magFilter?c.magFilter:b.LINEAR,e=c.minFilter?c.minFilter:b.LINEAR,f=c.wrapS?c.wrapS:b.CLAMP_TO_EDGE,g=c.wrapT?c.wrapT:b.CLAMP_TO_EDGE,h=c.luminance?b.LUMINANCE:b.RGBA;if(c.repeat&&(f=b.REPEAT,g=b.REPEAT),b.pixelStorei(b.UNPACK_FLIP_Y_WEBGL,!!c.flipY),c.width){var i=c.width?c.width:512,j=c.height?c.height:2,k=c.border?c.border:0;b.texImage2D(b.TEXTURE_2D,0,h,i,j,k,h,b.UNSIGNED_BYTE,null)}else b.texImage2D(b.TEXTURE_2D,0,h,b.RGBA,b.UNSIGNED_BYTE,a.value.baseTexture.source);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,d),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,e),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,f),b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,g)}b.uniform1i(a.uniformLocation,this.textureCount),a._init=!0,this.textureCount++}},b.PixiShader.prototype.syncUniforms=function(){this.textureCount=1;var a,c=this.gl;for(var d in this.uniforms)a=this.uniforms[d],1===a.glValueLength?a.glMatrix===!0?a.glFunc.call(c,a.uniformLocation,a.transpose,a.value):a.glFunc.call(c,a.uniformLocation,a.value):2===a.glValueLength?a.glFunc.call(c,a.uniformLocation,a.value.x,a.value.y):3===a.glValueLength?a.glFunc.call(c,a.uniformLocation,a.value.x,a.value.y,a.value.z):4===a.glValueLength?a.glFunc.call(c,a.uniformLocation,a.value.x,a.value.y,a.value.z,a.value.w):"sampler2D"===a.type&&(a._init?(c.activeTexture(c["TEXTURE"+this.textureCount]),a.value.baseTexture._dirty[c.id]?b.instances[c.id].updateTexture(a.value.baseTexture):c.bindTexture(c.TEXTURE_2D,a.value.baseTexture._glTextures[c.id]),c.uniform1i(a.uniformLocation,this.textureCount),this.textureCount++):this.initSampler2D(a))},b.PixiShader.prototype.destroy=function(){this.gl.deleteProgram(this.program),this.uniforms=null,this.gl=null,this.attributes=null},b.PixiShader.defaultVertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","attribute vec4 aColor;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","varying vec2 vTextureCoord;","varying vec4 vColor;","const vec2 center = vec2(-1.0, 1.0);","void main(void) {","   gl_Position = vec4( ((aVertexPosition + offsetVector) / projectionVector) + center , 0.0, 1.0);","   vTextureCoord = aTextureCoord;","   vColor = vec4(aColor.rgb * aColor.a, aColor.a);","}"],b.PixiFastShader=function(a){this._UID=b._UID++,this.gl=a,this.program=null,this.fragmentSrc=["precision lowp float;","varying vec2 vTextureCoord;","varying float vColor;","uniform sampler2D uSampler;","void main(void) {","   gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aPositionCoord;","attribute vec2 aScale;","attribute float aRotation;","attribute vec2 aTextureCoord;","attribute float aColor;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","uniform mat3 uMatrix;","varying vec2 vTextureCoord;","varying float vColor;","const vec2 center = vec2(-1.0, 1.0);","void main(void) {","   vec2 v;","   vec2 sv = aVertexPosition * aScale;","   v.x = (sv.x) * cos(aRotation) - (sv.y) * sin(aRotation);","   v.y = (sv.x) * sin(aRotation) + (sv.y) * cos(aRotation);","   v = ( uMatrix * vec3(v + aPositionCoord , 1.0) ).xy ;","   gl_Position = vec4( ( v / projectionVector) + center , 0.0, 1.0);","   vTextureCoord = aTextureCoord;","   vColor = aColor;","}"],this.textureCount=0,this.init()},b.PixiFastShader.prototype.constructor=b.PixiFastShader,b.PixiFastShader.prototype.init=function(){var a=this.gl,c=b.compileProgram(a,this.vertexSrc,this.fragmentSrc);a.useProgram(c),this.uSampler=a.getUniformLocation(c,"uSampler"),this.projectionVector=a.getUniformLocation(c,"projectionVector"),this.offsetVector=a.getUniformLocation(c,"offsetVector"),this.dimensions=a.getUniformLocation(c,"dimensions"),this.uMatrix=a.getUniformLocation(c,"uMatrix"),this.aVertexPosition=a.getAttribLocation(c,"aVertexPosition"),this.aPositionCoord=a.getAttribLocation(c,"aPositionCoord"),this.aScale=a.getAttribLocation(c,"aScale"),this.aRotation=a.getAttribLocation(c,"aRotation"),this.aTextureCoord=a.getAttribLocation(c,"aTextureCoord"),this.colorAttribute=a.getAttribLocation(c,"aColor"),-1===this.colorAttribute&&(this.colorAttribute=2),this.attributes=[this.aVertexPosition,this.aPositionCoord,this.aScale,this.aRotation,this.aTextureCoord,this.colorAttribute],this.program=c},b.PixiFastShader.prototype.destroy=function(){this.gl.deleteProgram(this.program),this.uniforms=null,this.gl=null,this.attributes=null},b.StripShader=function(a){this._UID=b._UID++,this.gl=a,this.program=null,this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","uniform float alpha;","uniform sampler2D uSampler;","void main(void) {","   gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y)) * alpha;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec2 aTextureCoord;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","varying vec2 vTextureCoord;","void main(void) {","   vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);","   v -= offsetVector.xyx;","   gl_Position = vec4( v.x / projectionVector.x -1.0, v.y / -projectionVector.y + 1.0 , 0.0, 1.0);","   vTextureCoord = aTextureCoord;","}"],this.init()},b.StripShader.prototype.constructor=b.StripShader,b.StripShader.prototype.init=function(){var a=this.gl,c=b.compileProgram(a,this.vertexSrc,this.fragmentSrc);a.useProgram(c),this.uSampler=a.getUniformLocation(c,"uSampler"),this.projectionVector=a.getUniformLocation(c,"projectionVector"),this.offsetVector=a.getUniformLocation(c,"offsetVector"),this.colorAttribute=a.getAttribLocation(c,"aColor"),this.aVertexPosition=a.getAttribLocation(c,"aVertexPosition"),this.aTextureCoord=a.getAttribLocation(c,"aTextureCoord"),this.attributes=[this.aVertexPosition,this.aTextureCoord],this.translationMatrix=a.getUniformLocation(c,"translationMatrix"),this.alpha=a.getUniformLocation(c,"alpha"),this.program=c},b.StripShader.prototype.destroy=function(){this.gl.deleteProgram(this.program),this.uniforms=null,this.gl=null,this.attribute=null},b.PrimitiveShader=function(a){this._UID=b._UID++,this.gl=a,this.program=null,this.fragmentSrc=["precision mediump float;","varying vec4 vColor;","void main(void) {","   gl_FragColor = vColor;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","attribute vec4 aColor;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","uniform float alpha;","uniform float flipY;","uniform vec3 tint;","varying vec4 vColor;","void main(void) {","   vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);","   v -= offsetVector.xyx;","   gl_Position = vec4( v.x / projectionVector.x -1.0, (v.y / projectionVector.y * -flipY) + flipY , 0.0, 1.0);","   vColor = aColor * vec4(tint * alpha, alpha);","}"],this.init()},b.PrimitiveShader.prototype.constructor=b.PrimitiveShader,b.PrimitiveShader.prototype.init=function(){var a=this.gl,c=b.compileProgram(a,this.vertexSrc,this.fragmentSrc);a.useProgram(c),this.projectionVector=a.getUniformLocation(c,"projectionVector"),this.offsetVector=a.getUniformLocation(c,"offsetVector"),this.tintColor=a.getUniformLocation(c,"tint"),this.flipY=a.getUniformLocation(c,"flipY"),this.aVertexPosition=a.getAttribLocation(c,"aVertexPosition"),this.colorAttribute=a.getAttribLocation(c,"aColor"),this.attributes=[this.aVertexPosition,this.colorAttribute],this.translationMatrix=a.getUniformLocation(c,"translationMatrix"),this.alpha=a.getUniformLocation(c,"alpha"),this.program=c},b.PrimitiveShader.prototype.destroy=function(){this.gl.deleteProgram(this.program),this.uniforms=null,this.gl=null,this.attributes=null},b.ComplexPrimitiveShader=function(a){this._UID=b._UID++,this.gl=a,this.program=null,this.fragmentSrc=["precision mediump float;","varying vec4 vColor;","void main(void) {","   gl_FragColor = vColor;","}"],this.vertexSrc=["attribute vec2 aVertexPosition;","uniform mat3 translationMatrix;","uniform vec2 projectionVector;","uniform vec2 offsetVector;","uniform vec3 tint;","uniform float alpha;","uniform vec3 color;","uniform float flipY;","varying vec4 vColor;","void main(void) {","   vec3 v = translationMatrix * vec3(aVertexPosition , 1.0);","   v -= offsetVector.xyx;","   gl_Position = vec4( v.x / projectionVector.x -1.0, (v.y / projectionVector.y * -flipY) + flipY , 0.0, 1.0);","   vColor = vec4(color * alpha * tint, alpha);","}"],this.init()},b.ComplexPrimitiveShader.prototype.constructor=b.ComplexPrimitiveShader,b.ComplexPrimitiveShader.prototype.init=function(){var a=this.gl,c=b.compileProgram(a,this.vertexSrc,this.fragmentSrc);a.useProgram(c),this.projectionVector=a.getUniformLocation(c,"projectionVector"),this.offsetVector=a.getUniformLocation(c,"offsetVector"),this.tintColor=a.getUniformLocation(c,"tint"),this.color=a.getUniformLocation(c,"color"),this.flipY=a.getUniformLocation(c,"flipY"),this.aVertexPosition=a.getAttribLocation(c,"aVertexPosition"),this.attributes=[this.aVertexPosition,this.colorAttribute],this.translationMatrix=a.getUniformLocation(c,"translationMatrix"),this.alpha=a.getUniformLocation(c,"alpha"),this.program=c},b.ComplexPrimitiveShader.prototype.destroy=function(){this.gl.deleteProgram(this.program),this.uniforms=null,this.gl=null,this.attribute=null},b.WebGLGraphics=function(){},b.WebGLGraphics.renderGraphics=function(a,c){var d,e=c.gl,f=c.projection,g=c.offset,h=c.shaderManager.primitiveShader;a.dirty&&b.WebGLGraphics.updateGraphics(a,e);for(var i=a._webGL[e.id],j=0;j<i.data.length;j++)1===i.data[j].mode?(d=i.data[j],c.stencilManager.pushStencil(a,d,c),e.drawElements(e.TRIANGLE_FAN,4,e.UNSIGNED_SHORT,2*(d.indices.length-4)),c.stencilManager.popStencil(a,d,c)):(d=i.data[j],c.shaderManager.setShader(h),h=c.shaderManager.primitiveShader,e.uniformMatrix3fv(h.translationMatrix,!1,a.worldTransform.toArray(!0)),e.uniform1f(h.flipY,1),e.uniform2f(h.projectionVector,f.x,-f.y),e.uniform2f(h.offsetVector,-g.x,-g.y),e.uniform3fv(h.tintColor,b.hex2rgb(a.tint)),e.uniform1f(h.alpha,a.worldAlpha),e.bindBuffer(e.ARRAY_BUFFER,d.buffer),e.vertexAttribPointer(h.aVertexPosition,2,e.FLOAT,!1,24,0),e.vertexAttribPointer(h.colorAttribute,4,e.FLOAT,!1,24,8),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,d.indexBuffer),e.drawElements(e.TRIANGLE_STRIP,d.indices.length,e.UNSIGNED_SHORT,0))},b.WebGLGraphics.updateGraphics=function(a,c){var d=a._webGL[c.id];d||(d=a._webGL[c.id]={lastIndex:0,data:[],gl:c}),a.dirty=!1;var e;if(a.clearDirty){for(a.clearDirty=!1,e=0;e<d.data.length;e++){var f=d.data[e];f.reset(),b.WebGLGraphics.graphicsDataPool.push(f)}d.data=[],d.lastIndex=0}var g;for(e=d.lastIndex;e<a.graphicsData.length;e++){var h=a.graphicsData[e];if(h.type===b.Graphics.POLY){if(h.points=h.shape.points.slice(),h.shape.closed&&(h.points[0]!==h.points[h.points.length-2]||h.points[1]!==h.points[h.points.length-1])&&h.points.push(h.points[0],h.points[1]),h.fill&&h.points.length>=6)if(h.points.length<12){g=b.WebGLGraphics.switchMode(d,0);var i=b.WebGLGraphics.buildPoly(h,g);i||(g=b.WebGLGraphics.switchMode(d,1),b.WebGLGraphics.buildComplexPoly(h,g))}else g=b.WebGLGraphics.switchMode(d,1),b.WebGLGraphics.buildComplexPoly(h,g);h.lineWidth>0&&(g=b.WebGLGraphics.switchMode(d,0),b.WebGLGraphics.buildLine(h,g))}else g=b.WebGLGraphics.switchMode(d,0),h.type===b.Graphics.RECT?b.WebGLGraphics.buildRectangle(h,g):h.type===b.Graphics.CIRC||h.type===b.Graphics.ELIP?b.WebGLGraphics.buildCircle(h,g):h.type===b.Graphics.RREC&&b.WebGLGraphics.buildRoundedRectangle(h,g);d.lastIndex++}for(e=0;e<d.data.length;e++)g=d.data[e],g.dirty&&g.upload()},b.WebGLGraphics.switchMode=function(a,c){var d;return a.data.length?(d=a.data[a.data.length-1],(d.mode!==c||1===c)&&(d=b.WebGLGraphics.graphicsDataPool.pop()||new b.WebGLGraphicsData(a.gl),d.mode=c,a.data.push(d))):(d=b.WebGLGraphics.graphicsDataPool.pop()||new b.WebGLGraphicsData(a.gl),d.mode=c,a.data.push(d)),d.dirty=!0,d},b.WebGLGraphics.buildRectangle=function(a,c){var d=a.shape,e=d.x,f=d.y,g=d.width,h=d.height;if(a.fill){var i=b.hex2rgb(a.fillColor),j=a.fillAlpha,k=i[0]*j,l=i[1]*j,m=i[2]*j,n=c.points,o=c.indices,p=n.length/6;n.push(e,f),n.push(k,l,m,j),n.push(e+g,f),n.push(k,l,m,j),n.push(e,f+h),n.push(k,l,m,j),n.push(e+g,f+h),n.push(k,l,m,j),o.push(p,p,p+1,p+2,p+3,p+3)}if(a.lineWidth){var q=a.points;a.points=[e,f,e+g,f,e+g,f+h,e,f+h,e,f],b.WebGLGraphics.buildLine(a,c),a.points=q}},b.WebGLGraphics.buildRoundedRectangle=function(a,c){var d=a.shape,e=d.x,f=d.y,g=d.width,h=d.height,i=d.radius,j=[];if(j.push(e,f+i),j=j.concat(b.WebGLGraphics.quadraticBezierCurve(e,f+h-i,e,f+h,e+i,f+h)),j=j.concat(b.WebGLGraphics.quadraticBezierCurve(e+g-i,f+h,e+g,f+h,e+g,f+h-i)),j=j.concat(b.WebGLGraphics.quadraticBezierCurve(e+g,f+i,e+g,f,e+g-i,f)),j=j.concat(b.WebGLGraphics.quadraticBezierCurve(e+i,f,e,f,e,f+i)),a.fill){var k=b.hex2rgb(a.fillColor),l=a.fillAlpha,m=k[0]*l,n=k[1]*l,o=k[2]*l,p=c.points,q=c.indices,r=p.length/6,s=b.PolyK.Triangulate(j),t=0;for(t=0;t<s.length;t+=3)q.push(s[t]+r),q.push(s[t]+r),q.push(s[t+1]+r),q.push(s[t+2]+r),q.push(s[t+2]+r);for(t=0;t<j.length;t++)p.push(j[t],j[++t],m,n,o,l)}if(a.lineWidth){var u=a.points;a.points=j,b.WebGLGraphics.buildLine(a,c),a.points=u}},b.WebGLGraphics.quadraticBezierCurve=function(a,b,c,d,e,f){function g(a,b,c){var d=b-a;return a+d*c}for(var h,i,j,k,l,m,n=20,o=[],p=0,q=0;n>=q;q++)p=q/n,h=g(a,c,p),i=g(b,d,p),j=g(c,e,p),k=g(d,f,p),l=g(h,j,p),m=g(i,k,p),o.push(l,m);return o},b.WebGLGraphics.buildCircle=function(a,c){var d,e,f=a.shape,g=f.x,h=f.y;a.type===b.Graphics.CIRC?(d=f.radius,e=f.radius):(d=f.width,e=f.height);var i=40,j=2*Math.PI/i,k=0;if(a.fill){var l=b.hex2rgb(a.fillColor),m=a.fillAlpha,n=l[0]*m,o=l[1]*m,p=l[2]*m,q=c.points,r=c.indices,s=q.length/6;for(r.push(s),k=0;i+1>k;k++)q.push(g,h,n,o,p,m),q.push(g+Math.sin(j*k)*d,h+Math.cos(j*k)*e,n,o,p,m),r.push(s++,s++);r.push(s-1)}if(a.lineWidth){var t=a.points;for(a.points=[],k=0;i+1>k;k++)a.points.push(g+Math.sin(j*k)*d,h+Math.cos(j*k)*e);b.WebGLGraphics.buildLine(a,c),a.points=t}},b.WebGLGraphics.buildLine=function(a,c){var d=0,e=a.points;if(0!==e.length){if(a.lineWidth%2)for(d=0;d<e.length;d++)e[d]+=.5;var f=new b.Point(e[0],e[1]),g=new b.Point(e[e.length-2],e[e.length-1]);if(f.x===g.x&&f.y===g.y){e=e.slice(),e.pop(),e.pop(),g=new b.Point(e[e.length-2],e[e.length-1]);var h=g.x+.5*(f.x-g.x),i=g.y+.5*(f.y-g.y);e.unshift(h,i),e.push(h,i)}var j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G=c.points,H=c.indices,I=e.length/2,J=e.length,K=G.length/6,L=a.lineWidth/2,M=b.hex2rgb(a.lineColor),N=a.lineAlpha,O=M[0]*N,P=M[1]*N,Q=M[2]*N;for(l=e[0],m=e[1],n=e[2],o=e[3],r=-(m-o),s=l-n,F=Math.sqrt(r*r+s*s),r/=F,s/=F,r*=L,s*=L,G.push(l-r,m-s,O,P,Q,N),G.push(l+r,m+s,O,P,Q,N),d=1;I-1>d;d++)l=e[2*(d-1)],m=e[2*(d-1)+1],n=e[2*d],o=e[2*d+1],p=e[2*(d+1)],q=e[2*(d+1)+1],r=-(m-o),s=l-n,F=Math.sqrt(r*r+s*s),r/=F,s/=F,r*=L,s*=L,t=-(o-q),u=n-p,F=Math.sqrt(t*t+u*u),t/=F,u/=F,t*=L,u*=L,x=-s+m-(-s+o),y=-r+n-(-r+l),z=(-r+l)*(-s+o)-(-r+n)*(-s+m),A=-u+q-(-u+o),B=-t+n-(-t+p),C=(-t+p)*(-u+o)-(-t+n)*(-u+q),D=x*B-A*y,Math.abs(D)<.1?(D+=10.1,G.push(n-r,o-s,O,P,Q,N),G.push(n+r,o+s,O,P,Q,N)):(j=(y*C-B*z)/D,k=(A*z-x*C)/D,E=(j-n)*(j-n)+(k-o)+(k-o),E>19600?(v=r-t,w=s-u,F=Math.sqrt(v*v+w*w),v/=F,w/=F,v*=L,w*=L,G.push(n-v,o-w),G.push(O,P,Q,N),G.push(n+v,o+w),G.push(O,P,Q,N),G.push(n-v,o-w),G.push(O,P,Q,N),J++):(G.push(j,k),G.push(O,P,Q,N),G.push(n-(j-n),o-(k-o)),G.push(O,P,Q,N)));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6805
for(l=e[2*(I-2)],m=e[2*(I-2)+1],n=e[2*(I-1)],o=e[2*(I-1)+1],r=-(m-o),s=l-n,F=Math.sqrt(r*r+s*s),r/=F,s/=F,r*=L,s*=L,G.push(n-r,o-s),G.push(O,P,Q,N),G.push(n+r,o+s),G.push(O,P,Q,N),H.push(K),d=0;J>d;d++)H.push(K++);H.push(K-1)}},b.WebGLGraphics.buildComplexPoly=function(a,c){var d=a.points.slice();if(!(d.length<6)){var e=c.indices;c.points=d,c.alpha=a.fillAlpha,c.color=b.hex2rgb(a.fillColor);for(var f,g,h=1/0,i=-1/0,j=1/0,k=-1/0,l=0;l<d.length;l+=2)f=d[l],g=d[l+1],h=h>f?f:h,i=f>i?f:i,j=j>g?g:j,k=g>k?g:k;d.push(h,j,i,j,i,k,h,k);var m=d.length/2;for(l=0;m>l;l++)e.push(l)}},b.WebGLGraphics.buildPoly=function(a,c){var d=a.points;if(!(d.length<6)){var e=c.points,f=c.indices,g=d.length/2,h=b.hex2rgb(a.fillColor),i=a.fillAlpha,j=h[0]*i,k=h[1]*i,l=h[2]*i,m=b.PolyK.Triangulate(d);if(!m)return!1;var n=e.length/6,o=0;for(o=0;o<m.length;o+=3)f.push(m[o]+n),f.push(m[o]+n),f.push(m[o+1]+n),f.push(m[o+2]+n),f.push(m[o+2]+n);for(o=0;g>o;o++)e.push(d[2*o],d[2*o+1],j,k,l,i);return!0}},b.WebGLGraphics.graphicsDataPool=[],b.WebGLGraphicsData=function(a){this.gl=a,this.color=[0,0,0],this.points=[],this.indices=[],this.buffer=a.createBuffer(),this.indexBuffer=a.createBuffer(),this.mode=1,this.alpha=1,this.dirty=!0},b.WebGLGraphicsData.prototype.reset=function(){this.points=[],this.indices=[]},b.WebGLGraphicsData.prototype.upload=function(){var a=this.gl;this.glPoints=new b.Float32Array(this.points),a.bindBuffer(a.ARRAY_BUFFER,this.buffer),a.bufferData(a.ARRAY_BUFFER,this.glPoints,a.STATIC_DRAW),this.glIndicies=new b.Uint16Array(this.indices),a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.glIndicies,a.STATIC_DRAW),this.dirty=!1},b.glContexts=[],b.instances=[],b.WebGLRenderer=function(a,c,d){if(d)for(var e in b.defaultRenderOptions)"undefined"==typeof d[e]&&(d[e]=b.defaultRenderOptions[e]);else d=b.defaultRenderOptions;b.defaultRenderer||(b.sayHello("webGL"),b.defaultRenderer=this),this.type=b.WEBGL_RENDERER,this.resolution=d.resolution,this.transparent=d.transparent,this.autoResize=d.autoResize||!1,this.preserveDrawingBuffer=d.preserveDrawingBuffer,this.clearBeforeRender=d.clearBeforeRender,this.width=a||800,this.height=c||600,this.view=d.view||document.createElement("canvas"),this.contextLostBound=this.handleContextLost.bind(this),this.contextRestoredBound=this.handleContextRestored.bind(this),this.view.addEventListener("webglcontextlost",this.contextLostBound,!1),this.view.addEventListener("webglcontextrestored",this.contextRestoredBound,!1),this._contextOptions={alpha:this.transparent,antialias:d.antialias,premultipliedAlpha:this.transparent&&"notMultiplied"!==this.transparent,stencil:!0,preserveDrawingBuffer:d.preserveDrawingBuffer},this.projection=new b.Point,this.offset=new b.Point(0,0),this.shaderManager=new b.WebGLShaderManager,this.spriteBatch=new b.WebGLSpriteBatch,this.maskManager=new b.WebGLMaskManager,this.filterManager=new b.WebGLFilterManager,this.stencilManager=new b.WebGLStencilManager,this.blendModeManager=new b.WebGLBlendModeManager,this.renderSession={},this.renderSession.gl=this.gl,this.renderSession.drawCount=0,this.renderSession.shaderManager=this.shaderManager,this.renderSession.maskManager=this.maskManager,this.renderSession.filterManager=this.filterManager,this.renderSession.blendModeManager=this.blendModeManager,this.renderSession.spriteBatch=this.spriteBatch,this.renderSession.stencilManager=this.stencilManager,this.renderSession.renderer=this,this.renderSession.resolution=this.resolution,this.initContext(),this.mapBlendModes()},b.WebGLRenderer.prototype.constructor=b.WebGLRenderer,b.WebGLRenderer.prototype.initContext=function(){var a=this.view.getContext("webgl",this._contextOptions)||this.view.getContext("experimental-webgl",this._contextOptions);if(this.gl=a,!a)throw new Error("This browser does not support webGL. Try using the canvas renderer");this.glContextId=a.id=b.WebGLRenderer.glContextId++,b.glContexts[this.glContextId]=a,b.instances[this.glContextId]=this,a.disable(a.DEPTH_TEST),a.disable(a.CULL_FACE),a.enable(a.BLEND),this.shaderManager.setContext(a),this.spriteBatch.setContext(a),this.maskManager.setContext(a),this.filterManager.setContext(a),this.blendModeManager.setContext(a),this.stencilManager.setContext(a),this.renderSession.gl=this.gl,this.resize(this.width,this.height)},b.WebGLRenderer.prototype.render=function(a){if(!this.contextLost){this.__stage!==a&&(a.interactive&&a.interactionManager.removeEvents(),this.__stage=a),a.updateTransform();var b=this.gl;a._interactive?a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this)):a._interactiveEventsAdded&&(a._interactiveEventsAdded=!1,a.interactionManager.setTarget(this)),b.viewport(0,0,this.width,this.height),b.bindFramebuffer(b.FRAMEBUFFER,null),this.clearBeforeRender&&(this.transparent?b.clearColor(0,0,0,0):b.clearColor(a.backgroundColorSplit[0],a.backgroundColorSplit[1],a.backgroundColorSplit[2],1),b.clear(b.COLOR_BUFFER_BIT)),this.renderDisplayObject(a,this.projection)}},b.WebGLRenderer.prototype.renderDisplayObject=function(a,c,d){this.renderSession.blendModeManager.setBlendMode(b.blendModes.NORMAL),this.renderSession.drawCount=0,this.renderSession.flipY=d?-1:1,this.renderSession.projection=c,this.renderSession.offset=this.offset,this.spriteBatch.begin(this.renderSession),this.filterManager.begin(this.renderSession,d),a._renderWebGL(this.renderSession),this.spriteBatch.end()},b.WebGLRenderer.prototype.resize=function(a,b){this.width=a*this.resolution,this.height=b*this.resolution,this.view.width=this.width,this.view.height=this.height,this.autoResize&&(this.view.style.width=this.width/this.resolution+"px",this.view.style.height=this.height/this.resolution+"px"),this.gl.viewport(0,0,this.width,this.height),this.projection.x=this.width/2/this.resolution,this.projection.y=-this.height/2/this.resolution},b.WebGLRenderer.prototype.updateTexture=function(a){if(a.hasLoaded){var c=this.gl;return a._glTextures[c.id]||(a._glTextures[c.id]=c.createTexture()),c.bindTexture(c.TEXTURE_2D,a._glTextures[c.id]),c.pixelStorei(c.UNPACK_PREMULTIPLY_ALPHA_WEBGL,a.premultipliedAlpha),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,c.RGBA,c.UNSIGNED_BYTE,a.source),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,a.scaleMode===b.scaleModes.LINEAR?c.LINEAR:c.NEAREST),a.mipmap&&b.isPowerOfTwo(a.width,a.height)?(c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,a.scaleMode===b.scaleModes.LINEAR?c.LINEAR_MIPMAP_LINEAR:c.NEAREST_MIPMAP_NEAREST),c.generateMipmap(c.TEXTURE_2D)):c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,a.scaleMode===b.scaleModes.LINEAR?c.LINEAR:c.NEAREST),a._powerOf2?(c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.REPEAT),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.REPEAT)):(c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE)),a._dirty[c.id]=!1,a._glTextures[c.id]}},b.WebGLRenderer.prototype.handleContextLost=function(a){a.preventDefault(),this.contextLost=!0},b.WebGLRenderer.prototype.handleContextRestored=function(){this.initContext();for(var a in b.TextureCache){var c=b.TextureCache[a].baseTexture;c._glTextures=[]}this.contextLost=!1},b.WebGLRenderer.prototype.destroy=function(){this.view.removeEventListener("webglcontextlost",this.contextLostBound),this.view.removeEventListener("webglcontextrestored",this.contextRestoredBound),b.glContexts[this.glContextId]=null,this.projection=null,this.offset=null,this.shaderManager.destroy(),this.spriteBatch.destroy(),this.maskManager.destroy(),this.filterManager.destroy(),this.shaderManager=null,this.spriteBatch=null,this.maskManager=null,this.filterManager=null,this.gl=null,this.renderSession=null},b.WebGLRenderer.prototype.mapBlendModes=function(){var a=this.gl;b.blendModesWebGL||(b.blendModesWebGL=[],b.blendModesWebGL[b.blendModes.NORMAL]=[a.ONE,a.ONE_MINUS_SRC_ALPHA],b.blendModesWebGL[b.blendModes.ADD]=[a.SRC_ALPHA,a.DST_ALPHA],b.blendModesWebGL[b.blendModes.MULTIPLY]=[a.DST_COLOR,a.ONE_MINUS_SRC_ALPHA],b.blendModesWebGL[b.blendModes.SCREEN]=[a.SRC_ALPHA,a.ONE],b.blendModesWebGL[b.blendModes.OVERLAY]=[a.ONE,a.ONE_MINUS_SRC_ALPHA],b.blendModesWebGL[b.blendModes.DARKEN]=[a.ONE,a.ONE_MINUS_SRC_ALPHA],b.blendModesWebGL[b.blendModes.LIGHTEN]=[a.ONE,a.ONE_MINUS_SRC_ALPHA],b.blendModesWebGL[b.blendModes.COLOR_DODGE]=[a.ONE,a.ONE_MINUS_SRC_ALPHA],b.blendModesWebGL[b.blendModes.COLOR_BURN]=[a.ONE,a.ONE_MINUS_SRC_ALPHA],b.blendModesWebGL[b.blendModes.HARD_LIGHT]=[a.ONE,a.ONE_MINUS_SRC_ALPHA],b.blendModesWebGL[b.blendModes.SOFT_LIGHT]=[a.ONE,a.ONE_MINUS_SRC_ALPHA],b.blendModesWebGL[b.blendModes.DIFFERENCE]=[a.ONE,a.ONE_MINUS_SRC_ALPHA],b.blendModesWebGL[b.blendModes.EXCLUSION]=[a.ONE,a.ONE_MINUS_SRC_ALPHA],b.blendModesWebGL[b.blendModes.HUE]=[a.ONE,a.ONE_MINUS_SRC_ALPHA],b.blendModesWebGL[b.blendModes.SATURATION]=[a.ONE,a.ONE_MINUS_SRC_ALPHA],b.blendModesWebGL[b.blendModes.COLOR]=[a.ONE,a.ONE_MINUS_SRC_ALPHA],b.blendModesWebGL[b.blendModes.LUMINOSITY]=[a.ONE,a.ONE_MINUS_SRC_ALPHA])},b.WebGLRenderer.glContextId=0,b.WebGLBlendModeManager=function(){this.currentBlendMode=99999},b.WebGLBlendModeManager.prototype.constructor=b.WebGLBlendModeManager,b.WebGLBlendModeManager.prototype.setContext=function(a){this.gl=a},b.WebGLBlendModeManager.prototype.setBlendMode=function(a){if(this.currentBlendMode===a)return!1;this.currentBlendMode=a;var c=b.blendModesWebGL[this.currentBlendMode];return this.gl.blendFunc(c[0],c[1]),!0},b.WebGLBlendModeManager.prototype.destroy=function(){this.gl=null},b.WebGLMaskManager=function(){},b.WebGLMaskManager.prototype.constructor=b.WebGLMaskManager,b.WebGLMaskManager.prototype.setContext=function(a){this.gl=a},b.WebGLMaskManager.prototype.pushMask=function(a,c){var d=c.gl;a.dirty&&b.WebGLGraphics.updateGraphics(a,d),a._webGL[d.id].data.length&&c.stencilManager.pushStencil(a,a._webGL[d.id].data[0],c)},b.WebGLMaskManager.prototype.popMask=function(a,b){var c=this.gl;b.stencilManager.popStencil(a,a._webGL[c.id].data[0],b)},b.WebGLMaskManager.prototype.destroy=function(){this.gl=null},b.WebGLStencilManager=function(){this.stencilStack=[],this.reverse=!0,this.count=0},b.WebGLStencilManager.prototype.setContext=function(a){this.gl=a},b.WebGLStencilManager.prototype.pushStencil=function(a,b,c){var d=this.gl;this.bindGraphics(a,b,c),0===this.stencilStack.length&&(d.enable(d.STENCIL_TEST),d.clear(d.STENCIL_BUFFER_BIT),this.reverse=!0,this.count=0),this.stencilStack.push(b);var e=this.count;d.colorMask(!1,!1,!1,!1),d.stencilFunc(d.ALWAYS,0,255),d.stencilOp(d.KEEP,d.KEEP,d.INVERT),1===b.mode?(d.drawElements(d.TRIANGLE_FAN,b.indices.length-4,d.UNSIGNED_SHORT,0),this.reverse?(d.stencilFunc(d.EQUAL,255-e,255),d.stencilOp(d.KEEP,d.KEEP,d.DECR)):(d.stencilFunc(d.EQUAL,e,255),d.stencilOp(d.KEEP,d.KEEP,d.INCR)),d.drawElements(d.TRIANGLE_FAN,4,d.UNSIGNED_SHORT,2*(b.indices.length-4)),this.reverse?d.stencilFunc(d.EQUAL,255-(e+1),255):d.stencilFunc(d.EQUAL,e+1,255),this.reverse=!this.reverse):(this.reverse?(d.stencilFunc(d.EQUAL,e,255),d.stencilOp(d.KEEP,d.KEEP,d.INCR)):(d.stencilFunc(d.EQUAL,255-e,255),d.stencilOp(d.KEEP,d.KEEP,d.DECR)),d.drawElements(d.TRIANGLE_STRIP,b.indices.length,d.UNSIGNED_SHORT,0),this.reverse?d.stencilFunc(d.EQUAL,e+1,255):d.stencilFunc(d.EQUAL,255-(e+1),255)),d.colorMask(!0,!0,!0,!0),d.stencilOp(d.KEEP,d.KEEP,d.KEEP),this.count++},b.WebGLStencilManager.prototype.bindGraphics=function(a,c,d){this._currentGraphics=a;var e,f=this.gl,g=d.projection,h=d.offset;1===c.mode?(e=d.shaderManager.complexPrimitiveShader,d.shaderManager.setShader(e),f.uniform1f(e.flipY,d.flipY),f.uniformMatrix3fv(e.translationMatrix,!1,a.worldTransform.toArray(!0)),f.uniform2f(e.projectionVector,g.x,-g.y),f.uniform2f(e.offsetVector,-h.x,-h.y),f.uniform3fv(e.tintColor,b.hex2rgb(a.tint)),f.uniform3fv(e.color,c.color),f.uniform1f(e.alpha,a.worldAlpha*c.alpha),f.bindBuffer(f.ARRAY_BUFFER,c.buffer),f.vertexAttribPointer(e.aVertexPosition,2,f.FLOAT,!1,8,0),f.bindBuffer(f.ELEMENT_ARRAY_BUFFER,c.indexBuffer)):(e=d.shaderManager.primitiveShader,d.shaderManager.setShader(e),f.uniformMatrix3fv(e.translationMatrix,!1,a.worldTransform.toArray(!0)),f.uniform1f(e.flipY,d.flipY),f.uniform2f(e.projectionVector,g.x,-g.y),f.uniform2f(e.offsetVector,-h.x,-h.y),f.uniform3fv(e.tintColor,b.hex2rgb(a.tint)),f.uniform1f(e.alpha,a.worldAlpha),f.bindBuffer(f.ARRAY_BUFFER,c.buffer),f.vertexAttribPointer(e.aVertexPosition,2,f.FLOAT,!1,24,0),f.vertexAttribPointer(e.colorAttribute,4,f.FLOAT,!1,24,8),f.bindBuffer(f.ELEMENT_ARRAY_BUFFER,c.indexBuffer))},b.WebGLStencilManager.prototype.popStencil=function(a,b,c){var d=this.gl;if(this.stencilStack.pop(),this.count--,0===this.stencilStack.length)d.disable(d.STENCIL_TEST);else{var e=this.count;this.bindGraphics(a,b,c),d.colorMask(!1,!1,!1,!1),1===b.mode?(this.reverse=!this.reverse,this.reverse?(d.stencilFunc(d.EQUAL,255-(e+1),255),d.stencilOp(d.KEEP,d.KEEP,d.INCR)):(d.stencilFunc(d.EQUAL,e+1,255),d.stencilOp(d.KEEP,d.KEEP,d.DECR)),d.drawElements(d.TRIANGLE_FAN,4,d.UNSIGNED_SHORT,2*(b.indices.length-4)),d.stencilFunc(d.ALWAYS,0,255),d.stencilOp(d.KEEP,d.KEEP,d.INVERT),d.drawElements(d.TRIANGLE_FAN,b.indices.length-4,d.UNSIGNED_SHORT,0),this.reverse?d.stencilFunc(d.EQUAL,e,255):d.stencilFunc(d.EQUAL,255-e,255)):(this.reverse?(d.stencilFunc(d.EQUAL,e+1,255),d.stencilOp(d.KEEP,d.KEEP,d.DECR)):(d.stencilFunc(d.EQUAL,255-(e+1),255),d.stencilOp(d.KEEP,d.KEEP,d.INCR)),d.drawElements(d.TRIANGLE_STRIP,b.indices.length,d.UNSIGNED_SHORT,0),this.reverse?d.stencilFunc(d.EQUAL,e,255):d.stencilFunc(d.EQUAL,255-e,255)),d.colorMask(!0,!0,!0,!0),d.stencilOp(d.KEEP,d.KEEP,d.KEEP)}},b.WebGLStencilManager.prototype.destroy=function(){this.stencilStack=null,this.gl=null},b.WebGLShaderManager=function(){this.maxAttibs=10,this.attribState=[],this.tempAttribState=[];for(var a=0;a<this.maxAttibs;a++)this.attribState[a]=!1;this.stack=[]},b.WebGLShaderManager.prototype.constructor=b.WebGLShaderManager,b.WebGLShaderManager.prototype.setContext=function(a){this.gl=a,this.primitiveShader=new b.PrimitiveShader(a),this.complexPrimitiveShader=new b.ComplexPrimitiveShader(a),this.defaultShader=new b.PixiShader(a),this.fastShader=new b.PixiFastShader(a),this.stripShader=new b.StripShader(a),this.setShader(this.defaultShader)},b.WebGLShaderManager.prototype.setAttribs=function(a){var b;for(b=0;b<this.tempAttribState.length;b++)this.tempAttribState[b]=!1;for(b=0;b<a.length;b++){var c=a[b];this.tempAttribState[c]=!0}var d=this.gl;for(b=0;b<this.attribState.length;b++)this.attribState[b]!==this.tempAttribState[b]&&(this.attribState[b]=this.tempAttribState[b],this.tempAttribState[b]?d.enableVertexAttribArray(b):d.disableVertexAttribArray(b))},b.WebGLShaderManager.prototype.setShader=function(a){return this._currentId===a._UID?!1:(this._currentId=a._UID,this.currentShader=a,this.gl.useProgram(a.program),this.setAttribs(a.attributes),!0)},b.WebGLShaderManager.prototype.destroy=function(){this.attribState=null,this.tempAttribState=null,this.primitiveShader.destroy(),this.complexPrimitiveShader.destroy(),this.defaultShader.destroy(),this.fastShader.destroy(),this.stripShader.destroy(),this.gl=null},b.WebGLSpriteBatch=function(){this.vertSize=5,this.size=2e3;var a=4*this.size*4*this.vertSize,c=6*this.size;this.vertices=new b.ArrayBuffer(a),this.positions=new b.Float32Array(this.vertices),this.colors=new b.Uint32Array(this.vertices),this.indices=new b.Uint16Array(c),this.lastIndexCount=0;for(var d=0,e=0;c>d;d+=6,e+=4)this.indices[d+0]=e+0,this.indices[d+1]=e+1,this.indices[d+2]=e+2,this.indices[d+3]=e+0,this.indices[d+4]=e+2,this.indices[d+5]=e+3;this.drawing=!1,this.currentBatchSize=0,this.currentBaseTexture=null,this.dirty=!0,this.textures=[],this.blendModes=[],this.shaders=[],this.sprites=[],this.defaultShader=new b.AbstractFilter(["precision lowp float;","varying vec2 vTextureCoord;","varying vec4 vColor;","uniform sampler2D uSampler;","void main(void) {","   gl_FragColor = texture2D(uSampler, vTextureCoord) * vColor ;","}"])},b.WebGLSpriteBatch.prototype.setContext=function(a){this.gl=a,this.vertexBuffer=a.createBuffer(),this.indexBuffer=a.createBuffer(),a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.indices,a.STATIC_DRAW),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),a.bufferData(a.ARRAY_BUFFER,this.vertices,a.DYNAMIC_DRAW),this.currentBlendMode=99999;var c=new b.PixiShader(a);c.fragmentSrc=this.defaultShader.fragmentSrc,c.uniforms={},c.init(),this.defaultShader.shaders[a.id]=c},b.WebGLSpriteBatch.prototype.begin=function(a){this.renderSession=a,this.shader=this.renderSession.shaderManager.defaultShader,this.start()},b.WebGLSpriteBatch.prototype.end=function(){this.flush()},b.WebGLSpriteBatch.prototype.render=function(a){var b=a.texture;this.currentBatchSize>=this.size&&(this.flush(),this.currentBaseTexture=b.baseTexture);var c=b._uvs;if(c){var d,e,f,g,h=a.anchor.x,i=a.anchor.y;if(b.trim){var j=b.trim;e=j.x-h*j.width,d=e+b.crop.width,g=j.y-i*j.height,f=g+b.crop.height}else d=b.frame.width*(1-h),e=b.frame.width*-h,f=b.frame.height*(1-i),g=b.frame.height*-i;var k=4*this.currentBatchSize*this.vertSize,l=b.baseTexture.resolution,m=a.worldTransform,n=m.a/l,o=m.b/l,p=m.c/l,q=m.d/l,r=m.tx,s=m.ty,t=this.colors,u=this.positions;this.renderSession.roundPixels?(u[k]=n*e+p*g+r|0,u[k+1]=q*g+o*e+s|0,u[k+5]=n*d+p*g+r|0,u[k+6]=q*g+o*d+s|0,u[k+10]=n*d+p*f+r|0,u[k+11]=q*f+o*d+s|0,u[k+15]=n*e+p*f+r|0,u[k+16]=q*f+o*e+s|0):(u[k]=n*e+p*g+r,u[k+1]=q*g+o*e+s,u[k+5]=n*d+p*g+r,u[k+6]=q*g+o*d+s,u[k+10]=n*d+p*f+r,u[k+11]=q*f+o*d+s,u[k+15]=n*e+p*f+r,u[k+16]=q*f+o*e+s),u[k+2]=c.x0,u[k+3]=c.y0,u[k+7]=c.x1,u[k+8]=c.y1,u[k+12]=c.x2,u[k+13]=c.y2,u[k+17]=c.x3,u[k+18]=c.y3;var v=a.tint;t[k+4]=t[k+9]=t[k+14]=t[k+19]=(v>>16)+(65280&v)+((255&v)<<16)+(255*a.worldAlpha<<24),this.sprites[this.currentBatchSize++]=a}},b.WebGLSpriteBatch.prototype.renderTilingSprite=function(a){var c=a.tilingTexture;this.currentBatchSize>=this.size&&(this.flush(),this.currentBaseTexture=c.baseTexture),a._uvs||(a._uvs=new b.TextureUvs);var d=a._uvs;a.tilePosition.x%=c.baseTexture.width*a.tileScaleOffset.x,a.tilePosition.y%=c.baseTexture.height*a.tileScaleOffset.y;var e=a.tilePosition.x/(c.baseTexture.width*a.tileScaleOffset.x),f=a.tilePosition.y/(c.baseTexture.height*a.tileScaleOffset.y),g=a.width/c.baseTexture.width/(a.tileScale.x*a.tileScaleOffset.x),h=a.height/c.baseTexture.height/(a.tileScale.y*a.tileScaleOffset.y);d.x0=0-e,d.y0=0-f,d.x1=1*g-e,d.y1=0-f,d.x2=1*g-e,d.y2=1*h-f,d.x3=0-e,d.y3=1*h-f;var i=a.tint,j=(i>>16)+(65280&i)+((255&i)<<16)+(255*a.alpha<<24),k=this.positions,l=this.colors,m=a.width,n=a.height,o=a.anchor.x,p=a.anchor.y,q=m*(1-o),r=m*-o,s=n*(1-p),t=n*-p,u=4*this.currentBatchSize*this.vertSize,v=c.baseTexture.resolution,w=a.worldTransform,x=w.a/v,y=w.b/v,z=w.c/v,A=w.d/v,B=w.tx,C=w.ty;k[u++]=x*r+z*t+B,k[u++]=A*t+y*r+C,k[u++]=d.x0,k[u++]=d.y0,l[u++]=j,k[u++]=x*q+z*t+B,k[u++]=A*t+y*q+C,k[u++]=d.x1,k[u++]=d.y1,l[u++]=j,k[u++]=x*q+z*s+B,k[u++]=A*s+y*q+C,k[u++]=d.x2,k[u++]=d.y2,l[u++]=j,k[u++]=x*r+z*s+B,k[u++]=A*s+y*r+C,k[u++]=d.x3,k[u++]=d.y3,l[u++]=j,this.sprites[this.currentBatchSize++]=a},b.WebGLSpriteBatch.prototype.flush=function(){if(0!==this.currentBatchSize){var a,c=this.gl;if(this.dirty){this.dirty=!1,c.activeTexture(c.TEXTURE0),c.bindBuffer(c.ARRAY_BUFFER,this.vertexBuffer),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a=this.defaultShader.shaders[c.id];var d=4*this.vertSize;c.vertexAttribPointer(a.aVertexPosition,2,c.FLOAT,!1,d,0),c.vertexAttribPointer(a.aTextureCoord,2,c.FLOAT,!1,d,8),c.vertexAttribPointer(a.colorAttribute,4,c.UNSIGNED_BYTE,!0,d,16)}if(this.currentBatchSize>.5*this.size)c.bufferSubData(c.ARRAY_BUFFER,0,this.vertices);else{var e=this.positions.subarray(0,4*this.currentBatchSize*this.vertSize);c.bufferSubData(c.ARRAY_BUFFER,0,e)}for(var f,g,h,i,j=0,k=0,l=null,m=this.renderSession.blendModeManager.currentBlendMode,n=null,o=!1,p=!1,q=0,r=this.currentBatchSize;r>q;q++){if(i=this.sprites[q],f=i.texture.baseTexture,g=i.blendMode,h=i.shader||this.defaultShader,o=m!==g,p=n!==h,(l!==f||o||p)&&(this.renderBatch(l,j,k),k=q,j=0,l=f,o&&(m=g,this.renderSession.blendModeManager.setBlendMode(m)),p)){n=h,a=n.shaders[c.id],a||(a=new b.PixiShader(c),a.fragmentSrc=n.fragmentSrc,a.uniforms=n.uniforms,a.init(),n.shaders[c.id]=a),this.renderSession.shaderManager.setShader(a),a.dirty&&a.syncUniforms();var s=this.renderSession.projection;c.uniform2f(a.projectionVector,s.x,s.y);var t=this.renderSession.offset;c.uniform2f(a.offsetVector,t.x,t.y)}j++}this.renderBatch(l,j,k),this.currentBatchSize=0}},b.WebGLSpriteBatch.prototype.renderBatch=function(a,b,c){if(0!==b){var d=this.gl;a._dirty[d.id]?this.renderSession.renderer.updateTexture(a):d.bindTexture(d.TEXTURE_2D,a._glTextures[d.id]),d.drawElements(d.TRIANGLES,6*b,d.UNSIGNED_SHORT,6*c*2),this.renderSession.drawCount++}},b.WebGLSpriteBatch.prototype.stop=function(){this.flush(),this.dirty=!0},b.WebGLSpriteBatch.prototype.start=function(){this.dirty=!0},b.WebGLSpriteBatch.prototype.destroy=function(){this.vertices=null,this.indices=null,this.gl.deleteBuffer(this.vertexBuffer),this.gl.deleteBuffer(this.indexBuffer),this.currentBaseTexture=null,this.gl=null},b.WebGLFastSpriteBatch=function(a){this.vertSize=10,this.maxSize=6e3,this.size=this.maxSize;var c=4*this.size*this.vertSize,d=6*this.maxSize;this.vertices=new b.Float32Array(c),this.indices=new b.Uint16Array(d),this.vertexBuffer=null,this.indexBuffer=null,this.lastIndexCount=0;for(var e=0,f=0;d>e;e+=6,f+=4)this.indices[e+0]=f+0,this.indices[e+1]=f+1,this.indices[e+2]=f+2,this.indices[e+3]=f+0,this.indices[e+4]=f+2,this.indices[e+5]=f+3;this.drawing=!1,this.currentBatchSize=0,this.currentBaseTexture=null,this.currentBlendMode=0,this.renderSession=null,this.shader=null,this.matrix=null,this.setContext(a)},b.WebGLFastSpriteBatch.prototype.constructor=b.WebGLFastSpriteBatch,b.WebGLFastSpriteBatch.prototype.setContext=function(a){this.gl=a,this.vertexBuffer=a.createBuffer(),this.indexBuffer=a.createBuffer(),a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,this.indices,a.STATIC_DRAW),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),a.bufferData(a.ARRAY_BUFFER,this.vertices,a.DYNAMIC_DRAW)},b.WebGLFastSpriteBatch.prototype.begin=function(a,b){this.renderSession=b,this.shader=this.renderSession.shaderManager.fastShader,this.matrix=a.worldTransform.toArray(!0),this.start()},b.WebGLFastSpriteBatch.prototype.end=function(){this.flush()},b.WebGLFastSpriteBatch.prototype.render=function(a){var b=a.children,c=b[0];if(c.texture._uvs){this.currentBaseTexture=c.texture.baseTexture,c.blendMode!==this.renderSession.blendModeManager.currentBlendMode&&(this.flush(),this.renderSession.blendModeManager.setBlendMode(c.blendMode));for(var d=0,e=b.length;e>d;d++)this.renderSprite(b[d]);this.flush()}},b.WebGLFastSpriteBatch.prototype.renderSprite=function(a){if(a.visible&&(a.texture.baseTexture===this.currentBaseTexture||(this.flush(),this.currentBaseTexture=a.texture.baseTexture,a.texture._uvs))){var b,c,d,e,f,g,h,i,j=this.vertices;if(b=a.texture._uvs,c=a.texture.frame.width,d=a.texture.frame.height,a.texture.trim){var k=a.texture.trim;f=k.x-a.anchor.x*k.width,e=f+a.texture.crop.width,h=k.y-a.anchor.y*k.height,g=h+a.texture.crop.height}else e=a.texture.frame.width*(1-a.anchor.x),f=a.texture.frame.width*-a.anchor.x,g=a.texture.frame.height*(1-a.anchor.y),h=a.texture.frame.height*-a.anchor.y;i=4*this.currentBatchSize*this.vertSize,j[i++]=f,j[i++]=h,j[i++]=a.position.x,j[i++]=a.position.y,j[i++]=a.scale.x,j[i++]=a.scale.y,j[i++]=a.rotation,j[i++]=b.x0,j[i++]=b.y1,j[i++]=a.alpha,j[i++]=e,j[i++]=h,j[i++]=a.position.x,j[i++]=a.position.y,j[i++]=a.scale.x,j[i++]=a.scale.y,j[i++]=a.rotation,j[i++]=b.x1,j[i++]=b.y1,j[i++]=a.alpha,j[i++]=e,j[i++]=g,j[i++]=a.position.x,j[i++]=a.position.y,j[i++]=a.scale.x,j[i++]=a.scale.y,j[i++]=a.rotation,j[i++]=b.x2,j[i++]=b.y2,j[i++]=a.alpha,j[i++]=f,j[i++]=g,j[i++]=a.position.x,j[i++]=a.position.y,j[i++]=a.scale.x,j[i++]=a.scale.y,j[i++]=a.rotation,j[i++]=b.x3,j[i++]=b.y3,j[i++]=a.alpha,this.currentBatchSize++,this.currentBatchSize>=this.size&&this.flush()}},b.WebGLFastSpriteBatch.prototype.flush=function(){if(0!==this.currentBatchSize){var a=this.gl;if(this.currentBaseTexture._glTextures[a.id]||this.renderSession.renderer.updateTexture(this.currentBaseTexture,a),a.bindTexture(a.TEXTURE_2D,this.currentBaseTexture._glTextures[a.id]),this.currentBatchSize>.5*this.size)a.bufferSubData(a.ARRAY_BUFFER,0,this.vertices);else{var b=this.vertices.subarray(0,4*this.currentBatchSize*this.vertSize);a.bufferSubData(a.ARRAY_BUFFER,0,b)}a.drawElements(a.TRIANGLES,6*this.currentBatchSize,a.UNSIGNED_SHORT,0),this.currentBatchSize=0,this.renderSession.drawCount++}},b.WebGLFastSpriteBatch.prototype.stop=function(){this.flush()},b.WebGLFastSpriteBatch.prototype.start=function(){var a=this.gl;a.activeTexture(a.TEXTURE0),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer);var b=this.renderSession.projection;a.uniform2f(this.shader.projectionVector,b.x,b.y),a.uniformMatrix3fv(this.shader.uMatrix,!1,this.matrix);var c=4*this.vertSize;a.vertexAttribPointer(this.shader.aVertexPosition,2,a.FLOAT,!1,c,0),a.vertexAttribPointer(this.shader.aPositionCoord,2,a.FLOAT,!1,c,8),a.vertexAttribPointer(this.shader.aScale,2,a.FLOAT,!1,c,16),a.vertexAttribPointer(this.shader.aRotation,1,a.FLOAT,!1,c,24),a.vertexAttribPointer(this.shader.aTextureCoord,2,a.FLOAT,!1,c,28),a.vertexAttribPointer(this.shader.colorAttribute,1,a.FLOAT,!1,c,36)},b.WebGLFilterManager=function(){this.filterStack=[],this.offsetX=0,this.offsetY=0},b.WebGLFilterManager.prototype.constructor=b.WebGLFilterManager,b.WebGLFilterManager.prototype.setContext=function(a){this.gl=a,this.texturePool=[],this.initShaderBuffers()},b.WebGLFilterManager.prototype.begin=function(a,b){this.renderSession=a,this.defaultShader=a.shaderManager.defaultShader;var c=this.renderSession.projection;this.width=2*c.x,this.height=2*-c.y,this.buffer=b},b.WebGLFilterManager.prototype.pushFilter=function(a){var c=this.gl,d=this.renderSession.projection,e=this.renderSession.offset;a._filterArea=a.target.filterArea||a.target.getBounds(),this.filterStack.push(a);var f=a.filterPasses[0];this.offsetX+=a._filterArea.x,this.offsetY+=a._filterArea.y;var g=this.texturePool.pop();g?g.resize(this.width,this.height):g=new b.FilterTexture(this.gl,this.width,this.height),c.bindTexture(c.TEXTURE_2D,g.texture);var h=a._filterArea,i=f.padding;h.x-=i,h.y-=i,h.width+=2*i,h.height+=2*i,h.x<0&&(h.x=0),h.width>this.width&&(h.width=this.width),h.y<0&&(h.y=0),h.height>this.height&&(h.height=this.height),c.bindFramebuffer(c.FRAMEBUFFER,g.frameBuffer),c.viewport(0,0,h.width,h.height),d.x=h.width/2,d.y=-h.height/2,e.x=-h.x,e.y=-h.y,c.colorMask(!0,!0,!0,!0),c.clearColor(0,0,0,0),c.clear(c.COLOR_BUFFER_BIT),a._glFilterTexture=g},b.WebGLFilterManager.prototype.popFilter=function(){var a=this.gl,c=this.filterStack.pop(),d=c._filterArea,e=c._glFilterTexture,f=this.renderSession.projection,g=this.renderSession.offset;if(c.filterPasses.length>1){a.viewport(0,0,d.width,d.height),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),this.vertexArray[0]=0,this.vertexArray[1]=d.height,this.vertexArray[2]=d.width,this.vertexArray[3]=d.height,this.vertexArray[4]=0,this.vertexArray[5]=0,this.vertexArray[6]=d.width,this.vertexArray[7]=0,a.bufferSubData(a.ARRAY_BUFFER,0,this.vertexArray),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),this.uvArray[2]=d.width/this.width,this.uvArray[5]=d.height/this.height,this.uvArray[6]=d.width/this.width,this.uvArray[7]=d.height/this.height,a.bufferSubData(a.ARRAY_BUFFER,0,this.uvArray);var h=e,i=this.texturePool.pop();i||(i=new b.FilterTexture(this.gl,this.width,this.height)),i.resize(this.width,this.height),a.bindFramebuffer(a.FRAMEBUFFER,i.frameBuffer),a.clear(a.COLOR_BUFFER_BIT),a.disable(a.BLEND);for(var j=0;j<c.filterPasses.length-1;j++){var k=c.filterPasses[j];a.bindFramebuffer(a.FRAMEBUFFER,i.frameBuffer),a.activeTexture(a.TEXTURE0),a.bindTexture(a.TEXTURE_2D,h.texture),this.applyFilterPass(k,d,d.width,d.height);var l=h;h=i,i=l}a.enable(a.BLEND),e=h,this.texturePool.push(i)}var m=c.filterPasses[c.filterPasses.length-1];this.offsetX-=d.x,this.offsetY-=d.y;var n=this.width,o=this.height,p=0,q=0,r=this.buffer;if(0===this.filterStack.length)a.colorMask(!0,!0,!0,!0);else{var s=this.filterStack[this.filterStack.length-1];d=s._filterArea,n=d.width,o=d.height,p=d.x,q=d.y,r=s._glFilterTexture.frameBuffer}f.x=n/2,f.y=-o/2,g.x=p,g.y=q,d=c._filterArea;var t=d.x-p,u=d.y-q;a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),this.vertexArray[0]=t,this.vertexArray[1]=u+d.height,this.vertexArray[2]=t+d.width,this.vertexArray[3]=u+d.height,this.vertexArray[4]=t,this.vertexArray[5]=u,this.vertexArray[6]=t+d.width,this.vertexArray[7]=u,a.bufferSubData(a.ARRAY_BUFFER,0,this.vertexArray),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),this.uvArray[2]=d.width/this.width,this.uvArray[5]=d.height/this.height,this.uvArray[6]=d.width/this.width,this.uvArray[7]=d.height/this.height,a.bufferSubData(a.ARRAY_BUFFER,0,this.uvArray),a.viewport(0,0,n,o),a.bindFramebuffer(a.FRAMEBUFFER,r),a.activeTexture(a.TEXTURE0),a.bindTexture(a.TEXTURE_2D,e.texture),this.applyFilterPass(m,d,n,o),this.texturePool.push(e),c._glFilterTexture=null},b.WebGLFilterManager.prototype.applyFilterPass=function(a,c,d,e){var f=this.gl,g=a.shaders[f.id];g||(g=new b.PixiShader(f),g.fragmentSrc=a.fragmentSrc,g.uniforms=a.uniforms,g.init(),a.shaders[f.id]=g),this.renderSession.shaderManager.setShader(g),f.uniform2f(g.projectionVector,d/2,-e/2),f.uniform2f(g.offsetVector,0,0),a.uniforms.dimensions&&(a.uniforms.dimensions.value[0]=this.width,a.uniforms.dimensions.value[1]=this.height,a.uniforms.dimensions.value[2]=this.vertexArray[0],a.uniforms.dimensions.value[3]=this.vertexArray[5]),g.syncUniforms(),f.bindBuffer(f.ARRAY_BUFFER,this.vertexBuffer),f.vertexAttribPointer(g.aVertexPosition,2,f.FLOAT,!1,0,0),f.bindBuffer(f.ARRAY_BUFFER,this.uvBuffer),f.vertexAttribPointer(g.aTextureCoord,2,f.FLOAT,!1,0,0),f.bindBuffer(f.ARRAY_BUFFER,this.colorBuffer),f.vertexAttribPointer(g.colorAttribute,2,f.FLOAT,!1,0,0),f.bindBuffer(f.ELEMENT_ARRAY_BUFFER,this.indexBuffer),f.drawElements(f.TRIANGLES,6,f.UNSIGNED_SHORT,0),this.renderSession.drawCount++},b.WebGLFilterManager.prototype.initShaderBuffers=function(){var a=this.gl;this.vertexBuffer=a.createBuffer(),this.uvBuffer=a.createBuffer(),this.colorBuffer=a.createBuffer(),this.indexBuffer=a.createBuffer(),this.vertexArray=new b.Float32Array([0,0,1,0,0,1,1,1]),a.bindBuffer(a.ARRAY_BUFFER,this.vertexBuffer),a.bufferData(a.ARRAY_BUFFER,this.vertexArray,a.STATIC_DRAW),this.uvArray=new b.Float32Array([0,0,1,0,0,1,1,1]),a.bindBuffer(a.ARRAY_BUFFER,this.uvBuffer),a.bufferData(a.ARRAY_BUFFER,this.uvArray,a.STATIC_DRAW),this.colorArray=new b.Float32Array([1,16777215,1,16777215,1,16777215,1,16777215]),a.bindBuffer(a.ARRAY_BUFFER,this.colorBuffer),a.bufferData(a.ARRAY_BUFFER,this.colorArray,a.STATIC_DRAW),a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,this.indexBuffer),a.bufferData(a.ELEMENT_ARRAY_BUFFER,new Uint16Array([0,1,2,1,3,2]),a.STATIC_DRAW)},b.WebGLFilterManager.prototype.destroy=function(){var a=this.gl;this.filterStack=null,this.offsetX=0,this.offsetY=0;for(var b=0;b<this.texturePool.length;b++)this.texturePool[b].destroy();this.texturePool=null,a.deleteBuffer(this.vertexBuffer),a.deleteBuffer(this.uvBuffer),a.deleteBuffer(this.colorBuffer),a.deleteBuffer(this.indexBuffer)},b.FilterTexture=function(a,c,d,e){this.gl=a,this.frameBuffer=a.createFramebuffer(),this.texture=a.createTexture(),e=e||b.scaleModes.DEFAULT,a.bindTexture(a.TEXTURE_2D,this.texture),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,e===b.scaleModes.LINEAR?a.LINEAR:a.NEAREST),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,e===b.scaleModes.LINEAR?a.LINEAR:a.NEAREST),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE),a.bindFramebuffer(a.FRAMEBUFFER,this.frameBuffer),a.bindFramebuffer(a.FRAMEBUFFER,this.frameBuffer),a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,this.texture,0),this.renderBuffer=a.createRenderbuffer(),a.bindRenderbuffer(a.RENDERBUFFER,this.renderBuffer),a.framebufferRenderbuffer(a.FRAMEBUFFER,a.DEPTH_STENCIL_ATTACHMENT,a.RENDERBUFFER,this.renderBuffer),this.resize(c,d)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6806
},b.FilterTexture.prototype.constructor=b.FilterTexture,b.FilterTexture.prototype.clear=function(){var a=this.gl;a.clearColor(0,0,0,0),a.clear(a.COLOR_BUFFER_BIT)},b.FilterTexture.prototype.resize=function(a,b){if(this.width!==a||this.height!==b){this.width=a,this.height=b;var c=this.gl;c.bindTexture(c.TEXTURE_2D,this.texture),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,a,b,0,c.RGBA,c.UNSIGNED_BYTE,null),c.bindRenderbuffer(c.RENDERBUFFER,this.renderBuffer),c.renderbufferStorage(c.RENDERBUFFER,c.DEPTH_STENCIL,a,b)}},b.FilterTexture.prototype.destroy=function(){var a=this.gl;a.deleteFramebuffer(this.frameBuffer),a.deleteTexture(this.texture),this.frameBuffer=null,this.texture=null},b.CanvasBuffer=function(a,b){this.width=a,this.height=b,this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),this.canvas.width=a,this.canvas.height=b},b.CanvasBuffer.prototype.constructor=b.CanvasBuffer,b.CanvasBuffer.prototype.clear=function(){this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.width,this.height)},b.CanvasBuffer.prototype.resize=function(a,b){this.width=this.canvas.width=a,this.height=this.canvas.height=b},b.CanvasMaskManager=function(){},b.CanvasMaskManager.prototype.constructor=b.CanvasMaskManager,b.CanvasMaskManager.prototype.pushMask=function(a,c){var d=c.context;d.save();var e=a.alpha,f=a.worldTransform,g=c.resolution;d.setTransform(f.a*g,f.b*g,f.c*g,f.d*g,f.tx*g,f.ty*g),b.CanvasGraphics.renderGraphicsMask(a,d),d.clip(),a.worldAlpha=e},b.CanvasMaskManager.prototype.popMask=function(a){a.context.restore()},b.CanvasTinter=function(){},b.CanvasTinter.getTintedTexture=function(a,c){var d=a.texture;c=b.CanvasTinter.roundColor(c);var e="#"+("00000"+(0|c).toString(16)).substr(-6);if(d.tintCache=d.tintCache||{},d.tintCache[e])return d.tintCache[e];var f=b.CanvasTinter.canvas||document.createElement("canvas");if(b.CanvasTinter.tintMethod(d,c,f),b.CanvasTinter.convertTintToImage){var g=new Image;g.src=f.toDataURL(),d.tintCache[e]=g}else d.tintCache[e]=f,b.CanvasTinter.canvas=null;return f},b.CanvasTinter.tintWithMultiply=function(a,b,c){var d=c.getContext("2d"),e=a.crop;c.width=e.width,c.height=e.height,d.fillStyle="#"+("00000"+(0|b).toString(16)).substr(-6),d.fillRect(0,0,e.width,e.height),d.globalCompositeOperation="multiply",d.drawImage(a.baseTexture.source,e.x,e.y,e.width,e.height,0,0,e.width,e.height),d.globalCompositeOperation="destination-atop",d.drawImage(a.baseTexture.source,e.x,e.y,e.width,e.height,0,0,e.width,e.height)},b.CanvasTinter.tintWithOverlay=function(a,b,c){var d=c.getContext("2d"),e=a.crop;c.width=e.width,c.height=e.height,d.globalCompositeOperation="copy",d.fillStyle="#"+("00000"+(0|b).toString(16)).substr(-6),d.fillRect(0,0,e.width,e.height),d.globalCompositeOperation="destination-atop",d.drawImage(a.baseTexture.source,e.x,e.y,e.width,e.height,0,0,e.width,e.height)},b.CanvasTinter.tintWithPerPixel=function(a,c,d){var e=d.getContext("2d"),f=a.crop;d.width=f.width,d.height=f.height,e.globalCompositeOperation="copy",e.drawImage(a.baseTexture.source,f.x,f.y,f.width,f.height,0,0,f.width,f.height);for(var g=b.hex2rgb(c),h=g[0],i=g[1],j=g[2],k=e.getImageData(0,0,f.width,f.height),l=k.data,m=0;m<l.length;m+=4)l[m+0]*=h,l[m+1]*=i,l[m+2]*=j;e.putImageData(k,0,0)},b.CanvasTinter.roundColor=function(a){var c=b.CanvasTinter.cacheStepsPerColorChannel,d=b.hex2rgb(a);return d[0]=Math.min(255,d[0]/c*c),d[1]=Math.min(255,d[1]/c*c),d[2]=Math.min(255,d[2]/c*c),b.rgb2hex(d)},b.CanvasTinter.cacheStepsPerColorChannel=8,b.CanvasTinter.convertTintToImage=!1,b.CanvasTinter.canUseMultiply=b.canUseNewCanvasBlendModes(),b.CanvasTinter.tintMethod=b.CanvasTinter.canUseMultiply?b.CanvasTinter.tintWithMultiply:b.CanvasTinter.tintWithPerPixel,b.CanvasRenderer=function(a,c,d){if(d)for(var e in b.defaultRenderOptions)"undefined"==typeof d[e]&&(d[e]=b.defaultRenderOptions[e]);else d=b.defaultRenderOptions;b.defaultRenderer||(b.sayHello("Canvas"),b.defaultRenderer=this),this.type=b.CANVAS_RENDERER,this.resolution=d.resolution,this.clearBeforeRender=d.clearBeforeRender,this.transparent=d.transparent,this.autoResize=d.autoResize||!1,this.width=a||800,this.height=c||600,this.width*=this.resolution,this.height*=this.resolution,this.view=d.view||document.createElement("canvas"),this.context=this.view.getContext("2d",{alpha:this.transparent}),this.refresh=!0,this.view.width=this.width*this.resolution,this.view.height=this.height*this.resolution,this.count=0,this.maskManager=new b.CanvasMaskManager,this.renderSession={context:this.context,maskManager:this.maskManager,scaleMode:null,smoothProperty:null,roundPixels:!1},this.mapBlendModes(),this.resize(a,c),"imageSmoothingEnabled"in this.context?this.renderSession.smoothProperty="imageSmoothingEnabled":"webkitImageSmoothingEnabled"in this.context?this.renderSession.smoothProperty="webkitImageSmoothingEnabled":"mozImageSmoothingEnabled"in this.context?this.renderSession.smoothProperty="mozImageSmoothingEnabled":"oImageSmoothingEnabled"in this.context?this.renderSession.smoothProperty="oImageSmoothingEnabled":"msImageSmoothingEnabled"in this.context&&(this.renderSession.smoothProperty="msImageSmoothingEnabled")},b.CanvasRenderer.prototype.constructor=b.CanvasRenderer,b.CanvasRenderer.prototype.render=function(a){a.updateTransform(),this.context.setTransform(1,0,0,1,0,0),this.context.globalAlpha=1,this.renderSession.currentBlendMode=b.blendModes.NORMAL,this.context.globalCompositeOperation=b.blendModesCanvas[b.blendModes.NORMAL],navigator.isCocoonJS&&this.view.screencanvas&&(this.context.fillStyle="black",this.context.clear()),this.clearBeforeRender&&(this.transparent?this.context.clearRect(0,0,this.width,this.height):(this.context.fillStyle=a.backgroundColorString,this.context.fillRect(0,0,this.width,this.height))),this.renderDisplayObject(a),a.interactive&&(a._interactiveEventsAdded||(a._interactiveEventsAdded=!0,a.interactionManager.setTarget(this)))},b.CanvasRenderer.prototype.destroy=function(a){"undefined"==typeof a&&(a=!0),a&&this.view.parent&&this.view.parent.removeChild(this.view),this.view=null,this.context=null,this.maskManager=null,this.renderSession=null},b.CanvasRenderer.prototype.resize=function(a,b){this.width=a*this.resolution,this.height=b*this.resolution,this.view.width=this.width,this.view.height=this.height,this.autoResize&&(this.view.style.width=this.width/this.resolution+"px",this.view.style.height=this.height/this.resolution+"px")},b.CanvasRenderer.prototype.renderDisplayObject=function(a,b){this.renderSession.context=b||this.context,this.renderSession.resolution=this.resolution,a._renderCanvas(this.renderSession)},b.CanvasRenderer.prototype.mapBlendModes=function(){b.blendModesCanvas||(b.blendModesCanvas=[],b.canUseNewCanvasBlendModes()?(b.blendModesCanvas[b.blendModes.NORMAL]="source-over",b.blendModesCanvas[b.blendModes.ADD]="lighter",b.blendModesCanvas[b.blendModes.MULTIPLY]="multiply",b.blendModesCanvas[b.blendModes.SCREEN]="screen",b.blendModesCanvas[b.blendModes.OVERLAY]="overlay",b.blendModesCanvas[b.blendModes.DARKEN]="darken",b.blendModesCanvas[b.blendModes.LIGHTEN]="lighten",b.blendModesCanvas[b.blendModes.COLOR_DODGE]="color-dodge",b.blendModesCanvas[b.blendModes.COLOR_BURN]="color-burn",b.blendModesCanvas[b.blendModes.HARD_LIGHT]="hard-light",b.blendModesCanvas[b.blendModes.SOFT_LIGHT]="soft-light",b.blendModesCanvas[b.blendModes.DIFFERENCE]="difference",b.blendModesCanvas[b.blendModes.EXCLUSION]="exclusion",b.blendModesCanvas[b.blendModes.HUE]="hue",b.blendModesCanvas[b.blendModes.SATURATION]="saturation",b.blendModesCanvas[b.blendModes.COLOR]="color",b.blendModesCanvas[b.blendModes.LUMINOSITY]="luminosity"):(b.blendModesCanvas[b.blendModes.NORMAL]="source-over",b.blendModesCanvas[b.blendModes.ADD]="lighter",b.blendModesCanvas[b.blendModes.MULTIPLY]="source-over",b.blendModesCanvas[b.blendModes.SCREEN]="source-over",b.blendModesCanvas[b.blendModes.OVERLAY]="source-over",b.blendModesCanvas[b.blendModes.DARKEN]="source-over",b.blendModesCanvas[b.blendModes.LIGHTEN]="source-over",b.blendModesCanvas[b.blendModes.COLOR_DODGE]="source-over",b.blendModesCanvas[b.blendModes.COLOR_BURN]="source-over",b.blendModesCanvas[b.blendModes.HARD_LIGHT]="source-over",b.blendModesCanvas[b.blendModes.SOFT_LIGHT]="source-over",b.blendModesCanvas[b.blendModes.DIFFERENCE]="source-over",b.blendModesCanvas[b.blendModes.EXCLUSION]="source-over",b.blendModesCanvas[b.blendModes.HUE]="source-over",b.blendModesCanvas[b.blendModes.SATURATION]="source-over",b.blendModesCanvas[b.blendModes.COLOR]="source-over",b.blendModesCanvas[b.blendModes.LUMINOSITY]="source-over"))},b.CanvasGraphics=function(){},b.CanvasGraphics.renderGraphics=function(a,c){var d=a.worldAlpha;a.dirty&&(this.updateGraphicsTint(a),a.dirty=!1);for(var e=0;e<a.graphicsData.length;e++){var f=a.graphicsData[e],g=f.shape,h=f._fillTint,i=f._lineTint;if(c.lineWidth=f.lineWidth,f.type===b.Graphics.POLY){c.beginPath();var j=g.points;c.moveTo(j[0],j[1]);for(var k=1;k<j.length/2;k++)c.lineTo(j[2*k],j[2*k+1]);g.closed&&c.lineTo(j[0],j[1]),j[0]===j[j.length-2]&&j[1]===j[j.length-1]&&c.closePath(),f.fill&&(c.globalAlpha=f.fillAlpha*d,c.fillStyle="#"+("00000"+(0|h).toString(16)).substr(-6),c.fill()),f.lineWidth&&(c.globalAlpha=f.lineAlpha*d,c.strokeStyle="#"+("00000"+(0|i).toString(16)).substr(-6),c.stroke())}else if(f.type===b.Graphics.RECT)(f.fillColor||0===f.fillColor)&&(c.globalAlpha=f.fillAlpha*d,c.fillStyle="#"+("00000"+(0|h).toString(16)).substr(-6),c.fillRect(g.x,g.y,g.width,g.height)),f.lineWidth&&(c.globalAlpha=f.lineAlpha*d,c.strokeStyle="#"+("00000"+(0|i).toString(16)).substr(-6),c.strokeRect(g.x,g.y,g.width,g.height));else if(f.type===b.Graphics.CIRC)c.beginPath(),c.arc(g.x,g.y,g.radius,0,2*Math.PI),c.closePath(),f.fill&&(c.globalAlpha=f.fillAlpha*d,c.fillStyle="#"+("00000"+(0|h).toString(16)).substr(-6),c.fill()),f.lineWidth&&(c.globalAlpha=f.lineAlpha*d,c.strokeStyle="#"+("00000"+(0|i).toString(16)).substr(-6),c.stroke());else if(f.type===b.Graphics.ELIP){var l=2*g.width,m=2*g.height,n=g.x-l/2,o=g.y-m/2;c.beginPath();var p=.5522848,q=l/2*p,r=m/2*p,s=n+l,t=o+m,u=n+l/2,v=o+m/2;c.moveTo(n,v),c.bezierCurveTo(n,v-r,u-q,o,u,o),c.bezierCurveTo(u+q,o,s,v-r,s,v),c.bezierCurveTo(s,v+r,u+q,t,u,t),c.bezierCurveTo(u-q,t,n,v+r,n,v),c.closePath(),f.fill&&(c.globalAlpha=f.fillAlpha*d,c.fillStyle="#"+("00000"+(0|h).toString(16)).substr(-6),c.fill()),f.lineWidth&&(c.globalAlpha=f.lineAlpha*d,c.strokeStyle="#"+("00000"+(0|i).toString(16)).substr(-6),c.stroke())}else if(f.type===b.Graphics.RREC){var w=g.x,x=g.y,y=g.width,z=g.height,A=g.radius,B=Math.min(y,z)/2|0;A=A>B?B:A,c.beginPath(),c.moveTo(w,x+A),c.lineTo(w,x+z-A),c.quadraticCurveTo(w,x+z,w+A,x+z),c.lineTo(w+y-A,x+z),c.quadraticCurveTo(w+y,x+z,w+y,x+z-A),c.lineTo(w+y,x+A),c.quadraticCurveTo(w+y,x,w+y-A,x),c.lineTo(w+A,x),c.quadraticCurveTo(w,x,w,x+A),c.closePath(),(f.fillColor||0===f.fillColor)&&(c.globalAlpha=f.fillAlpha*d,c.fillStyle="#"+("00000"+(0|h).toString(16)).substr(-6),c.fill()),f.lineWidth&&(c.globalAlpha=f.lineAlpha*d,c.strokeStyle="#"+("00000"+(0|i).toString(16)).substr(-6),c.stroke())}}},b.CanvasGraphics.renderGraphicsMask=function(a,c){var d=a.graphicsData.length;if(0!==d){d>1&&(d=1,window.console.log("Pixi.js warning: masks in canvas can only mask using the first path in the graphics object"));for(var e=0;1>e;e++){var f=a.graphicsData[e],g=f.shape;if(f.type===b.Graphics.POLY){c.beginPath();var h=g.points;c.moveTo(h[0],h[1]);for(var i=1;i<h.length/2;i++)c.lineTo(h[2*i],h[2*i+1]);h[0]===h[h.length-2]&&h[1]===h[h.length-1]&&c.closePath()}else if(f.type===b.Graphics.RECT)c.beginPath(),c.rect(g.x,g.y,g.width,g.height),c.closePath();else if(f.type===b.Graphics.CIRC)c.beginPath(),c.arc(g.x,g.y,g.radius,0,2*Math.PI),c.closePath();else if(f.type===b.Graphics.ELIP){var j=2*g.width,k=2*g.height,l=g.x-j/2,m=g.y-k/2;c.beginPath();var n=.5522848,o=j/2*n,p=k/2*n,q=l+j,r=m+k,s=l+j/2,t=m+k/2;c.moveTo(l,t),c.bezierCurveTo(l,t-p,s-o,m,s,m),c.bezierCurveTo(s+o,m,q,t-p,q,t),c.bezierCurveTo(q,t+p,s+o,r,s,r),c.bezierCurveTo(s-o,r,l,t+p,l,t),c.closePath()}else if(f.type===b.Graphics.RREC){var u=g.points,v=u[0],w=u[1],x=u[2],y=u[3],z=u[4],A=Math.min(x,y)/2|0;z=z>A?A:z,c.beginPath(),c.moveTo(v,w+z),c.lineTo(v,w+y-z),c.quadraticCurveTo(v,w+y,v+z,w+y),c.lineTo(v+x-z,w+y),c.quadraticCurveTo(v+x,w+y,v+x,w+y-z),c.lineTo(v+x,w+z),c.quadraticCurveTo(v+x,w,v+x-z,w),c.lineTo(v+z,w),c.quadraticCurveTo(v,w,v,w+z),c.closePath()}}}},b.CanvasGraphics.updateGraphicsTint=function(a){if(16777215!==a.tint)for(var b=(a.tint>>16&255)/255,c=(a.tint>>8&255)/255,d=(255&a.tint)/255,e=0;e<a.graphicsData.length;e++){var f=a.graphicsData[e],g=0|f.fillColor,h=0|f.lineColor;f._fillTint=((g>>16&255)/255*b*255<<16)+((g>>8&255)/255*c*255<<8)+(255&g)/255*d*255,f._lineTint=((h>>16&255)/255*b*255<<16)+((h>>8&255)/255*c*255<<8)+(255&h)/255*d*255}},b.Graphics=function(){b.DisplayObjectContainer.call(this),this.renderable=!0,this.fillAlpha=1,this.lineWidth=0,this.lineColor=0,this.graphicsData=[],this.tint=16777215,this.blendMode=b.blendModes.NORMAL,this.currentPath=null,this._webGL=[],this.isMask=!1,this.boundsPadding=0,this._localBounds=new b.Rectangle(0,0,1,1),this.dirty=!0,this.webGLDirty=!1,this.cachedSpriteDirty=!1},b.Graphics.prototype=Object.create(b.DisplayObjectContainer.prototype),b.Graphics.prototype.constructor=b.Graphics,Object.defineProperty(b.Graphics.prototype,"cacheAsBitmap",{get:function(){return this._cacheAsBitmap},set:function(a){this._cacheAsBitmap=a,this._cacheAsBitmap?this._generateCachedSprite():(this.destroyCachedSprite(),this.dirty=!0)}}),b.Graphics.prototype.lineStyle=function(a,c,d){if(this.lineWidth=a||0,this.lineColor=c||0,this.lineAlpha=arguments.length<3?1:d,this.currentPath){if(this.currentPath.shape.points.length)return this.drawShape(new b.Polygon(this.currentPath.shape.points.slice(-2))),this;this.currentPath.lineWidth=this.lineWidth,this.currentPath.lineColor=this.lineColor,this.currentPath.lineAlpha=this.lineAlpha}return this},b.Graphics.prototype.moveTo=function(a,c){return this.drawShape(new b.Polygon([a,c])),this},b.Graphics.prototype.lineTo=function(a,b){return this.currentPath.shape.points.push(a,b),this.dirty=!0,this},b.Graphics.prototype.quadraticCurveTo=function(a,b,c,d){this.currentPath?0===this.currentPath.shape.points.length&&(this.currentPath.shape.points=[0,0]):this.moveTo(0,0);var e,f,g=20,h=this.currentPath.shape.points;0===h.length&&this.moveTo(0,0);for(var i=h[h.length-2],j=h[h.length-1],k=0,l=1;g>=l;l++)k=l/g,e=i+(a-i)*k,f=j+(b-j)*k,h.push(e+(a+(c-a)*k-e)*k,f+(b+(d-b)*k-f)*k);return this.dirty=!0,this},b.Graphics.prototype.bezierCurveTo=function(a,b,c,d,e,f){this.currentPath?0===this.currentPath.shape.points.length&&(this.currentPath.shape.points=[0,0]):this.moveTo(0,0);for(var g,h,i,j,k,l=20,m=this.currentPath.shape.points,n=m[m.length-2],o=m[m.length-1],p=0,q=1;l>=q;q++)p=q/l,g=1-p,h=g*g,i=h*g,j=p*p,k=j*p,m.push(i*n+3*h*p*a+3*g*j*c+k*e,i*o+3*h*p*b+3*g*j*d+k*f);return this.dirty=!0,this},b.Graphics.prototype.arcTo=function(a,b,c,d,e){this.currentPath?0===this.currentPath.shape.points.length&&this.currentPath.shape.points.push(a,b):this.moveTo(a,b);var f=this.currentPath.shape.points,g=f[f.length-2],h=f[f.length-1],i=h-b,j=g-a,k=d-b,l=c-a,m=Math.abs(i*l-j*k);if(1e-8>m||0===e)(f[f.length-2]!==a||f[f.length-1]!==b)&&f.push(a,b);else{var n=i*i+j*j,o=k*k+l*l,p=i*k+j*l,q=e*Math.sqrt(n)/m,r=e*Math.sqrt(o)/m,s=q*p/n,t=r*p/o,u=q*l+r*j,v=q*k+r*i,w=j*(r+s),x=i*(r+s),y=l*(q+t),z=k*(q+t),A=Math.atan2(x-v,w-u),B=Math.atan2(z-v,y-u);this.arc(u+a,v+b,e,A,B,j*k>l*i)}return this.dirty=!0,this},b.Graphics.prototype.arc=function(a,b,c,d,e,f){var g,h=a+Math.cos(d)*c,i=b+Math.sin(d)*c;if(this.currentPath?(g=this.currentPath.shape.points,0===g.length?g.push(h,i):(g[g.length-2]!==h||g[g.length-1]!==i)&&g.push(h,i)):(this.moveTo(h,i),g=this.currentPath.shape.points),d===e)return this;!f&&d>=e?e+=2*Math.PI:f&&e>=d&&(d+=2*Math.PI);var j=f?-1*(d-e):e-d,k=Math.abs(j)/(2*Math.PI)*40;if(0===j)return this;for(var l=j/(2*k),m=2*l,n=Math.cos(l),o=Math.sin(l),p=k-1,q=p%1/p,r=0;p>=r;r++){var s=r+q*r,t=l+d+m*s,u=Math.cos(t),v=-Math.sin(t);g.push((n*u+o*v)*c+a,(n*-v+o*u)*c+b)}return this.dirty=!0,this},b.Graphics.prototype.beginFill=function(a,b){return this.filling=!0,this.fillColor=a||0,this.fillAlpha=void 0===b?1:b,this.currentPath&&this.currentPath.shape.points.length<=2&&(this.currentPath.fill=this.filling,this.currentPath.fillColor=this.fillColor,this.currentPath.fillAlpha=this.fillAlpha),this},b.Graphics.prototype.endFill=function(){return this.filling=!1,this.fillColor=null,this.fillAlpha=1,this},b.Graphics.prototype.drawRect=function(a,c,d,e){return this.drawShape(new b.Rectangle(a,c,d,e)),this},b.Graphics.prototype.drawRoundedRect=function(a,c,d,e,f){return this.drawShape(new b.RoundedRectangle(a,c,d,e,f)),this},b.Graphics.prototype.drawCircle=function(a,c,d){return this.drawShape(new b.Circle(a,c,d)),this},b.Graphics.prototype.drawEllipse=function(a,c,d,e){return this.drawShape(new b.Ellipse(a,c,d,e)),this},b.Graphics.prototype.drawPolygon=function(a){return a instanceof Array||(a=Array.prototype.slice.call(arguments)),this.drawShape(new b.Polygon(a)),this},b.Graphics.prototype.clear=function(){return this.lineWidth=0,this.filling=!1,this.dirty=!0,this.clearDirty=!0,this.graphicsData=[],this},b.Graphics.prototype.generateTexture=function(a,c){a=a||1;var d=this.getBounds(),e=new b.CanvasBuffer(d.width*a,d.height*a),f=b.Texture.fromCanvas(e.canvas,c);return f.baseTexture.resolution=a,e.context.scale(a,a),e.context.translate(-d.x,-d.y),b.CanvasGraphics.renderGraphics(this,e.context),f},b.Graphics.prototype._renderWebGL=function(a){if(this.visible!==!1&&0!==this.alpha&&this.isMask!==!0){if(this._cacheAsBitmap)return(this.dirty||this.cachedSpriteDirty)&&(this._generateCachedSprite(),this.updateCachedSpriteTexture(),this.cachedSpriteDirty=!1,this.dirty=!1),this._cachedSprite.worldAlpha=this.worldAlpha,void b.Sprite.prototype._renderWebGL.call(this._cachedSprite,a);if(a.spriteBatch.stop(),a.blendModeManager.setBlendMode(this.blendMode),this._mask&&a.maskManager.pushMask(this._mask,a),this._filters&&a.filterManager.pushFilter(this._filterBlock),this.blendMode!==a.spriteBatch.currentBlendMode){a.spriteBatch.currentBlendMode=this.blendMode;var c=b.blendModesWebGL[a.spriteBatch.currentBlendMode];a.spriteBatch.gl.blendFunc(c[0],c[1])}if(this.webGLDirty&&(this.dirty=!0,this.webGLDirty=!1),b.WebGLGraphics.renderGraphics(this,a),this.children.length){a.spriteBatch.start();for(var d=0,e=this.children.length;e>d;d++)this.children[d]._renderWebGL(a);a.spriteBatch.stop()}this._filters&&a.filterManager.popFilter(),this._mask&&a.maskManager.popMask(this.mask,a),a.drawCount++,a.spriteBatch.start()}},b.Graphics.prototype._renderCanvas=function(a){if(this.visible!==!1&&0!==this.alpha&&this.isMask!==!0){if(this._cacheAsBitmap)return(this.dirty||this.cachedSpriteDirty)&&(this._generateCachedSprite(),this.updateCachedSpriteTexture(),this.cachedSpriteDirty=!1,this.dirty=!1),this._cachedSprite.alpha=this.alpha,void b.Sprite.prototype._renderCanvas.call(this._cachedSprite,a);var c=a.context,d=this.worldTransform;this.blendMode!==a.currentBlendMode&&(a.currentBlendMode=this.blendMode,c.globalCompositeOperation=b.blendModesCanvas[a.currentBlendMode]),this._mask&&a.maskManager.pushMask(this._mask,a);var e=a.resolution;c.setTransform(d.a*e,d.b*e,d.c*e,d.d*e,d.tx*e,d.ty*e),b.CanvasGraphics.renderGraphics(this,c);for(var f=0,g=this.children.length;g>f;f++)this.children[f]._renderCanvas(a);this._mask&&a.maskManager.popMask(a)}},b.Graphics.prototype.getBounds=function(a){if(this.isMask)return b.EmptyRectangle;this.dirty&&(this.updateLocalBounds(),this.webGLDirty=!0,this.cachedSpriteDirty=!0,this.dirty=!1);var c=this._localBounds,d=c.x,e=c.width+c.x,f=c.y,g=c.height+c.y,h=a||this.worldTransform,i=h.a,j=h.b,k=h.c,l=h.d,m=h.tx,n=h.ty,o=i*e+k*g+m,p=l*g+j*e+n,q=i*d+k*g+m,r=l*g+j*d+n,s=i*d+k*f+m,t=l*f+j*d+n,u=i*e+k*f+m,v=l*f+j*e+n,w=o,x=p,y=o,z=p;return y=y>q?q:y,y=y>s?s:y,y=y>u?u:y,z=z>r?r:z,z=z>t?t:z,z=z>v?v:z,w=q>w?q:w,w=s>w?s:w,w=u>w?u:w,x=r>x?r:x,x=t>x?t:x,x=v>x?v:x,this._bounds.x=y,this._bounds.width=w-y,this._bounds.y=z,this._bounds.height=x-z,this._bounds},b.Graphics.prototype.updateLocalBounds=function(){var a=1/0,c=-1/0,d=1/0,e=-1/0;if(this.graphicsData.length)for(var f,g,h,i,j,k,l=0;l<this.graphicsData.length;l++){var m=this.graphicsData[l],n=m.type,o=m.lineWidth;if(f=m.shape,n===b.Graphics.RECT||n===b.Graphics.RREC)h=f.x-o/2,i=f.y-o/2,j=f.width+o,k=f.height+o,a=a>h?h:a,c=h+j>c?h+j:c,d=d>i?i:d,e=i+k>e?i+k:e;else if(n===b.Graphics.CIRC)h=f.x,i=f.y,j=f.radius+o/2,k=f.radius+o/2,a=a>h-j?h-j:a,c=h+j>c?h+j:c,d=d>i-k?i-k:d,e=i+k>e?i+k:e;else if(n===b.Graphics.ELIP)h=f.x,i=f.y,j=f.width+o/2,k=f.height+o/2,a=a>h-j?h-j:a,c=h+j>c?h+j:c,d=d>i-k?i-k:d,e=i+k>e?i+k:e;else{g=f.points;for(var p=0;p<g.length;p+=2)h=g[p],i=g[p+1],a=a>h-o?h-o:a,c=h+o>c?h+o:c,d=d>i-o?i-o:d,e=i+o>e?i+o:e}}else a=0,c=0,d=0,e=0;var q=this.boundsPadding;this._localBounds.x=a-q,this._localBounds.width=c-a+2*q,this._localBounds.y=d-q,this._localBounds.height=e-d+2*q},b.Graphics.prototype._generateCachedSprite=function(){var a=this.getLocalBounds();if(this._cachedSprite)this._cachedSprite.buffer.resize(a.width,a.height);else{var c=new b.CanvasBuffer(a.width,a.height),d=b.Texture.fromCanvas(c.canvas);this._cachedSprite=new b.Sprite(d),this._cachedSprite.buffer=c,this._cachedSprite.worldTransform=this.worldTransform}this._cachedSprite.anchor.x=-(a.x/a.width),this._cachedSprite.anchor.y=-(a.y/a.height),this._cachedSprite.buffer.context.translate(-a.x,-a.y),this.worldAlpha=1,b.CanvasGraphics.renderGraphics(this,this._cachedSprite.buffer.context),this._cachedSprite.alpha=this.alpha},b.Graphics.prototype.updateCachedSpriteTexture=function(){var a=this._cachedSprite,b=a.texture,c=a.buffer.canvas;b.baseTexture.width=c.width,b.baseTexture.height=c.height,b.crop.width=b.frame.width=c.width,b.crop.height=b.frame.height=c.height,a._width=c.width,a._height=c.height,b.baseTexture.dirty()},b.Graphics.prototype.destroyCachedSprite=function(){this._cachedSprite.texture.destroy(!0),this._cachedSprite=null},b.Graphics.prototype.drawShape=function(a){this.currentPath&&this.currentPath.shape.points.length<=2&&this.graphicsData.pop(),this.currentPath=null;var c=new b.GraphicsData(this.lineWidth,this.lineColor,this.lineAlpha,this.fillColor,this.fillAlpha,this.filling,a);return this.graphicsData.push(c),c.type===b.Graphics.POLY&&(c.shape.closed=this.filling,this.currentPath=c),this.dirty=!0,c},b.GraphicsData=function(a,b,c,d,e,f,g){this.lineWidth=a,this.lineColor=b,this.lineAlpha=c,this._lineTint=b,this.fillColor=d,this.fillAlpha=e,this._fillTint=d,this.fill=f,this.shape=g,this.type=g.type},b.Graphics.POLY=0,b.Graphics.RECT=1,b.Graphics.CIRC=2,b.Graphics.ELIP=3,b.Graphics.RREC=4,b.Polygon.prototype.type=b.Graphics.POLY,b.Rectangle.prototype.type=b.Graphics.RECT,b.Circle.prototype.type=b.Graphics.CIRC,b.Ellipse.prototype.type=b.Graphics.ELIP,b.RoundedRectangle.prototype.type=b.Graphics.RREC,b.Strip=function(a){b.DisplayObjectContainer.call(this),this.texture=a,this.uvs=new b.Float32Array([0,1,1,1,1,0,0,1]),this.vertices=new b.Float32Array([0,0,100,0,100,100,0,100]),this.colors=new b.Float32Array([1,1,1,1]),this.indices=new b.Uint16Array([0,1,2,3]),this.dirty=!0,this.blendMode=b.blendModes.NORMAL,this.canvasPadding=0,this.drawMode=b.Strip.DrawModes.TRIANGLE_STRIP},b.Strip.prototype=Object.create(b.DisplayObjectContainer.prototype),b.Strip.prototype.constructor=b.Strip,b.Strip.prototype._renderWebGL=function(a){!this.visible||this.alpha<=0||(a.spriteBatch.stop(),this._vertexBuffer||this._initWebGL(a),a.shaderManager.setShader(a.shaderManager.stripShader),this._renderStrip(a),a.spriteBatch.start())},b.Strip.prototype._initWebGL=function(a){var b=a.gl;this._vertexBuffer=b.createBuffer(),this._indexBuffer=b.createBuffer(),this._uvBuffer=b.createBuffer(),this._colorBuffer=b.createBuffer(),b.bindBuffer(b.ARRAY_BUFFER,this._vertexBuffer),b.bufferData(b.ARRAY_BUFFER,this.vertices,b.DYNAMIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,this._uvBuffer),b.bufferData(b.ARRAY_BUFFER,this.uvs,b.STATIC_DRAW),b.bindBuffer(b.ARRAY_BUFFER,this._colorBuffer),b.bufferData(b.ARRAY_BUFFER,this.colors,b.STATIC_DRAW),b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,this._indexBuffer),b.bufferData(b.ELEMENT_ARRAY_BUFFER,this.indices,b.STATIC_DRAW)},b.Strip.prototype._renderStrip=function(a){var c=a.gl,d=a.projection,e=a.offset,f=a.shaderManager.stripShader,g=this.drawMode===b.Strip.DrawModes.TRIANGLE_STRIP?c.TRIANGLE_STRIP:c.TRIANGLES;a.blendModeManager.setBlendMode(this.blendMode),c.uniformMatrix3fv(f.translationMatrix,!1,this.worldTransform.toArray(!0)),c.uniform2f(f.projectionVector,d.x,-d.y),c.uniform2f(f.offsetVector,-e.x,-e.y),c.uniform1f(f.alpha,this.worldAlpha),this.dirty?(this.dirty=!1,c.bindBuffer(c.ARRAY_BUFFER,this._vertexBuffer),c.bufferData(c.ARRAY_BUFFER,this.vertices,c.STATIC_DRAW),c.vertexAttribPointer(f.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,this._uvBuffer),c.bufferData(c.ARRAY_BUFFER,this.uvs,c.STATIC_DRAW),c.vertexAttribPointer(f.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),this.texture.baseTexture._dirty[c.id]?a.renderer.updateTexture(this.texture.baseTexture):c.bindTexture(c.TEXTURE_2D,this.texture.baseTexture._glTextures[c.id]),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,this._indexBuffer),c.bufferData(c.ELEMENT_ARRAY_BUFFER,this.indices,c.STATIC_DRAW)):(c.bindBuffer(c.ARRAY_BUFFER,this._vertexBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,this.vertices),c.vertexAttribPointer(f.aVertexPosition,2,c.FLOAT,!1,0,0),c.bindBuffer(c.ARRAY_BUFFER,this._uvBuffer),c.vertexAttribPointer(f.aTextureCoord,2,c.FLOAT,!1,0,0),c.activeTexture(c.TEXTURE0),this.texture.baseTexture._dirty[c.id]?a.renderer.updateTexture(this.texture.baseTexture):c.bindTexture(c.TEXTURE_2D,this.texture.baseTexture._glTextures[c.id]),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,this._indexBuffer)),c.drawElements(g,this.indices.length,c.UNSIGNED_SHORT,0)},b.Strip.prototype._renderCanvas=function(a){var c=a.context,d=this.worldTransform;a.roundPixels?c.setTransform(d.a,d.b,d.c,d.d,0|d.tx,0|d.ty):c.setTransform(d.a,d.b,d.c,d.d,d.tx,d.ty),this.drawMode===b.Strip.DrawModes.TRIANGLE_STRIP?this._renderCanvasTriangleStrip(c):this._renderCanvasTriangles(c)},b.Strip.prototype._renderCanvasTriangleStrip=function(a){var b=this.vertices,c=this.uvs,d=b.length/2;this.count++;for(var e=0;d-2>e;e++){var f=2*e;this._renderCanvasDrawTriangle(a,b,c,f,f+2,f+4)}},b.Strip.prototype._renderCanvasTriangles=function(a){var b=this.vertices,c=this.uvs,d=this.indices,e=d.length;this.count++;for(var f=0;e>f;f+=3){var g=2*d[f],h=2*d[f+1],i=2*d[f+2];this._renderCanvasDrawTriangle(a,b,c,g,h,i)}},b.Strip.prototype._renderCanvasDrawTriangle=function(a,b,c,d,e,f){var g=this.texture.baseTexture.source,h=this.texture.width,i=this.texture.height,j=b[d],k=b[e],l=b[f],m=b[d+1],n=b[e+1],o=b[f+1],p=c[d]*h,q=c[e]*h,r=c[f]*h,s=c[d+1]*i,t=c[e+1]*i,u=c[f+1]*i;if(this.canvasPadding>0){var v=this.canvasPadding/this.worldTransform.a,w=this.canvasPadding/this.worldTransform.d,x=(j+k+l)/3,y=(m+n+o)/3,z=j-x,A=m-y,B=Math.sqrt(z*z+A*A);j=x+z/B*(B+v),m=y+A/B*(B+w),z=k-x,A=n-y,B=Math.sqrt(z*z+A*A),k=x+z/B*(B+v),n=y+A/B*(B+w),z=l-x,A=o-y,B=Math.sqrt(z*z+A*A),l=x+z/B*(B+v),o=y+A/B*(B+w)}a.save(),a.beginPath(),a.moveTo(j,m),a.lineTo(k,n),a.lineTo(l,o),a.closePath(),a.clip();var C=p*t+s*r+q*u-t*r-s*q-p*u,D=j*t+s*l+k*u-t*l-s*k-j*u,E=p*k+j*r+q*l-k*r-j*q-p*l,F=p*t*l+s*k*r+j*q*u-j*t*r-s*q*l-p*k*u,G=m*t+s*o+n*u-t*o-s*n-m*u,H=p*n+m*r+q*o-n*r-m*q-p*o,I=p*t*o+s*n*r+m*q*u-m*t*r-s*q*o-p*n*u;a.transform(D/C,G/C,E/C,H/C,F/C,I/C),a.drawImage(g,0,0),a.restore()},b.Strip.prototype.renderStripFlat=function(a){var b=this.context,c=a.vertices,d=c.length/2;this.count++,b.beginPath();for(var e=1;d-2>e;e++){var f=2*e,g=c[f],h=c[f+2],i=c[f+4],j=c[f+1],k=c[f+3],l=c[f+5];b.moveTo(g,j),b.lineTo(h,k),b.lineTo(i,l)}b.fillStyle="#FF0000",b.fill(),b.closePath()},b.Strip.prototype.onTextureUpdate=function(){this.updateFrame=!0},b.Strip.prototype.getBounds=function(a){for(var c=a||this.worldTransform,d=c.a,e=c.b,f=c.c,g=c.d,h=c.tx,i=c.ty,j=-1/0,k=-1/0,l=1/0,m=1/0,n=this.vertices,o=0,p=n.length;p>o;o+=2){var q=n[o],r=n[o+1],s=d*q+f*r+h,t=g*r+e*q+i;l=l>s?s:l,m=m>t?t:m,j=s>j?s:j,k=t>k?t:k}if(l===-1/0||1/0===k)return b.EmptyRectangle;var u=this._bounds;return u.x=l,u.width=j-l,u.y=m,u.height=k-m,this._currentBounds=u,u},b.Strip.DrawModes={TRIANGLE_STRIP:0,TRIANGLES:1},b.Rope=function(a,c){b.Strip.call(this,a),this.points=c,this.vertices=new b.Float32Array(4*c.length),this.uvs=new b.Float32Array(4*c.length),this.colors=new b.Float32Array(2*c.length),this.indices=new b.Uint16Array(2*c.length),this.refresh()},b.Rope.prototype=Object.create(b.Strip.prototype),b.Rope.prototype.constructor=b.Rope,b.Rope.prototype.refresh=function(){var a=this.points;if(!(a.length<1)){var b=this.uvs,c=a[0],d=this.indices,e=this.colors;this.count-=.2,b[0]=0,b[1]=0,b[2]=0,b[3]=1,e[0]=1,e[1]=1,d[0]=0,d[1]=1;for(var f,g,h,i=a.length,j=1;i>j;j++)f=a[j],g=4*j,h=j/(i-1),j%2?(b[g]=h,b[g+1]=0,b[g+2]=h,b[g+3]=1):(b[g]=h,b[g+1]=0,b[g+2]=h,b[g+3]=1),g=2*j,e[g]=1,e[g+1]=1,g=2*j,d[g]=g,d[g+1]=g+1,c=f}},b.Rope.prototype.updateTransform=function(){var a=this.points;if(!(a.length<1)){var c,d=a[0],e={x:0,y:0};this.count-=.2;for(var f,g,h,i,j,k=this.vertices,l=a.length,m=0;l>m;m++)f=a[m],g=4*m,c=m<a.length-1?a[m+1]:f,e.y=-(c.x-d.x),e.x=c.y-d.y,h=10*(1-m/(l-1)),h>1&&(h=1),i=Math.sqrt(e.x*e.x+e.y*e.y),j=this.texture.height/2,e.x/=i,e.y/=i,e.x*=j,e.y*=j,k[g]=f.x+e.x,k[g+1]=f.y+e.y,k[g+2]=f.x-e.x,k[g+3]=f.y-e.y,d=f;b.DisplayObjectContainer.prototype.updateTransform.call(this)}},b.Rope.prototype.setTexture=function(a){this.texture=a},b.TilingSprite=function(a,c,d){b.Sprite.call(this,a),this._width=c||100,this._height=d||100,this.tileScale=new b.Point(1,1),this.tileScaleOffset=new b.Point(1,1),this.tilePosition=new b.Point(0,0),this.renderable=!0,this.tint=16777215,this.blendMode=b.blendModes.NORMAL},b.TilingSprite.prototype=Object.create(b.Sprite.prototype),b.TilingSprite.prototype.constructor=b.TilingSprite,Object.defineProperty(b.TilingSprite.prototype,"width",{get:function(){return this._width},set:function(a){this._width=a}}),Object.defineProperty(b.TilingSprite.prototype,"height",{get:function(){return this._height},set:function(a){this._height=a}}),b.TilingSprite.prototype.setTexture=function(a){this.texture!==a&&(this.texture=a,this.refreshTexture=!0,this.cachedTint=16777215)},b.TilingSprite.prototype._renderWebGL=function(a){if(this.visible!==!1&&0!==this.alpha){var b,c;for(this._mask&&(a.spriteBatch.stop(),a.maskManager.pushMask(this.mask,a),a.spriteBatch.start()),this._filters&&(a.spriteBatch.flush(),a.filterManager.pushFilter(this._filterBlock)),!this.tilingTexture||this.refreshTexture?(this.generateTilingTexture(!0),this.tilingTexture&&this.tilingTexture.needsUpdate&&(a.renderer.updateTexture(this.tilingTexture.baseTexture),this.tilingTexture.needsUpdate=!1)):a.spriteBatch.renderTilingSprite(this),b=0,c=this.children.length;c>b;b++)this.children[b]._renderWebGL(a);a.spriteBatch.stop(),this._filters&&a.filterManager.popFilter(),this._mask&&a.maskManager.popMask(this._mask,a),a.spriteBatch.start()}},b.TilingSprite.prototype._renderCanvas=function(a){if(this.visible!==!1&&0!==this.alpha){var c=a.context;this._mask&&a.maskManager.pushMask(this._mask,c),c.globalAlpha=this.worldAlpha;var d,e,f=this.worldTransform,g=a.resolution;if(c.setTransform(f.a*g,f.b*g,f.c*g,f.d*g,f.tx*g,f.ty*g),!this.__tilePattern||this.refreshTexture){if(this.generateTilingTexture(!1),!this.tilingTexture)return;this.__tilePattern=c.createPattern(this.tilingTexture.baseTexture.source,"repeat")}this.blendMode!==a.currentBlendMode&&(a.currentBlendMode=this.blendMode,c.globalCompositeOperation=b.blendModesCanvas[a.currentBlendMode]);var h=this.tilePosition,i=this.tileScale;for(h.x%=this.tilingTexture.baseTexture.width,h.y%=this.tilingTexture.baseTexture.height,c.scale(i.x,i.y),c.translate(h.x+this.anchor.x*-this._width,h.y+this.anchor.y*-this._height),c.fillStyle=this.__tilePattern,c.fillRect(-h.x,-h.y,this._width/i.x,this._height/i.y),c.scale(1/i.x,1/i.y),c.translate(-h.x+this.anchor.x*this._width,-h.y+this.anchor.y*this._height),this._mask&&a.maskManager.popMask(a.context),d=0,e=this.children.length;e>d;d++)this.children[d]._renderCanvas(a)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6807
}},b.TilingSprite.prototype.getBounds=function(){var a=this._width,b=this._height,c=a*(1-this.anchor.x),d=a*-this.anchor.x,e=b*(1-this.anchor.y),f=b*-this.anchor.y,g=this.worldTransform,h=g.a,i=g.b,j=g.c,k=g.d,l=g.tx,m=g.ty,n=h*d+j*f+l,o=k*f+i*d+m,p=h*c+j*f+l,q=k*f+i*c+m,r=h*c+j*e+l,s=k*e+i*c+m,t=h*d+j*e+l,u=k*e+i*d+m,v=-1/0,w=-1/0,x=1/0,y=1/0;x=x>n?n:x,x=x>p?p:x,x=x>r?r:x,x=x>t?t:x,y=y>o?o:y,y=y>q?q:y,y=y>s?s:y,y=y>u?u:y,v=n>v?n:v,v=p>v?p:v,v=r>v?r:v,v=t>v?t:v,w=o>w?o:w,w=q>w?q:w,w=s>w?s:w,w=u>w?u:w;var z=this._bounds;return z.x=x,z.width=v-x,z.y=y,z.height=w-y,this._currentBounds=z,z},b.TilingSprite.prototype.onTextureUpdate=function(){},b.TilingSprite.prototype.generateTilingTexture=function(a){if(this.texture.baseTexture.hasLoaded){var c,d,e=this.originalTexture||this.texture,f=e.frame,g=f.width!==e.baseTexture.width||f.height!==e.baseTexture.height,h=!1;if(a?(c=b.getNextPowerOfTwo(f.width),d=b.getNextPowerOfTwo(f.height),(f.width!==c||f.height!==d||e.baseTexture.width!==c||e.baseTexture.height||d)&&(h=!0)):g&&(c=f.width,d=f.height,h=!0),h){var i;this.tilingTexture&&this.tilingTexture.isTiling?(i=this.tilingTexture.canvasBuffer,i.resize(c,d),this.tilingTexture.baseTexture.width=c,this.tilingTexture.baseTexture.height=d,this.tilingTexture.needsUpdate=!0):(i=new b.CanvasBuffer(c,d),this.tilingTexture=b.Texture.fromCanvas(i.canvas),this.tilingTexture.canvasBuffer=i,this.tilingTexture.isTiling=!0),i.context.drawImage(e.baseTexture.source,e.crop.x,e.crop.y,e.crop.width,e.crop.height,0,0,c,d),this.tileScaleOffset.x=f.width/c,this.tileScaleOffset.y=f.height/d}else this.tilingTexture&&this.tilingTexture.isTiling&&this.tilingTexture.destroy(!0),this.tileScaleOffset.x=1,this.tileScaleOffset.y=1,this.tilingTexture=e;this.refreshTexture=!1,this.originalTexture=this.texture,this.texture=this.tilingTexture,this.tilingTexture.baseTexture._powerOf2=!0}};var c={radDeg:180/Math.PI,degRad:Math.PI/180,temp:[],Float32Array:"undefined"==typeof Float32Array?Array:Float32Array,Uint16Array:"undefined"==typeof Uint16Array?Array:Uint16Array};c.BoneData=function(a,b){this.name=a,this.parent=b},c.BoneData.prototype={length:0,x:0,y:0,rotation:0,scaleX:1,scaleY:1,inheritScale:!0,inheritRotation:!0,flipX:!1,flipY:!1},c.SlotData=function(a,b){this.name=a,this.boneData=b},c.SlotData.prototype={r:1,g:1,b:1,a:1,attachmentName:null,additiveBlending:!1},c.IkConstraintData=function(a){this.name=a,this.bones=[]},c.IkConstraintData.prototype={target:null,bendDirection:1,mix:1},c.Bone=function(a,b,c){this.data=a,this.skeleton=b,this.parent=c,this.setToSetupPose()},c.Bone.yDown=!1,c.Bone.prototype={x:0,y:0,rotation:0,rotationIK:0,scaleX:1,scaleY:1,flipX:!1,flipY:!1,m00:0,m01:0,worldX:0,m10:0,m11:0,worldY:0,worldRotation:0,worldScaleX:1,worldScaleY:1,worldFlipX:!1,worldFlipY:!1,updateWorldTransform:function(){var a=this.parent;if(a)this.worldX=this.x*a.m00+this.y*a.m01+a.worldX,this.worldY=this.x*a.m10+this.y*a.m11+a.worldY,this.data.inheritScale?(this.worldScaleX=a.worldScaleX*this.scaleX,this.worldScaleY=a.worldScaleY*this.scaleY):(this.worldScaleX=this.scaleX,this.worldScaleY=this.scaleY),this.worldRotation=this.data.inheritRotation?a.worldRotation+this.rotationIK:this.rotationIK,this.worldFlipX=a.worldFlipX!=this.flipX,this.worldFlipY=a.worldFlipY!=this.flipY;else{var b=this.skeleton.flipX,d=this.skeleton.flipY;this.worldX=b?-this.x:this.x,this.worldY=d!=c.Bone.yDown?-this.y:this.y,this.worldScaleX=this.scaleX,this.worldScaleY=this.scaleY,this.worldRotation=this.rotationIK,this.worldFlipX=b!=this.flipX,this.worldFlipY=d!=this.flipY}var e=this.worldRotation*c.degRad,f=Math.cos(e),g=Math.sin(e);this.worldFlipX?(this.m00=-f*this.worldScaleX,this.m01=g*this.worldScaleY):(this.m00=f*this.worldScaleX,this.m01=-g*this.worldScaleY),this.worldFlipY!=c.Bone.yDown?(this.m10=-g*this.worldScaleX,this.m11=-f*this.worldScaleY):(this.m10=g*this.worldScaleX,this.m11=f*this.worldScaleY)},setToSetupPose:function(){var a=this.data;this.x=a.x,this.y=a.y,this.rotation=a.rotation,this.rotationIK=this.rotation,this.scaleX=a.scaleX,this.scaleY=a.scaleY,this.flipX=a.flipX,this.flipY=a.flipY},worldToLocal:function(a){var b=a[0]-this.worldX,d=a[1]-this.worldY,e=this.m00,f=this.m10,g=this.m01,h=this.m11;this.worldFlipX!=(this.worldFlipY!=c.Bone.yDown)&&(e=-e,h=-h);var i=1/(e*h-g*f);a[0]=b*e*i-d*g*i,a[1]=d*h*i-b*f*i},localToWorld:function(a){var b=a[0],c=a[1];a[0]=b*this.m00+c*this.m01+this.worldX,a[1]=b*this.m10+c*this.m11+this.worldY}},c.Slot=function(a,b){this.data=a,this.bone=b,this.setToSetupPose()},c.Slot.prototype={r:1,g:1,b:1,a:1,_attachmentTime:0,attachment:null,attachmentVertices:[],setAttachment:function(a){this.attachment=a,this._attachmentTime=this.bone.skeleton.time,this.attachmentVertices.length=0},setAttachmentTime:function(a){this._attachmentTime=this.bone.skeleton.time-a},getAttachmentTime:function(){return this.bone.skeleton.time-this._attachmentTime},setToSetupPose:function(){var a=this.data;this.r=a.r,this.g=a.g,this.b=a.b,this.a=a.a;for(var b=this.bone.skeleton.data.slots,c=0,d=b.length;d>c;c++)if(b[c]==a){this.setAttachment(a.attachmentName?this.bone.skeleton.getAttachmentBySlotIndex(c,a.attachmentName):null);break}}},c.IkConstraint=function(a,b){this.data=a,this.mix=a.mix,this.bendDirection=a.bendDirection,this.bones=[];for(var c=0,d=a.bones.length;d>c;c++)this.bones.push(b.findBone(a.bones[c].name));this.target=b.findBone(a.target.name)},c.IkConstraint.prototype={apply:function(){var a=this.target,b=this.bones;switch(b.length){case 1:c.IkConstraint.apply1(b[0],a.worldX,a.worldY,this.mix);break;case 2:c.IkConstraint.apply2(b[0],b[1],a.worldX,a.worldY,this.bendDirection,this.mix)}}},c.IkConstraint.apply1=function(a,b,d,e){var f=a.data.inheritRotation&&a.parent?a.parent.worldRotation:0,g=a.rotation,h=Math.atan2(d-a.worldY,b-a.worldX)*c.radDeg-f;a.rotationIK=g+(h-g)*e},c.IkConstraint.apply2=function(a,b,d,e,f,g){var h=b.rotation,i=a.rotation;if(!g)return b.rotationIK=h,void(a.rotationIK=i);var j,k,l=c.temp,m=a.parent;m?(l[0]=d,l[1]=e,m.worldToLocal(l),d=(l[0]-a.x)*m.worldScaleX,e=(l[1]-a.y)*m.worldScaleY):(d-=a.x,e-=a.y),b.parent==a?(j=b.x,k=b.y):(l[0]=b.x,l[1]=b.y,b.parent.localToWorld(l),a.worldToLocal(l),j=l[0],k=l[1]);var n=j*a.worldScaleX,o=k*a.worldScaleY,p=Math.atan2(o,n),q=Math.sqrt(n*n+o*o),r=b.data.length*b.worldScaleX,s=2*q*r;if(1e-4>s)return void(b.rotationIK=h+(Math.atan2(e,d)*c.radDeg-i-h)*g);var t=(d*d+e*e-q*q-r*r)/s;-1>t?t=-1:t>1&&(t=1);var u=Math.acos(t)*f,v=q+r*t,w=r*Math.sin(u),x=Math.atan2(e*v-d*w,d*v+e*w),y=(x-p)*c.radDeg-i;y>180?y-=360:-180>y&&(y+=360),a.rotationIK=i+y*g,y=(u+p)*c.radDeg-h,y>180?y-=360:-180>y&&(y+=360),b.rotationIK=h+(y+a.worldRotation-b.parent.worldRotation)*g},c.Skin=function(a){this.name=a,this.attachments={}},c.Skin.prototype={addAttachment:function(a,b,c){this.attachments[a+":"+b]=c},getAttachment:function(a,b){return this.attachments[a+":"+b]},_attachAll:function(a,b){for(var c in b.attachments){var d=c.indexOf(":"),e=parseInt(c.substring(0,d)),f=c.substring(d+1),g=a.slots[e];if(g.attachment&&g.attachment.name==f){var h=this.getAttachment(e,f);h&&g.setAttachment(h)}}}},c.Animation=function(a,b,c){this.name=a,this.timelines=b,this.duration=c},c.Animation.prototype={apply:function(a,b,c,d,e){d&&0!=this.duration&&(c%=this.duration,b%=this.duration);for(var f=this.timelines,g=0,h=f.length;h>g;g++)f[g].apply(a,b,c,e,1)},mix:function(a,b,c,d,e,f){d&&0!=this.duration&&(c%=this.duration,b%=this.duration);for(var g=this.timelines,h=0,i=g.length;i>h;h++)g[h].apply(a,b,c,e,f)}},c.Animation.binarySearch=function(a,b,c){var d=0,e=Math.floor(a.length/c)-2;if(!e)return c;for(var f=e>>>1;;){if(a[(f+1)*c]<=b?d=f+1:e=f,d==e)return(d+1)*c;f=d+e>>>1}},c.Animation.binarySearch1=function(a,b){var c=0,d=a.length-2;if(!d)return 1;for(var e=d>>>1;;){if(a[e+1]<=b?c=e+1:d=e,c==d)return c+1;e=c+d>>>1}},c.Animation.linearSearch=function(a,b,c){for(var d=0,e=a.length-c;e>=d;d+=c)if(a[d]>b)return d;return-1},c.Curves=function(){this.curves=[]},c.Curves.prototype={setLinear:function(a){this.curves[19*a]=0},setStepped:function(a){this.curves[19*a]=1},setCurve:function(a,b,c,d,e){var f=.1,g=f*f,h=g*f,i=3*f,j=3*g,k=6*g,l=6*h,m=2*-b+d,n=2*-c+e,o=3*(b-d)+1,p=3*(c-e)+1,q=b*i+m*j+o*h,r=c*i+n*j+p*h,s=m*k+o*l,t=n*k+p*l,u=o*l,v=p*l,w=19*a,x=this.curves;x[w++]=2;for(var y=q,z=r,A=w+19-1;A>w;w+=2)x[w]=y,x[w+1]=z,q+=s,r+=t,s+=u,t+=v,y+=q,z+=r},getCurvePercent:function(a,b){b=0>b?0:b>1?1:b;var c=this.curves,d=19*a,e=c[d];if(0===e)return b;if(1==e)return 0;d++;for(var f=0,g=d,h=d+19-1;h>d;d+=2)if(f=c[d],f>=b){var i,j;return d==g?(i=0,j=0):(i=c[d-2],j=c[d-1]),j+(c[d+1]-j)*(b-i)/(f-i)}var k=c[d-1];return k+(1-k)*(b-f)/(1-f)}},c.RotateTimeline=function(a){this.curves=new c.Curves(a),this.frames=[],this.frames.length=2*a},c.RotateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(a,b,c){a*=2,this.frames[a]=b,this.frames[a+1]=c},apply:function(a,b,d,e,f){var g=this.frames;if(!(d<g[0])){var h=a.bones[this.boneIndex];if(d>=g[g.length-2]){for(var i=h.data.rotation+g[g.length-1]-h.rotation;i>180;)i-=360;for(;-180>i;)i+=360;return void(h.rotation+=i*f)}var j=c.Animation.binarySearch(g,d,2),k=g[j-1],l=g[j],m=1-(d-l)/(g[j-2]-l);m=this.curves.getCurvePercent(j/2-1,m);for(var i=g[j+1]-k;i>180;)i-=360;for(;-180>i;)i+=360;for(i=h.data.rotation+(k+i*m)-h.rotation;i>180;)i-=360;for(;-180>i;)i+=360;h.rotation+=i*f}}},c.TranslateTimeline=function(a){this.curves=new c.Curves(a),this.frames=[],this.frames.length=3*a},c.TranslateTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,d,e,f){var g=this.frames;if(!(d<g[0])){var h=a.bones[this.boneIndex];if(d>=g[g.length-3])return h.x+=(h.data.x+g[g.length-2]-h.x)*f,void(h.y+=(h.data.y+g[g.length-1]-h.y)*f);var i=c.Animation.binarySearch(g,d,3),j=g[i-2],k=g[i-1],l=g[i],m=1-(d-l)/(g[i+-3]-l);m=this.curves.getCurvePercent(i/3-1,m),h.x+=(h.data.x+j+(g[i+1]-j)*m-h.x)*f,h.y+=(h.data.y+k+(g[i+2]-k)*m-h.y)*f}}},c.ScaleTimeline=function(a){this.curves=new c.Curves(a),this.frames=[],this.frames.length=3*a},c.ScaleTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,d,e,f){var g=this.frames;if(!(d<g[0])){var h=a.bones[this.boneIndex];if(d>=g[g.length-3])return h.scaleX+=(h.data.scaleX*g[g.length-2]-h.scaleX)*f,void(h.scaleY+=(h.data.scaleY*g[g.length-1]-h.scaleY)*f);var i=c.Animation.binarySearch(g,d,3),j=g[i-2],k=g[i-1],l=g[i],m=1-(d-l)/(g[i+-3]-l);m=this.curves.getCurvePercent(i/3-1,m),h.scaleX+=(h.data.scaleX*(j+(g[i+1]-j)*m)-h.scaleX)*f,h.scaleY+=(h.data.scaleY*(k+(g[i+2]-k)*m)-h.scaleY)*f}}},c.ColorTimeline=function(a){this.curves=new c.Curves(a),this.frames=[],this.frames.length=5*a},c.ColorTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length/5},setFrame:function(a,b,c,d,e,f){a*=5,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d,this.frames[a+3]=e,this.frames[a+4]=f},apply:function(a,b,d,e,f){var g=this.frames;if(!(d<g[0])){var h,i,j,k;if(d>=g[g.length-5]){var l=g.length-1;h=g[l-3],i=g[l-2],j=g[l-1],k=g[l]}else{var m=c.Animation.binarySearch(g,d,5),n=g[m-4],o=g[m-3],p=g[m-2],q=g[m-1],r=g[m],s=1-(d-r)/(g[m-5]-r);s=this.curves.getCurvePercent(m/5-1,s),h=n+(g[m+1]-n)*s,i=o+(g[m+2]-o)*s,j=p+(g[m+3]-p)*s,k=q+(g[m+4]-q)*s}var t=a.slots[this.slotIndex];1>f?(t.r+=(h-t.r)*f,t.g+=(i-t.g)*f,t.b+=(j-t.b)*f,t.a+=(k-t.a)*f):(t.r=h,t.g=i,t.b=j,t.a=k)}}},c.AttachmentTimeline=function(a){this.curves=new c.Curves(a),this.frames=[],this.frames.length=a,this.attachmentNames=[],this.attachmentNames.length=a},c.AttachmentTimeline.prototype={slotIndex:0,getFrameCount:function(){return this.frames.length},setFrame:function(a,b,c){this.frames[a]=b,this.attachmentNames[a]=c},apply:function(a,b,d){var e=this.frames;if(d<e[0])return void(b>d&&this.apply(a,b,Number.MAX_VALUE,null,0));b>d&&(b=-1);var f=d>=e[e.length-1]?e.length-1:c.Animation.binarySearch1(e,d)-1;if(!(e[f]<b)){var g=this.attachmentNames[f];a.slots[this.slotIndex].setAttachment(g?a.getAttachmentBySlotIndex(this.slotIndex,g):null)}}},c.EventTimeline=function(a){this.frames=[],this.frames.length=a,this.events=[],this.events.length=a},c.EventTimeline.prototype={getFrameCount:function(){return this.frames.length},setFrame:function(a,b,c){this.frames[a]=b,this.events[a]=c},apply:function(a,b,d,e,f){if(e){var g=this.frames,h=g.length;if(b>d)this.apply(a,b,Number.MAX_VALUE,e,f),b=-1;else if(b>=g[h-1])return;if(!(d<g[0])){var i;if(b<g[0])i=0;else{i=c.Animation.binarySearch1(g,b);for(var j=g[i];i>0&&g[i-1]==j;)i--}for(var k=this.events;h>i&&d>=g[i];i++)e.push(k[i])}}}},c.DrawOrderTimeline=function(a){this.frames=[],this.frames.length=a,this.drawOrders=[],this.drawOrders.length=a},c.DrawOrderTimeline.prototype={getFrameCount:function(){return this.frames.length},setFrame:function(a,b,c){this.frames[a]=b,this.drawOrders[a]=c},apply:function(a,b,d){var e=this.frames;if(!(d<e[0])){var f;f=d>=e[e.length-1]?e.length-1:c.Animation.binarySearch1(e,d)-1;var g=a.drawOrder,h=a.slots,i=this.drawOrders[f];if(i)for(var j=0,k=i.length;k>j;j++)g[j]=a.slots[i[j]];else for(var j=0,k=h.length;k>j;j++)g[j]=h[j]}}},c.FfdTimeline=function(a){this.curves=new c.Curves(a),this.frames=[],this.frames.length=a,this.frameVertices=[],this.frameVertices.length=a},c.FfdTimeline.prototype={slotIndex:0,attachment:0,getFrameCount:function(){return this.frames.length},setFrame:function(a,b,c){this.frames[a]=b,this.frameVertices[a]=c},apply:function(a,b,d,e,f){var g=a.slots[this.slotIndex];if(g.attachment==this.attachment){var h=this.frames;if(!(d<h[0])){var i=this.frameVertices,j=i[0].length,k=g.attachmentVertices;if(k.length!=j&&(f=1),k.length=j,d>=h[h.length-1]){var l=i[h.length-1];if(1>f)for(var m=0;j>m;m++)k[m]+=(l[m]-k[m])*f;else for(var m=0;j>m;m++)k[m]=l[m]}else{var n=c.Animation.binarySearch1(h,d),o=h[n],p=1-(d-o)/(h[n-1]-o);p=this.curves.getCurvePercent(n-1,0>p?0:p>1?1:p);var q=i[n-1],r=i[n];if(1>f)for(var m=0;j>m;m++){var s=q[m];k[m]+=(s+(r[m]-s)*p-k[m])*f}else for(var m=0;j>m;m++){var s=q[m];k[m]=s+(r[m]-s)*p}}}}}},c.IkConstraintTimeline=function(a){this.curves=new c.Curves(a),this.frames=[],this.frames.length=3*a},c.IkConstraintTimeline.prototype={ikConstraintIndex:0,getFrameCount:function(){return this.frames.length/3},setFrame:function(a,b,c,d){a*=3,this.frames[a]=b,this.frames[a+1]=c,this.frames[a+2]=d},apply:function(a,b,d,e,f){var g=this.frames;if(!(d<g[0])){var h=a.ikConstraints[this.ikConstraintIndex];if(d>=g[g.length-3])return h.mix+=(g[g.length-2]-h.mix)*f,void(h.bendDirection=g[g.length-1]);var i=c.Animation.binarySearch(g,d,3),j=g[i+-2],k=g[i],l=1-(d-k)/(g[i+-3]-k);l=this.curves.getCurvePercent(i/3-1,l);var m=j+(g[i+1]-j)*l;h.mix+=(m-h.mix)*f,h.bendDirection=g[i+-1]}}},c.FlipXTimeline=function(a){this.curves=new c.Curves(a),this.frames=[],this.frames.length=2*a},c.FlipXTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(a,b,c){a*=2,this.frames[a]=b,this.frames[a+1]=c?1:0},apply:function(a,b,d){var e=this.frames;if(d<e[0])return void(b>d&&this.apply(a,b,Number.MAX_VALUE,null,0));b>d&&(b=-1);var f=(d>=e[e.length-2]?e.length:c.Animation.binarySearch(e,d,2))-2;e[f]<b||(a.bones[boneIndex].flipX=0!=e[f+1])}},c.FlipYTimeline=function(a){this.curves=new c.Curves(a),this.frames=[],this.frames.length=2*a},c.FlipYTimeline.prototype={boneIndex:0,getFrameCount:function(){return this.frames.length/2},setFrame:function(a,b,c){a*=2,this.frames[a]=b,this.frames[a+1]=c?1:0},apply:function(a,b,d){var e=this.frames;if(d<e[0])return void(b>d&&this.apply(a,b,Number.MAX_VALUE,null,0));b>d&&(b=-1);var f=(d>=e[e.length-2]?e.length:c.Animation.binarySearch(e,d,2))-2;e[f]<b||(a.bones[boneIndex].flipY=0!=e[f+1])}},c.SkeletonData=function(){this.bones=[],this.slots=[],this.skins=[],this.events=[],this.animations=[],this.ikConstraints=[]},c.SkeletonData.prototype={name:null,defaultSkin:null,width:0,height:0,version:null,hash:null,findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return slot[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].name==a)return c;return-1},findSkin:function(a){for(var b=this.skins,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findEvent:function(a){for(var b=this.events,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findAnimation:function(a){for(var b=this.animations,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},findIkConstraint:function(a){for(var b=this.ikConstraints,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null}},c.Skeleton=function(a){this.data=a,this.bones=[];for(var b=0,d=a.bones.length;d>b;b++){var e=a.bones[b],f=e.parent?this.bones[a.bones.indexOf(e.parent)]:null;this.bones.push(new c.Bone(e,this,f))}this.slots=[],this.drawOrder=[];for(var b=0,d=a.slots.length;d>b;b++){var g=a.slots[b],h=this.bones[a.bones.indexOf(g.boneData)],i=new c.Slot(g,h);this.slots.push(i),this.drawOrder.push(i)}this.ikConstraints=[];for(var b=0,d=a.ikConstraints.length;d>b;b++)this.ikConstraints.push(new c.IkConstraint(a.ikConstraints[b],this));this.boneCache=[],this.updateCache()},c.Skeleton.prototype={x:0,y:0,skin:null,r:1,g:1,b:1,a:1,time:0,flipX:!1,flipY:!1,updateCache:function(){var a=this.ikConstraints,b=a.length,c=b+1,d=this.boneCache;d.length>c&&(d.length=c);for(var e=0,f=d.length;f>e;e++)d[e].length=0;for(;d.length<c;)d[d.length]=[];var g=d[0],h=this.bones;a:for(var e=0,f=h.length;f>e;e++){var i=h[e],j=i;do{for(var k=0;b>k;k++)for(var l=a[k],m=l.bones[0],n=l.bones[l.bones.length-1];;){if(j==n){d[k].push(i),d[k+1].push(i);continue a}if(n==m)break;n=n.parent}j=j.parent}while(j);g[g.length]=i}},updateWorldTransform:function(){for(var a=this.bones,b=0,c=a.length;c>b;b++){var d=a[b];d.rotationIK=d.rotation}for(var b=0,e=this.boneCache.length-1;;){for(var f=this.boneCache[b],g=0,h=f.length;h>g;g++)f[g].updateWorldTransform();if(b==e)break;this.ikConstraints[b].apply(),b++}},setToSetupPose:function(){this.setBonesToSetupPose(),this.setSlotsToSetupPose()},setBonesToSetupPose:function(){for(var a=this.bones,b=0,c=a.length;c>b;b++)a[b].setToSetupPose();for(var d=this.ikConstraints,b=0,c=d.length;c>b;b++){var e=d[b];e.bendDirection=e.data.bendDirection,e.mix=e.data.mix}},setSlotsToSetupPose:function(){for(var a=this.slots,b=this.drawOrder,c=0,d=a.length;d>c;c++)b[c]=a[c],a[c].setToSetupPose(c)},getRootBone:function(){return this.bones.length?this.bones[0]:null},findBone:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findBoneIndex:function(a){for(var b=this.bones,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},findSlot:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},findSlotIndex:function(a){for(var b=this.slots,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return c;return-1},setSkinByName:function(a){var b=this.data.findSkin(a);if(!b)throw"Skin not found: "+a;this.setSkin(b)},setSkin:function(a){if(a)if(this.skin)a._attachAll(this,this.skin);else for(var b=this.slots,c=0,d=b.length;d>c;c++){var e=b[c],f=e.data.attachmentName;if(f){var g=a.getAttachment(c,f);g&&e.setAttachment(g)}}this.skin=a},getAttachmentBySlotName:function(a,b){return this.getAttachmentBySlotIndex(this.data.findSlotIndex(a),b)},getAttachmentBySlotIndex:function(a,b){if(this.skin){var c=this.skin.getAttachment(a,b);if(c)return c}return this.data.defaultSkin?this.data.defaultSkin.getAttachment(a,b):null},setAttachment:function(a,b){for(var c=this.slots,d=0,e=c.length;e>d;d++){var f=c[d];if(f.data.name==a){var g=null;if(b&&(g=this.getAttachmentBySlotIndex(d,b),!g))throw"Attachment not found: "+b+", for slot: "+a;return void f.setAttachment(g)}}throw"Slot not found: "+a},findIkConstraint:function(a){for(var b=this.ikConstraints,c=0,d=b.length;d>c;c++)if(b[c].data.name==a)return b[c];return null},update:function(a){this.time+=a}},c.EventData=function(a){this.name=a},c.EventData.prototype={intValue:0,floatValue:0,stringValue:null},c.Event=function(a){this.data=a},c.Event.prototype={intValue:0,floatValue:0,stringValue:null},c.AttachmentType={region:0,boundingbox:1,mesh:2,skinnedmesh:3},c.RegionAttachment=function(a){this.name=a,this.offset=[],this.offset.length=8,this.uvs=[],this.uvs.length=8},c.RegionAttachment.prototype={type:c.AttachmentType.region,x:0,y:0,rotation:0,scaleX:1,scaleY:1,width:0,height:0,r:1,g:1,b:1,a:1,path:null,rendererObject:null,regionOffsetX:0,regionOffsetY:0,regionWidth:0,regionHeight:0,regionOriginalWidth:0,regionOriginalHeight:0,setUVs:function(a,b,c,d,e){var f=this.uvs;e?(f[2]=a,f[3]=d,f[4]=a,f[5]=b,f[6]=c,f[7]=b,f[0]=c,f[1]=d):(f[0]=a,f[1]=d,f[2]=a,f[3]=b,f[4]=c,f[5]=b,f[6]=c,f[7]=d)},updateOffset:function(){var a=this.width/this.regionOriginalWidth*this.scaleX,b=this.height/this.regionOriginalHeight*this.scaleY,d=-this.width/2*this.scaleX+this.regionOffsetX*a,e=-this.height/2*this.scaleY+this.regionOffsetY*b,f=d+this.regionWidth*a,g=e+this.regionHeight*b,h=this.rotation*c.degRad,i=Math.cos(h),j=Math.sin(h),k=d*i+this.x,l=d*j,m=e*i+this.y,n=e*j,o=f*i+this.x,p=f*j,q=g*i+this.y,r=g*j,s=this.offset;s[0]=k-n,s[1]=m+l,s[2]=k-r,s[3]=q+l,s[4]=o-r,s[5]=q+p,s[6]=o-n,s[7]=m+p},computeVertices:function(a,b,c,d){a+=c.worldX,b+=c.worldY;var e=c.m00,f=c.m01,g=c.m10,h=c.m11,i=this.offset;d[0]=i[0]*e+i[1]*f+a,d[1]=i[0]*g+i[1]*h+b,d[2]=i[2]*e+i[3]*f+a,d[3]=i[2]*g+i[3]*h+b,d[4]=i[4]*e+i[5]*f+a,d[5]=i[4]*g+i[5]*h+b,d[6]=i[6]*e+i[7]*f+a,d[7]=i[6]*g+i[7]*h+b}},c.MeshAttachment=function(a){this.name=a},c.MeshAttachment.prototype={type:c.AttachmentType.mesh,vertices:null,uvs:null,regionUVs:null,triangles:null,hullLength:0,r:1,g:1,b:1,a:1,path:null,rendererObject:null,regionU:0,regionV:0,regionU2:0,regionV2:0,regionRotate:!1,regionOffsetX:0,regionOffsetY:0,regionWidth:0,regionHeight:0,regionOriginalWidth:0,regionOriginalHeight:0,edges:null,width:0,height:0,updateUVs:function(){var a=this.regionU2-this.regionU,b=this.regionV2-this.regionV,d=this.regionUVs.length;if(this.uvs&&this.uvs.length==d||(this.uvs=new c.Float32Array(d)),this.regionRotate)for(var e=0;d>e;e+=2)this.uvs[e]=this.regionU+this.regionUVs[e+1]*a,this.uvs[e+1]=this.regionV+b-this.regionUVs[e]*b;else for(var e=0;d>e;e+=2)this.uvs[e]=this.regionU+this.regionUVs[e]*a,this.uvs[e+1]=this.regionV+this.regionUVs[e+1]*b},computeWorldVertices:function(a,b,c,d){var e=c.bone;a+=e.worldX,b+=e.worldY;var f=e.m00,g=e.m01,h=e.m10,i=e.m11,j=this.vertices,k=j.length;c.attachmentVertices.length==k&&(j=c.attachmentVertices);for(var l=0;k>l;l+=2){var m=j[l],n=j[l+1];d[l]=m*f+n*g+a,d[l+1]=m*h+n*i+b}}},c.SkinnedMeshAttachment=function(a){this.name=a},c.SkinnedMeshAttachment.prototype={type:c.AttachmentType.skinnedmesh,bones:null,weights:null,uvs:null,regionUVs:null,triangles:null,hullLength:0,r:1,g:1,b:1,a:1,path:null,rendererObject:null,regionU:0,regionV:0,regionU2:0,regionV2:0,regionRotate:!1,regionOffsetX:0,regionOffsetY:0,regionWidth:0,regionHeight:0,regionOriginalWidth:0,regionOriginalHeight:0,edges:null,width:0,height:0,updateUVs:function(){var a=this.regionU2-this.regionU,b=this.regionV2-this.regionV,d=this.regionUVs.length;if(this.uvs&&this.uvs.length==d||(this.uvs=new c.Float32Array(d)),this.regionRotate)for(var e=0;d>e;e+=2)this.uvs[e]=this.regionU+this.regionUVs[e+1]*a,this.uvs[e+1]=this.regionV+b-this.regionUVs[e]*b;else for(var e=0;d>e;e+=2)this.uvs[e]=this.regionU+this.regionUVs[e]*a,this.uvs[e+1]=this.regionV+this.regionUVs[e+1]*b},computeWorldVertices:function(a,b,c,d){var e,f,g,h,i,j,k,l=c.bone.skeleton.bones,m=this.weights,n=this.bones,o=0,p=0,q=0,r=0,s=n.length;if(c.attachmentVertices.length)for(var t=c.attachmentVertices;s>p;o+=2){for(f=0,g=0,e=n[p++]+p;e>p;p++,q+=3,r+=2)h=l[n[p]],i=m[q]+t[r],j=m[q+1]+t[r+1],k=m[q+2],f+=(i*h.m00+j*h.m01+h.worldX)*k,g+=(i*h.m10+j*h.m11+h.worldY)*k;d[o]=f+a,d[o+1]=g+b}else for(;s>p;o+=2){for(f=0,g=0,e=n[p++]+p;e>p;p++,q+=3)h=l[n[p]],i=m[q],j=m[q+1],k=m[q+2],f+=(i*h.m00+j*h.m01+h.worldX)*k,g+=(i*h.m10+j*h.m11+h.worldY)*k;d[o]=f+a,d[o+1]=g+b}}},c.BoundingBoxAttachment=function(a){this.name=a,this.vertices=[]},c.BoundingBoxAttachment.prototype={type:c.AttachmentType.boundingbox,computeWorldVertices:function(a,b,c,d){a+=c.worldX,b+=c.worldY;for(var e=c.m00,f=c.m01,g=c.m10,h=c.m11,i=this.vertices,j=0,k=i.length;k>j;j+=2){var l=i[j],m=i[j+1];d[j]=l*e+m*f+a,d[j+1]=l*g+m*h+b}}},c.AnimationStateData=function(a){this.skeletonData=a,this.animationToMixTime={}},c.AnimationStateData.prototype={defaultMix:0,setMixByName:function(a,b,c){var d=this.skeletonData.findAnimation(a);if(!d)throw"Animation not found: "+a;var e=this.skeletonData.findAnimation(b);if(!e)throw"Animation not found: "+b;this.setMix(d,e,c)},setMix:function(a,b,c){this.animationToMixTime[a.name+":"+b.name]=c},getMix:function(a,b){var c=a.name+":"+b.name;return this.animationToMixTime.hasOwnProperty(c)?this.animationToMixTime[c]:this.defaultMix}},c.TrackEntry=function(){},c.TrackEntry.prototype={next:null,previous:null,animation:null,loop:!1,delay:0,time:0,lastTime:-1,endTime:0,timeScale:1,mixTime:0,mixDuration:0,mix:1,onStart:null,onEnd:null,onComplete:null,onEvent:null},c.AnimationState=function(a){this.data=a,this.tracks=[],this.events=[]},c.AnimationState.prototype={onStart:null,onEnd:null,onComplete:null,onEvent:null,timeScale:1,update:function(a){a*=this.timeScale;for(var b=0;b<this.tracks.length;b++){var c=this.tracks[b];if(c){if(c.time+=a*c.timeScale,c.previous){var d=a*c.previous.timeScale;c.previous.time+=d,c.mixTime+=d}var e=c.next;e?(e.time=c.lastTime-e.delay,e.time>=0&&this.setCurrent(b,e)):!c.loop&&c.lastTime>=c.endTime&&this.clearTrack(b)}}},apply:function(a){for(var b=0;b<this.tracks.length;b++){var c=this.tracks[b];if(c){this.events.length=0;var d=c.time,e=c.lastTime,f=c.endTime,g=c.loop;!g&&d>f&&(d=f);var h=c.previous;if(h){var i=h.time;!h.loop&&i>h.endTime&&(i=h.endTime),h.animation.apply(a,i,i,h.loop,null);var j=c.mixTime/c.mixDuration*c.mix;j>=1&&(j=1,c.previous=null),c.animation.mix(a,c.lastTime,d,g,this.events,j)}else 1==c.mix?c.animation.apply(a,c.lastTime,d,g,this.events):c.animation.mix(a,c.lastTime,d,g,this.events,c.mix);for(var k=0,l=this.events.length;l>k;k++){var m=this.events[k];c.onEvent&&c.onEvent(b,m),this.onEvent&&this.onEvent(b,m)}if(g?e%f>d%f:f>e&&d>=f){var n=Math.floor(d/f);c.onComplete&&c.onComplete(b,n),this.onComplete&&this.onComplete(b,n)}c.lastTime=c.time}}},clearTracks:function(){for(var a=0,b=this.tracks.length;b>a;a++)this.clearTrack(a);this.tracks.length=0},clearTrack:function(a){if(!(a>=this.tracks.length)){var b=this.tracks[a];b&&(b.onEnd&&b.onEnd(a),this.onEnd&&this.onEnd(a),this.tracks[a]=null)}},_expandToIndex:function(a){if(a<this.tracks.length)return this.tracks[a];for(;a>=this.tracks.length;)this.tracks.push(null);return null},setCurrent:function(a,b){var c=this._expandToIndex(a);if(c){var d=c.previous;c.previous=null,c.onEnd&&c.onEnd(a),this.onEnd&&this.onEnd(a),b.mixDuration=this.data.getMix(c.animation,b.animation),b.mixDuration>0&&(b.mixTime=0,b.previous=d&&c.mixTime/c.mixDuration<.5?d:c)}this.tracks[a]=b,b.onStart&&b.onStart(a),this.onStart&&this.onStart(a)},setAnimationByName:function(a,b,c){var d=this.data.skeletonData.findAnimation(b);if(!d)throw"Animation not found: "+b;return this.setAnimation(a,d,c)},setAnimation:function(a,b,d){var e=new c.TrackEntry;return e.animation=b,e.loop=d,e.endTime=b.duration,this.setCurrent(a,e),e},addAnimationByName:function(a,b,c,d){var e=this.data.skeletonData.findAnimation(b);if(!e)throw"Animation not found: "+b;return this.addAnimation(a,e,c,d)},addAnimation:function(a,b,d,e){var f=new c.TrackEntry;f.animation=b,f.loop=d,f.endTime=b.duration;var g=this._expandToIndex(a);if(g){for(;g.next;)g=g.next;g.next=f}else this.tracks[a]=f;return 0>=e&&(g?e+=g.endTime-this.data.getMix(g.animation,b):e=0),f.delay=e,f},getCurrent:function(a){return a>=this.tracks.length?null:this.tracks[a]}},c.SkeletonJson=function(a){this.attachmentLoader=a},c.SkeletonJson.prototype={scale:1,readSkeletonData:function(a,b){var d=new c.SkeletonData;d.name=b;var e=a.skeleton;e&&(d.hash=e.hash,d.version=e.spine,d.width=e.width||0,d.height=e.height||0);for(var f=a.bones,g=0,h=f.length;h>g;g++){var i=f[g],j=null;if(i.parent&&(j=d.findBone(i.parent),!j))throw"Parent bone not found: "+i.parent;var k=new c.BoneData(i.name,j);k.length=(i.length||0)*this.scale,k.x=(i.x||0)*this.scale,k.y=(i.y||0)*this.scale,k.rotation=i.rotation||0,k.scaleX=i.hasOwnProperty("scaleX")?i.scaleX:1,k.scaleY=i.hasOwnProperty("scaleY")?i.scaleY:1,k.inheritScale=i.hasOwnProperty("inheritScale")?i.inheritScale:!0,k.inheritRotation=i.hasOwnProperty("inheritRotation")?i.inheritRotation:!0,d.bones.push(k)}var l=a.ik;if(l)for(var g=0,h=l.length;h>g;g++){for(var m=l[g],n=new c.IkConstraintData(m.name),f=m.bones,o=0,p=f.length;p>o;o++){var q=d.findBone(f[o]);if(!q)throw"IK bone not found: "+f[o];n.bones.push(q)}if(n.target=d.findBone(m.target),!n.target)throw"Target bone not found: "+m.target;n.bendDirection=!m.hasOwnProperty("bendPositive")||m.bendPositive?1:-1,n.mix=m.hasOwnProperty("mix")?m.mix:1,d.ikConstraints.push(n)}for(var r=a.slots,g=0,h=r.length;h>g;g++){var s=r[g],k=d.findBone(s.bone);if(!k)throw"Slot bone not found: "+s.bone;var t=new c.SlotData(s.name,k),u=s.color;u&&(t.r=this.toColor(u,0),t.g=this.toColor(u,1),t.b=this.toColor(u,2),t.a=this.toColor(u,3)),t.attachmentName=s.attachment,t.additiveBlending=s.additive&&"true"==s.additive,d.slots.push(t)}var v=a.skins;for(var w in v)if(v.hasOwnProperty(w)){var x=v[w],y=new c.Skin(w);for(var z in x)if(x.hasOwnProperty(z)){var A=d.findSlotIndex(z),B=x[z];for(var C in B)if(B.hasOwnProperty(C)){var D=this.readAttachment(y,C,B[C]);D&&y.addAttachment(A,C,D)}}d.skins.push(y),"default"==y.name&&(d.defaultSkin=y)}var E=a.events;for(var F in E)if(E.hasOwnProperty(F)){var G=E[F],H=new c.EventData(F);H.intValue=G["int"]||0,H.floatValue=G["float"]||0,H.stringValue=G.string||null,d.events.push(H)}var I=a.animations;for(var J in I)I.hasOwnProperty(J)&&this.readAnimation(J,I[J],d);return d},readAttachment:function(a,b,d){b=d.name||b;var e=c.AttachmentType[d.type||"region"],f=d.path||b,g=this.scale;if(e==c.AttachmentType.region){var h=this.attachmentLoader.newRegionAttachment(a,b,f);if(!h)return null;h.path=f,h.x=(d.x||0)*g,h.y=(d.y||0)*g,h.scaleX=d.hasOwnProperty("scaleX")?d.scaleX:1,h.scaleY=d.hasOwnProperty("scaleY")?d.scaleY:1,h.rotation=d.rotation||0,h.width=(d.width||0)*g,h.height=(d.height||0)*g;var i=d.color;return i&&(h.r=this.toColor(i,0),h.g=this.toColor(i,1),h.b=this.toColor(i,2),h.a=this.toColor(i,3)),h.updateOffset(),h}if(e==c.AttachmentType.mesh){var j=this.attachmentLoader.newMeshAttachment(a,b,f);return j?(j.path=f,j.vertices=this.getFloatArray(d,"vertices",g),j.triangles=this.getIntArray(d,"triangles"),j.regionUVs=this.getFloatArray(d,"uvs",1),j.updateUVs(),i=d.color,i&&(j.r=this.toColor(i,0),j.g=this.toColor(i,1),j.b=this.toColor(i,2),j.a=this.toColor(i,3)),j.hullLength=2*(d.hull||0),d.edges&&(j.edges=this.getIntArray(d,"edges")),j.width=(d.width||0)*g,j.height=(d.height||0)*g,j):null}if(e==c.AttachmentType.skinnedmesh){var j=this.attachmentLoader.newSkinnedMeshAttachment(a,b,f);if(!j)return null;j.path=f;for(var k=this.getFloatArray(d,"uvs",1),l=this.getFloatArray(d,"vertices",1),m=[],n=[],o=0,p=l.length;p>o;){var q=0|l[o++];n[n.length]=q;for(var r=o+4*q;r>o;)n[n.length]=l[o],m[m.length]=l[o+1]*g,m[m.length]=l[o+2]*g,m[m.length]=l[o+3],o+=4}return j.bones=n,j.weights=m,j.triangles=this.getIntArray(d,"triangles"),j.regionUVs=k,j.updateUVs(),i=d.color,i&&(j.r=this.toColor(i,0),j.g=this.toColor(i,1),j.b=this.toColor(i,2),j.a=this.toColor(i,3)),j.hullLength=2*(d.hull||0),d.edges&&(j.edges=this.getIntArray(d,"edges")),j.width=(d.width||0)*g,j.height=(d.height||0)*g,j
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6808
}if(e==c.AttachmentType.boundingbox){for(var s=this.attachmentLoader.newBoundingBoxAttachment(a,b),l=d.vertices,o=0,p=l.length;p>o;o++)s.vertices.push(l[o]*g);return s}throw"Unknown attachment type: "+e},readAnimation:function(a,b,d){var e=[],f=0,g=b.slots;for(var h in g)if(g.hasOwnProperty(h)){var i=g[h],j=d.findSlotIndex(h);for(var k in i)if(i.hasOwnProperty(k)){var l=i[k];if("color"==k){var m=new c.ColorTimeline(l.length);m.slotIndex=j;for(var n=0,o=0,p=l.length;p>o;o++){var q=l[o],r=q.color,s=this.toColor(r,0),t=this.toColor(r,1),u=this.toColor(r,2),v=this.toColor(r,3);m.setFrame(n,q.time,s,t,u,v),this.readCurve(m,n,q),n++}e.push(m),f=Math.max(f,m.frames[5*m.getFrameCount()-5])}else{if("attachment"!=k)throw"Invalid timeline type for a slot: "+k+" ("+h+")";var m=new c.AttachmentTimeline(l.length);m.slotIndex=j;for(var n=0,o=0,p=l.length;p>o;o++){var q=l[o];m.setFrame(n++,q.time,q.name)}e.push(m),f=Math.max(f,m.frames[m.getFrameCount()-1])}}}var w=b.bones;for(var x in w)if(w.hasOwnProperty(x)){var y=d.findBoneIndex(x);if(-1==y)throw"Bone not found: "+x;var z=w[x];for(var k in z)if(z.hasOwnProperty(k)){var l=z[k];if("rotate"==k){var m=new c.RotateTimeline(l.length);m.boneIndex=y;for(var n=0,o=0,p=l.length;p>o;o++){var q=l[o];m.setFrame(n,q.time,q.angle),this.readCurve(m,n,q),n++}e.push(m),f=Math.max(f,m.frames[2*m.getFrameCount()-2])}else if("translate"==k||"scale"==k){var m,A=1;"scale"==k?m=new c.ScaleTimeline(l.length):(m=new c.TranslateTimeline(l.length),A=this.scale),m.boneIndex=y;for(var n=0,o=0,p=l.length;p>o;o++){var q=l[o],B=(q.x||0)*A,C=(q.y||0)*A;m.setFrame(n,q.time,B,C),this.readCurve(m,n,q),n++}e.push(m),f=Math.max(f,m.frames[3*m.getFrameCount()-3])}else{if("flipX"!=k&&"flipY"!=k)throw"Invalid timeline type for a bone: "+k+" ("+x+")";var B="flipX"==k,m=B?new c.FlipXTimeline(l.length):new c.FlipYTimeline(l.length);m.boneIndex=y;for(var D=B?"x":"y",n=0,o=0,p=l.length;p>o;o++){var q=l[o];m.setFrame(n,q.time,q[D]||!1),n++}e.push(m),f=Math.max(f,m.frames[2*m.getFrameCount()-2])}}}var E=b.ik;for(var F in E)if(E.hasOwnProperty(F)){var G=d.findIkConstraint(F),l=E[F],m=new c.IkConstraintTimeline(l.length);m.ikConstraintIndex=d.ikConstraints.indexOf(G);for(var n=0,o=0,p=l.length;p>o;o++){var q=l[o],H=q.hasOwnProperty("mix")?q.mix:1,I=!q.hasOwnProperty("bendPositive")||q.bendPositive?1:-1;m.setFrame(n,q.time,H,I),this.readCurve(m,n,q),n++}e.push(m),f=Math.max(f,m.frames[3*m.frameCount-3])}var J=b.ffd;for(var K in J){var L=d.findSkin(K),i=J[K];for(h in i){var j=d.findSlotIndex(h),M=i[h];for(var N in M){var l=M[N],m=new c.FfdTimeline(l.length),O=L.getAttachment(j,N);if(!O)throw"FFD attachment not found: "+N;m.slotIndex=j,m.attachment=O;var P,Q=O.type==c.AttachmentType.mesh;P=Q?O.vertices.length:O.weights.length/3*2;for(var n=0,o=0,p=l.length;p>o;o++){var R,q=l[o];if(q.vertices){var S=q.vertices,R=[];R.length=P;var T=q.offset||0,U=S.length;if(1==this.scale)for(var V=0;U>V;V++)R[V+T]=S[V];else for(var V=0;U>V;V++)R[V+T]=S[V]*this.scale;if(Q)for(var W=O.vertices,V=0,U=R.length;U>V;V++)R[V]+=W[V]}else Q?R=O.vertices:(R=[],R.length=P);m.setFrame(n,q.time,R),this.readCurve(m,n,q),n++}e[e.length]=m,f=Math.max(f,m.frames[m.frameCount-1])}}}var X=b.drawOrder;if(X||(X=b.draworder),X){for(var m=new c.DrawOrderTimeline(X.length),Y=d.slots.length,n=0,o=0,p=X.length;p>o;o++){var Z=X[o],$=null;if(Z.offsets){$=[],$.length=Y;for(var V=Y-1;V>=0;V--)$[V]=-1;var _=Z.offsets,ab=[];ab.length=Y-_.length;for(var bb=0,cb=0,V=0,U=_.length;U>V;V++){var db=_[V],j=d.findSlotIndex(db.slot);if(-1==j)throw"Slot not found: "+db.slot;for(;bb!=j;)ab[cb++]=bb++;$[bb+db.offset]=bb++}for(;Y>bb;)ab[cb++]=bb++;for(var V=Y-1;V>=0;V--)-1==$[V]&&($[V]=ab[--cb])}m.setFrame(n++,Z.time,$)}e.push(m),f=Math.max(f,m.frames[m.getFrameCount()-1])}var eb=b.events;if(eb){for(var m=new c.EventTimeline(eb.length),n=0,o=0,p=eb.length;p>o;o++){var fb=eb[o],gb=d.findEvent(fb.name);if(!gb)throw"Event not found: "+fb.name;var hb=new c.Event(gb);hb.intValue=fb.hasOwnProperty("int")?fb["int"]:gb.intValue,hb.floatValue=fb.hasOwnProperty("float")?fb["float"]:gb.floatValue,hb.stringValue=fb.hasOwnProperty("string")?fb.string:gb.stringValue,m.setFrame(n++,fb.time,hb)}e.push(m),f=Math.max(f,m.frames[m.getFrameCount()-1])}d.animations.push(new c.Animation(a,e,f))},readCurve:function(a,b,c){var d=c.curve;d?"stepped"==d?a.curves.setStepped(b):d instanceof Array&&a.curves.setCurve(b,d[0],d[1],d[2],d[3]):a.curves.setLinear(b)},toColor:function(a,b){if(8!=a.length)throw"Color hexidecimal length must be 8, recieved: "+a;return parseInt(a.substring(2*b,2*b+2),16)/255},getFloatArray:function(a,b,d){var e=a[b],f=new c.Float32Array(e.length),g=0,h=e.length;if(1==d)for(;h>g;g++)f[g]=e[g];else for(;h>g;g++)f[g]=e[g]*d;return f},getIntArray:function(a,b){for(var d=a[b],e=new c.Uint16Array(d.length),f=0,g=d.length;g>f;f++)e[f]=0|d[f];return e}},c.Atlas=function(a,b){this.textureLoader=b,this.pages=[],this.regions=[];var d=new c.AtlasReader(a),e=[];e.length=4;for(var f=null;;){var g=d.readLine();if(null===g)break;if(g=d.trim(g),g.length)if(f){var h=new c.AtlasRegion;h.name=g,h.page=f,h.rotate="true"==d.readValue(),d.readTuple(e);var i=parseInt(e[0]),j=parseInt(e[1]);d.readTuple(e);var k=parseInt(e[0]),l=parseInt(e[1]);h.u=i/f.width,h.v=j/f.height,h.rotate?(h.u2=(i+l)/f.width,h.v2=(j+k)/f.height):(h.u2=(i+k)/f.width,h.v2=(j+l)/f.height),h.x=i,h.y=j,h.width=Math.abs(k),h.height=Math.abs(l),4==d.readTuple(e)&&(h.splits=[parseInt(e[0]),parseInt(e[1]),parseInt(e[2]),parseInt(e[3])],4==d.readTuple(e)&&(h.pads=[parseInt(e[0]),parseInt(e[1]),parseInt(e[2]),parseInt(e[3])],d.readTuple(e))),h.originalWidth=parseInt(e[0]),h.originalHeight=parseInt(e[1]),d.readTuple(e),h.offsetX=parseInt(e[0]),h.offsetY=parseInt(e[1]),h.index=parseInt(d.readValue()),this.regions.push(h)}else{f=new c.AtlasPage,f.name=g,2==d.readTuple(e)&&(f.width=parseInt(e[0]),f.height=parseInt(e[1]),d.readTuple(e)),f.format=c.Atlas.Format[e[0]],d.readTuple(e),f.minFilter=c.Atlas.TextureFilter[e[0]],f.magFilter=c.Atlas.TextureFilter[e[1]];var m=d.readValue();f.uWrap=c.Atlas.TextureWrap.clampToEdge,f.vWrap=c.Atlas.TextureWrap.clampToEdge,"x"==m?f.uWrap=c.Atlas.TextureWrap.repeat:"y"==m?f.vWrap=c.Atlas.TextureWrap.repeat:"xy"==m&&(f.uWrap=f.vWrap=c.Atlas.TextureWrap.repeat),b.load(f,g,this),this.pages.push(f)}else f=null}},c.Atlas.prototype={findRegion:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++)if(b[c].name==a)return b[c];return null},dispose:function(){for(var a=this.pages,b=0,c=a.length;c>b;b++)this.textureLoader.unload(a[b].rendererObject)},updateUVs:function(a){for(var b=this.regions,c=0,d=b.length;d>c;c++){var e=b[c];e.page==a&&(e.u=e.x/a.width,e.v=e.y/a.height,e.rotate?(e.u2=(e.x+e.height)/a.width,e.v2=(e.y+e.width)/a.height):(e.u2=(e.x+e.width)/a.width,e.v2=(e.y+e.height)/a.height))}}},c.Atlas.Format={alpha:0,intensity:1,luminanceAlpha:2,rgb565:3,rgba4444:4,rgb888:5,rgba8888:6},c.Atlas.TextureFilter={nearest:0,linear:1,mipMap:2,mipMapNearestNearest:3,mipMapLinearNearest:4,mipMapNearestLinear:5,mipMapLinearLinear:6},c.Atlas.TextureWrap={mirroredRepeat:0,clampToEdge:1,repeat:2},c.AtlasPage=function(){},c.AtlasPage.prototype={name:null,format:null,minFilter:null,magFilter:null,uWrap:null,vWrap:null,rendererObject:null,width:0,height:0},c.AtlasRegion=function(){},c.AtlasRegion.prototype={page:null,name:null,x:0,y:0,width:0,height:0,u:0,v:0,u2:0,v2:0,offsetX:0,offsetY:0,originalWidth:0,originalHeight:0,index:0,rotate:!1,splits:null,pads:null},c.AtlasReader=function(a){this.lines=a.split(/\r\n|\r|\n/)},c.AtlasReader.prototype={index:0,trim:function(a){return a.replace(/^\s+|\s+$/g,"")},readLine:function(){return this.index>=this.lines.length?null:this.lines[this.index++]},readValue:function(){var a=this.readLine(),b=a.indexOf(":");if(-1==b)throw"Invalid line: "+a;return this.trim(a.substring(b+1))},readTuple:function(a){var b=this.readLine(),c=b.indexOf(":");if(-1==c)throw"Invalid line: "+b;for(var d=0,e=c+1;3>d;d++){var f=b.indexOf(",",e);if(-1==f)break;a[d]=this.trim(b.substr(e,f-e)),e=f+1}return a[d]=this.trim(b.substring(e)),d+1}},c.AtlasAttachmentLoader=function(a){this.atlas=a},c.AtlasAttachmentLoader.prototype={newRegionAttachment:function(a,b,d){var e=this.atlas.findRegion(d);if(!e)throw"Region not found in atlas: "+d+" (region attachment: "+b+")";var f=new c.RegionAttachment(b);return f.rendererObject=e,f.setUVs(e.u,e.v,e.u2,e.v2,e.rotate),f.regionOffsetX=e.offsetX,f.regionOffsetY=e.offsetY,f.regionWidth=e.width,f.regionHeight=e.height,f.regionOriginalWidth=e.originalWidth,f.regionOriginalHeight=e.originalHeight,f},newMeshAttachment:function(a,b,d){var e=this.atlas.findRegion(d);if(!e)throw"Region not found in atlas: "+d+" (mesh attachment: "+b+")";var f=new c.MeshAttachment(b);return f.rendererObject=e,f.regionU=e.u,f.regionV=e.v,f.regionU2=e.u2,f.regionV2=e.v2,f.regionRotate=e.rotate,f.regionOffsetX=e.offsetX,f.regionOffsetY=e.offsetY,f.regionWidth=e.width,f.regionHeight=e.height,f.regionOriginalWidth=e.originalWidth,f.regionOriginalHeight=e.originalHeight,f},newSkinnedMeshAttachment:function(a,b,d){var e=this.atlas.findRegion(d);if(!e)throw"Region not found in atlas: "+d+" (skinned mesh attachment: "+b+")";var f=new c.SkinnedMeshAttachment(b);return f.rendererObject=e,f.regionU=e.u,f.regionV=e.v,f.regionU2=e.u2,f.regionV2=e.v2,f.regionRotate=e.rotate,f.regionOffsetX=e.offsetX,f.regionOffsetY=e.offsetY,f.regionWidth=e.width,f.regionHeight=e.height,f.regionOriginalWidth=e.originalWidth,f.regionOriginalHeight=e.originalHeight,f},newBoundingBoxAttachment:function(a,b){return new c.BoundingBoxAttachment(b)}},c.SkeletonBounds=function(){this.polygonPool=[],this.polygons=[],this.boundingBoxes=[]},c.SkeletonBounds.prototype={minX:0,minY:0,maxX:0,maxY:0,update:function(a,b){var d=a.slots,e=d.length,f=a.x,g=a.y,h=this.boundingBoxes,i=this.polygonPool,j=this.polygons;h.length=0;for(var k=0,l=j.length;l>k;k++)i.push(j[k]);j.length=0;for(var k=0;e>k;k++){var m=d[k],n=m.attachment;if(n.type==c.AttachmentType.boundingbox){h.push(n);var o,p=i.length;p>0?(o=i[p-1],i.splice(p-1,1)):o=[],j.push(o),o.length=n.vertices.length,n.computeWorldVertices(f,g,m.bone,o)}}b&&this.aabbCompute()},aabbCompute:function(){for(var a=this.polygons,b=Number.MAX_VALUE,c=Number.MAX_VALUE,d=Number.MIN_VALUE,e=Number.MIN_VALUE,f=0,g=a.length;g>f;f++)for(var h=a[f],i=0,j=h.length;j>i;i+=2){var k=h[i],l=h[i+1];b=Math.min(b,k),c=Math.min(c,l),d=Math.max(d,k),e=Math.max(e,l)}this.minX=b,this.minY=c,this.maxX=d,this.maxY=e},aabbContainsPoint:function(a,b){return a>=this.minX&&a<=this.maxX&&b>=this.minY&&b<=this.maxY},aabbIntersectsSegment:function(a,b,c,d){var e=this.minX,f=this.minY,g=this.maxX,h=this.maxY;if(e>=a&&e>=c||f>=b&&f>=d||a>=g&&c>=g||b>=h&&d>=h)return!1;var i=(d-b)/(c-a),j=i*(e-a)+b;if(j>f&&h>j)return!0;if(j=i*(g-a)+b,j>f&&h>j)return!0;var k=(f-b)/i+a;return k>e&&g>k?!0:(k=(h-b)/i+a,k>e&&g>k?!0:!1)},aabbIntersectsSkeleton:function(a){return this.minX<a.maxX&&this.maxX>a.minX&&this.minY<a.maxY&&this.maxY>a.minY},containsPoint:function(a,b){for(var c=this.polygons,d=0,e=c.length;e>d;d++)if(this.polygonContainsPoint(c[d],a,b))return this.boundingBoxes[d];return null},intersectsSegment:function(a,b,c,d){for(var e=this.polygons,f=0,g=e.length;g>f;f++)if(e[f].intersectsSegment(a,b,c,d))return this.boundingBoxes[f];return null},polygonContainsPoint:function(a,b,c){for(var d=a.length,e=d-2,f=!1,g=0;d>g;g+=2){var h=a[g+1],i=a[e+1];if(c>h&&i>=c||c>i&&h>=c){var j=a[g];j+(c-h)/(i-h)*(a[e]-j)<b&&(f=!f)}e=g}return f},polygonIntersectsSegment:function(a,b,c,d,e){for(var f=a.length,g=b-d,h=c-e,i=b*e-c*d,j=a[f-2],k=a[f-1],l=0;f>l;l+=2){var m=a[l],n=a[l+1],o=j*n-k*m,p=j-m,q=k-n,r=g*q-h*p,s=(i*p-g*o)/r;if((s>=j&&m>=s||s>=m&&j>=s)&&(s>=b&&d>=s||s>=d&&b>=s)){var t=(i*q-h*o)/r;if((t>=k&&n>=t||t>=n&&k>=t)&&(t>=c&&e>=t||t>=e&&c>=t))return!0}j=m,k=n}return!1},getPolygon:function(a){var b=this.boundingBoxes.indexOf(a);return-1==b?null:this.polygons[b]},getWidth:function(){return this.maxX-this.minX},getHeight:function(){return this.maxY-this.minY}},c.Bone.yDown=!0,b.AnimCache={},b.SpineTextureLoader=function(a,c){b.EventTarget.call(this),this.basePath=a,this.crossorigin=c,this.loadingCount=0},b.SpineTextureLoader.prototype=b.SpineTextureLoader,b.SpineTextureLoader.prototype.load=function(a,c){if(a.rendererObject=b.BaseTexture.fromImage(this.basePath+"/"+c,this.crossorigin),!a.rendererObject.hasLoaded){var d=this;++d.loadingCount,a.rendererObject.addEventListener("loaded",function(){--d.loadingCount,d.dispatchEvent({type:"loadedBaseTexture",content:d})})}},b.SpineTextureLoader.prototype.unload=function(a){a.destroy(!0)},b.Spine=function(a){if(b.DisplayObjectContainer.call(this),this.spineData=b.AnimCache[a],!this.spineData)throw new Error("Spine data must be preloaded using PIXI.SpineLoader or PIXI.AssetLoader: "+a);this.skeleton=new c.Skeleton(this.spineData),this.skeleton.updateWorldTransform(),this.stateData=new c.AnimationStateData(this.spineData),this.state=new c.AnimationState(this.stateData),this.slotContainers=[];for(var d=0,e=this.skeleton.drawOrder.length;e>d;d++){var f=this.skeleton.drawOrder[d],g=f.attachment,h=new b.DisplayObjectContainer;if(this.slotContainers.push(h),this.addChild(h),g instanceof c.RegionAttachment){var i=g.rendererObject.name,j=this.createSprite(f,g);f.currentSprite=j,f.currentSpriteName=i,h.addChild(j)}else{if(!(g instanceof c.MeshAttachment))continue;var k=this.createMesh(f,g);f.currentMesh=k,f.currentMeshName=g.name,h.addChild(k)}}this.autoUpdate=!0},b.Spine.prototype=Object.create(b.DisplayObjectContainer.prototype),b.Spine.prototype.constructor=b.Spine,Object.defineProperty(b.Spine.prototype,"autoUpdate",{get:function(){return this.updateTransform===b.Spine.prototype.autoUpdateTransform},set:function(a){this.updateTransform=a?b.Spine.prototype.autoUpdateTransform:b.DisplayObjectContainer.prototype.updateTransform}}),b.Spine.prototype.update=function(a){this.state.update(a),this.state.apply(this.skeleton),this.skeleton.updateWorldTransform();for(var d=this.skeleton.drawOrder,e=0,f=d.length;f>e;e++){var g=d[e],h=g.attachment,i=this.slotContainers[e];if(h){var j=h.type;if(j===c.AttachmentType.region){if(h.rendererObject&&(!g.currentSpriteName||g.currentSpriteName!==h.name)){var k=h.rendererObject.name;if(void 0!==g.currentSprite&&(g.currentSprite.visible=!1),g.sprites=g.sprites||{},void 0!==g.sprites[k])g.sprites[k].visible=!0;else{var l=this.createSprite(g,h);i.addChild(l)}g.currentSprite=g.sprites[k],g.currentSpriteName=k}var m=g.bone;i.position.x=m.worldX+h.x*m.m00+h.y*m.m01,i.position.y=m.worldY+h.x*m.m10+h.y*m.m11,i.scale.x=m.worldScaleX,i.scale.y=m.worldScaleY,i.rotation=-(g.bone.worldRotation*c.degRad),g.currentSprite.tint=b.rgb2hex([g.r,g.g,g.b])}else{if(j!==c.AttachmentType.skinnedmesh){i.visible=!1;continue}if(!g.currentMeshName||g.currentMeshName!==h.name){var n=h.name;if(void 0!==g.currentMesh&&(g.currentMesh.visible=!1),g.meshes=g.meshes||{},void 0!==g.meshes[n])g.meshes[n].visible=!0;else{var o=this.createMesh(g,h);i.addChild(o)}g.currentMesh=g.meshes[n],g.currentMeshName=n}h.computeWorldVertices(g.bone.skeleton.x,g.bone.skeleton.y,g,g.currentMesh.vertices)}i.visible=!0,i.alpha=g.a}else i.visible=!1}},b.Spine.prototype.autoUpdateTransform=function(){this.lastTime=this.lastTime||Date.now();var a=.001*(Date.now()-this.lastTime);this.lastTime=Date.now(),this.update(a),b.DisplayObjectContainer.prototype.updateTransform.call(this)},b.Spine.prototype.createSprite=function(a,d){var e=d.rendererObject,f=e.page.rendererObject,g=new b.Rectangle(e.x,e.y,e.rotate?e.height:e.width,e.rotate?e.width:e.height),h=new b.Texture(f,g),i=new b.Sprite(h),j=e.rotate?.5*Math.PI:0;return i.scale.set(e.width/e.originalWidth,e.height/e.originalHeight),i.rotation=j-d.rotation*c.degRad,i.anchor.x=i.anchor.y=.5,a.sprites=a.sprites||{},a.sprites[e.name]=i,i},b.Spine.prototype.createMesh=function(a,c){var d=c.rendererObject,e=d.page.rendererObject,f=new b.Texture(e),g=new b.Strip(f);return g.drawMode=b.Strip.DrawModes.TRIANGLES,g.canvasPadding=1.5,g.vertices=new b.Float32Array(c.uvs.length),g.uvs=c.uvs,g.indices=c.triangles,a.meshes=a.meshes||{},a.meshes[c.name]=g,g},b.BaseTextureCache={},b.BaseTextureCacheIdGenerator=0,b.BaseTexture=function(a,c){if(this.resolution=1,this.width=100,this.height=100,this.scaleMode=c||b.scaleModes.DEFAULT,this.hasLoaded=!1,this.source=a,this._UID=b._UID++,this.premultipliedAlpha=!0,this._glTextures=[],this.mipmap=!1,this._dirty=[!0,!0,!0,!0],a){if((this.source.complete||this.source.getContext)&&this.source.width&&this.source.height)this.hasLoaded=!0,this.width=this.source.naturalWidth||this.source.width,this.height=this.source.naturalHeight||this.source.height,this.dirty();else{var d=this;this.source.onload=function(){d.hasLoaded=!0,d.width=d.source.naturalWidth||d.source.width,d.height=d.source.naturalHeight||d.source.height,d.dirty(),d.dispatchEvent({type:"loaded",content:d})},this.source.onerror=function(){d.dispatchEvent({type:"error",content:d})}}this.imageUrl=null,this._powerOf2=!1}},b.BaseTexture.prototype.constructor=b.BaseTexture,b.EventTarget.mixin(b.BaseTexture.prototype),b.BaseTexture.prototype.destroy=function(){this.imageUrl?(delete b.BaseTextureCache[this.imageUrl],delete b.TextureCache[this.imageUrl],this.imageUrl=null,navigator.isCocoonJS||(this.source.src="")):this.source&&this.source._pixiId&&delete b.BaseTextureCache[this.source._pixiId],this.source=null,this.unloadFromGPU()},b.BaseTexture.prototype.updateSourceImage=function(a){this.hasLoaded=!1,this.source.src=null,this.source.src=a},b.BaseTexture.prototype.dirty=function(){for(var a=0;a<this._glTextures.length;a++)this._dirty[a]=!0},b.BaseTexture.prototype.unloadFromGPU=function(){this.dirty();for(var a=this._glTextures.length-1;a>=0;a--){var c=this._glTextures[a],d=b.glContexts[a];d&&c&&d.deleteTexture(c)}this._glTextures.length=0,this.dirty()},b.BaseTexture.fromImage=function(a,c,d){var e=b.BaseTextureCache[a];if(void 0===c&&-1===a.indexOf("data:")&&(c=!0),!e){var f=new Image;c&&(f.crossOrigin=""),f.src=a,e=new b.BaseTexture(f,d),e.imageUrl=a,b.BaseTextureCache[a]=e,-1!==a.indexOf(b.RETINA_PREFIX+".")&&(e.resolution=2)}return e},b.BaseTexture.fromCanvas=function(a,c){a._pixiId||(a._pixiId="canvas_"+b.TextureCacheIdGenerator++);var d=b.BaseTextureCache[a._pixiId];return d||(d=new b.BaseTexture(a,c),b.BaseTextureCache[a._pixiId]=d),d},b.TextureCache={},b.FrameCache={},b.TextureCacheIdGenerator=0,b.Texture=function(a,c,d,e){this.noFrame=!1,c||(this.noFrame=!0,c=new b.Rectangle(0,0,1,1)),a instanceof b.Texture&&(a=a.baseTexture),this.baseTexture=a,this.frame=c,this.trim=e,this.valid=!1,this.requiresUpdate=!1,this._uvs=null,this.width=0,this.height=0,this.crop=d||new b.Rectangle(0,0,1,1),a.hasLoaded?(this.noFrame&&(c=new b.Rectangle(0,0,a.width,a.height)),this.setFrame(c)):a.addEventListener("loaded",this.onBaseTextureLoaded.bind(this))},b.Texture.prototype.constructor=b.Texture,b.EventTarget.mixin(b.Texture.prototype),b.Texture.prototype.onBaseTextureLoaded=function(){var a=this.baseTexture;a.removeEventListener("loaded",this.onLoaded),this.noFrame&&(this.frame=new b.Rectangle(0,0,a.width,a.height)),this.setFrame(this.frame),this.dispatchEvent({type:"update",content:this})},b.Texture.prototype.destroy=function(a){a&&this.baseTexture.destroy(),this.valid=!1},b.Texture.prototype.setFrame=function(a){if(this.noFrame=!1,this.frame=a,this.width=a.width,this.height=a.height,this.crop.x=a.x,this.crop.y=a.y,this.crop.width=a.width,this.crop.height=a.height,!this.trim&&(a.x+a.width>this.baseTexture.width||a.y+a.height>this.baseTexture.height))throw new Error("Texture Error: frame does not fit inside the base Texture dimensions "+this);this.valid=a&&a.width&&a.height&&this.baseTexture.source&&this.baseTexture.hasLoaded,this.trim&&(this.width=this.trim.width,this.height=this.trim.height,this.frame.width=this.trim.width,this.frame.height=this.trim.height),this.valid&&this._updateUvs()},b.Texture.prototype._updateUvs=function(){this._uvs||(this._uvs=new b.TextureUvs);var a=this.crop,c=this.baseTexture.width,d=this.baseTexture.height;this._uvs.x0=a.x/c,this._uvs.y0=a.y/d,this._uvs.x1=(a.x+a.width)/c,this._uvs.y1=a.y/d,this._uvs.x2=(a.x+a.width)/c,this._uvs.y2=(a.y+a.height)/d,this._uvs.x3=a.x/c,this._uvs.y3=(a.y+a.height)/d},b.Texture.fromImage=function(a,c,d){var e=b.TextureCache[a];return e||(e=new b.Texture(b.BaseTexture.fromImage(a,c,d)),b.TextureCache[a]=e),e},b.Texture.fromFrame=function(a){var c=b.TextureCache[a];if(!c)throw new Error('The frameId "'+a+'" does not exist in the texture cache ');return c},b.Texture.fromCanvas=function(a,c){var d=b.BaseTexture.fromCanvas(a,c);return new b.Texture(d)},b.Texture.addTextureToCache=function(a,c){b.TextureCache[c]=a},b.Texture.removeTextureFromCache=function(a){var c=b.TextureCache[a];return delete b.TextureCache[a],delete b.BaseTextureCache[a],c},b.TextureUvs=function(){this.x0=0,this.y0=0,this.x1=0,this.y1=0,this.x2=0,this.y2=0,this.x3=0,this.y3=0},b.Texture.emptyTexture=new b.Texture(new b.BaseTexture),b.RenderTexture=function(a,c,d,e,f){if(this.width=a||100,this.height=c||100,this.resolution=f||1,this.frame=new b.Rectangle(0,0,this.width*this.resolution,this.height*this.resolution),this.crop=new b.Rectangle(0,0,this.width*this.resolution,this.height*this.resolution),this.baseTexture=new b.BaseTexture,this.baseTexture.width=this.width*this.resolution,this.baseTexture.height=this.height*this.resolution,this.baseTexture._glTextures=[],this.baseTexture.resolution=this.resolution,this.baseTexture.scaleMode=e||b.scaleModes.DEFAULT,this.baseTexture.hasLoaded=!0,b.Texture.call(this,this.baseTexture,new b.Rectangle(0,0,this.width,this.height)),this.renderer=d||b.defaultRenderer,this.renderer.type===b.WEBGL_RENDERER){var g=this.renderer.gl;this.baseTexture._dirty[g.id]=!1,this.textureBuffer=new b.FilterTexture(g,this.width*this.resolution,this.height*this.resolution,this.baseTexture.scaleMode),this.baseTexture._glTextures[g.id]=this.textureBuffer.texture,this.render=this.renderWebGL,this.projection=new b.Point(.5*this.width,.5*-this.height)}else this.render=this.renderCanvas,this.textureBuffer=new b.CanvasBuffer(this.width*this.resolution,this.height*this.resolution),this.baseTexture.source=this.textureBuffer.canvas;this.valid=!0,this._updateUvs()},b.RenderTexture.prototype=Object.create(b.Texture.prototype),b.RenderTexture.prototype.constructor=b.RenderTexture,b.RenderTexture.prototype.resize=function(a,c,d){(a!==this.width||c!==this.height)&&(this.valid=a>0&&c>0,this.width=this.frame.width=this.crop.width=a,this.height=this.frame.height=this.crop.height=c,d&&(this.baseTexture.width=this.width,this.baseTexture.height=this.height),this.renderer.type===b.WEBGL_RENDERER&&(this.projection.x=this.width/2,this.projection.y=-this.height/2),this.valid&&this.textureBuffer.resize(this.width*this.resolution,this.height*this.resolution))},b.RenderTexture.prototype.clear=function(){this.valid&&(this.renderer.type===b.WEBGL_RENDERER&&this.renderer.gl.bindFramebuffer(this.renderer.gl.FRAMEBUFFER,this.textureBuffer.frameBuffer),this.textureBuffer.clear())},b.RenderTexture.prototype.renderWebGL=function(a,b,c){if(this.valid){var d=a.worldTransform;d.identity(),d.translate(0,2*this.projection.y),b&&d.append(b),d.scale(1,-1),a.worldAlpha=1;for(var e=a.children,f=0,g=e.length;g>f;f++)e[f].updateTransform();var h=this.renderer.gl;h.viewport(0,0,this.width*this.resolution,this.height*this.resolution),h.bindFramebuffer(h.FRAMEBUFFER,this.textureBuffer.frameBuffer),c&&this.textureBuffer.clear(),this.renderer.spriteBatch.dirty=!0,this.renderer.renderDisplayObject(a,this.projection,this.textureBuffer.frameBuffer),this.renderer.spriteBatch.dirty=!0}},b.RenderTexture.prototype.renderCanvas=function(a,b,c){if(this.valid){var d=a.worldTransform;d.identity(),b&&d.append(b),a.worldAlpha=1;for(var e=a.children,f=0,g=e.length;g>f;f++)e[f].updateTransform();c&&this.textureBuffer.clear();var h=this.textureBuffer.context,i=this.renderer.resolution;this.renderer.resolution=this.resolution,this.renderer.renderDisplayObject(a,h),this.renderer.resolution=i}},b.RenderTexture.prototype.getImage=function(){var a=new Image;return a.src=this.getBase64(),a},b.RenderTexture.prototype.getBase64=function(){return this.getCanvas().toDataURL()},b.RenderTexture.prototype.getCanvas=function(){if(this.renderer.type===b.WEBGL_RENDERER){var a=this.renderer.gl,c=this.textureBuffer.width,d=this.textureBuffer.height,e=new Uint8Array(4*c*d);a.bindFramebuffer(a.FRAMEBUFFER,this.textureBuffer.frameBuffer),a.readPixels(0,0,c,d,a.RGBA,a.UNSIGNED_BYTE,e),a.bindFramebuffer(a.FRAMEBUFFER,null);var f=new b.CanvasBuffer(c,d),g=f.context.getImageData(0,0,c,d);return g.data.set(e),f.context.putImageData(g,0,0),f.canvas}return this.textureBuffer.canvas},b.RenderTexture.tempMatrix=new b.Matrix,b.VideoTexture=function(a,c){if(!a)throw new Error("No video source element specified.");(a.readyState===a.HAVE_ENOUGH_DATA||a.readyState===a.HAVE_FUTURE_DATA)&&a.width&&a.height&&(a.complete=!0),b.BaseTexture.call(this,a,c),this.autoUpdate=!1,this.updateBound=this._onUpdate.bind(this),a.complete||(this._onCanPlay=this.onCanPlay.bind(this),a.addEventListener("canplay",this._onCanPlay),a.addEventListener("canplaythrough",this._onCanPlay),a.addEventListener("play",this.onPlayStart.bind(this)),a.addEventListener("pause",this.onPlayStop.bind(this)))},b.VideoTexture.prototype=Object.create(b.BaseTexture.prototype),b.VideoTexture.constructor=b.VideoTexture,b.VideoTexture.prototype._onUpdate=function(){this.autoUpdate&&(window.requestAnimationFrame(this.updateBound),this.dirty())},b.VideoTexture.prototype.onPlayStart=function(){this.autoUpdate||(window.requestAnimationFrame(this.updateBound),this.autoUpdate=!0)},b.VideoTexture.prototype.onPlayStop=function(){this.autoUpdate=!1},b.VideoTexture.prototype.onCanPlay=function(){"canplaythrough"===event.type&&(this.hasLoaded=!0,this.source&&(this.source.removeEventListener("canplay",this._onCanPlay),this.source.removeEventListener("canplaythrough",this._onCanPlay),this.width=this.source.videoWidth,this.height=this.source.videoHeight,this.__loaded||(this.__loaded=!0,this.dispatchEvent({type:"loaded",content:this}))))},b.VideoTexture.prototype.destroy=function(){this.source&&this.source._pixiId&&(b.BaseTextureCache[this.source._pixiId]=null,delete b.BaseTextureCache[this.source._pixiId],this.source._pixiId=null,delete this.source._pixiId),b.BaseTexture.prototype.destroy.call(this)},b.VideoTexture.baseTextureFromVideo=function(a,c){a._pixiId||(a._pixiId="video_"+b.TextureCacheIdGenerator++);var d=b.BaseTextureCache[a._pixiId];return d||(d=new b.VideoTexture(a,c),b.BaseTextureCache[a._pixiId]=d),d},b.VideoTexture.textureFromVideo=function(a,c){var d=b.VideoTexture.baseTextureFromVideo(a,c);return new b.Texture(d)},b.VideoTexture.fromUrl=function(a,c){var d=document.createElement("video");return d.src=a,d.autoPlay=!0,d.play(),b.VideoTexture.textureFromVideo(d,c)},b.AssetLoader=function(a,c){this.assetURLs=a,this.crossorigin=c,this.loadersByType={jpg:b.ImageLoader,jpeg:b.ImageLoader,png:b.ImageLoader,gif:b.ImageLoader,webp:b.ImageLoader,json:b.JsonLoader,atlas:b.AtlasLoader,anim:b.SpineLoader,xml:b.BitmapFontLoader,fnt:b.BitmapFontLoader}},b.EventTarget.mixin(b.AssetLoader.prototype),b.AssetLoader.prototype.constructor=b.AssetLoader,b.AssetLoader.prototype._getDataType=function(a){var b="data:",c=a.slice(0,b.length).toLowerCase();if(c===b){var d=a.slice(b.length),e=d.indexOf(",");if(-1===e)return null;var f=d.slice(0,e).split(";")[0];return f&&"text/plain"!==f.toLowerCase()?f.split("/").pop().toLowerCase():"txt"}return null},b.AssetLoader.prototype.load=function(){function a(a){b.onAssetLoaded(a.data.content)}var b=this;this.loadCount=this.assetURLs.length;for(var c=0;c<this.assetURLs.length;c++){var d=this.assetURLs[c],e=this._getDataType(d);e||(e=d.split("?").shift().split(".").pop().toLowerCase());var f=this.loadersByType[e];if(!f)throw new Error(e+" is an unsupported file type");var g=new f(d,this.crossorigin);g.on("loaded",a),g.load()}},b.AssetLoader.prototype.onAssetLoaded=function(a){this.loadCount--,this.emit("onProgress",{content:this,loader:a}),this.onProgress&&this.onProgress(a),this.loadCount||(this.emit("onComplete",{content:this}),this.onComplete&&this.onComplete())},b.JsonLoader=function(a,b){this.url=a,this.crossorigin=b,this.baseUrl=a.replace(/[^\/]*$/,""),this.loaded=!1},b.JsonLoader.prototype.constructor=b.JsonLoader,b.EventTarget.mixin(b.JsonLoader.prototype),b.JsonLoader.prototype.load=function(){window.XDomainRequest&&this.crossorigin?(this.ajaxRequest=new window.XDomainRequest,this.ajaxRequest.timeout=3e3,this.ajaxRequest.onerror=this.onError.bind(this),this.ajaxRequest.ontimeout=this.onError.bind(this),this.ajaxRequest.onprogress=function(){},this.ajaxRequest.onload=this.onJSONLoaded.bind(this)):(this.ajaxRequest=window.XMLHttpRequest?new window.XMLHttpRequest:new window.ActiveXObject("Microsoft.XMLHTTP"),this.ajaxRequest.onreadystatechange=this.onReadyStateChanged.bind(this)),this.ajaxRequest.open("GET",this.url,!0),this.ajaxRequest.send()},b.JsonLoader.prototype.onReadyStateChanged=function(){4!==this.ajaxRequest.readyState||200!==this.ajaxRequest.status&&-1!==window.location.href.indexOf("http")||this.onJSONLoaded()},b.JsonLoader.prototype.onJSONLoaded=function(){if(!this.ajaxRequest.responseText)return void this.onError();if(this.json=JSON.parse(this.ajaxRequest.responseText),this.json.frames&&this.json.meta&&this.json.meta.image){var a=this.baseUrl+this.json.meta.image,d=new b.ImageLoader(a,this.crossorigin),e=this.json.frames;this.texture=d.texture.baseTexture,d.addEventListener("loaded",this.onLoaded.bind(this));for(var f in e){var g=e[f].frame;if(g){var h=new b.Rectangle(g.x,g.y,g.w,g.h),i=h.clone(),j=null;if(e[f].trimmed){var k=e[f].sourceSize,l=e[f].spriteSourceSize;j=new b.Rectangle(l.x,l.y,k.w,k.h)}b.TextureCache[f]=new b.Texture(this.texture,h,i,j)}}d.load()}else if(this.json.bones)if(b.AnimCache[this.url])this.onLoaded();else{var m=this.url.substr(0,this.url.lastIndexOf("."))+".atlas",n=new b.JsonLoader(m,this.crossorigin),o=this;n.onJSONLoaded=function(){if(!this.ajaxRequest.responseText)return void this.onError();var a=new b.SpineTextureLoader(this.url.substring(0,this.url.lastIndexOf("/"))),d=new c.Atlas(this.ajaxRequest.responseText,a),e=new c.AtlasAttachmentLoader(d),f=new c.SkeletonJson(e),g=f.readSkeletonData(o.json);b.AnimCache[o.url]=g,o.spine=g,o.spineAtlas=d,o.spineAtlasLoader=n,a.loadingCount>0?a.addEventListener("loadedBaseTexture",function(a){a.content.content.loadingCount<=0&&o.onLoaded()}):o.onLoaded()},n.load()}else this.onLoaded()},b.JsonLoader.prototype.onLoaded=function(){this.loaded=!0,this.dispatchEvent({type:"loaded",content:this})},b.JsonLoader.prototype.onError=function(){this.dispatchEvent({type:"error",content:this})},b.AtlasLoader=function(a,b){this.url=a,this.baseUrl=a.replace(/[^\/]*$/,""),this.crossorigin=b,this.loaded=!1},b.AtlasLoader.constructor=b.AtlasLoader,b.EventTarget.mixin(b.AtlasLoader.prototype),b.AtlasLoader.prototype.load=function(){this.ajaxRequest=new b.AjaxRequest,this.ajaxRequest.onreadystatechange=this.onAtlasLoaded.bind(this),this.ajaxRequest.open("GET",this.url,!0),this.ajaxRequest.overrideMimeType&&this.ajaxRequest.overrideMimeType("application/json"),this.ajaxRequest.send(null)},b.AtlasLoader.prototype.onAtlasLoaded=function(){if(4===this.ajaxRequest.readyState)if(200===this.ajaxRequest.status||-1===window.location.href.indexOf("http")){this.atlas={meta:{image:[]},frames:[]};var a=this.ajaxRequest.responseText.split(/\r?\n/),c=-3,d=0,e=null,f=!1,g=0,h=0,i=this.onLoaded.bind(this);for(g=0;g<a.length;g++)if(a[g]=a[g].replace(/^\s+|\s+$/g,""),""===a[g]&&(f=g+1),a[g].length>0){if(f===g)this.atlas.meta.image.push(a[g]),d=this.atlas.meta.image.length-1,this.atlas.frames.push({}),c=-3;else if(c>0)if(c%7===1)null!=e&&(this.atlas.frames[d][e.name]=e),e={name:a[g],frame:{}};else{var j=a[g].split(" ");if(c%7===3)e.frame.x=Number(j[1].replace(",","")),e.frame.y=Number(j[2]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6809
else if(c%7===4)e.frame.w=Number(j[1].replace(",","")),e.frame.h=Number(j[2]);else if(c%7===5){var k={x:0,y:0,w:Number(j[1].replace(",","")),h:Number(j[2])};k.w>e.frame.w||k.h>e.frame.h?(e.trimmed=!0,e.realSize=k):e.trimmed=!1}}c++}if(null!=e&&(this.atlas.frames[d][e.name]=e),this.atlas.meta.image.length>0){for(this.images=[],h=0;h<this.atlas.meta.image.length;h++){var l=this.baseUrl+this.atlas.meta.image[h],m=this.atlas.frames[h];this.images.push(new b.ImageLoader(l,this.crossorigin));for(g in m){var n=m[g].frame;n&&(b.TextureCache[g]=new b.Texture(this.images[h].texture.baseTexture,{x:n.x,y:n.y,width:n.w,height:n.h}),m[g].trimmed&&(b.TextureCache[g].realSize=m[g].realSize,b.TextureCache[g].trim.x=0,b.TextureCache[g].trim.y=0))}}for(this.currentImageId=0,h=0;h<this.images.length;h++)this.images[h].on("loaded",i);this.images[this.currentImageId].load()}else this.onLoaded()}else this.onError()},b.AtlasLoader.prototype.onLoaded=function(){this.images.length-1>this.currentImageId?(this.currentImageId++,this.images[this.currentImageId].load()):(this.loaded=!0,this.emit("loaded",{content:this}))},b.AtlasLoader.prototype.onError=function(){this.emit("error",{content:this})},b.SpriteSheetLoader=function(a,b){this.url=a,this.crossorigin=b,this.baseUrl=a.replace(/[^\/]*$/,""),this.texture=null,this.frames={}},b.SpriteSheetLoader.prototype.constructor=b.SpriteSheetLoader,b.EventTarget.mixin(b.SpriteSheetLoader.prototype),b.SpriteSheetLoader.prototype.load=function(){var a=this,c=new b.JsonLoader(this.url,this.crossorigin);c.on("loaded",function(b){a.json=b.data.content.json,a.onLoaded()}),c.load()},b.SpriteSheetLoader.prototype.onLoaded=function(){this.emit("loaded",{content:this})},b.ImageLoader=function(a,c){this.texture=b.Texture.fromImage(a,c),this.frames=[]},b.ImageLoader.prototype.constructor=b.ImageLoader,b.EventTarget.mixin(b.ImageLoader.prototype),b.ImageLoader.prototype.load=function(){this.texture.baseTexture.hasLoaded?this.onLoaded():this.texture.baseTexture.on("loaded",this.onLoaded.bind(this))},b.ImageLoader.prototype.onLoaded=function(){this.emit("loaded",{content:this})},b.ImageLoader.prototype.loadFramedSpriteSheet=function(a,c,d){this.frames=[];for(var e=Math.floor(this.texture.width/a),f=Math.floor(this.texture.height/c),g=0,h=0;f>h;h++)for(var i=0;e>i;i++,g++){var j=new b.Texture(this.texture.baseTexture,{x:i*a,y:h*c,width:a,height:c});this.frames.push(j),d&&(b.TextureCache[d+"-"+g]=j)}this.load()},b.BitmapFontLoader=function(a,b){this.url=a,this.crossorigin=b,this.baseUrl=a.replace(/[^\/]*$/,""),this.texture=null},b.BitmapFontLoader.prototype.constructor=b.BitmapFontLoader,b.EventTarget.mixin(b.BitmapFontLoader.prototype),b.BitmapFontLoader.prototype.load=function(){this.ajaxRequest=new b.AjaxRequest,this.ajaxRequest.onreadystatechange=this.onXMLLoaded.bind(this),this.ajaxRequest.open("GET",this.url,!0),this.ajaxRequest.overrideMimeType&&this.ajaxRequest.overrideMimeType("application/xml"),this.ajaxRequest.send(null)},b.BitmapFontLoader.prototype.onXMLLoaded=function(){if(4===this.ajaxRequest.readyState&&(200===this.ajaxRequest.status||-1===window.location.protocol.indexOf("http"))){var a=this.ajaxRequest.responseXML;if(!a||/MSIE 9/i.test(navigator.userAgent)||navigator.isCocoonJS)if("function"==typeof window.DOMParser){var c=new DOMParser;a=c.parseFromString(this.ajaxRequest.responseText,"text/xml")}else{var d=document.createElement("div");d.innerHTML=this.ajaxRequest.responseText,a=d}var e=this.baseUrl+a.getElementsByTagName("page")[0].getAttribute("file"),f=new b.ImageLoader(e,this.crossorigin);this.texture=f.texture.baseTexture;var g={},h=a.getElementsByTagName("info")[0],i=a.getElementsByTagName("common")[0];g.font=h.getAttribute("face"),g.size=parseInt(h.getAttribute("size"),10),g.lineHeight=parseInt(i.getAttribute("lineHeight"),10),g.chars={};for(var j=a.getElementsByTagName("char"),k=0;k<j.length;k++){var l=parseInt(j[k].getAttribute("id"),10),m=new b.Rectangle(parseInt(j[k].getAttribute("x"),10),parseInt(j[k].getAttribute("y"),10),parseInt(j[k].getAttribute("width"),10),parseInt(j[k].getAttribute("height"),10));g.chars[l]={xOffset:parseInt(j[k].getAttribute("xoffset"),10),yOffset:parseInt(j[k].getAttribute("yoffset"),10),xAdvance:parseInt(j[k].getAttribute("xadvance"),10),kerning:{},texture:b.TextureCache[l]=new b.Texture(this.texture,m)}}var n=a.getElementsByTagName("kerning");for(k=0;k<n.length;k++){var o=parseInt(n[k].getAttribute("first"),10),p=parseInt(n[k].getAttribute("second"),10),q=parseInt(n[k].getAttribute("amount"),10);g.chars[p].kerning[o]=q}b.BitmapText.fonts[g.font]=g,f.addEventListener("loaded",this.onLoaded.bind(this)),f.load()}},b.BitmapFontLoader.prototype.onLoaded=function(){this.emit("loaded",{content:this})},b.SpineLoader=function(a,b){this.url=a,this.crossorigin=b,this.loaded=!1},b.SpineLoader.prototype.constructor=b.SpineLoader,b.EventTarget.mixin(b.SpineLoader.prototype),b.SpineLoader.prototype.load=function(){var a=this,c=new b.JsonLoader(this.url,this.crossorigin);c.on("loaded",function(b){a.json=b.data.content.json,a.onLoaded()}),c.load()},b.SpineLoader.prototype.onLoaded=function(){this.loaded=!0,this.emit("loaded",{content:this})},b.AbstractFilter=function(a,b){this.passes=[this],this.shaders=[],this.dirty=!0,this.padding=0,this.uniforms=b||{},this.fragmentSrc=a||[]},b.AbstractFilter.prototype.constructor=b.AbstractFilter,b.AbstractFilter.prototype.syncUniforms=function(){for(var a=0,b=this.shaders.length;b>a;a++)this.shaders[a].dirty=!0},b.AlphaMaskFilter=function(a){b.AbstractFilter.call(this),this.passes=[this],a.baseTexture._powerOf2=!0,this.uniforms={mask:{type:"sampler2D",value:a},mapDimensions:{type:"2f",value:{x:1,y:5112}},dimensions:{type:"4fv",value:[0,0,0,0]}},a.baseTexture.hasLoaded?(this.uniforms.mask.value.x=a.width,this.uniforms.mask.value.y=a.height):(this.boundLoadedFunction=this.onTextureLoaded.bind(this),a.baseTexture.on("loaded",this.boundLoadedFunction)),this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying vec4 vColor;","uniform sampler2D mask;","uniform sampler2D uSampler;","uniform vec2 offset;","uniform vec4 dimensions;","uniform vec2 mapDimensions;","void main(void) {","   vec2 mapCords = vTextureCoord.xy;","   mapCords += (dimensions.zw + offset)/ dimensions.xy ;","   mapCords.y *= -1.0;","   mapCords.y += 1.0;","   mapCords *= dimensions.xy / mapDimensions;","   vec4 original =  texture2D(uSampler, vTextureCoord);","   float maskAlpha =  texture2D(mask, mapCords).r;","   original *= maskAlpha;","   gl_FragColor =  original;","}"]},b.AlphaMaskFilter.prototype=Object.create(b.AbstractFilter.prototype),b.AlphaMaskFilter.prototype.constructor=b.AlphaMaskFilter,b.AlphaMaskFilter.prototype.onTextureLoaded=function(){this.uniforms.mapDimensions.value.x=this.uniforms.mask.value.width,this.uniforms.mapDimensions.value.y=this.uniforms.mask.value.height,this.uniforms.mask.value.baseTexture.off("loaded",this.boundLoadedFunction)},Object.defineProperty(b.AlphaMaskFilter.prototype,"map",{get:function(){return this.uniforms.mask.value},set:function(a){this.uniforms.mask.value=a}}),b.ColorMatrixFilter=function(){b.AbstractFilter.call(this),this.passes=[this],this.uniforms={matrix:{type:"mat4",value:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}},this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying vec4 vColor;","uniform float invert;","uniform mat4 matrix;","uniform sampler2D uSampler;","void main(void) {","   gl_FragColor = texture2D(uSampler, vTextureCoord) * matrix;","}"]},b.ColorMatrixFilter.prototype=Object.create(b.AbstractFilter.prototype),b.ColorMatrixFilter.prototype.constructor=b.ColorMatrixFilter,Object.defineProperty(b.ColorMatrixFilter.prototype,"matrix",{get:function(){return this.uniforms.matrix.value},set:function(a){this.uniforms.matrix.value=a}}),b.GrayFilter=function(){b.AbstractFilter.call(this),this.passes=[this],this.uniforms={gray:{type:"1f",value:1}},this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying vec4 vColor;","uniform sampler2D uSampler;","uniform float gray;","void main(void) {","   gl_FragColor = texture2D(uSampler, vTextureCoord);","   gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.2126*gl_FragColor.r + 0.7152*gl_FragColor.g + 0.0722*gl_FragColor.b), gray);","}"]},b.GrayFilter.prototype=Object.create(b.AbstractFilter.prototype),b.GrayFilter.prototype.constructor=b.GrayFilter,Object.defineProperty(b.GrayFilter.prototype,"gray",{get:function(){return this.uniforms.gray.value},set:function(a){this.uniforms.gray.value=a}}),b.DisplacementFilter=function(a){b.AbstractFilter.call(this),this.passes=[this],a.baseTexture._powerOf2=!0,this.uniforms={displacementMap:{type:"sampler2D",value:a},scale:{type:"2f",value:{x:30,y:30}},offset:{type:"2f",value:{x:0,y:0}},mapDimensions:{type:"2f",value:{x:1,y:5112}},dimensions:{type:"4fv",value:[0,0,0,0]}},a.baseTexture.hasLoaded?(this.uniforms.mapDimensions.value.x=a.width,this.uniforms.mapDimensions.value.y=a.height):(this.boundLoadedFunction=this.onTextureLoaded.bind(this),a.baseTexture.on("loaded",this.boundLoadedFunction)),this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying vec4 vColor;","uniform sampler2D displacementMap;","uniform sampler2D uSampler;","uniform vec2 scale;","uniform vec2 offset;","uniform vec4 dimensions;","uniform vec2 mapDimensions;","void main(void) {","   vec2 mapCords = vTextureCoord.xy;","   mapCords += (dimensions.zw + offset)/ dimensions.xy ;","   mapCords.y *= -1.0;","   mapCords.y += 1.0;","   vec2 matSample = texture2D(displacementMap, mapCords).xy;","   matSample -= 0.5;","   matSample *= scale;","   matSample /= mapDimensions;","   gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x + matSample.x, vTextureCoord.y + matSample.y));","   gl_FragColor.rgb = mix( gl_FragColor.rgb, gl_FragColor.rgb, 1.0);","   vec2 cord = vTextureCoord;","}"]},b.DisplacementFilter.prototype=Object.create(b.AbstractFilter.prototype),b.DisplacementFilter.prototype.constructor=b.DisplacementFilter,b.DisplacementFilter.prototype.onTextureLoaded=function(){this.uniforms.mapDimensions.value.x=this.uniforms.displacementMap.value.width,this.uniforms.mapDimensions.value.y=this.uniforms.displacementMap.value.height,this.uniforms.displacementMap.value.baseTexture.off("loaded",this.boundLoadedFunction)},Object.defineProperty(b.DisplacementFilter.prototype,"map",{get:function(){return this.uniforms.displacementMap.value},set:function(a){this.uniforms.displacementMap.value=a}}),Object.defineProperty(b.DisplacementFilter.prototype,"scale",{get:function(){return this.uniforms.scale.value},set:function(a){this.uniforms.scale.value=a}}),Object.defineProperty(b.DisplacementFilter.prototype,"offset",{get:function(){return this.uniforms.offset.value},set:function(a){this.uniforms.offset.value=a}}),b.PixelateFilter=function(){b.AbstractFilter.call(this),this.passes=[this],this.uniforms={invert:{type:"1f",value:0},dimensions:{type:"4fv",value:new b.Float32Array([1e4,100,10,10])},pixelSize:{type:"2f",value:{x:10,y:10}}},this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying vec4 vColor;","uniform vec2 testDim;","uniform vec4 dimensions;","uniform vec2 pixelSize;","uniform sampler2D uSampler;","void main(void) {","   vec2 coord = vTextureCoord;","   vec2 size = dimensions.xy/pixelSize;","   vec2 color = floor( ( vTextureCoord * size ) ) / size + pixelSize/dimensions.xy * 0.5;","   gl_FragColor = texture2D(uSampler, color);","}"]},b.PixelateFilter.prototype=Object.create(b.AbstractFilter.prototype),b.PixelateFilter.prototype.constructor=b.PixelateFilter,Object.defineProperty(b.PixelateFilter.prototype,"size",{get:function(){return this.uniforms.pixelSize.value},set:function(a){this.dirty=!0,this.uniforms.pixelSize.value=a}}),b.BlurXFilter=function(){b.AbstractFilter.call(this),this.passes=[this],this.uniforms={blur:{type:"1f",value:1/512}},this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying vec4 vColor;","uniform float blur;","uniform sampler2D uSampler;","void main(void) {","   vec4 sum = vec4(0.0);","   sum += texture2D(uSampler, vec2(vTextureCoord.x - 4.0*blur, vTextureCoord.y)) * 0.05;","   sum += texture2D(uSampler, vec2(vTextureCoord.x - 3.0*blur, vTextureCoord.y)) * 0.09;","   sum += texture2D(uSampler, vec2(vTextureCoord.x - 2.0*blur, vTextureCoord.y)) * 0.12;","   sum += texture2D(uSampler, vec2(vTextureCoord.x - blur, vTextureCoord.y)) * 0.15;","   sum += texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y)) * 0.16;","   sum += texture2D(uSampler, vec2(vTextureCoord.x + blur, vTextureCoord.y)) * 0.15;","   sum += texture2D(uSampler, vec2(vTextureCoord.x + 2.0*blur, vTextureCoord.y)) * 0.12;","   sum += texture2D(uSampler, vec2(vTextureCoord.x + 3.0*blur, vTextureCoord.y)) * 0.09;","   sum += texture2D(uSampler, vec2(vTextureCoord.x + 4.0*blur, vTextureCoord.y)) * 0.05;","   gl_FragColor = sum;","}"]},b.BlurXFilter.prototype=Object.create(b.AbstractFilter.prototype),b.BlurXFilter.prototype.constructor=b.BlurXFilter,Object.defineProperty(b.BlurXFilter.prototype,"blur",{get:function(){return this.uniforms.blur.value/(1/7e3)},set:function(a){this.dirty=!0,this.uniforms.blur.value=1/7e3*a}}),b.BlurYFilter=function(){b.AbstractFilter.call(this),this.passes=[this],this.uniforms={blur:{type:"1f",value:1/512}},this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying vec4 vColor;","uniform float blur;","uniform sampler2D uSampler;","void main(void) {","   vec4 sum = vec4(0.0);","   sum += texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y - 4.0*blur)) * 0.05;","   sum += texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y - 3.0*blur)) * 0.09;","   sum += texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y - 2.0*blur)) * 0.12;","   sum += texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y - blur)) * 0.15;","   sum += texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y)) * 0.16;","   sum += texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y + blur)) * 0.15;","   sum += texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y + 2.0*blur)) * 0.12;","   sum += texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y + 3.0*blur)) * 0.09;","   sum += texture2D(uSampler, vec2(vTextureCoord.x, vTextureCoord.y + 4.0*blur)) * 0.05;","   gl_FragColor = sum;","}"]},b.BlurYFilter.prototype=Object.create(b.AbstractFilter.prototype),b.BlurYFilter.prototype.constructor=b.BlurYFilter,Object.defineProperty(b.BlurYFilter.prototype,"blur",{get:function(){return this.uniforms.blur.value/(1/7e3)},set:function(a){this.uniforms.blur.value=1/7e3*a}}),b.BlurFilter=function(){this.blurXFilter=new b.BlurXFilter,this.blurYFilter=new b.BlurYFilter,this.passes=[this.blurXFilter,this.blurYFilter]},b.BlurFilter.prototype=Object.create(b.AbstractFilter.prototype),b.BlurFilter.prototype.constructor=b.BlurFilter,Object.defineProperty(b.BlurFilter.prototype,"blur",{get:function(){return this.blurXFilter.blur},set:function(a){this.blurXFilter.blur=this.blurYFilter.blur=a}}),Object.defineProperty(b.BlurFilter.prototype,"blurX",{get:function(){return this.blurXFilter.blur},set:function(a){this.blurXFilter.blur=a}}),Object.defineProperty(b.BlurFilter.prototype,"blurY",{get:function(){return this.blurYFilter.blur},set:function(a){this.blurYFilter.blur=a}}),b.InvertFilter=function(){b.AbstractFilter.call(this),this.passes=[this],this.uniforms={invert:{type:"1f",value:1}},this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying vec4 vColor;","uniform float invert;","uniform sampler2D uSampler;","void main(void) {","   gl_FragColor = texture2D(uSampler, vTextureCoord);","   gl_FragColor.rgb = mix( (vec3(1)-gl_FragColor.rgb) * gl_FragColor.a, gl_FragColor.rgb, 1.0 - invert);","}"]},b.InvertFilter.prototype=Object.create(b.AbstractFilter.prototype),b.InvertFilter.prototype.constructor=b.InvertFilter,Object.defineProperty(b.InvertFilter.prototype,"invert",{get:function(){return this.uniforms.invert.value},set:function(a){this.uniforms.invert.value=a}}),b.SepiaFilter=function(){b.AbstractFilter.call(this),this.passes=[this],this.uniforms={sepia:{type:"1f",value:1}},this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying vec4 vColor;","uniform float sepia;","uniform sampler2D uSampler;","const mat3 sepiaMatrix = mat3(0.3588, 0.7044, 0.1368, 0.2990, 0.5870, 0.1140, 0.2392, 0.4696, 0.0912);","void main(void) {","   gl_FragColor = texture2D(uSampler, vTextureCoord);","   gl_FragColor.rgb = mix( gl_FragColor.rgb, gl_FragColor.rgb * sepiaMatrix, sepia);","}"]},b.SepiaFilter.prototype=Object.create(b.AbstractFilter.prototype),b.SepiaFilter.prototype.constructor=b.SepiaFilter,Object.defineProperty(b.SepiaFilter.prototype,"sepia",{get:function(){return this.uniforms.sepia.value},set:function(a){this.uniforms.sepia.value=a}}),b.TwistFilter=function(){b.AbstractFilter.call(this),this.passes=[this],this.uniforms={radius:{type:"1f",value:.5},angle:{type:"1f",value:5},offset:{type:"2f",value:{x:.5,y:.5}}},this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying vec4 vColor;","uniform vec4 dimensions;","uniform sampler2D uSampler;","uniform float radius;","uniform float angle;","uniform vec2 offset;","void main(void) {","   vec2 coord = vTextureCoord - offset;","   float distance = length(coord);","   if (distance < radius) {","       float ratio = (radius - distance) / radius;","       float angleMod = ratio * ratio * angle;","       float s = sin(angleMod);","       float c = cos(angleMod);","       coord = vec2(coord.x * c - coord.y * s, coord.x * s + coord.y * c);","   }","   gl_FragColor = texture2D(uSampler, coord+offset);","}"]},b.TwistFilter.prototype=Object.create(b.AbstractFilter.prototype),b.TwistFilter.prototype.constructor=b.TwistFilter,Object.defineProperty(b.TwistFilter.prototype,"offset",{get:function(){return this.uniforms.offset.value},set:function(a){this.dirty=!0,this.uniforms.offset.value=a}}),Object.defineProperty(b.TwistFilter.prototype,"radius",{get:function(){return this.uniforms.radius.value},set:function(a){this.dirty=!0,this.uniforms.radius.value=a}}),Object.defineProperty(b.TwistFilter.prototype,"angle",{get:function(){return this.uniforms.angle.value},set:function(a){this.dirty=!0,this.uniforms.angle.value=a}}),b.ColorStepFilter=function(){b.AbstractFilter.call(this),this.passes=[this],this.uniforms={step:{type:"1f",value:5}},this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying vec4 vColor;","uniform sampler2D uSampler;","uniform float step;","void main(void) {","   vec4 color = texture2D(uSampler, vTextureCoord);","   color = floor(color * step) / step;","   gl_FragColor = color;","}"]},b.ColorStepFilter.prototype=Object.create(b.AbstractFilter.prototype),b.ColorStepFilter.prototype.constructor=b.ColorStepFilter,Object.defineProperty(b.ColorStepFilter.prototype,"step",{get:function(){return this.uniforms.step.value},set:function(a){this.uniforms.step.value=a}}),b.DotScreenFilter=function(){b.AbstractFilter.call(this),this.passes=[this],this.uniforms={scale:{type:"1f",value:1},angle:{type:"1f",value:5},dimensions:{type:"4fv",value:[0,0,0,0]}},this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying vec4 vColor;","uniform vec4 dimensions;","uniform sampler2D uSampler;","uniform float angle;","uniform float scale;","float pattern() {","   float s = sin(angle), c = cos(angle);","   vec2 tex = vTextureCoord * dimensions.xy;","   vec2 point = vec2(","       c * tex.x - s * tex.y,","       s * tex.x + c * tex.y","   ) * scale;","   return (sin(point.x) * sin(point.y)) * 4.0;","}","void main() {","   vec4 color = texture2D(uSampler, vTextureCoord);","   float average = (color.r + color.g + color.b) / 3.0;","   gl_FragColor = vec4(vec3(average * 10.0 - 5.0 + pattern()), color.a);","}"]},b.DotScreenFilter.prototype=Object.create(b.AbstractFilter.prototype),b.DotScreenFilter.prototype.constructor=b.DotScreenFilter,Object.defineProperty(b.DotScreenFilter.prototype,"scale",{get:function(){return this.uniforms.scale.value},set:function(a){this.dirty=!0,this.uniforms.scale.value=a}}),Object.defineProperty(b.DotScreenFilter.prototype,"angle",{get:function(){return this.uniforms.angle.value},set:function(a){this.dirty=!0,this.uniforms.angle.value=a}}),b.CrossHatchFilter=function(){b.AbstractFilter.call(this),this.passes=[this],this.uniforms={blur:{type:"1f",value:1/512}},this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying vec4 vColor;","uniform float blur;","uniform sampler2D uSampler;","void main(void) {","    float lum = length(texture2D(uSampler, vTextureCoord.xy).rgb);","    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);","    if (lum < 1.00) {","        if (mod(gl_FragCoord.x + gl_FragCoord.y, 10.0) == 0.0) {","            gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);","        }","    }","    if (lum < 0.75) {","        if (mod(gl_FragCoord.x - gl_FragCoord.y, 10.0) == 0.0) {","            gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);","        }","    }","    if (lum < 0.50) {","        if (mod(gl_FragCoord.x + gl_FragCoord.y - 5.0, 10.0) == 0.0) {","            gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);","        }","    }","    if (lum < 0.3) {","        if (mod(gl_FragCoord.x - gl_FragCoord.y - 5.0, 10.0) == 0.0) {","            gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);","        }","    }","}"]},b.CrossHatchFilter.prototype=Object.create(b.AbstractFilter.prototype),b.CrossHatchFilter.prototype.constructor=b.CrossHatchFilter,Object.defineProperty(b.CrossHatchFilter.prototype,"blur",{get:function(){return this.uniforms.blur.value/(1/7e3)},set:function(a){this.uniforms.blur.value=1/7e3*a}}),b.RGBSplitFilter=function(){b.AbstractFilter.call(this),this.passes=[this],this.uniforms={red:{type:"2f",value:{x:20,y:20}},green:{type:"2f",value:{x:-20,y:20}},blue:{type:"2f",value:{x:20,y:-20}},dimensions:{type:"4fv",value:[0,0,0,0]}},this.fragmentSrc=["precision mediump float;","varying vec2 vTextureCoord;","varying vec4 vColor;","uniform vec2 red;","uniform vec2 green;","uniform vec2 blue;","uniform vec4 dimensions;","uniform sampler2D uSampler;","void main(void) {","   gl_FragColor.r = texture2D(uSampler, vTextureCoord + red/dimensions.xy).r;","   gl_FragColor.g = texture2D(uSampler, vTextureCoord + green/dimensions.xy).g;","   gl_FragColor.b = texture2D(uSampler, vTextureCoord + blue/dimensions.xy).b;","   gl_FragColor.a = texture2D(uSampler, vTextureCoord).a;","}"]},b.RGBSplitFilter.prototype=Object.create(b.AbstractFilter.prototype),b.RGBSplitFilter.prototype.constructor=b.RGBSplitFilter,Object.defineProperty(b.RGBSplitFilter.prototype,"red",{get:function(){return this.uniforms.red.value},set:function(a){this.uniforms.red.value=a}}),Object.defineProperty(b.RGBSplitFilter.prototype,"green",{get:function(){return this.uniforms.green.value},set:function(a){this.uniforms.green.value=a}}),Object.defineProperty(b.RGBSplitFilter.prototype,"blue",{get:function(){return this.uniforms.blue.value},set:function(a){this.uniforms.blue.value=a}}),"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=b),exports.PIXI=b):"undefined"!=typeof define&&define.amd?define(b):a.PIXI=b}).call(this);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6810
},{}],"randomColor":[function(require,module,exports){
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6811
;(function(root, factory) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6812
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6813
  // Support AMD
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6814
  if (typeof define === 'function' && define.amd) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6815
    define([], factory);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6816
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6817
  // Support CommonJS
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6818
  } else if (typeof exports === 'object') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6819
    var randomColor = factory();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6820
    
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6821
    // Support NodeJS & Component, which allow module.exports to be a function
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6822
    if (typeof module === 'object' && module && module.exports) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6823
      exports = module.exports = randomColor;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6824
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6825
    
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6826
    // Support CommonJS 1.1.1 spec
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6827
    exports.randomColor = randomColor;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6828
  
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6829
  // Support vanilla script loading
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6830
  } else {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6831
    root.randomColor = factory();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6832
  };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6833
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6834
}(this, function() {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6835
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6836
  // Shared color dictionary
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6837
  var colorDictionary = {};
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6838
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6839
  // Populate the color dictionary
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6840
  loadColorBounds();
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6841
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6842
  var randomColor = function(options) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6843
    options = options || {};
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6844
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6845
    var H,S,B;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6846
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6847
    // Check if we need to generate multiple colors
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6848
    if (options.count) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6849
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6850
      var totalColors = options.count,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6851
          colors = [];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6852
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6853
      options.count = false;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6854
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6855
      while (totalColors > colors.length) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6856
        colors.push(randomColor(options));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6857
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6858
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6859
      return colors;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6860
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6861
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6862
    // First we pick a hue (H)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6863
    H = pickHue(options);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6864
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6865
    // Then use H to determine saturation (S)
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6866
    S = pickSaturation(H, options);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6867
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6868
    // Then use S and H to determine brightness (B).
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6869
    B = pickBrightness(H, S, options);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6870
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6871
    // Then we return the HSB color in the desired format
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6872
    return setFormat([H,S,B], options);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6873
  };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6874
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6875
  function pickHue (options) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6876
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6877
    var hueRange = getHueRange(options.hue),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6878
        hue = randomWithin(hueRange);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6879
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6880
    // Instead of storing red as two seperate ranges,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6881
    // we group them, using negative numbers
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6882
    if (hue < 0) {hue = 360 + hue}
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6883
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6884
    return hue;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6885
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6886
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6887
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6888
  function pickSaturation (hue, options) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6889
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6890
    if (options.luminosity === 'random') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6891
      return randomWithin([0,100]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6892
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6893
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6894
    if (options.hue === 'monochrome') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6895
      return 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6896
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6897
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6898
    var saturationRange = getSaturationRange(hue);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6899
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6900
    var sMin = saturationRange[0],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6901
        sMax = saturationRange[1];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6902
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6903
    switch (options.luminosity) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6904
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6905
      case 'bright':
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6906
        sMin = 55;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6907
        break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6908
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6909
      case 'dark':
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6910
        sMin = sMax - 10;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6911
        break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6912
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6913
      case 'light':
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6914
        sMax = 55;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6915
        break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6916
   }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6917
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6918
    return randomWithin([sMin, sMax]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6919
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6920
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6921
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6922
  function pickBrightness (H, S, options) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6923
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6924
    var brightness,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6925
        bMin = getMinimumBrightness(H, S),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6926
        bMax = 100;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6927
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6928
    switch (options.luminosity) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6929
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6930
      case 'dark':
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6931
        bMax = bMin + 20;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6932
        break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6933
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6934
      case 'light':
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6935
        bMin = (bMax + bMin)/2;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6936
        break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6937
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6938
      case 'random':
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6939
        bMin = 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6940
        bMax = 100;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6941
        break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6942
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6943
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6944
    return randomWithin([bMin, bMax]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6945
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6946
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6947
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6948
  function setFormat (hsv, options) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6949
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6950
    switch (options.format) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6951
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6952
      case 'hsvArray':
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6953
        return hsv;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6954
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6955
      case 'hsv':
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6956
        return colorString('hsv', hsv);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6957
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6958
      case 'rgbArray':
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6959
        return HSVtoRGB(hsv);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6960
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6961
      case 'rgb':
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6962
        return colorString('rgb', HSVtoRGB(hsv));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6963
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6964
      default:
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6965
        return HSVtoHex(hsv);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6966
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6967
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6968
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6969
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6970
  function getMinimumBrightness(H, S) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6971
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6972
    var lowerBounds = getColorInfo(H).lowerBounds;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6973
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6974
    for (var i = 0; i < lowerBounds.length - 1; i++) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6975
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6976
      var s1 = lowerBounds[i][0],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6977
          v1 = lowerBounds[i][1];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6978
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6979
      var s2 = lowerBounds[i+1][0],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6980
          v2 = lowerBounds[i+1][1];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6981
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6982
      if (S >= s1 && S <= s2) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6983
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6984
         var m = (v2 - v1)/(s2 - s1),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6985
             b = v1 - m*s1;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6986
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6987
         return m*S + b;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6988
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6989
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6990
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6991
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6992
    return 0;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6993
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6994
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6995
  function getHueRange (colorInput) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6996
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6997
    if (typeof parseInt(colorInput) === 'number') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6998
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  6999
      var number = parseInt(colorInput);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7000
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7001
      if (number < 360 && number > 0) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7002
        return [number, number];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7003
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7004
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7005
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7006
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7007
    if (typeof colorInput === 'string') {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7008
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7009
      if (colorDictionary[colorInput]) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7010
        var color = colorDictionary[colorInput];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7011
        if (color.hueRange) {return color.hueRange}
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7012
      }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7013
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7014
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7015
    return [0,360];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7016
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7017
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7018
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7019
  function getSaturationRange (hue) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7020
    return getColorInfo(hue).saturationRange;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7021
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7022
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7023
  function getColorInfo (hue) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7024
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7025
    // Maps red colors to make picking hue easier
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7026
    if (hue >= 334 && hue <= 360) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7027
      hue-= 360;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7028
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7029
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7030
    for (var colorName in colorDictionary) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7031
       var color = colorDictionary[colorName];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7032
       if (color.hueRange &&
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7033
           hue >= color.hueRange[0] &&
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7034
           hue <= color.hueRange[1]) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7035
          return colorDictionary[colorName];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7036
       }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7037
    } return 'Color not found';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7038
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7039
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7040
  function randomWithin (range) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7041
    return Math.floor(range[0] + Math.random()*(range[1] + 1 - range[0]));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7042
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7043
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7044
  function shiftHue (h, degrees) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7045
    return (h + degrees)%360;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7046
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7047
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7048
  function HSVtoHex (hsv){
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7049
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7050
    var rgb = HSVtoRGB(hsv);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7051
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7052
    function componentToHex(c) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7053
        var hex = c.toString(16);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7054
        return hex.length == 1 ? "0" + hex : hex;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7055
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7056
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7057
    var hex = "#" + componentToHex(rgb[0]) + componentToHex(rgb[1]) + componentToHex(rgb[2]);
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7058
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7059
    return hex;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7060
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7061
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7062
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7063
  function defineColor (name, hueRange, lowerBounds) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7064
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7065
    var sMin = lowerBounds[0][0],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7066
        sMax = lowerBounds[lowerBounds.length - 1][0],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7067
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7068
        bMin = lowerBounds[lowerBounds.length - 1][1],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7069
        bMax = lowerBounds[0][1];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7070
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7071
    colorDictionary[name] = {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7072
      hueRange: hueRange,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7073
      lowerBounds: lowerBounds,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7074
      saturationRange: [sMin, sMax],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7075
      brightnessRange: [bMin, bMax]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7076
    };
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7077
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7078
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7079
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7080
  function loadColorBounds () {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7081
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7082
    defineColor(
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7083
      'monochrome',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7084
      null,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7085
      [[0,0],[100,0]]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7086
    );
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7087
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7088
    defineColor(
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7089
      'red',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7090
      [-26,18],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7091
      [[20,100],[30,92],[40,89],[50,85],[60,78],[70,70],[80,60],[90,55],[100,50]]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7092
    );
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7093
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7094
    defineColor(
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7095
      'orange',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7096
      [19,46],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7097
      [[20,100],[30,93],[40,88],[50,86],[60,85],[70,70],[100,70]]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7098
    );
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7099
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7100
    defineColor(
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7101
      'yellow',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7102
      [47,62],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7103
      [[25,100],[40,94],[50,89],[60,86],[70,84],[80,82],[90,80],[100,75]]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7104
    );
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7105
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7106
    defineColor(
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7107
      'green',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7108
      [63,158],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7109
      [[30,100],[40,90],[50,85],[60,81],[70,74],[80,64],[90,50],[100,40]]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7110
    );
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7111
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7112
    defineColor(
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7113
      'blue',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7114
      [159, 257],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7115
      [[20,100],[30,86],[40,80],[50,74],[60,60],[70,52],[80,44],[90,39],[100,35]]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7116
    );
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7117
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7118
    defineColor(
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7119
      'purple',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7120
      [258, 282],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7121
      [[20,100],[30,87],[40,79],[50,70],[60,65],[70,59],[80,52],[90,45],[100,42]]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7122
    );
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7123
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7124
    defineColor(
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7125
      'pink',
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7126
      [283, 334],
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7127
      [[20,100],[30,90],[40,86],[60,84],[80,80],[90,75],[100,73]]
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7128
    );
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7129
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7130
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7131
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7132
  function HSVtoRGB (hsv) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7133
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7134
    // this doesn't work for the values of 0 and 360
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7135
    // here's the hacky fix
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7136
    var h = hsv[0];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7137
    if (h === 0) {h = 1}
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7138
    if (h === 360) {h = 359}
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7139
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7140
    // Rebase the h,s,v values
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7141
    h = h/360;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7142
    var s = hsv[1]/100,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7143
        v = hsv[2]/100;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7144
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7145
    var h_i = Math.floor(h*6),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7146
      f = h * 6 - h_i,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7147
      p = v * (1 - s),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7148
      q = v * (1 - f*s),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7149
      t = v * (1 - (1 - f)*s),
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7150
      r = 256,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7151
      g = 256,
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7152
      b = 256;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7153
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7154
    switch(h_i) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7155
      case 0: r = v, g = t, b = p;  break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7156
      case 1: r = q, g = v, b = p;  break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7157
      case 2: r = p, g = v, b = t;  break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7158
      case 3: r = p, g = q, b = v;  break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7159
      case 4: r = t, g = p, b = v;  break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7160
      case 5: r = v, g = p, b = q;  break;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7161
    }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7162
    var result = [Math.floor(r*255), Math.floor(g*255), Math.floor(b*255)];
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7163
    return result;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7164
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7165
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7166
  function colorString (prefix, values) {
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7167
    return prefix + '(' + values.join(', ') + ')';
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7168
  }
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7169
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7170
  return randomColor;
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7171
}));
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7172
},{}]},{},[])
082b64a5c699 add vizualizations to server
ymh <ymh.work@gmail.com>
parents:
diff changeset
  7173
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJhcHAvbGliL2xvZGFzaC9kaXN0L2xvZGFzaC5qcyIsIi4vYXBwL2xpYi9waXhpL2Jpbi9waXhpLmpzIiwiLi9hcHAvbGliL3JhbmRvbUNvbG9yL3JhbmRvbUNvbG9yLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ2pvTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBMby1EYXNoIDIuNC4xIChDdXN0b20gQnVpbGQpIDxodHRwOi8vbG9kYXNoLmNvbS8+XG4gKiBCdWlsZDogYGxvZGFzaCBtb2Rlcm4gLW8gLi9kaXN0L2xvZGFzaC5qc2BcbiAqIENvcHlyaWdodCAyMDEyLTIwMTMgVGhlIERvam8gRm91bmRhdGlvbiA8aHR0cDovL2Rvam9mb3VuZGF0aW9uLm9yZy8+XG4gKiBCYXNlZCBvbiBVbmRlcnNjb3JlLmpzIDEuNS4yIDxodHRwOi8vdW5kZXJzY29yZWpzLm9yZy9MSUNFTlNFPlxuICogQ29weXJpZ2h0IDIwMDktMjAxMyBKZXJlbXkgQXNoa2VuYXMsIERvY3VtZW50Q2xvdWQgYW5kIEludmVzdGlnYXRpdmUgUmVwb3J0ZXJzICYgRWRpdG9yc1xuICogQXZhaWxhYmxlIHVuZGVyIE1JVCBsaWNlbnNlIDxodHRwOi8vbG9kYXNoLmNvbS9saWNlbnNlPlxuICovXG47KGZ1bmN0aW9uKCkge1xuXG4gIC8qKiBVc2VkIGFzIGEgc2FmZSByZWZlcmVuY2UgZm9yIGB1bmRlZmluZWRgIGluIHByZSBFUzUgZW52aXJvbm1lbnRzICovXG4gIHZhciB1bmRlZmluZWQ7XG5cbiAgLyoqIFVzZWQgdG8gcG9vbCBhcnJheXMgYW5kIG9iamVjdHMgdXNlZCBpbnRlcm5hbGx5ICovXG4gIHZhciBhcnJheVBvb2wgPSBbXSxcbiAgICAgIG9iamVjdFBvb2wgPSBbXTtcblxuICAvKiogVXNlZCB0byBnZW5lcmF0ZSB1bmlxdWUgSURzICovXG4gIHZhciBpZENvdW50ZXIgPSAwO1xuXG4gIC8qKiBVc2VkIHRvIHByZWZpeCBrZXlzIHRvIGF2b2lkIGlzc3VlcyB3aXRoIGBfX3Byb3RvX19gIGFuZCBwcm9wZXJ0aWVzIG9uIGBPYmplY3QucHJvdG90eXBlYCAqL1xuICB2YXIga2V5UHJlZml4ID0gK25ldyBEYXRlICsgJyc7XG5cbiAgLyoqIFVzZWQgYXMgdGhlIHNpemUgd2hlbiBvcHRpbWl6YXRpb25zIGFyZSBlbmFibGVkIGZvciBsYXJnZSBhcnJheXMgKi9cbiAgdmFyIGxhcmdlQXJyYXlTaXplID0gNzU7XG5cbiAgLyoqIFVzZWQgYXMgdGhlIG1heCBzaXplIG9mIHRoZSBgYXJyYXlQb29sYCBhbmQgYG9iamVjdFBvb2xgICovXG4gIHZhciBtYXhQb29sU2l6ZSA9IDQwO1xuXG4gIC8qKiBVc2VkIHRvIGRldGVjdCBhbmQgdGVzdCB3aGl0ZXNwYWNlICovXG4gIHZhciB3aGl0ZXNwYWNlID0gKFxuICAgIC8vIHdoaXRlc3BhY2VcbiAgICAnIFxcdFxceDBCXFxmXFx4QTBcXHVmZWZmJyArXG5cbiAgICAvLyBsaW5lIHRlcm1pbmF0b3JzXG4gICAgJ1xcblxcclxcdTIwMjhcXHUyMDI5JyArXG5cbiAgICAvLyB1bmljb2RlIGNhdGVnb3J5IFwiWnNcIiBzcGFjZSBzZXBhcmF0b3JzXG4gICAgJ1xcdTE2ODBcXHUxODBlXFx1MjAwMFxcdTIwMDFcXHUyMDAyXFx1MjAwM1xcdTIwMDRcXHUyMDA1XFx1MjAwNlxcdTIwMDdcXHUyMDA4XFx1MjAwOVxcdTIwMGFcXHUyMDJmXFx1MjA1ZlxcdTMwMDAnXG4gICk7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggZW1wdHkgc3RyaW5nIGxpdGVyYWxzIGluIGNvbXBpbGVkIHRlbXBsYXRlIHNvdXJjZSAqL1xuICB2YXIgcmVFbXB0eVN0cmluZ0xlYWRpbmcgPSAvXFxiX19wIFxcKz0gJyc7L2csXG4gICAgICByZUVtcHR5U3RyaW5nTWlkZGxlID0gL1xcYihfX3AgXFwrPSkgJycgXFwrL2csXG4gICAgICByZUVtcHR5U3RyaW5nVHJhaWxpbmcgPSAvKF9fZVxcKC4qP1xcKXxcXGJfX3RcXCkpIFxcK1xcbicnOy9nO1xuXG4gIC8qKlxuICAgKiBVc2VkIHRvIG1hdGNoIEVTNiB0ZW1wbGF0ZSBkZWxpbWl0ZXJzXG4gICAqIGh0dHA6Ly9wZW9wbGUubW96aWxsYS5vcmcvfmpvcmVuZG9yZmYvZXM2LWRyYWZ0Lmh0bWwjc2VjLWxpdGVyYWxzLXN0cmluZy1saXRlcmFsc1xuICAgKi9cbiAgdmFyIHJlRXNUZW1wbGF0ZSA9IC9cXCRcXHsoW15cXFxcfV0qKD86XFxcXC5bXlxcXFx9XSopKilcXH0vZztcblxuICAvKiogVXNlZCB0byBtYXRjaCByZWdleHAgZmxhZ3MgZnJvbSB0aGVpciBjb2VyY2VkIHN0cmluZyB2YWx1ZXMgKi9cbiAgdmFyIHJlRmxhZ3MgPSAvXFx3KiQvO1xuXG4gIC8qKiBVc2VkIHRvIGRldGVjdGVkIG5hbWVkIGZ1bmN0aW9ucyAqL1xuICB2YXIgcmVGdW5jTmFtZSA9IC9eXFxzKmZ1bmN0aW9uWyBcXG5cXHJcXHRdK1xcdy87XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggXCJpbnRlcnBvbGF0ZVwiIHRlbXBsYXRlIGRlbGltaXRlcnMgKi9cbiAgdmFyIHJlSW50ZXJwb2xhdGUgPSAvPCU9KFtcXHNcXFNdKz8pJT4vZztcblxuICAvKiogVXNlZCB0byBtYXRjaCBsZWFkaW5nIHdoaXRlc3BhY2UgYW5kIHplcm9zIHRvIGJlIHJlbW92ZWQgKi9cbiAgdmFyIHJlTGVhZGluZ1NwYWNlc0FuZFplcm9zID0gUmVnRXhwKCdeWycgKyB3aGl0ZXNwYWNlICsgJ10qMCsoPz0uJCknKTtcblxuICAvKiogVXNlZCB0byBlbnN1cmUgY2FwdHVyaW5nIG9yZGVyIG9mIHRlbXBsYXRlIGRlbGltaXRlcnMgKi9cbiAgdmFyIHJlTm9NYXRjaCA9IC8oJF4pLztcblxuICAvKiogVXNlZCB0byBkZXRlY3QgZnVuY3Rpb25zIGNvbnRhaW5pbmcgYSBgdGhpc2AgcmVmZXJlbmNlICovXG4gIHZhciByZVRoaXMgPSAvXFxidGhpc1xcYi87XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggdW5lc2NhcGVkIGNoYXJhY3RlcnMgaW4gY29tcGlsZWQgc3RyaW5nIGxpdGVyYWxzICovXG4gIHZhciByZVVuZXNjYXBlZFN0cmluZyA9IC9bJ1xcblxcclxcdFxcdTIwMjhcXHUyMDI5XFxcXF0vZztcblxuICAvKiogVXNlZCB0byBhc3NpZ24gZGVmYXVsdCBgY29udGV4dGAgb2JqZWN0IHByb3BlcnRpZXMgKi9cbiAgdmFyIGNvbnRleHRQcm9wcyA9IFtcbiAgICAnQXJyYXknLCAnQm9vbGVhbicsICdEYXRlJywgJ0Z1bmN0aW9uJywgJ01hdGgnLCAnTnVtYmVyJywgJ09iamVjdCcsXG4gICAgJ1JlZ0V4cCcsICdTdHJpbmcnLCAnXycsICdhdHRhY2hFdmVudCcsICdjbGVhclRpbWVvdXQnLCAnaXNGaW5pdGUnLCAnaXNOYU4nLFxuICAgICdwYXJzZUludCcsICdzZXRUaW1lb3V0J1xuICBdO1xuXG4gIC8qKiBVc2VkIHRvIG1ha2UgdGVtcGxhdGUgc291cmNlVVJMcyBlYXNpZXIgdG8gaWRlbnRpZnkgKi9cbiAgdmFyIHRlbXBsYXRlQ291bnRlciA9IDA7XG5cbiAgLyoqIGBPYmplY3QjdG9TdHJpbmdgIHJlc3VsdCBzaG9ydGN1dHMgKi9cbiAgdmFyIGFyZ3NDbGFzcyA9ICdbb2JqZWN0IEFyZ3VtZW50c10nLFxuICAgICAgYXJyYXlDbGFzcyA9ICdbb2JqZWN0IEFycmF5XScsXG4gICAgICBib29sQ2xhc3MgPSAnW29iamVjdCBCb29sZWFuXScsXG4gICAgICBkYXRlQ2xhc3MgPSAnW29iamVjdCBEYXRlXScsXG4gICAgICBmdW5jQ2xhc3MgPSAnW29iamVjdCBGdW5jdGlvbl0nLFxuICAgICAgbnVtYmVyQ2xhc3MgPSAnW29iamVjdCBOdW1iZXJdJyxcbiAgICAgIG9iamVjdENsYXNzID0gJ1tvYmplY3QgT2JqZWN0XScsXG4gICAgICByZWdleHBDbGFzcyA9ICdbb2JqZWN0IFJlZ0V4cF0nLFxuICAgICAgc3RyaW5nQ2xhc3MgPSAnW29iamVjdCBTdHJpbmddJztcblxuICAvKiogVXNlZCB0byBpZGVudGlmeSBvYmplY3QgY2xhc3NpZmljYXRpb25zIHRoYXQgYF8uY2xvbmVgIHN1cHBvcnRzICovXG4gIHZhciBjbG9uZWFibGVDbGFzc2VzID0ge307XG4gIGNsb25lYWJsZUNsYXNzZXNbZnVuY0NsYXNzXSA9IGZhbHNlO1xuICBjbG9uZWFibGVDbGFzc2VzW2FyZ3NDbGFzc10gPSBjbG9uZWFibGVDbGFzc2VzW2FycmF5Q2xhc3NdID1cbiAgY2xvbmVhYmxlQ2xhc3Nlc1tib29sQ2xhc3NdID0gY2xvbmVhYmxlQ2xhc3Nlc1tkYXRlQ2xhc3NdID1cbiAgY2xvbmVhYmxlQ2xhc3Nlc1tudW1iZXJDbGFzc10gPSBjbG9uZWFibGVDbGFzc2VzW29iamVjdENsYXNzXSA9XG4gIGNsb25lYWJsZUNsYXNzZXNbcmVnZXhwQ2xhc3NdID0gY2xvbmVhYmxlQ2xhc3Nlc1tzdHJpbmdDbGFzc10gPSB0cnVlO1xuXG4gIC8qKiBVc2VkIGFzIGFuIGludGVybmFsIGBfLmRlYm91bmNlYCBvcHRpb25zIG9iamVjdCAqL1xuICB2YXIgZGVib3VuY2VPcHRpb25zID0ge1xuICAgICdsZWFkaW5nJzogZmFsc2UsXG4gICAgJ21heFdhaXQnOiAwLFxuICAgICd0cmFpbGluZyc6IGZhbHNlXG4gIH07XG5cbiAgLyoqIFVzZWQgYXMgdGhlIHByb3BlcnR5IGRlc2NyaXB0b3IgZm9yIGBfX2JpbmREYXRhX19gICovXG4gIHZhciBkZXNjcmlwdG9yID0ge1xuICAgICdjb25maWd1cmFibGUnOiBmYWxzZSxcbiAgICAnZW51bWVyYWJsZSc6IGZhbHNlLFxuICAgICd2YWx1ZSc6IG51bGwsXG4gICAgJ3dyaXRhYmxlJzogZmFsc2VcbiAgfTtcblxuICAvKiogVXNlZCB0byBkZXRlcm1pbmUgaWYgdmFsdWVzIGFyZSBvZiB0aGUgbGFuZ3VhZ2UgdHlwZSBPYmplY3QgKi9cbiAgdmFyIG9iamVjdFR5cGVzID0ge1xuICAgICdib29sZWFuJzogZmFsc2UsXG4gICAgJ2Z1bmN0aW9uJzogdHJ1ZSxcbiAgICAnb2JqZWN0JzogdHJ1ZSxcbiAgICAnbnVtYmVyJzogZmFsc2UsXG4gICAgJ3N0cmluZyc6IGZhbHNlLFxuICAgICd1bmRlZmluZWQnOiBmYWxzZVxuICB9O1xuXG4gIC8qKiBVc2VkIHRvIGVzY2FwZSBjaGFyYWN0ZXJzIGZvciBpbmNsdXNpb24gaW4gY29tcGlsZWQgc3RyaW5nIGxpdGVyYWxzICovXG4gIHZhciBzdHJpbmdFc2NhcGVzID0ge1xuICAgICdcXFxcJzogJ1xcXFwnLFxuICAgIFwiJ1wiOiBcIidcIixcbiAgICAnXFxuJzogJ24nLFxuICAgICdcXHInOiAncicsXG4gICAgJ1xcdCc6ICd0JyxcbiAgICAnXFx1MjAyOCc6ICd1MjAyOCcsXG4gICAgJ1xcdTIwMjknOiAndTIwMjknXG4gIH07XG5cbiAgLyoqIFVzZWQgYXMgYSByZWZlcmVuY2UgdG8gdGhlIGdsb2JhbCBvYmplY3QgKi9cbiAgdmFyIHJvb3QgPSAob2JqZWN0VHlwZXNbdHlwZW9mIHdpbmRvd10gJiYgd2luZG93KSB8fCB0aGlzO1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZXhwb3J0c2AgKi9cbiAgdmFyIGZyZWVFeHBvcnRzID0gb2JqZWN0VHlwZXNbdHlwZW9mIGV4cG9ydHNdICYmIGV4cG9ydHMgJiYgIWV4cG9ydHMubm9kZVR5cGUgJiYgZXhwb3J0cztcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYG1vZHVsZWAgKi9cbiAgdmFyIGZyZWVNb2R1bGUgPSBvYmplY3RUeXBlc1t0eXBlb2YgbW9kdWxlXSAmJiBtb2R1bGUgJiYgIW1vZHVsZS5ub2RlVHlwZSAmJiBtb2R1bGU7XG5cbiAgLyoqIERldGVjdCB0aGUgcG9wdWxhciBDb21tb25KUyBleHRlbnNpb24gYG1vZHVsZS5leHBvcnRzYCAqL1xuICB2YXIgbW9kdWxlRXhwb3J0cyA9IGZyZWVNb2R1bGUgJiYgZnJlZU1vZHVsZS5leHBvcnRzID09PSBmcmVlRXhwb3J0cyAmJiBmcmVlRXhwb3J0cztcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYGdsb2JhbGAgZnJvbSBOb2RlLmpzIG9yIEJyb3dzZXJpZmllZCBjb2RlIGFuZCB1c2UgaXQgYXMgYHJvb3RgICovXG4gIHZhciBmcmVlR2xvYmFsID0gb2JqZWN0VHlwZXNbdHlwZW9mIGdsb2JhbF0gJiYgZ2xvYmFsO1xuICBpZiAoZnJlZUdsb2JhbCAmJiAoZnJlZUdsb2JhbC5nbG9iYWwgPT09IGZyZWVHbG9iYWwgfHwgZnJlZUdsb2JhbC53aW5kb3cgPT09IGZyZWVHbG9iYWwpKSB7XG4gICAgcm9vdCA9IGZyZWVHbG9iYWw7XG4gIH1cblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaW5kZXhPZmAgd2l0aG91dCBzdXBwb3J0IGZvciBiaW5hcnkgc2VhcmNoZXNcbiAgICogb3IgYGZyb21JbmRleGAgY29uc3RyYWludHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBzZWFyY2guXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNlYXJjaCBmb3IuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbZnJvbUluZGV4PTBdIFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUgb3IgYC0xYC5cbiAgICovXG4gIGZ1bmN0aW9uIGJhc2VJbmRleE9mKGFycmF5LCB2YWx1ZSwgZnJvbUluZGV4KSB7XG4gICAgdmFyIGluZGV4ID0gKGZyb21JbmRleCB8fCAwKSAtIDEsXG4gICAgICAgIGxlbmd0aCA9IGFycmF5ID8gYXJyYXkubGVuZ3RoIDogMDtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICBpZiAoYXJyYXlbaW5kZXhdID09PSB2YWx1ZSkge1xuICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiAtMTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbiBpbXBsZW1lbnRhdGlvbiBvZiBgXy5jb250YWluc2AgZm9yIGNhY2hlIG9iamVjdHMgdGhhdCBtaW1pY3MgdGhlIHJldHVyblxuICAgKiBzaWduYXR1cmUgb2YgYF8uaW5kZXhPZmAgYnkgcmV0dXJuaW5nIGAwYCBpZiB0aGUgdmFsdWUgaXMgZm91bmQsIGVsc2UgYC0xYC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtPYmplY3R9IGNhY2hlIFRoZSBjYWNoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2VhcmNoIGZvci5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyBgMGAgaWYgYHZhbHVlYCBpcyBmb3VuZCwgZWxzZSBgLTFgLlxuICAgKi9cbiAgZnVuY3Rpb24gY2FjaGVJbmRleE9mKGNhY2hlLCB2YWx1ZSkge1xuICAgIHZhciB0eXBlID0gdHlwZW9mIHZhbHVlO1xuICAgIGNhY2hlID0gY2FjaGUuY2FjaGU7XG5cbiAgICBpZiAodHlwZSA9PSAnYm9vbGVhbicgfHwgdmFsdWUgPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGNhY2hlW3ZhbHVlXSA/IDAgOiAtMTtcbiAgICB9XG4gICAgaWYgKHR5cGUgIT0gJ251bWJlcicgJiYgdHlwZSAhPSAnc3RyaW5nJykge1xuICAgICAgdHlwZSA9ICdvYmplY3QnO1xuICAgIH1cbiAgICB2YXIga2V5ID0gdHlwZSA9PSAnbnVtYmVyJyA/IHZhbHVlIDoga2V5UHJlZml4ICsgdmFsdWU7XG4gICAgY2FjaGUgPSAoY2FjaGUgPSBjYWNoZVt0eXBlXSkgJiYgY2FjaGVba2V5XTtcblxuICAgIHJldHVybiB0eXBlID09ICdvYmplY3QnXG4gICAgICA/IChjYWNoZSAmJiBiYXNlSW5kZXhPZihjYWNoZSwgdmFsdWUpID4gLTEgPyAwIDogLTEpXG4gICAgICA6IChjYWNoZSA/IDAgOiAtMSk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIGdpdmVuIHZhbHVlIHRvIHRoZSBjb3JyZXNwb25kaW5nIGNhY2hlIG9iamVjdC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gYWRkIHRvIHRoZSBjYWNoZS5cbiAgICovXG4gIGZ1bmN0aW9uIGNhY2hlUHVzaCh2YWx1ZSkge1xuICAgIHZhciBjYWNoZSA9IHRoaXMuY2FjaGUsXG4gICAgICAgIHR5cGUgPSB0eXBlb2YgdmFsdWU7XG5cbiAgICBpZiAodHlwZSA9PSAnYm9vbGVhbicgfHwgdmFsdWUgPT0gbnVsbCkge1xuICAgICAgY2FjaGVbdmFsdWVdID0gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHR5cGUgIT0gJ251bWJlcicgJiYgdHlwZSAhPSAnc3RyaW5nJykge1xuICAgICAgICB0eXBlID0gJ29iamVjdCc7XG4gICAgICB9XG4gICAgICB2YXIga2V5ID0gdHlwZSA9PSAnbnVtYmVyJyA/IHZhbHVlIDoga2V5UHJlZml4ICsgdmFsdWUsXG4gICAgICAgICAgdHlwZUNhY2hlID0gY2FjaGVbdHlwZV0gfHwgKGNhY2hlW3R5cGVdID0ge30pO1xuXG4gICAgICBpZiAodHlwZSA9PSAnb2JqZWN0Jykge1xuICAgICAgICAodHlwZUNhY2hlW2tleV0gfHwgKHR5cGVDYWNoZVtrZXldID0gW10pKS5wdXNoKHZhbHVlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHR5cGVDYWNoZVtrZXldID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVXNlZCBieSBgXy5tYXhgIGFuZCBgXy5taW5gIGFzIHRoZSBkZWZhdWx0IGNhbGxiYWNrIHdoZW4gYSBnaXZlblxuICAgKiBjb2xsZWN0aW9uIGlzIGEgc3RyaW5nIHZhbHVlLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgVGhlIGNoYXJhY3RlciB0byBpbnNwZWN0LlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBjb2RlIHVuaXQgb2YgZ2l2ZW4gY2hhcmFjdGVyLlxuICAgKi9cbiAgZnVuY3Rpb24gY2hhckF0Q2FsbGJhY2sodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUuY2hhckNvZGVBdCgwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIGJ5IGBzb3J0QnlgIHRvIGNvbXBhcmUgdHJhbnNmb3JtZWQgYGNvbGxlY3Rpb25gIGVsZW1lbnRzLCBzdGFibGUgc29ydGluZ1xuICAgKiB0aGVtIGluIGFzY2VuZGluZyBvcmRlci5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtPYmplY3R9IGEgVGhlIG9iamVjdCB0byBjb21wYXJlIHRvIGBiYC5cbiAgICogQHBhcmFtIHtPYmplY3R9IGIgVGhlIG9iamVjdCB0byBjb21wYXJlIHRvIGBhYC5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgc29ydCBvcmRlciBpbmRpY2F0b3Igb2YgYDFgIG9yIGAtMWAuXG4gICAqL1xuICBmdW5jdGlvbiBjb21wYXJlQXNjZW5kaW5nKGEsIGIpIHtcbiAgICB2YXIgYWMgPSBhLmNyaXRlcmlhLFxuICAgICAgICBiYyA9IGIuY3JpdGVyaWEsXG4gICAgICAgIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IGFjLmxlbmd0aDtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICB2YXIgdmFsdWUgPSBhY1tpbmRleF0sXG4gICAgICAgICAgb3RoZXIgPSBiY1tpbmRleF07XG5cbiAgICAgIGlmICh2YWx1ZSAhPT0gb3RoZXIpIHtcbiAgICAgICAgaWYgKHZhbHVlID4gb3RoZXIgfHwgdHlwZW9mIHZhbHVlID09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlIDwgb3RoZXIgfHwgdHlwZW9mIG90aGVyID09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIC8vIEZpeGVzIGFuIGBBcnJheSNzb3J0YCBidWcgaW4gdGhlIEpTIGVuZ2luZSBlbWJlZGRlZCBpbiBBZG9iZSBhcHBsaWNhdGlvbnNcbiAgICAvLyB0aGF0IGNhdXNlcyBpdCwgdW5kZXIgY2VydGFpbiBjaXJjdW1zdGFuY2VzLCB0byByZXR1cm4gdGhlIHNhbWUgdmFsdWUgZm9yXG4gICAgLy8gYGFgIGFuZCBgYmAuIFNlZSBodHRwczovL2dpdGh1Yi5jb20vamFzaGtlbmFzL3VuZGVyc2NvcmUvcHVsbC8xMjQ3XG4gICAgLy9cbiAgICAvLyBUaGlzIGFsc28gZW5zdXJlcyBhIHN0YWJsZSBzb3J0IGluIFY4IGFuZCBvdGhlciBlbmdpbmVzLlxuICAgIC8vIFNlZSBodHRwOi8vY29kZS5nb29nbGUuY29tL3AvdjgvaXNzdWVzL2RldGFpbD9pZD05MFxuICAgIHJldHVybiBhLmluZGV4IC0gYi5pbmRleDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgY2FjaGUgb2JqZWN0IHRvIG9wdGltaXplIGxpbmVhciBzZWFyY2hlcyBvZiBsYXJnZSBhcnJheXMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IFthcnJheT1bXV0gVGhlIGFycmF5IHRvIHNlYXJjaC5cbiAgICogQHJldHVybnMge251bGx8T2JqZWN0fSBSZXR1cm5zIHRoZSBjYWNoZSBvYmplY3Qgb3IgYG51bGxgIGlmIGNhY2hpbmcgc2hvdWxkIG5vdCBiZSB1c2VkLlxuICAgKi9cbiAgZnVuY3Rpb24gY3JlYXRlQ2FjaGUoYXJyYXkpIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICBmaXJzdCA9IGFycmF5WzBdLFxuICAgICAgICBtaWQgPSBhcnJheVsobGVuZ3RoIC8gMikgfCAwXSxcbiAgICAgICAgbGFzdCA9IGFycmF5W2xlbmd0aCAtIDFdO1xuXG4gICAgaWYgKGZpcnN0ICYmIHR5cGVvZiBmaXJzdCA9PSAnb2JqZWN0JyAmJlxuICAgICAgICBtaWQgJiYgdHlwZW9mIG1pZCA9PSAnb2JqZWN0JyAmJiBsYXN0ICYmIHR5cGVvZiBsYXN0ID09ICdvYmplY3QnKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHZhciBjYWNoZSA9IGdldE9iamVjdCgpO1xuICAgIGNhY2hlWydmYWxzZSddID0gY2FjaGVbJ251bGwnXSA9IGNhY2hlWyd0cnVlJ10gPSBjYWNoZVsndW5kZWZpbmVkJ10gPSBmYWxzZTtcblxuICAgIHZhciByZXN1bHQgPSBnZXRPYmplY3QoKTtcbiAgICByZXN1bHQuYXJyYXkgPSBhcnJheTtcbiAgICByZXN1bHQuY2FjaGUgPSBjYWNoZTtcbiAgICByZXN1bHQucHVzaCA9IGNhY2hlUHVzaDtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICByZXN1bHQucHVzaChhcnJheVtpbmRleF0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgYnkgYHRlbXBsYXRlYCB0byBlc2NhcGUgY2hhcmFjdGVycyBmb3IgaW5jbHVzaW9uIGluIGNvbXBpbGVkXG4gICAqIHN0cmluZyBsaXRlcmFscy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IG1hdGNoIFRoZSBtYXRjaGVkIGNoYXJhY3RlciB0byBlc2NhcGUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGVzY2FwZWQgY2hhcmFjdGVyLlxuICAgKi9cbiAgZnVuY3Rpb24gZXNjYXBlU3RyaW5nQ2hhcihtYXRjaCkge1xuICAgIHJldHVybiAnXFxcXCcgKyBzdHJpbmdFc2NhcGVzW21hdGNoXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIGFuIGFycmF5IGZyb20gdGhlIGFycmF5IHBvb2wgb3IgY3JlYXRlcyBhIG5ldyBvbmUgaWYgdGhlIHBvb2wgaXMgZW1wdHkuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEByZXR1cm5zIHtBcnJheX0gVGhlIGFycmF5IGZyb20gdGhlIHBvb2wuXG4gICAqL1xuICBmdW5jdGlvbiBnZXRBcnJheSgpIHtcbiAgICByZXR1cm4gYXJyYXlQb29sLnBvcCgpIHx8IFtdO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgYW4gb2JqZWN0IGZyb20gdGhlIG9iamVjdCBwb29sIG9yIGNyZWF0ZXMgYSBuZXcgb25lIGlmIHRoZSBwb29sIGlzIGVtcHR5LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgb2JqZWN0IGZyb20gdGhlIHBvb2wuXG4gICAqL1xuICBmdW5jdGlvbiBnZXRPYmplY3QoKSB7XG4gICAgcmV0dXJuIG9iamVjdFBvb2wucG9wKCkgfHwge1xuICAgICAgJ2FycmF5JzogbnVsbCxcbiAgICAgICdjYWNoZSc6IG51bGwsXG4gICAgICAnY3JpdGVyaWEnOiBudWxsLFxuICAgICAgJ2ZhbHNlJzogZmFsc2UsXG4gICAgICAnaW5kZXgnOiAwLFxuICAgICAgJ251bGwnOiBmYWxzZSxcbiAgICAgICdudW1iZXInOiBudWxsLFxuICAgICAgJ29iamVjdCc6IG51bGwsXG4gICAgICAncHVzaCc6IG51bGwsXG4gICAgICAnc3RyaW5nJzogbnVsbCxcbiAgICAgICd0cnVlJzogZmFsc2UsXG4gICAgICAndW5kZWZpbmVkJzogZmFsc2UsXG4gICAgICAndmFsdWUnOiBudWxsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWxlYXNlcyB0aGUgZ2l2ZW4gYXJyYXkgYmFjayB0byB0aGUgYXJyYXkgcG9vbC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gW2FycmF5XSBUaGUgYXJyYXkgdG8gcmVsZWFzZS5cbiAgICovXG4gIGZ1bmN0aW9uIHJlbGVhc2VBcnJheShhcnJheSkge1xuICAgIGFycmF5Lmxlbmd0aCA9IDA7XG4gICAgaWYgKGFycmF5UG9vbC5sZW5ndGggPCBtYXhQb29sU2l6ZSkge1xuICAgICAgYXJyYXlQb29sLnB1c2goYXJyYXkpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZWxlYXNlcyB0aGUgZ2l2ZW4gb2JqZWN0IGJhY2sgdG8gdGhlIG9iamVjdCBwb29sLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29iamVjdF0gVGhlIG9iamVjdCB0byByZWxlYXNlLlxuICAgKi9cbiAgZnVuY3Rpb24gcmVsZWFzZU9iamVjdChvYmplY3QpIHtcbiAgICB2YXIgY2FjaGUgPSBvYmplY3QuY2FjaGU7XG4gICAgaWYgKGNhY2hlKSB7XG4gICAgICByZWxlYXNlT2JqZWN0KGNhY2hlKTtcbiAgICB9XG4gICAgb2JqZWN0LmFycmF5ID0gb2JqZWN0LmNhY2hlID0gb2JqZWN0LmNyaXRlcmlhID0gb2JqZWN0Lm9iamVjdCA9IG9iamVjdC5udW1iZXIgPSBvYmplY3Quc3RyaW5nID0gb2JqZWN0LnZhbHVlID0gbnVsbDtcbiAgICBpZiAob2JqZWN0UG9vbC5sZW5ndGggPCBtYXhQb29sU2l6ZSkge1xuICAgICAgb2JqZWN0UG9vbC5wdXNoKG9iamVjdCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNsaWNlcyB0aGUgYGNvbGxlY3Rpb25gIGZyb20gdGhlIGBzdGFydGAgaW5kZXggdXAgdG8sIGJ1dCBub3QgaW5jbHVkaW5nLFxuICAgKiB0aGUgYGVuZGAgaW5kZXguXG4gICAqXG4gICAqIE5vdGU6IFRoaXMgZnVuY3Rpb24gaXMgdXNlZCBpbnN0ZWFkIG9mIGBBcnJheSNzbGljZWAgdG8gc3VwcG9ydCBub2RlIGxpc3RzXG4gICAqIGluIElFIDwgOSBhbmQgdG8gZW5zdXJlIGRlbnNlIGFycmF5cyBhcmUgcmV0dXJuZWQuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBzbGljZS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHN0YXJ0IFRoZSBzdGFydCBpbmRleC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGVuZCBUaGUgZW5kIGluZGV4LlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheS5cbiAgICovXG4gIGZ1bmN0aW9uIHNsaWNlKGFycmF5LCBzdGFydCwgZW5kKSB7XG4gICAgc3RhcnQgfHwgKHN0YXJ0ID0gMCk7XG4gICAgaWYgKHR5cGVvZiBlbmQgPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGVuZCA9IGFycmF5ID8gYXJyYXkubGVuZ3RoIDogMDtcbiAgICB9XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IGVuZCAtIHN0YXJ0IHx8IDAsXG4gICAgICAgIHJlc3VsdCA9IEFycmF5KGxlbmd0aCA8IDAgPyAwIDogbGVuZ3RoKTtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICByZXN1bHRbaW5kZXhdID0gYXJyYXlbc3RhcnQgKyBpbmRleF07XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IGBsb2Rhc2hgIGZ1bmN0aW9uIHVzaW5nIHRoZSBnaXZlbiBjb250ZXh0IG9iamVjdC5cbiAgICpcbiAgICogQHN0YXRpY1xuICAgKiBAbWVtYmVyT2YgX1xuICAgKiBAY2F0ZWdvcnkgVXRpbGl0aWVzXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbY29udGV4dD1yb290XSBUaGUgY29udGV4dCBvYmplY3QuXG4gICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgYGxvZGFzaGAgZnVuY3Rpb24uXG4gICAqL1xuICBmdW5jdGlvbiBydW5JbkNvbnRleHQoY29udGV4dCkge1xuICAgIC8vIEF2b2lkIGlzc3VlcyB3aXRoIHNvbWUgRVMzIGVudmlyb25tZW50cyB0aGF0IGF0dGVtcHQgdG8gdXNlIHZhbHVlcywgbmFtZWRcbiAgICAvLyBhZnRlciBidWlsdC1pbiBjb25zdHJ1Y3RvcnMgbGlrZSBgT2JqZWN0YCwgZm9yIHRoZSBjcmVhdGlvbiBvZiBsaXRlcmFscy5cbiAgICAvLyBFUzUgY2xlYXJzIHRoaXMgdXAgYnkgc3RhdGluZyB0aGF0IGxpdGVyYWxzIG11c3QgdXNlIGJ1aWx0LWluIGNvbnN0cnVjdG9ycy5cbiAgICAvLyBTZWUgaHR0cDovL2VzNS5naXRodWIuaW8vI3gxMS4xLjUuXG4gICAgY29udGV4dCA9IGNvbnRleHQgPyBfLmRlZmF1bHRzKHJvb3QuT2JqZWN0KCksIGNvbnRleHQsIF8ucGljayhyb290LCBjb250ZXh0UHJvcHMpKSA6IHJvb3Q7XG5cbiAgICAvKiogTmF0aXZlIGNvbnN0cnVjdG9yIHJlZmVyZW5jZXMgKi9cbiAgICB2YXIgQXJyYXkgPSBjb250ZXh0LkFycmF5LFxuICAgICAgICBCb29sZWFuID0gY29udGV4dC5Cb29sZWFuLFxuICAgICAgICBEYXRlID0gY29udGV4dC5EYXRlLFxuICAgICAgICBGdW5jdGlvbiA9IGNvbnRleHQuRnVuY3Rpb24sXG4gICAgICAgIE1hdGggPSBjb250ZXh0Lk1hdGgsXG4gICAgICAgIE51bWJlciA9IGNvbnRleHQuTnVtYmVyLFxuICAgICAgICBPYmplY3QgPSBjb250ZXh0Lk9iamVjdCxcbiAgICAgICAgUmVnRXhwID0gY29udGV4dC5SZWdFeHAsXG4gICAgICAgIFN0cmluZyA9IGNvbnRleHQuU3RyaW5nLFxuICAgICAgICBUeXBlRXJyb3IgPSBjb250ZXh0LlR5cGVFcnJvcjtcblxuICAgIC8qKlxuICAgICAqIFVzZWQgZm9yIGBBcnJheWAgbWV0aG9kIHJlZmVyZW5jZXMuXG4gICAgICpcbiAgICAgKiBOb3JtYWxseSBgQXJyYXkucHJvdG90eXBlYCB3b3VsZCBzdWZmaWNlLCBob3dldmVyLCB1c2luZyBhbiBhcnJheSBsaXRlcmFsXG4gICAgICogYXZvaWRzIGlzc3VlcyBpbiBOYXJ3aGFsLlxuICAgICAqL1xuICAgIHZhciBhcnJheVJlZiA9IFtdO1xuXG4gICAgLyoqIFVzZWQgZm9yIG5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcyAqL1xuICAgIHZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbiAgICAvKiogVXNlZCB0byByZXN0b3JlIHRoZSBvcmlnaW5hbCBgX2AgcmVmZXJlbmNlIGluIGBub0NvbmZsaWN0YCAqL1xuICAgIHZhciBvbGREYXNoID0gY29udGV4dC5fO1xuXG4gICAgLyoqIFVzZWQgdG8gcmVzb2x2ZSB0aGUgaW50ZXJuYWwgW1tDbGFzc11dIG9mIHZhbHVlcyAqL1xuICAgIHZhciB0b1N0cmluZyA9IG9iamVjdFByb3RvLnRvU3RyaW5nO1xuXG4gICAgLyoqIFVzZWQgdG8gZGV0ZWN0IGlmIGEgbWV0aG9kIGlzIG5hdGl2ZSAqL1xuICAgIHZhciByZU5hdGl2ZSA9IFJlZ0V4cCgnXicgK1xuICAgICAgU3RyaW5nKHRvU3RyaW5nKVxuICAgICAgICAucmVwbGFjZSgvWy4qKz9eJHt9KCl8W1xcXVxcXFxdL2csICdcXFxcJCYnKVxuICAgICAgICAucmVwbGFjZSgvdG9TdHJpbmd8IGZvciBbXlxcXV0rL2csICcuKj8nKSArICckJ1xuICAgICk7XG5cbiAgICAvKiogTmF0aXZlIG1ldGhvZCBzaG9ydGN1dHMgKi9cbiAgICB2YXIgY2VpbCA9IE1hdGguY2VpbCxcbiAgICAgICAgY2xlYXJUaW1lb3V0ID0gY29udGV4dC5jbGVhclRpbWVvdXQsXG4gICAgICAgIGZsb29yID0gTWF0aC5mbG9vcixcbiAgICAgICAgZm5Ub1N0cmluZyA9IEZ1bmN0aW9uLnByb3RvdHlwZS50b1N0cmluZyxcbiAgICAgICAgZ2V0UHJvdG90eXBlT2YgPSBpc05hdGl2ZShnZXRQcm90b3R5cGVPZiA9IE9iamVjdC5nZXRQcm90b3R5cGVPZikgJiYgZ2V0UHJvdG90eXBlT2YsXG4gICAgICAgIGhhc093blByb3BlcnR5ID0gb2JqZWN0UHJvdG8uaGFzT3duUHJvcGVydHksXG4gICAgICAgIHB1c2ggPSBhcnJheVJlZi5wdXNoLFxuICAgICAgICBzZXRUaW1lb3V0ID0gY29udGV4dC5zZXRUaW1lb3V0LFxuICAgICAgICBzcGxpY2UgPSBhcnJheVJlZi5zcGxpY2UsXG4gICAgICAgIHVuc2hpZnQgPSBhcnJheVJlZi51bnNoaWZ0O1xuXG4gICAgLyoqIFVzZWQgdG8gc2V0IG1ldGEgZGF0YSBvbiBmdW5jdGlvbnMgKi9cbiAgICB2YXIgZGVmaW5lUHJvcGVydHkgPSAoZnVuY3Rpb24oKSB7XG4gICAgICAvLyBJRSA4IG9ubHkgYWNjZXB0cyBET00gZWxlbWVudHNcbiAgICAgIHRyeSB7XG4gICAgICAgIHZhciBvID0ge30sXG4gICAgICAgICAgICBmdW5jID0gaXNOYXRpdmUoZnVuYyA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSkgJiYgZnVuYyxcbiAgICAgICAgICAgIHJlc3VsdCA9IGZ1bmMobywgbywgbykgJiYgZnVuYztcbiAgICAgIH0gY2F0Y2goZSkgeyB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0oKSk7XG5cbiAgICAvKiBOYXRpdmUgbWV0aG9kIHNob3J0Y3V0cyBmb3IgbWV0aG9kcyB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgb3RoZXIgYGxvZGFzaGAgbWV0aG9kcyAqL1xuICAgIHZhciBuYXRpdmVDcmVhdGUgPSBpc05hdGl2ZShuYXRpdmVDcmVhdGUgPSBPYmplY3QuY3JlYXRlKSAmJiBuYXRpdmVDcmVhdGUsXG4gICAgICAgIG5hdGl2ZUlzQXJyYXkgPSBpc05hdGl2ZShuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheSkgJiYgbmF0aXZlSXNBcnJheSxcbiAgICAgICAgbmF0aXZlSXNGaW5pdGUgPSBjb250ZXh0LmlzRmluaXRlLFxuICAgICAgICBuYXRpdmVJc05hTiA9IGNvbnRleHQuaXNOYU4sXG4gICAgICAgIG5hdGl2ZUtleXMgPSBpc05hdGl2ZShuYXRpdmVLZXlzID0gT2JqZWN0LmtleXMpICYmIG5hdGl2ZUtleXMsXG4gICAgICAgIG5hdGl2ZU1heCA9IE1hdGgubWF4LFxuICAgICAgICBuYXRpdmVNaW4gPSBNYXRoLm1pbixcbiAgICAgICAgbmF0aXZlUGFyc2VJbnQgPSBjb250ZXh0LnBhcnNlSW50LFxuICAgICAgICBuYXRpdmVSYW5kb20gPSBNYXRoLnJhbmRvbTtcblxuICAgIC8qKiBVc2VkIHRvIGxvb2t1cCBhIGJ1aWx0LWluIGNvbnN0cnVjdG9yIGJ5IFtbQ2xhc3NdXSAqL1xuICAgIHZhciBjdG9yQnlDbGFzcyA9IHt9O1xuICAgIGN0b3JCeUNsYXNzW2FycmF5Q2xhc3NdID0gQXJyYXk7XG4gICAgY3RvckJ5Q2xhc3NbYm9vbENsYXNzXSA9IEJvb2xlYW47XG4gICAgY3RvckJ5Q2xhc3NbZGF0ZUNsYXNzXSA9IERhdGU7XG4gICAgY3RvckJ5Q2xhc3NbZnVuY0NsYXNzXSA9IEZ1bmN0aW9uO1xuICAgIGN0b3JCeUNsYXNzW29iamVjdENsYXNzXSA9IE9iamVjdDtcbiAgICBjdG9yQnlDbGFzc1tudW1iZXJDbGFzc10gPSBOdW1iZXI7XG4gICAgY3RvckJ5Q2xhc3NbcmVnZXhwQ2xhc3NdID0gUmVnRXhwO1xuICAgIGN0b3JCeUNsYXNzW3N0cmluZ0NsYXNzXSA9IFN0cmluZztcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGBsb2Rhc2hgIG9iamVjdCB3aGljaCB3cmFwcyB0aGUgZ2l2ZW4gdmFsdWUgdG8gZW5hYmxlIGludHVpdGl2ZVxuICAgICAqIG1ldGhvZCBjaGFpbmluZy5cbiAgICAgKlxuICAgICAqIEluIGFkZGl0aW9uIHRvIExvLURhc2ggbWV0aG9kcywgd3JhcHBlcnMgYWxzbyBoYXZlIHRoZSBmb2xsb3dpbmcgYEFycmF5YCBtZXRob2RzOlxuICAgICAqIGBjb25jYXRgLCBgam9pbmAsIGBwb3BgLCBgcHVzaGAsIGByZXZlcnNlYCwgYHNoaWZ0YCwgYHNsaWNlYCwgYHNvcnRgLCBgc3BsaWNlYCxcbiAgICAgKiBhbmQgYHVuc2hpZnRgXG4gICAgICpcbiAgICAgKiBDaGFpbmluZyBpcyBzdXBwb3J0ZWQgaW4gY3VzdG9tIGJ1aWxkcyBhcyBsb25nIGFzIHRoZSBgdmFsdWVgIG1ldGhvZCBpc1xuICAgICAqIGltcGxpY2l0bHkgb3IgZXhwbGljaXRseSBpbmNsdWRlZCBpbiB0aGUgYnVpbGQuXG4gICAgICpcbiAgICAgKiBUaGUgY2hhaW5hYmxlIHdyYXBwZXIgZnVuY3Rpb25zIGFyZTpcbiAgICAgKiBgYWZ0ZXJgLCBgYXNzaWduYCwgYGJpbmRgLCBgYmluZEFsbGAsIGBiaW5kS2V5YCwgYGNoYWluYCwgYGNvbXBhY3RgLFxuICAgICAqIGBjb21wb3NlYCwgYGNvbmNhdGAsIGBjb3VudEJ5YCwgYGNyZWF0ZWAsIGBjcmVhdGVDYWxsYmFja2AsIGBjdXJyeWAsXG4gICAgICogYGRlYm91bmNlYCwgYGRlZmF1bHRzYCwgYGRlZmVyYCwgYGRlbGF5YCwgYGRpZmZlcmVuY2VgLCBgZmlsdGVyYCwgYGZsYXR0ZW5gLFxuICAgICAqIGBmb3JFYWNoYCwgYGZvckVhY2hSaWdodGAsIGBmb3JJbmAsIGBmb3JJblJpZ2h0YCwgYGZvck93bmAsIGBmb3JPd25SaWdodGAsXG4gICAgICogYGZ1bmN0aW9uc2AsIGBncm91cEJ5YCwgYGluZGV4QnlgLCBgaW5pdGlhbGAsIGBpbnRlcnNlY3Rpb25gLCBgaW52ZXJ0YCxcbiAgICAgKiBgaW52b2tlYCwgYGtleXNgLCBgbWFwYCwgYG1heGAsIGBtZW1vaXplYCwgYG1lcmdlYCwgYG1pbmAsIGBvYmplY3RgLCBgb21pdGAsXG4gICAgICogYG9uY2VgLCBgcGFpcnNgLCBgcGFydGlhbGAsIGBwYXJ0aWFsUmlnaHRgLCBgcGlja2AsIGBwbHVja2AsIGBwdWxsYCwgYHB1c2hgLFxuICAgICAqIGByYW5nZWAsIGByZWplY3RgLCBgcmVtb3ZlYCwgYHJlc3RgLCBgcmV2ZXJzZWAsIGBzaHVmZmxlYCwgYHNsaWNlYCwgYHNvcnRgLFxuICAgICAqIGBzb3J0QnlgLCBgc3BsaWNlYCwgYHRhcGAsIGB0aHJvdHRsZWAsIGB0aW1lc2AsIGB0b0FycmF5YCwgYHRyYW5zZm9ybWAsXG4gICAgICogYHVuaW9uYCwgYHVuaXFgLCBgdW5zaGlmdGAsIGB1bnppcGAsIGB2YWx1ZXNgLCBgd2hlcmVgLCBgd2l0aG91dGAsIGB3cmFwYCxcbiAgICAgKiBhbmQgYHppcGBcbiAgICAgKlxuICAgICAqIFRoZSBub24tY2hhaW5hYmxlIHdyYXBwZXIgZnVuY3Rpb25zIGFyZTpcbiAgICAgKiBgY2xvbmVgLCBgY2xvbmVEZWVwYCwgYGNvbnRhaW5zYCwgYGVzY2FwZWAsIGBldmVyeWAsIGBmaW5kYCwgYGZpbmRJbmRleGAsXG4gICAgICogYGZpbmRLZXlgLCBgZmluZExhc3RgLCBgZmluZExhc3RJbmRleGAsIGBmaW5kTGFzdEtleWAsIGBoYXNgLCBgaWRlbnRpdHlgLFxuICAgICAqIGBpbmRleE9mYCwgYGlzQXJndW1lbnRzYCwgYGlzQXJyYXlgLCBgaXNCb29sZWFuYCwgYGlzRGF0ZWAsIGBpc0VsZW1lbnRgLFxuICAgICAqIGBpc0VtcHR5YCwgYGlzRXF1YWxgLCBgaXNGaW5pdGVgLCBgaXNGdW5jdGlvbmAsIGBpc05hTmAsIGBpc051bGxgLCBgaXNOdW1iZXJgLFxuICAgICAqIGBpc09iamVjdGAsIGBpc1BsYWluT2JqZWN0YCwgYGlzUmVnRXhwYCwgYGlzU3RyaW5nYCwgYGlzVW5kZWZpbmVkYCwgYGpvaW5gLFxuICAgICAqIGBsYXN0SW5kZXhPZmAsIGBtaXhpbmAsIGBub0NvbmZsaWN0YCwgYHBhcnNlSW50YCwgYHBvcGAsIGByYW5kb21gLCBgcmVkdWNlYCxcbiAgICAgKiBgcmVkdWNlUmlnaHRgLCBgcmVzdWx0YCwgYHNoaWZ0YCwgYHNpemVgLCBgc29tZWAsIGBzb3J0ZWRJbmRleGAsIGBydW5JbkNvbnRleHRgLFxuICAgICAqIGB0ZW1wbGF0ZWAsIGB1bmVzY2FwZWAsIGB1bmlxdWVJZGAsIGFuZCBgdmFsdWVgXG4gICAgICpcbiAgICAgKiBUaGUgd3JhcHBlciBmdW5jdGlvbnMgYGZpcnN0YCBhbmQgYGxhc3RgIHJldHVybiB3cmFwcGVkIHZhbHVlcyB3aGVuIGBuYCBpc1xuICAgICAqIHByb3ZpZGVkLCBvdGhlcndpc2UgdGhleSByZXR1cm4gdW53cmFwcGVkIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEV4cGxpY2l0IGNoYWluaW5nIGNhbiBiZSBlbmFibGVkIGJ5IHVzaW5nIHRoZSBgXy5jaGFpbmAgbWV0aG9kLlxuICAgICAqXG4gICAgICogQG5hbWUgX1xuICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAqIEBjYXRlZ29yeSBDaGFpbmluZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHdyYXAgaW4gYSBgbG9kYXNoYCBpbnN0YW5jZS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGEgYGxvZGFzaGAgaW5zdGFuY2UuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB3cmFwcGVkID0gXyhbMSwgMiwgM10pO1xuICAgICAqXG4gICAgICogLy8gcmV0dXJucyBhbiB1bndyYXBwZWQgdmFsdWVcbiAgICAgKiB3cmFwcGVkLnJlZHVjZShmdW5jdGlvbihzdW0sIG51bSkge1xuICAgICAqICAgcmV0dXJuIHN1bSArIG51bTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiA2XG4gICAgICpcbiAgICAgKiAvLyByZXR1cm5zIGEgd3JhcHBlZCB2YWx1ZVxuICAgICAqIHZhciBzcXVhcmVzID0gd3JhcHBlZC5tYXAoZnVuY3Rpb24obnVtKSB7XG4gICAgICogICByZXR1cm4gbnVtICogbnVtO1xuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogXy5pc0FycmF5KHNxdWFyZXMpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXkoc3F1YXJlcy52YWx1ZSgpKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gbG9kYXNoKHZhbHVlKSB7XG4gICAgICAvLyBkb24ndCB3cmFwIGlmIGFscmVhZHkgd3JhcHBlZCwgZXZlbiBpZiB3cmFwcGVkIGJ5IGEgZGlmZmVyZW50IGBsb2Rhc2hgIGNvbnN0cnVjdG9yXG4gICAgICByZXR1cm4gKHZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PSAnb2JqZWN0JyAmJiAhaXNBcnJheSh2YWx1ZSkgJiYgaGFzT3duUHJvcGVydHkuY2FsbCh2YWx1ZSwgJ19fd3JhcHBlZF9fJykpXG4gICAgICAgPyB2YWx1ZVxuICAgICAgIDogbmV3IGxvZGFzaFdyYXBwZXIodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgZmFzdCBwYXRoIGZvciBjcmVhdGluZyBgbG9kYXNoYCB3cmFwcGVyIG9iamVjdHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHdyYXAgaW4gYSBgbG9kYXNoYCBpbnN0YW5jZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGNoYWluQWxsIEEgZmxhZyB0byBlbmFibGUgY2hhaW5pbmcgZm9yIGFsbCBtZXRob2RzXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBhIGBsb2Rhc2hgIGluc3RhbmNlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGxvZGFzaFdyYXBwZXIodmFsdWUsIGNoYWluQWxsKSB7XG4gICAgICB0aGlzLl9fY2hhaW5fXyA9ICEhY2hhaW5BbGw7XG4gICAgICB0aGlzLl9fd3JhcHBlZF9fID0gdmFsdWU7XG4gICAgfVxuICAgIC8vIGVuc3VyZSBgbmV3IGxvZGFzaFdyYXBwZXJgIGlzIGFuIGluc3RhbmNlIG9mIGBsb2Rhc2hgXG4gICAgbG9kYXNoV3JhcHBlci5wcm90b3R5cGUgPSBsb2Rhc2gucHJvdG90eXBlO1xuXG4gICAgLyoqXG4gICAgICogQW4gb2JqZWN0IHVzZWQgdG8gZmxhZyBlbnZpcm9ubWVudHMgZmVhdHVyZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAdHlwZSBPYmplY3RcbiAgICAgKi9cbiAgICB2YXIgc3VwcG9ydCA9IGxvZGFzaC5zdXBwb3J0ID0ge307XG5cbiAgICAvKipcbiAgICAgKiBEZXRlY3QgaWYgZnVuY3Rpb25zIGNhbiBiZSBkZWNvbXBpbGVkIGJ5IGBGdW5jdGlvbiN0b1N0cmluZ2BcbiAgICAgKiAoYWxsIGJ1dCBQUzMgYW5kIG9sZGVyIE9wZXJhIG1vYmlsZSBicm93c2VycyAmIGF2b2lkZWQgaW4gV2luZG93cyA4IGFwcHMpLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIF8uc3VwcG9ydFxuICAgICAqIEB0eXBlIGJvb2xlYW5cbiAgICAgKi9cbiAgICBzdXBwb3J0LmZ1bmNEZWNvbXAgPSAhaXNOYXRpdmUoY29udGV4dC5XaW5SVEVycm9yKSAmJiByZVRoaXMudGVzdChydW5JbkNvbnRleHQpO1xuXG4gICAgLyoqXG4gICAgICogRGV0ZWN0IGlmIGBGdW5jdGlvbiNuYW1lYCBpcyBzdXBwb3J0ZWQgKGFsbCBidXQgSUUpLlxuICAgICAqXG4gICAgICogQG1lbWJlck9mIF8uc3VwcG9ydFxuICAgICAqIEB0eXBlIGJvb2xlYW5cbiAgICAgKi9cbiAgICBzdXBwb3J0LmZ1bmNOYW1lcyA9IHR5cGVvZiBGdW5jdGlvbi5uYW1lID09ICdzdHJpbmcnO1xuXG4gICAgLyoqXG4gICAgICogQnkgZGVmYXVsdCwgdGhlIHRlbXBsYXRlIGRlbGltaXRlcnMgdXNlZCBieSBMby1EYXNoIGFyZSBzaW1pbGFyIHRvIHRob3NlIGluXG4gICAgICogZW1iZWRkZWQgUnVieSAoRVJCKS4gQ2hhbmdlIHRoZSBmb2xsb3dpbmcgdGVtcGxhdGUgc2V0dGluZ3MgdG8gdXNlIGFsdGVybmF0aXZlXG4gICAgICogZGVsaW1pdGVycy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEB0eXBlIE9iamVjdFxuICAgICAqL1xuICAgIGxvZGFzaC50ZW1wbGF0ZVNldHRpbmdzID0ge1xuXG4gICAgICAvKipcbiAgICAgICAqIFVzZWQgdG8gZGV0ZWN0IGBkYXRhYCBwcm9wZXJ0eSB2YWx1ZXMgdG8gYmUgSFRNTC1lc2NhcGVkLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBfLnRlbXBsYXRlU2V0dGluZ3NcbiAgICAgICAqIEB0eXBlIFJlZ0V4cFxuICAgICAgICovXG4gICAgICAnZXNjYXBlJzogLzwlLShbXFxzXFxTXSs/KSU+L2csXG5cbiAgICAgIC8qKlxuICAgICAgICogVXNlZCB0byBkZXRlY3QgY29kZSB0byBiZSBldmFsdWF0ZWQuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIF8udGVtcGxhdGVTZXR0aW5nc1xuICAgICAgICogQHR5cGUgUmVnRXhwXG4gICAgICAgKi9cbiAgICAgICdldmFsdWF0ZSc6IC88JShbXFxzXFxTXSs/KSU+L2csXG5cbiAgICAgIC8qKlxuICAgICAgICogVXNlZCB0byBkZXRlY3QgYGRhdGFgIHByb3BlcnR5IHZhbHVlcyB0byBpbmplY3QuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIF8udGVtcGxhdGVTZXR0aW5nc1xuICAgICAgICogQHR5cGUgUmVnRXhwXG4gICAgICAgKi9cbiAgICAgICdpbnRlcnBvbGF0ZSc6IHJlSW50ZXJwb2xhdGUsXG5cbiAgICAgIC8qKlxuICAgICAgICogVXNlZCB0byByZWZlcmVuY2UgdGhlIGRhdGEgb2JqZWN0IGluIHRoZSB0ZW1wbGF0ZSB0ZXh0LlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBfLnRlbXBsYXRlU2V0dGluZ3NcbiAgICAgICAqIEB0eXBlIHN0cmluZ1xuICAgICAgICovXG4gICAgICAndmFyaWFibGUnOiAnJyxcblxuICAgICAgLyoqXG4gICAgICAgKiBVc2VkIHRvIGltcG9ydCB2YXJpYWJsZXMgaW50byB0aGUgY29tcGlsZWQgdGVtcGxhdGUuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIF8udGVtcGxhdGVTZXR0aW5nc1xuICAgICAgICogQHR5cGUgT2JqZWN0XG4gICAgICAgKi9cbiAgICAgICdpbXBvcnRzJzoge1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBIHJlZmVyZW5jZSB0byB0aGUgYGxvZGFzaGAgZnVuY3Rpb24uXG4gICAgICAgICAqXG4gICAgICAgICAqIEBtZW1iZXJPZiBfLnRlbXBsYXRlU2V0dGluZ3MuaW1wb3J0c1xuICAgICAgICAgKiBAdHlwZSBGdW5jdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgJ18nOiBsb2Rhc2hcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5iaW5kYCB0aGF0IGNyZWF0ZXMgdGhlIGJvdW5kIGZ1bmN0aW9uIGFuZFxuICAgICAqIHNldHMgaXRzIG1ldGEgZGF0YS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYmluZERhdGEgVGhlIGJpbmQgZGF0YSBhcnJheS5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBib3VuZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlQmluZChiaW5kRGF0YSkge1xuICAgICAgdmFyIGZ1bmMgPSBiaW5kRGF0YVswXSxcbiAgICAgICAgICBwYXJ0aWFsQXJncyA9IGJpbmREYXRhWzJdLFxuICAgICAgICAgIHRoaXNBcmcgPSBiaW5kRGF0YVs0XTtcblxuICAgICAgZnVuY3Rpb24gYm91bmQoKSB7XG4gICAgICAgIC8vIGBGdW5jdGlvbiNiaW5kYCBzcGVjXG4gICAgICAgIC8vIGh0dHA6Ly9lczUuZ2l0aHViLmlvLyN4MTUuMy40LjVcbiAgICAgICAgaWYgKHBhcnRpYWxBcmdzKSB7XG4gICAgICAgICAgLy8gYXZvaWQgYGFyZ3VtZW50c2Agb2JqZWN0IGRlb3B0aW1pemF0aW9ucyBieSB1c2luZyBgc2xpY2VgIGluc3RlYWRcbiAgICAgICAgICAvLyBvZiBgQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGxgIGFuZCBub3QgYXNzaWduaW5nIGBhcmd1bWVudHNgIHRvIGFcbiAgICAgICAgICAvLyB2YXJpYWJsZSBhcyBhIHRlcm5hcnkgZXhwcmVzc2lvblxuICAgICAgICAgIHZhciBhcmdzID0gc2xpY2UocGFydGlhbEFyZ3MpO1xuICAgICAgICAgIHB1c2guYXBwbHkoYXJncywgYXJndW1lbnRzKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBtaW1pYyB0aGUgY29uc3RydWN0b3IncyBgcmV0dXJuYCBiZWhhdmlvclxuICAgICAgICAvLyBodHRwOi8vZXM1LmdpdGh1Yi5pby8jeDEzLjIuMlxuICAgICAgICBpZiAodGhpcyBpbnN0YW5jZW9mIGJvdW5kKSB7XG4gICAgICAgICAgLy8gZW5zdXJlIGBuZXcgYm91bmRgIGlzIGFuIGluc3RhbmNlIG9mIGBmdW5jYFxuICAgICAgICAgIHZhciB0aGlzQmluZGluZyA9IGJhc2VDcmVhdGUoZnVuYy5wcm90b3R5cGUpLFxuICAgICAgICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KHRoaXNCaW5kaW5nLCBhcmdzIHx8IGFyZ3VtZW50cyk7XG4gICAgICAgICAgcmV0dXJuIGlzT2JqZWN0KHJlc3VsdCkgPyByZXN1bHQgOiB0aGlzQmluZGluZztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnVuYy5hcHBseSh0aGlzQXJnLCBhcmdzIHx8IGFyZ3VtZW50cyk7XG4gICAgICB9XG4gICAgICBzZXRCaW5kRGF0YShib3VuZCwgYmluZERhdGEpO1xuICAgICAgcmV0dXJuIGJvdW5kO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmNsb25lYCB3aXRob3V0IGFyZ3VtZW50IGp1Z2dsaW5nIG9yIHN1cHBvcnRcbiAgICAgKiBmb3IgYHRoaXNBcmdgIGJpbmRpbmcuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNsb25lLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzRGVlcD1mYWxzZV0gU3BlY2lmeSBhIGRlZXAgY2xvbmUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2NhbGxiYWNrXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNsb25pbmcgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtzdGFja0E9W11dIFRyYWNrcyB0cmF2ZXJzZWQgc291cmNlIG9iamVjdHMuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW3N0YWNrQj1bXV0gQXNzb2NpYXRlcyBjbG9uZXMgd2l0aCBzb3VyY2UgY291bnRlcnBhcnRzLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBjbG9uZWQgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUNsb25lKHZhbHVlLCBpc0RlZXAsIGNhbGxiYWNrLCBzdGFja0EsIHN0YWNrQikge1xuICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBjYWxsYmFjayh2YWx1ZSk7XG4gICAgICAgIGlmICh0eXBlb2YgcmVzdWx0ICE9ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gaW5zcGVjdCBbW0NsYXNzXV1cbiAgICAgIHZhciBpc09iaiA9IGlzT2JqZWN0KHZhbHVlKTtcbiAgICAgIGlmIChpc09iaikge1xuICAgICAgICB2YXIgY2xhc3NOYW1lID0gdG9TdHJpbmcuY2FsbCh2YWx1ZSk7XG4gICAgICAgIGlmICghY2xvbmVhYmxlQ2xhc3Nlc1tjbGFzc05hbWVdKSB7XG4gICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjdG9yID0gY3RvckJ5Q2xhc3NbY2xhc3NOYW1lXTtcbiAgICAgICAgc3dpdGNoIChjbGFzc05hbWUpIHtcbiAgICAgICAgICBjYXNlIGJvb2xDbGFzczpcbiAgICAgICAgICBjYXNlIGRhdGVDbGFzczpcbiAgICAgICAgICAgIHJldHVybiBuZXcgY3RvcigrdmFsdWUpO1xuXG4gICAgICAgICAgY2FzZSBudW1iZXJDbGFzczpcbiAgICAgICAgICBjYXNlIHN0cmluZ0NsYXNzOlxuICAgICAgICAgICAgcmV0dXJuIG5ldyBjdG9yKHZhbHVlKTtcblxuICAgICAgICAgIGNhc2UgcmVnZXhwQ2xhc3M6XG4gICAgICAgICAgICByZXN1bHQgPSBjdG9yKHZhbHVlLnNvdXJjZSwgcmVGbGFncy5leGVjKHZhbHVlKSk7XG4gICAgICAgICAgICByZXN1bHQubGFzdEluZGV4ID0gdmFsdWUubGFzdEluZGV4O1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfVxuICAgICAgdmFyIGlzQXJyID0gaXNBcnJheSh2YWx1ZSk7XG4gICAgICBpZiAoaXNEZWVwKSB7XG4gICAgICAgIC8vIGNoZWNrIGZvciBjaXJjdWxhciByZWZlcmVuY2VzIGFuZCByZXR1cm4gY29ycmVzcG9uZGluZyBjbG9uZVxuICAgICAgICB2YXIgaW5pdGVkU3RhY2sgPSAhc3RhY2tBO1xuICAgICAgICBzdGFja0EgfHwgKHN0YWNrQSA9IGdldEFycmF5KCkpO1xuICAgICAgICBzdGFja0IgfHwgKHN0YWNrQiA9IGdldEFycmF5KCkpO1xuXG4gICAgICAgIHZhciBsZW5ndGggPSBzdGFja0EubGVuZ3RoO1xuICAgICAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgICAgICBpZiAoc3RhY2tBW2xlbmd0aF0gPT0gdmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybiBzdGFja0JbbGVuZ3RoXTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmVzdWx0ID0gaXNBcnIgPyBjdG9yKHZhbHVlLmxlbmd0aCkgOiB7fTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICByZXN1bHQgPSBpc0FyciA/IHNsaWNlKHZhbHVlKSA6IGFzc2lnbih7fSwgdmFsdWUpO1xuICAgICAgfVxuICAgICAgLy8gYWRkIGFycmF5IHByb3BlcnRpZXMgYXNzaWduZWQgYnkgYFJlZ0V4cCNleGVjYFxuICAgICAgaWYgKGlzQXJyKSB7XG4gICAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKHZhbHVlLCAnaW5kZXgnKSkge1xuICAgICAgICAgIHJlc3VsdC5pbmRleCA9IHZhbHVlLmluZGV4O1xuICAgICAgICB9XG4gICAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKHZhbHVlLCAnaW5wdXQnKSkge1xuICAgICAgICAgIHJlc3VsdC5pbnB1dCA9IHZhbHVlLmlucHV0O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBleGl0IGZvciBzaGFsbG93IGNsb25lXG4gICAgICBpZiAoIWlzRGVlcCkge1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgICAgLy8gYWRkIHRoZSBzb3VyY2UgdmFsdWUgdG8gdGhlIHN0YWNrIG9mIHRyYXZlcnNlZCBvYmplY3RzXG4gICAgICAvLyBhbmQgYXNzb2NpYXRlIGl0IHdpdGggaXRzIGNsb25lXG4gICAgICBzdGFja0EucHVzaCh2YWx1ZSk7XG4gICAgICBzdGFja0IucHVzaChyZXN1bHQpO1xuXG4gICAgICAvLyByZWN1cnNpdmVseSBwb3B1bGF0ZSBjbG9uZSAoc3VzY2VwdGlibGUgdG8gY2FsbCBzdGFjayBsaW1pdHMpXG4gICAgICAoaXNBcnIgPyBmb3JFYWNoIDogZm9yT3duKSh2YWx1ZSwgZnVuY3Rpb24ob2JqVmFsdWUsIGtleSkge1xuICAgICAgICByZXN1bHRba2V5XSA9IGJhc2VDbG9uZShvYmpWYWx1ZSwgaXNEZWVwLCBjYWxsYmFjaywgc3RhY2tBLCBzdGFja0IpO1xuICAgICAgfSk7XG5cbiAgICAgIGlmIChpbml0ZWRTdGFjaykge1xuICAgICAgICByZWxlYXNlQXJyYXkoc3RhY2tBKTtcbiAgICAgICAgcmVsZWFzZUFycmF5KHN0YWNrQik7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmNyZWF0ZWAgd2l0aG91dCBzdXBwb3J0IGZvciBhc3NpZ25pbmdcbiAgICAgKiBwcm9wZXJ0aWVzIHRvIHRoZSBjcmVhdGVkIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHByb3RvdHlwZSBUaGUgb2JqZWN0IHRvIGluaGVyaXQgZnJvbS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VDcmVhdGUocHJvdG90eXBlLCBwcm9wZXJ0aWVzKSB7XG4gICAgICByZXR1cm4gaXNPYmplY3QocHJvdG90eXBlKSA/IG5hdGl2ZUNyZWF0ZShwcm90b3R5cGUpIDoge307XG4gICAgfVxuICAgIC8vIGZhbGxiYWNrIGZvciBicm93c2VycyB3aXRob3V0IGBPYmplY3QuY3JlYXRlYFxuICAgIGlmICghbmF0aXZlQ3JlYXRlKSB7XG4gICAgICBiYXNlQ3JlYXRlID0gKGZ1bmN0aW9uKCkge1xuICAgICAgICBmdW5jdGlvbiBPYmplY3QoKSB7fVxuICAgICAgICByZXR1cm4gZnVuY3Rpb24ocHJvdG90eXBlKSB7XG4gICAgICAgICAgaWYgKGlzT2JqZWN0KHByb3RvdHlwZSkpIHtcbiAgICAgICAgICAgIE9iamVjdC5wcm90b3R5cGUgPSBwcm90b3R5cGU7XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gbmV3IE9iamVjdDtcbiAgICAgICAgICAgIE9iamVjdC5wcm90b3R5cGUgPSBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gcmVzdWx0IHx8IGNvbnRleHQuT2JqZWN0KCk7XG4gICAgICAgIH07XG4gICAgICB9KCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmNyZWF0ZUNhbGxiYWNrYCB3aXRob3V0IHN1cHBvcnQgZm9yIGNyZWF0aW5nXG4gICAgICogXCJfLnBsdWNrXCIgb3IgXCJfLndoZXJlXCIgc3R5bGUgY2FsbGJhY2tzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IFtmdW5jPWlkZW50aXR5XSBUaGUgdmFsdWUgdG8gY29udmVydCB0byBhIGNhbGxiYWNrLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiB0aGUgY3JlYXRlZCBjYWxsYmFjay5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2FyZ0NvdW50XSBUaGUgbnVtYmVyIG9mIGFyZ3VtZW50cyB0aGUgY2FsbGJhY2sgYWNjZXB0cy5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgYSBjYWxsYmFjayBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlQ3JlYXRlQ2FsbGJhY2soZnVuYywgdGhpc0FyZywgYXJnQ291bnQpIHtcbiAgICAgIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBpZGVudGl0eTtcbiAgICAgIH1cbiAgICAgIC8vIGV4aXQgZWFybHkgZm9yIG5vIGB0aGlzQXJnYCBvciBhbHJlYWR5IGJvdW5kIGJ5IGBGdW5jdGlvbiNiaW5kYFxuICAgICAgaWYgKHR5cGVvZiB0aGlzQXJnID09ICd1bmRlZmluZWQnIHx8ICEoJ3Byb3RvdHlwZScgaW4gZnVuYykpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmM7XG4gICAgICB9XG4gICAgICB2YXIgYmluZERhdGEgPSBmdW5jLl9fYmluZERhdGFfXztcbiAgICAgIGlmICh0eXBlb2YgYmluZERhdGEgPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgaWYgKHN1cHBvcnQuZnVuY05hbWVzKSB7XG4gICAgICAgICAgYmluZERhdGEgPSAhZnVuYy5uYW1lO1xuICAgICAgICB9XG4gICAgICAgIGJpbmREYXRhID0gYmluZERhdGEgfHwgIXN1cHBvcnQuZnVuY0RlY29tcDtcbiAgICAgICAgaWYgKCFiaW5kRGF0YSkge1xuICAgICAgICAgIHZhciBzb3VyY2UgPSBmblRvU3RyaW5nLmNhbGwoZnVuYyk7XG4gICAgICAgICAgaWYgKCFzdXBwb3J0LmZ1bmNOYW1lcykge1xuICAgICAgICAgICAgYmluZERhdGEgPSAhcmVGdW5jTmFtZS50ZXN0KHNvdXJjZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghYmluZERhdGEpIHtcbiAgICAgICAgICAgIC8vIGNoZWNrcyBpZiBgZnVuY2AgcmVmZXJlbmNlcyB0aGUgYHRoaXNgIGtleXdvcmQgYW5kIHN0b3JlcyB0aGUgcmVzdWx0XG4gICAgICAgICAgICBiaW5kRGF0YSA9IHJlVGhpcy50ZXN0KHNvdXJjZSk7XG4gICAgICAgICAgICBzZXRCaW5kRGF0YShmdW5jLCBiaW5kRGF0YSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBleGl0IGVhcmx5IGlmIHRoZXJlIGFyZSBubyBgdGhpc2AgcmVmZXJlbmNlcyBvciBgZnVuY2AgaXMgYm91bmRcbiAgICAgIGlmIChiaW5kRGF0YSA9PT0gZmFsc2UgfHwgKGJpbmREYXRhICE9PSB0cnVlICYmIGJpbmREYXRhWzFdICYgMSkpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmM7XG4gICAgICB9XG4gICAgICBzd2l0Y2ggKGFyZ0NvdW50KSB7XG4gICAgICAgIGNhc2UgMTogcmV0dXJuIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgICAgcmV0dXJuIGZ1bmMuY2FsbCh0aGlzQXJnLCB2YWx1ZSk7XG4gICAgICAgIH07XG4gICAgICAgIGNhc2UgMjogcmV0dXJuIGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgICByZXR1cm4gZnVuYy5jYWxsKHRoaXNBcmcsIGEsIGIpO1xuICAgICAgICB9O1xuICAgICAgICBjYXNlIDM6IHJldHVybiBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgICByZXR1cm4gZnVuYy5jYWxsKHRoaXNBcmcsIHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbik7XG4gICAgICAgIH07XG4gICAgICAgIGNhc2UgNDogcmV0dXJuIGZ1bmN0aW9uKGFjY3VtdWxhdG9yLCB2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgICByZXR1cm4gZnVuYy5jYWxsKHRoaXNBcmcsIGFjY3VtdWxhdG9yLCB2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pO1xuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJpbmQoZnVuYywgdGhpc0FyZyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYGNyZWF0ZVdyYXBwZXJgIHRoYXQgY3JlYXRlcyB0aGUgd3JhcHBlciBhbmRcbiAgICAgKiBzZXRzIGl0cyBtZXRhIGRhdGEuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGJpbmREYXRhIFRoZSBiaW5kIGRhdGEgYXJyYXkuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUNyZWF0ZVdyYXBwZXIoYmluZERhdGEpIHtcbiAgICAgIHZhciBmdW5jID0gYmluZERhdGFbMF0sXG4gICAgICAgICAgYml0bWFzayA9IGJpbmREYXRhWzFdLFxuICAgICAgICAgIHBhcnRpYWxBcmdzID0gYmluZERhdGFbMl0sXG4gICAgICAgICAgcGFydGlhbFJpZ2h0QXJncyA9IGJpbmREYXRhWzNdLFxuICAgICAgICAgIHRoaXNBcmcgPSBiaW5kRGF0YVs0XSxcbiAgICAgICAgICBhcml0eSA9IGJpbmREYXRhWzVdO1xuXG4gICAgICB2YXIgaXNCaW5kID0gYml0bWFzayAmIDEsXG4gICAgICAgICAgaXNCaW5kS2V5ID0gYml0bWFzayAmIDIsXG4gICAgICAgICAgaXNDdXJyeSA9IGJpdG1hc2sgJiA0LFxuICAgICAgICAgIGlzQ3VycnlCb3VuZCA9IGJpdG1hc2sgJiA4LFxuICAgICAgICAgIGtleSA9IGZ1bmM7XG5cbiAgICAgIGZ1bmN0aW9uIGJvdW5kKCkge1xuICAgICAgICB2YXIgdGhpc0JpbmRpbmcgPSBpc0JpbmQgPyB0aGlzQXJnIDogdGhpcztcbiAgICAgICAgaWYgKHBhcnRpYWxBcmdzKSB7XG4gICAgICAgICAgdmFyIGFyZ3MgPSBzbGljZShwYXJ0aWFsQXJncyk7XG4gICAgICAgICAgcHVzaC5hcHBseShhcmdzLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwYXJ0aWFsUmlnaHRBcmdzIHx8IGlzQ3VycnkpIHtcbiAgICAgICAgICBhcmdzIHx8IChhcmdzID0gc2xpY2UoYXJndW1lbnRzKSk7XG4gICAgICAgICAgaWYgKHBhcnRpYWxSaWdodEFyZ3MpIHtcbiAgICAgICAgICAgIHB1c2guYXBwbHkoYXJncywgcGFydGlhbFJpZ2h0QXJncyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChpc0N1cnJ5ICYmIGFyZ3MubGVuZ3RoIDwgYXJpdHkpIHtcbiAgICAgICAgICAgIGJpdG1hc2sgfD0gMTYgJiB+MzI7XG4gICAgICAgICAgICByZXR1cm4gYmFzZUNyZWF0ZVdyYXBwZXIoW2Z1bmMsIChpc0N1cnJ5Qm91bmQgPyBiaXRtYXNrIDogYml0bWFzayAmIH4zKSwgYXJncywgbnVsbCwgdGhpc0FyZywgYXJpdHldKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYXJncyB8fCAoYXJncyA9IGFyZ3VtZW50cyk7XG4gICAgICAgIGlmIChpc0JpbmRLZXkpIHtcbiAgICAgICAgICBmdW5jID0gdGhpc0JpbmRpbmdba2V5XTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcyBpbnN0YW5jZW9mIGJvdW5kKSB7XG4gICAgICAgICAgdGhpc0JpbmRpbmcgPSBiYXNlQ3JlYXRlKGZ1bmMucHJvdG90eXBlKTtcbiAgICAgICAgICB2YXIgcmVzdWx0ID0gZnVuYy5hcHBseSh0aGlzQmluZGluZywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIGlzT2JqZWN0KHJlc3VsdCkgPyByZXN1bHQgOiB0aGlzQmluZGluZztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnVuYy5hcHBseSh0aGlzQmluZGluZywgYXJncyk7XG4gICAgICB9XG4gICAgICBzZXRCaW5kRGF0YShib3VuZCwgYmluZERhdGEpO1xuICAgICAgcmV0dXJuIGJvdW5kO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmRpZmZlcmVuY2VgIHRoYXQgYWNjZXB0cyBhIHNpbmdsZSBhcnJheVxuICAgICAqIG9mIHZhbHVlcyB0byBleGNsdWRlLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcHJvY2Vzcy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbdmFsdWVzXSBUaGUgYXJyYXkgb2YgdmFsdWVzIHRvIGV4Y2x1ZGUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGEgbmV3IGFycmF5IG9mIGZpbHRlcmVkIHZhbHVlcy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlRGlmZmVyZW5jZShhcnJheSwgdmFsdWVzKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBpbmRleE9mID0gZ2V0SW5kZXhPZigpLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5ID8gYXJyYXkubGVuZ3RoIDogMCxcbiAgICAgICAgICBpc0xhcmdlID0gbGVuZ3RoID49IGxhcmdlQXJyYXlTaXplICYmIGluZGV4T2YgPT09IGJhc2VJbmRleE9mLFxuICAgICAgICAgIHJlc3VsdCA9IFtdO1xuXG4gICAgICBpZiAoaXNMYXJnZSkge1xuICAgICAgICB2YXIgY2FjaGUgPSBjcmVhdGVDYWNoZSh2YWx1ZXMpO1xuICAgICAgICBpZiAoY2FjaGUpIHtcbiAgICAgICAgICBpbmRleE9mID0gY2FjaGVJbmRleE9mO1xuICAgICAgICAgIHZhbHVlcyA9IGNhY2hlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlzTGFyZ2UgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdO1xuICAgICAgICBpZiAoaW5kZXhPZih2YWx1ZXMsIHZhbHVlKSA8IDApIHtcbiAgICAgICAgICByZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChpc0xhcmdlKSB7XG4gICAgICAgIHJlbGVhc2VPYmplY3QodmFsdWVzKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZmxhdHRlbmAgd2l0aG91dCBzdXBwb3J0IGZvciBjYWxsYmFja1xuICAgICAqIHNob3J0aGFuZHMgb3IgYHRoaXNBcmdgIGJpbmRpbmcuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBmbGF0dGVuLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzU2hhbGxvdz1mYWxzZV0gQSBmbGFnIHRvIHJlc3RyaWN0IGZsYXR0ZW5pbmcgdG8gYSBzaW5nbGUgbGV2ZWwuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbaXNTdHJpY3Q9ZmFsc2VdIEEgZmxhZyB0byByZXN0cmljdCBmbGF0dGVuaW5nIHRvIGFycmF5cyBhbmQgYGFyZ3VtZW50c2Agb2JqZWN0cy5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2Zyb21JbmRleD0wXSBUaGUgaW5kZXggdG8gc3RhcnQgZnJvbS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYSBuZXcgZmxhdHRlbmVkIGFycmF5LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VGbGF0dGVuKGFycmF5LCBpc1NoYWxsb3csIGlzU3RyaWN0LCBmcm9tSW5kZXgpIHtcbiAgICAgIHZhciBpbmRleCA9IChmcm9tSW5kZXggfHwgMCkgLSAxLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5ID8gYXJyYXkubGVuZ3RoIDogMCxcbiAgICAgICAgICByZXN1bHQgPSBbXTtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdO1xuXG4gICAgICAgIGlmICh2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT0gJ29iamVjdCcgJiYgdHlwZW9mIHZhbHVlLmxlbmd0aCA9PSAnbnVtYmVyJ1xuICAgICAgICAgICAgJiYgKGlzQXJyYXkodmFsdWUpIHx8IGlzQXJndW1lbnRzKHZhbHVlKSkpIHtcbiAgICAgICAgICAvLyByZWN1cnNpdmVseSBmbGF0dGVuIGFycmF5cyAoc3VzY2VwdGlibGUgdG8gY2FsbCBzdGFjayBsaW1pdHMpXG4gICAgICAgICAgaWYgKCFpc1NoYWxsb3cpIHtcbiAgICAgICAgICAgIHZhbHVlID0gYmFzZUZsYXR0ZW4odmFsdWUsIGlzU2hhbGxvdywgaXNTdHJpY3QpO1xuICAgICAgICAgIH1cbiAgICAgICAgICB2YXIgdmFsSW5kZXggPSAtMSxcbiAgICAgICAgICAgICAgdmFsTGVuZ3RoID0gdmFsdWUubGVuZ3RoLFxuICAgICAgICAgICAgICByZXNJbmRleCA9IHJlc3VsdC5sZW5ndGg7XG5cbiAgICAgICAgICByZXN1bHQubGVuZ3RoICs9IHZhbExlbmd0aDtcbiAgICAgICAgICB3aGlsZSAoKyt2YWxJbmRleCA8IHZhbExlbmd0aCkge1xuICAgICAgICAgICAgcmVzdWx0W3Jlc0luZGV4KytdID0gdmFsdWVbdmFsSW5kZXhdO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICghaXNTdHJpY3QpIHtcbiAgICAgICAgICByZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNFcXVhbGAsIHdpdGhvdXQgc3VwcG9ydCBmb3IgYHRoaXNBcmdgIGJpbmRpbmcsXG4gICAgICogdGhhdCBhbGxvd3MgcGFydGlhbCBcIl8ud2hlcmVcIiBzdHlsZSBjb21wYXJpc29ucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSBhIFRoZSB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7Kn0gYiBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY2FsbGJhY2tdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY29tcGFyaW5nIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXNXaGVyZT1mYWxzZV0gQSBmbGFnIHRvIGluZGljYXRlIHBlcmZvcm1pbmcgcGFydGlhbCBjb21wYXJpc29ucy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbc3RhY2tBPVtdXSBUcmFja3MgdHJhdmVyc2VkIGBhYCBvYmplY3RzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtzdGFja0I9W11dIFRyYWNrcyB0cmF2ZXJzZWQgYGJgIG9iamVjdHMuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSB2YWx1ZXMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSXNFcXVhbChhLCBiLCBjYWxsYmFjaywgaXNXaGVyZSwgc3RhY2tBLCBzdGFja0IpIHtcbiAgICAgIC8vIHVzZWQgdG8gaW5kaWNhdGUgdGhhdCB3aGVuIGNvbXBhcmluZyBvYmplY3RzLCBgYWAgaGFzIGF0IGxlYXN0IHRoZSBwcm9wZXJ0aWVzIG9mIGBiYFxuICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBjYWxsYmFjayhhLCBiKTtcbiAgICAgICAgaWYgKHR5cGVvZiByZXN1bHQgIT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICByZXR1cm4gISFyZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIGV4aXQgZWFybHkgZm9yIGlkZW50aWNhbCB2YWx1ZXNcbiAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgIC8vIHRyZWF0IGArMGAgdnMuIGAtMGAgYXMgbm90IGVxdWFsXG4gICAgICAgIHJldHVybiBhICE9PSAwIHx8ICgxIC8gYSA9PSAxIC8gYik7XG4gICAgICB9XG4gICAgICB2YXIgdHlwZSA9IHR5cGVvZiBhLFxuICAgICAgICAgIG90aGVyVHlwZSA9IHR5cGVvZiBiO1xuXG4gICAgICAvLyBleGl0IGVhcmx5IGZvciB1bmxpa2UgcHJpbWl0aXZlIHZhbHVlc1xuICAgICAgaWYgKGEgPT09IGEgJiZcbiAgICAgICAgICAhKGEgJiYgb2JqZWN0VHlwZXNbdHlwZV0pICYmXG4gICAgICAgICAgIShiICYmIG9iamVjdFR5cGVzW290aGVyVHlwZV0pKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIC8vIGV4aXQgZWFybHkgZm9yIGBudWxsYCBhbmQgYHVuZGVmaW5lZGAgYXZvaWRpbmcgRVMzJ3MgRnVuY3Rpb24jY2FsbCBiZWhhdmlvclxuICAgICAgLy8gaHR0cDovL2VzNS5naXRodWIuaW8vI3gxNS4zLjQuNFxuICAgICAgaWYgKGEgPT0gbnVsbCB8fCBiID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIGEgPT09IGI7XG4gICAgICB9XG4gICAgICAvLyBjb21wYXJlIFtbQ2xhc3NdXSBuYW1lc1xuICAgICAgdmFyIGNsYXNzTmFtZSA9IHRvU3RyaW5nLmNhbGwoYSksXG4gICAgICAgICAgb3RoZXJDbGFzcyA9IHRvU3RyaW5nLmNhbGwoYik7XG5cbiAgICAgIGlmIChjbGFzc05hbWUgPT0gYXJnc0NsYXNzKSB7XG4gICAgICAgIGNsYXNzTmFtZSA9IG9iamVjdENsYXNzO1xuICAgICAgfVxuICAgICAgaWYgKG90aGVyQ2xhc3MgPT0gYXJnc0NsYXNzKSB7XG4gICAgICAgIG90aGVyQ2xhc3MgPSBvYmplY3RDbGFzcztcbiAgICAgIH1cbiAgICAgIGlmIChjbGFzc05hbWUgIT0gb3RoZXJDbGFzcykge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBzd2l0Y2ggKGNsYXNzTmFtZSkge1xuICAgICAgICBjYXNlIGJvb2xDbGFzczpcbiAgICAgICAgY2FzZSBkYXRlQ2xhc3M6XG4gICAgICAgICAgLy8gY29lcmNlIGRhdGVzIGFuZCBib29sZWFucyB0byBudW1iZXJzLCBkYXRlcyB0byBtaWxsaXNlY29uZHMgYW5kIGJvb2xlYW5zXG4gICAgICAgICAgLy8gdG8gYDFgIG9yIGAwYCB0cmVhdGluZyBpbnZhbGlkIGRhdGVzIGNvZXJjZWQgdG8gYE5hTmAgYXMgbm90IGVxdWFsXG4gICAgICAgICAgcmV0dXJuICthID09ICtiO1xuXG4gICAgICAgIGNhc2UgbnVtYmVyQ2xhc3M6XG4gICAgICAgICAgLy8gdHJlYXQgYE5hTmAgdnMuIGBOYU5gIGFzIGVxdWFsXG4gICAgICAgICAgcmV0dXJuIChhICE9ICthKVxuICAgICAgICAgICAgPyBiICE9ICtiXG4gICAgICAgICAgICAvLyBidXQgdHJlYXQgYCswYCB2cy4gYC0wYCBhcyBub3QgZXF1YWxcbiAgICAgICAgICAgIDogKGEgPT0gMCA/ICgxIC8gYSA9PSAxIC8gYikgOiBhID09ICtiKTtcblxuICAgICAgICBjYXNlIHJlZ2V4cENsYXNzOlxuICAgICAgICBjYXNlIHN0cmluZ0NsYXNzOlxuICAgICAgICAgIC8vIGNvZXJjZSByZWdleGVzIHRvIHN0cmluZ3MgKGh0dHA6Ly9lczUuZ2l0aHViLmlvLyN4MTUuMTAuNi40KVxuICAgICAgICAgIC8vIHRyZWF0IHN0cmluZyBwcmltaXRpdmVzIGFuZCB0aGVpciBjb3JyZXNwb25kaW5nIG9iamVjdCBpbnN0YW5jZXMgYXMgZXF1YWxcbiAgICAgICAgICByZXR1cm4gYSA9PSBTdHJpbmcoYik7XG4gICAgICB9XG4gICAgICB2YXIgaXNBcnIgPSBjbGFzc05hbWUgPT0gYXJyYXlDbGFzcztcbiAgICAgIGlmICghaXNBcnIpIHtcbiAgICAgICAgLy8gdW53cmFwIGFueSBgbG9kYXNoYCB3cmFwcGVkIHZhbHVlc1xuICAgICAgICB2YXIgYVdyYXBwZWQgPSBoYXNPd25Qcm9wZXJ0eS5jYWxsKGEsICdfX3dyYXBwZWRfXycpLFxuICAgICAgICAgICAgYldyYXBwZWQgPSBoYXNPd25Qcm9wZXJ0eS5jYWxsKGIsICdfX3dyYXBwZWRfXycpO1xuXG4gICAgICAgIGlmIChhV3JhcHBlZCB8fCBiV3JhcHBlZCkge1xuICAgICAgICAgIHJldHVybiBiYXNlSXNFcXVhbChhV3JhcHBlZCA/IGEuX193cmFwcGVkX18gOiBhLCBiV3JhcHBlZCA/IGIuX193cmFwcGVkX18gOiBiLCBjYWxsYmFjaywgaXNXaGVyZSwgc3RhY2tBLCBzdGFja0IpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGV4aXQgZm9yIGZ1bmN0aW9ucyBhbmQgRE9NIG5vZGVzXG4gICAgICAgIGlmIChjbGFzc05hbWUgIT0gb2JqZWN0Q2xhc3MpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLy8gaW4gb2xkZXIgdmVyc2lvbnMgb2YgT3BlcmEsIGBhcmd1bWVudHNgIG9iamVjdHMgaGF2ZSBgQXJyYXlgIGNvbnN0cnVjdG9yc1xuICAgICAgICB2YXIgY3RvckEgPSBhLmNvbnN0cnVjdG9yLFxuICAgICAgICAgICAgY3RvckIgPSBiLmNvbnN0cnVjdG9yO1xuXG4gICAgICAgIC8vIG5vbiBgT2JqZWN0YCBvYmplY3QgaW5zdGFuY2VzIHdpdGggZGlmZmVyZW50IGNvbnN0cnVjdG9ycyBhcmUgbm90IGVxdWFsXG4gICAgICAgIGlmIChjdG9yQSAhPSBjdG9yQiAmJlxuICAgICAgICAgICAgICAhKGlzRnVuY3Rpb24oY3RvckEpICYmIGN0b3JBIGluc3RhbmNlb2YgY3RvckEgJiYgaXNGdW5jdGlvbihjdG9yQikgJiYgY3RvckIgaW5zdGFuY2VvZiBjdG9yQikgJiZcbiAgICAgICAgICAgICAgKCdjb25zdHJ1Y3RvcicgaW4gYSAmJiAnY29uc3RydWN0b3InIGluIGIpXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIGFzc3VtZSBjeWNsaWMgc3RydWN0dXJlcyBhcmUgZXF1YWxcbiAgICAgIC8vIHRoZSBhbGdvcml0aG0gZm9yIGRldGVjdGluZyBjeWNsaWMgc3RydWN0dXJlcyBpcyBhZGFwdGVkIGZyb20gRVMgNS4xXG4gICAgICAvLyBzZWN0aW9uIDE1LjEyLjMsIGFic3RyYWN0IG9wZXJhdGlvbiBgSk9gIChodHRwOi8vZXM1LmdpdGh1Yi5pby8jeDE1LjEyLjMpXG4gICAgICB2YXIgaW5pdGVkU3RhY2sgPSAhc3RhY2tBO1xuICAgICAgc3RhY2tBIHx8IChzdGFja0EgPSBnZXRBcnJheSgpKTtcbiAgICAgIHN0YWNrQiB8fCAoc3RhY2tCID0gZ2V0QXJyYXkoKSk7XG5cbiAgICAgIHZhciBsZW5ndGggPSBzdGFja0EubGVuZ3RoO1xuICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgIGlmIChzdGFja0FbbGVuZ3RoXSA9PSBhKSB7XG4gICAgICAgICAgcmV0dXJuIHN0YWNrQltsZW5ndGhdID09IGI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHZhciBzaXplID0gMDtcbiAgICAgIHJlc3VsdCA9IHRydWU7XG5cbiAgICAgIC8vIGFkZCBgYWAgYW5kIGBiYCB0byB0aGUgc3RhY2sgb2YgdHJhdmVyc2VkIG9iamVjdHNcbiAgICAgIHN0YWNrQS5wdXNoKGEpO1xuICAgICAgc3RhY2tCLnB1c2goYik7XG5cbiAgICAgIC8vIHJlY3Vyc2l2ZWx5IGNvbXBhcmUgb2JqZWN0cyBhbmQgYXJyYXlzIChzdXNjZXB0aWJsZSB0byBjYWxsIHN0YWNrIGxpbWl0cylcbiAgICAgIGlmIChpc0Fycikge1xuICAgICAgICAvLyBjb21wYXJlIGxlbmd0aHMgdG8gZGV0ZXJtaW5lIGlmIGEgZGVlcCBjb21wYXJpc29uIGlzIG5lY2Vzc2FyeVxuICAgICAgICBsZW5ndGggPSBhLmxlbmd0aDtcbiAgICAgICAgc2l6ZSA9IGIubGVuZ3RoO1xuICAgICAgICByZXN1bHQgPSBzaXplID09IGxlbmd0aDtcblxuICAgICAgICBpZiAocmVzdWx0IHx8IGlzV2hlcmUpIHtcbiAgICAgICAgICAvLyBkZWVwIGNvbXBhcmUgdGhlIGNvbnRlbnRzLCBpZ25vcmluZyBub24tbnVtZXJpYyBwcm9wZXJ0aWVzXG4gICAgICAgICAgd2hpbGUgKHNpemUtLSkge1xuICAgICAgICAgICAgdmFyIGluZGV4ID0gbGVuZ3RoLFxuICAgICAgICAgICAgICAgIHZhbHVlID0gYltzaXplXTtcblxuICAgICAgICAgICAgaWYgKGlzV2hlcmUpIHtcbiAgICAgICAgICAgICAgd2hpbGUgKGluZGV4LS0pIHtcbiAgICAgICAgICAgICAgICBpZiAoKHJlc3VsdCA9IGJhc2VJc0VxdWFsKGFbaW5kZXhdLCB2YWx1ZSwgY2FsbGJhY2ssIGlzV2hlcmUsIHN0YWNrQSwgc3RhY2tCKSkpIHtcbiAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmICghKHJlc3VsdCA9IGJhc2VJc0VxdWFsKGFbc2l6ZV0sIHZhbHVlLCBjYWxsYmFjaywgaXNXaGVyZSwgc3RhY2tBLCBzdGFja0IpKSkge1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICAvLyBkZWVwIGNvbXBhcmUgb2JqZWN0cyB1c2luZyBgZm9ySW5gLCBpbnN0ZWFkIG9mIGBmb3JPd25gLCB0byBhdm9pZCBgT2JqZWN0LmtleXNgXG4gICAgICAgIC8vIHdoaWNoLCBpbiB0aGlzIGNhc2UsIGlzIG1vcmUgY29zdGx5XG4gICAgICAgIGZvckluKGIsIGZ1bmN0aW9uKHZhbHVlLCBrZXksIGIpIHtcbiAgICAgICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChiLCBrZXkpKSB7XG4gICAgICAgICAgICAvLyBjb3VudCB0aGUgbnVtYmVyIG9mIHByb3BlcnRpZXMuXG4gICAgICAgICAgICBzaXplKys7XG4gICAgICAgICAgICAvLyBkZWVwIGNvbXBhcmUgZWFjaCBwcm9wZXJ0eSB2YWx1ZS5cbiAgICAgICAgICAgIHJldHVybiAocmVzdWx0ID0gaGFzT3duUHJvcGVydHkuY2FsbChhLCBrZXkpICYmIGJhc2VJc0VxdWFsKGFba2V5XSwgdmFsdWUsIGNhbGxiYWNrLCBpc1doZXJlLCBzdGFja0EsIHN0YWNrQikpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHJlc3VsdCAmJiAhaXNXaGVyZSkge1xuICAgICAgICAgIC8vIGVuc3VyZSBib3RoIG9iamVjdHMgaGF2ZSB0aGUgc2FtZSBudW1iZXIgb2YgcHJvcGVydGllc1xuICAgICAgICAgIGZvckluKGEsIGZ1bmN0aW9uKHZhbHVlLCBrZXksIGEpIHtcbiAgICAgICAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKGEsIGtleSkpIHtcbiAgICAgICAgICAgICAgLy8gYHNpemVgIHdpbGwgYmUgYC0xYCBpZiBgYWAgaGFzIG1vcmUgcHJvcGVydGllcyB0aGFuIGBiYFxuICAgICAgICAgICAgICByZXR1cm4gKHJlc3VsdCA9IC0tc2l6ZSA+IC0xKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgc3RhY2tBLnBvcCgpO1xuICAgICAgc3RhY2tCLnBvcCgpO1xuXG4gICAgICBpZiAoaW5pdGVkU3RhY2spIHtcbiAgICAgICAgcmVsZWFzZUFycmF5KHN0YWNrQSk7XG4gICAgICAgIHJlbGVhc2VBcnJheShzdGFja0IpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5tZXJnZWAgd2l0aG91dCBhcmd1bWVudCBqdWdnbGluZyBvciBzdXBwb3J0XG4gICAgICogZm9yIGB0aGlzQXJnYCBiaW5kaW5nLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY2FsbGJhY2tdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgbWVyZ2luZyBwcm9wZXJ0aWVzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtzdGFja0E9W11dIFRyYWNrcyB0cmF2ZXJzZWQgc291cmNlIG9iamVjdHMuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW3N0YWNrQj1bXV0gQXNzb2NpYXRlcyB2YWx1ZXMgd2l0aCBzb3VyY2UgY291bnRlcnBhcnRzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VNZXJnZShvYmplY3QsIHNvdXJjZSwgY2FsbGJhY2ssIHN0YWNrQSwgc3RhY2tCKSB7XG4gICAgICAoaXNBcnJheShzb3VyY2UpID8gZm9yRWFjaCA6IGZvck93bikoc291cmNlLCBmdW5jdGlvbihzb3VyY2UsIGtleSkge1xuICAgICAgICB2YXIgZm91bmQsXG4gICAgICAgICAgICBpc0FycixcbiAgICAgICAgICAgIHJlc3VsdCA9IHNvdXJjZSxcbiAgICAgICAgICAgIHZhbHVlID0gb2JqZWN0W2tleV07XG5cbiAgICAgICAgaWYgKHNvdXJjZSAmJiAoKGlzQXJyID0gaXNBcnJheShzb3VyY2UpKSB8fCBpc1BsYWluT2JqZWN0KHNvdXJjZSkpKSB7XG4gICAgICAgICAgLy8gYXZvaWQgbWVyZ2luZyBwcmV2aW91c2x5IG1lcmdlZCBjeWNsaWMgc291cmNlc1xuICAgICAgICAgIHZhciBzdGFja0xlbmd0aCA9IHN0YWNrQS5sZW5ndGg7XG4gICAgICAgICAgd2hpbGUgKHN0YWNrTGVuZ3RoLS0pIHtcbiAgICAgICAgICAgIGlmICgoZm91bmQgPSBzdGFja0Fbc3RhY2tMZW5ndGhdID09IHNvdXJjZSkpIHtcbiAgICAgICAgICAgICAgdmFsdWUgPSBzdGFja0Jbc3RhY2tMZW5ndGhdO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFmb3VuZCkge1xuICAgICAgICAgICAgdmFyIGlzU2hhbGxvdztcbiAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICByZXN1bHQgPSBjYWxsYmFjayh2YWx1ZSwgc291cmNlKTtcbiAgICAgICAgICAgICAgaWYgKChpc1NoYWxsb3cgPSB0eXBlb2YgcmVzdWx0ICE9ICd1bmRlZmluZWQnKSkge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gcmVzdWx0O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWlzU2hhbGxvdykge1xuICAgICAgICAgICAgICB2YWx1ZSA9IGlzQXJyXG4gICAgICAgICAgICAgICAgPyAoaXNBcnJheSh2YWx1ZSkgPyB2YWx1ZSA6IFtdKVxuICAgICAgICAgICAgICAgIDogKGlzUGxhaW5PYmplY3QodmFsdWUpID8gdmFsdWUgOiB7fSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBhZGQgYHNvdXJjZWAgYW5kIGFzc29jaWF0ZWQgYHZhbHVlYCB0byB0aGUgc3RhY2sgb2YgdHJhdmVyc2VkIG9iamVjdHNcbiAgICAgICAgICAgIHN0YWNrQS5wdXNoKHNvdXJjZSk7XG4gICAgICAgICAgICBzdGFja0IucHVzaCh2YWx1ZSk7XG5cbiAgICAgICAgICAgIC8vIHJlY3Vyc2l2ZWx5IG1lcmdlIG9iamVjdHMgYW5kIGFycmF5cyAoc3VzY2VwdGlibGUgdG8gY2FsbCBzdGFjayBsaW1pdHMpXG4gICAgICAgICAgICBpZiAoIWlzU2hhbGxvdykge1xuICAgICAgICAgICAgICBiYXNlTWVyZ2UodmFsdWUsIHNvdXJjZSwgY2FsbGJhY2ssIHN0YWNrQSwgc3RhY2tCKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICByZXN1bHQgPSBjYWxsYmFjayh2YWx1ZSwgc291cmNlKTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgcmVzdWx0ID09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgIHJlc3VsdCA9IHNvdXJjZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHR5cGVvZiByZXN1bHQgIT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHZhbHVlID0gcmVzdWx0O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBvYmplY3Rba2V5XSA9IHZhbHVlO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ucmFuZG9tYCB3aXRob3V0IGFyZ3VtZW50IGp1Z2dsaW5nIG9yIHN1cHBvcnRcbiAgICAgKiBmb3IgcmV0dXJuaW5nIGZsb2F0aW5nLXBvaW50IG51bWJlcnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBtaW4gVGhlIG1pbmltdW0gcG9zc2libGUgdmFsdWUuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG1heCBUaGUgbWF4aW11bSBwb3NzaWJsZSB2YWx1ZS5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIGEgcmFuZG9tIG51bWJlci5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlUmFuZG9tKG1pbiwgbWF4KSB7XG4gICAgICByZXR1cm4gbWluICsgZmxvb3IobmF0aXZlUmFuZG9tKCkgKiAobWF4IC0gbWluICsgMSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnVuaXFgIHdpdGhvdXQgc3VwcG9ydCBmb3IgY2FsbGJhY2sgc2hvcnRoYW5kc1xuICAgICAqIG9yIGB0aGlzQXJnYCBiaW5kaW5nLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcHJvY2Vzcy5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc1NvcnRlZD1mYWxzZV0gQSBmbGFnIHRvIGluZGljYXRlIHRoYXQgYGFycmF5YCBpcyBzb3J0ZWQuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2NhbGxiYWNrXSBUaGUgZnVuY3Rpb24gY2FsbGVkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGEgZHVwbGljYXRlLXZhbHVlLWZyZWUgYXJyYXkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVVuaXEoYXJyYXksIGlzU29ydGVkLCBjYWxsYmFjaykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgaW5kZXhPZiA9IGdldEluZGV4T2YoKSxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDAsXG4gICAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICAgIHZhciBpc0xhcmdlID0gIWlzU29ydGVkICYmIGxlbmd0aCA+PSBsYXJnZUFycmF5U2l6ZSAmJiBpbmRleE9mID09PSBiYXNlSW5kZXhPZixcbiAgICAgICAgICBzZWVuID0gKGNhbGxiYWNrIHx8IGlzTGFyZ2UpID8gZ2V0QXJyYXkoKSA6IHJlc3VsdDtcblxuICAgICAgaWYgKGlzTGFyZ2UpIHtcbiAgICAgICAgdmFyIGNhY2hlID0gY3JlYXRlQ2FjaGUoc2Vlbik7XG4gICAgICAgIGluZGV4T2YgPSBjYWNoZUluZGV4T2Y7XG4gICAgICAgIHNlZW4gPSBjYWNoZTtcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XSxcbiAgICAgICAgICAgIGNvbXB1dGVkID0gY2FsbGJhY2sgPyBjYWxsYmFjayh2YWx1ZSwgaW5kZXgsIGFycmF5KSA6IHZhbHVlO1xuXG4gICAgICAgIGlmIChpc1NvcnRlZFxuICAgICAgICAgICAgICA/ICFpbmRleCB8fCBzZWVuW3NlZW4ubGVuZ3RoIC0gMV0gIT09IGNvbXB1dGVkXG4gICAgICAgICAgICAgIDogaW5kZXhPZihzZWVuLCBjb21wdXRlZCkgPCAwXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICBpZiAoY2FsbGJhY2sgfHwgaXNMYXJnZSkge1xuICAgICAgICAgICAgc2Vlbi5wdXNoKGNvbXB1dGVkKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzdWx0LnB1c2godmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoaXNMYXJnZSkge1xuICAgICAgICByZWxlYXNlQXJyYXkoc2Vlbi5hcnJheSk7XG4gICAgICAgIHJlbGVhc2VPYmplY3Qoc2Vlbik7XG4gICAgICB9IGVsc2UgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgIHJlbGVhc2VBcnJheShzZWVuKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgYWdncmVnYXRlcyBhIGNvbGxlY3Rpb24sIGNyZWF0aW5nIGFuIG9iamVjdCBjb21wb3NlZFxuICAgICAqIG9mIGtleXMgZ2VuZXJhdGVkIGZyb20gdGhlIHJlc3VsdHMgb2YgcnVubmluZyBlYWNoIGVsZW1lbnQgb2YgdGhlIGNvbGxlY3Rpb25cbiAgICAgKiB0aHJvdWdoIGEgY2FsbGJhY2suIFRoZSBnaXZlbiBgc2V0dGVyYCBmdW5jdGlvbiBzZXRzIHRoZSBrZXlzIGFuZCB2YWx1ZXNcbiAgICAgKiBvZiB0aGUgY29tcG9zZWQgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBzZXR0ZXIgVGhlIHNldHRlciBmdW5jdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBhZ2dyZWdhdG9yIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUFnZ3JlZ2F0b3Ioc2V0dGVyKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oY29sbGVjdGlvbiwgY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgICBjYWxsYmFjayA9IGxvZGFzaC5jcmVhdGVDYWxsYmFjayhjYWxsYmFjaywgdGhpc0FyZywgMyk7XG5cbiAgICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgICBsZW5ndGggPSBjb2xsZWN0aW9uID8gY29sbGVjdGlvbi5sZW5ndGggOiAwO1xuXG4gICAgICAgIGlmICh0eXBlb2YgbGVuZ3RoID09ICdudW1iZXInKSB7XG4gICAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICAgIHZhciB2YWx1ZSA9IGNvbGxlY3Rpb25baW5kZXhdO1xuICAgICAgICAgICAgc2V0dGVyKHJlc3VsdCwgdmFsdWUsIGNhbGxiYWNrKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbiksIGNvbGxlY3Rpb24pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBmb3JPd24oY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGtleSwgY29sbGVjdGlvbikge1xuICAgICAgICAgICAgc2V0dGVyKHJlc3VsdCwgdmFsdWUsIGNhbGxiYWNrKHZhbHVlLCBrZXksIGNvbGxlY3Rpb24pLCBjb2xsZWN0aW9uKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCwgd2hlbiBjYWxsZWQsIGVpdGhlciBjdXJyaWVzIG9yIGludm9rZXMgYGZ1bmNgXG4gICAgICogd2l0aCBhbiBvcHRpb25hbCBgdGhpc2AgYmluZGluZyBhbmQgcGFydGlhbGx5IGFwcGxpZWQgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufHN0cmluZ30gZnVuYyBUaGUgZnVuY3Rpb24gb3IgbWV0aG9kIG5hbWUgdG8gcmVmZXJlbmNlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIG9mIG1ldGhvZCBmbGFncyB0byBjb21wb3NlLlxuICAgICAqICBUaGUgYml0bWFzayBtYXkgYmUgY29tcG9zZWQgb2YgdGhlIGZvbGxvd2luZyBmbGFnczpcbiAgICAgKiAgMSAtIGBfLmJpbmRgXG4gICAgICogIDIgLSBgXy5iaW5kS2V5YFxuICAgICAqICA0IC0gYF8uY3VycnlgXG4gICAgICogIDggLSBgXy5jdXJyeWAgKGJvdW5kKVxuICAgICAqICAxNiAtIGBfLnBhcnRpYWxgXG4gICAgICogIDMyIC0gYF8ucGFydGlhbFJpZ2h0YFxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtwYXJ0aWFsQXJnc10gQW4gYXJyYXkgb2YgYXJndW1lbnRzIHRvIHByZXBlbmQgdG8gdGhvc2VcbiAgICAgKiAgcHJvdmlkZWQgdG8gdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbcGFydGlhbFJpZ2h0QXJnc10gQW4gYXJyYXkgb2YgYXJndW1lbnRzIHRvIGFwcGVuZCB0byB0aG9zZVxuICAgICAqICBwcm92aWRlZCB0byB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgZnVuY2AuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFthcml0eV0gVGhlIGFyaXR5IG9mIGBmdW5jYC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVXcmFwcGVyKGZ1bmMsIGJpdG1hc2ssIHBhcnRpYWxBcmdzLCBwYXJ0aWFsUmlnaHRBcmdzLCB0aGlzQXJnLCBhcml0eSkge1xuICAgICAgdmFyIGlzQmluZCA9IGJpdG1hc2sgJiAxLFxuICAgICAgICAgIGlzQmluZEtleSA9IGJpdG1hc2sgJiAyLFxuICAgICAgICAgIGlzQ3VycnkgPSBiaXRtYXNrICYgNCxcbiAgICAgICAgICBpc0N1cnJ5Qm91bmQgPSBiaXRtYXNrICYgOCxcbiAgICAgICAgICBpc1BhcnRpYWwgPSBiaXRtYXNrICYgMTYsXG4gICAgICAgICAgaXNQYXJ0aWFsUmlnaHQgPSBiaXRtYXNrICYgMzI7XG5cbiAgICAgIGlmICghaXNCaW5kS2V5ICYmICFpc0Z1bmN0aW9uKGZ1bmMpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3I7XG4gICAgICB9XG4gICAgICBpZiAoaXNQYXJ0aWFsICYmICFwYXJ0aWFsQXJncy5sZW5ndGgpIHtcbiAgICAgICAgYml0bWFzayAmPSB+MTY7XG4gICAgICAgIGlzUGFydGlhbCA9IHBhcnRpYWxBcmdzID0gZmFsc2U7XG4gICAgICB9XG4gICAgICBpZiAoaXNQYXJ0aWFsUmlnaHQgJiYgIXBhcnRpYWxSaWdodEFyZ3MubGVuZ3RoKSB7XG4gICAgICAgIGJpdG1hc2sgJj0gfjMyO1xuICAgICAgICBpc1BhcnRpYWxSaWdodCA9IHBhcnRpYWxSaWdodEFyZ3MgPSBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHZhciBiaW5kRGF0YSA9IGZ1bmMgJiYgZnVuYy5fX2JpbmREYXRhX187XG4gICAgICBpZiAoYmluZERhdGEgJiYgYmluZERhdGEgIT09IHRydWUpIHtcbiAgICAgICAgLy8gY2xvbmUgYGJpbmREYXRhYFxuICAgICAgICBiaW5kRGF0YSA9IHNsaWNlKGJpbmREYXRhKTtcbiAgICAgICAgaWYgKGJpbmREYXRhWzJdKSB7XG4gICAgICAgICAgYmluZERhdGFbMl0gPSBzbGljZShiaW5kRGF0YVsyXSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGJpbmREYXRhWzNdKSB7XG4gICAgICAgICAgYmluZERhdGFbM10gPSBzbGljZShiaW5kRGF0YVszXSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gc2V0IGB0aGlzQmluZGluZ2AgaXMgbm90IHByZXZpb3VzbHkgYm91bmRcbiAgICAgICAgaWYgKGlzQmluZCAmJiAhKGJpbmREYXRhWzFdICYgMSkpIHtcbiAgICAgICAgICBiaW5kRGF0YVs0XSA9IHRoaXNBcmc7XG4gICAgICAgIH1cbiAgICAgICAgLy8gc2V0IGlmIHByZXZpb3VzbHkgYm91bmQgYnV0IG5vdCBjdXJyZW50bHkgKHN1YnNlcXVlbnQgY3VycmllZCBmdW5jdGlvbnMpXG4gICAgICAgIGlmICghaXNCaW5kICYmIGJpbmREYXRhWzFdICYgMSkge1xuICAgICAgICAgIGJpdG1hc2sgfD0gODtcbiAgICAgICAgfVxuICAgICAgICAvLyBzZXQgY3VycmllZCBhcml0eSBpZiBub3QgeWV0IHNldFxuICAgICAgICBpZiAoaXNDdXJyeSAmJiAhKGJpbmREYXRhWzFdICYgNCkpIHtcbiAgICAgICAgICBiaW5kRGF0YVs1XSA9IGFyaXR5O1xuICAgICAgICB9XG4gICAgICAgIC8vIGFwcGVuZCBwYXJ0aWFsIGxlZnQgYXJndW1lbnRzXG4gICAgICAgIGlmIChpc1BhcnRpYWwpIHtcbiAgICAgICAgICBwdXNoLmFwcGx5KGJpbmREYXRhWzJdIHx8IChiaW5kRGF0YVsyXSA9IFtdKSwgcGFydGlhbEFyZ3MpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGFwcGVuZCBwYXJ0aWFsIHJpZ2h0IGFyZ3VtZW50c1xuICAgICAgICBpZiAoaXNQYXJ0aWFsUmlnaHQpIHtcbiAgICAgICAgICB1bnNoaWZ0LmFwcGx5KGJpbmREYXRhWzNdIHx8IChiaW5kRGF0YVszXSA9IFtdKSwgcGFydGlhbFJpZ2h0QXJncyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gbWVyZ2UgZmxhZ3NcbiAgICAgICAgYmluZERhdGFbMV0gfD0gYml0bWFzaztcbiAgICAgICAgcmV0dXJuIGNyZWF0ZVdyYXBwZXIuYXBwbHkobnVsbCwgYmluZERhdGEpO1xuICAgICAgfVxuICAgICAgLy8gZmFzdCBwYXRoIGZvciBgXy5iaW5kYFxuICAgICAgdmFyIGNyZWF0ZXIgPSAoYml0bWFzayA9PSAxIHx8IGJpdG1hc2sgPT09IDE3KSA/IGJhc2VCaW5kIDogYmFzZUNyZWF0ZVdyYXBwZXI7XG4gICAgICByZXR1cm4gY3JlYXRlcihbZnVuYywgYml0bWFzaywgcGFydGlhbEFyZ3MsIHBhcnRpYWxSaWdodEFyZ3MsIHRoaXNBcmcsIGFyaXR5XSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXNlZCBieSBgZXNjYXBlYCB0byBjb252ZXJ0IGNoYXJhY3RlcnMgdG8gSFRNTCBlbnRpdGllcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1hdGNoIFRoZSBtYXRjaGVkIGNoYXJhY3RlciB0byBlc2NhcGUuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgZXNjYXBlZCBjaGFyYWN0ZXIuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZXNjYXBlSHRtbENoYXIobWF0Y2gpIHtcbiAgICAgIHJldHVybiBodG1sRXNjYXBlc1ttYXRjaF07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgYXBwcm9wcmlhdGUgXCJpbmRleE9mXCIgZnVuY3Rpb24uIElmIHRoZSBgXy5pbmRleE9mYCBtZXRob2QgaXNcbiAgICAgKiBjdXN0b21pemVkLCB0aGlzIG1ldGhvZCByZXR1cm5zIHRoZSBjdXN0b20gbWV0aG9kLCBvdGhlcndpc2UgaXQgcmV0dXJuc1xuICAgICAqIHRoZSBgYmFzZUluZGV4T2ZgIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIFwiaW5kZXhPZlwiIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldEluZGV4T2YoKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gKHJlc3VsdCA9IGxvZGFzaC5pbmRleE9mKSA9PT0gaW5kZXhPZiA/IGJhc2VJbmRleE9mIDogcmVzdWx0O1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIG5hdGl2ZSBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBgdmFsdWVgIGlzIGEgbmF0aXZlIGZ1bmN0aW9uLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNOYXRpdmUodmFsdWUpIHtcbiAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gJ2Z1bmN0aW9uJyAmJiByZU5hdGl2ZS50ZXN0KHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIGB0aGlzYCBiaW5kaW5nIGRhdGEgb24gYSBnaXZlbiBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gc2V0IGRhdGEgb24uXG4gICAgICogQHBhcmFtIHtBcnJheX0gdmFsdWUgVGhlIGRhdGEgYXJyYXkgdG8gc2V0LlxuICAgICAqL1xuICAgIHZhciBzZXRCaW5kRGF0YSA9ICFkZWZpbmVQcm9wZXJ0eSA/IG5vb3AgOiBmdW5jdGlvbihmdW5jLCB2YWx1ZSkge1xuICAgICAgZGVzY3JpcHRvci52YWx1ZSA9IHZhbHVlO1xuICAgICAgZGVmaW5lUHJvcGVydHkoZnVuYywgJ19fYmluZERhdGFfXycsIGRlc2NyaXB0b3IpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBIGZhbGxiYWNrIGltcGxlbWVudGF0aW9uIG9mIGBpc1BsYWluT2JqZWN0YCB3aGljaCBjaGVja3MgaWYgYSBnaXZlbiB2YWx1ZVxuICAgICAqIGlzIGFuIG9iamVjdCBjcmVhdGVkIGJ5IHRoZSBgT2JqZWN0YCBjb25zdHJ1Y3RvciwgYXNzdW1pbmcgb2JqZWN0cyBjcmVhdGVkXG4gICAgICogYnkgdGhlIGBPYmplY3RgIGNvbnN0cnVjdG9yIGhhdmUgbm8gaW5oZXJpdGVkIGVudW1lcmFibGUgcHJvcGVydGllcyBhbmQgdGhhdFxuICAgICAqIHRoZXJlIGFyZSBubyBgT2JqZWN0LnByb3RvdHlwZWAgZXh0ZW5zaW9ucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBwbGFpbiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzaGltSXNQbGFpbk9iamVjdCh2YWx1ZSkge1xuICAgICAgdmFyIGN0b3IsXG4gICAgICAgICAgcmVzdWx0O1xuXG4gICAgICAvLyBhdm9pZCBub24gT2JqZWN0IG9iamVjdHMsIGBhcmd1bWVudHNgIG9iamVjdHMsIGFuZCBET00gZWxlbWVudHNcbiAgICAgIGlmICghKHZhbHVlICYmIHRvU3RyaW5nLmNhbGwodmFsdWUpID09IG9iamVjdENsYXNzKSB8fFxuICAgICAgICAgIChjdG9yID0gdmFsdWUuY29uc3RydWN0b3IsIGlzRnVuY3Rpb24oY3RvcikgJiYgIShjdG9yIGluc3RhbmNlb2YgY3RvcikpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIC8vIEluIG1vc3QgZW52aXJvbm1lbnRzIGFuIG9iamVjdCdzIG93biBwcm9wZXJ0aWVzIGFyZSBpdGVyYXRlZCBiZWZvcmVcbiAgICAgIC8vIGl0cyBpbmhlcml0ZWQgcHJvcGVydGllcy4gSWYgdGhlIGxhc3QgaXRlcmF0ZWQgcHJvcGVydHkgaXMgYW4gb2JqZWN0J3NcbiAgICAgIC8vIG93biBwcm9wZXJ0eSB0aGVuIHRoZXJlIGFyZSBubyBpbmhlcml0ZWQgZW51bWVyYWJsZSBwcm9wZXJ0aWVzLlxuICAgICAgZm9ySW4odmFsdWUsIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICAgICAgcmVzdWx0ID0ga2V5O1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gdHlwZW9mIHJlc3VsdCA9PSAndW5kZWZpbmVkJyB8fCBoYXNPd25Qcm9wZXJ0eS5jYWxsKHZhbHVlLCByZXN1bHQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVzZWQgYnkgYHVuZXNjYXBlYCB0byBjb252ZXJ0IEhUTUwgZW50aXRpZXMgdG8gY2hhcmFjdGVycy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1hdGNoIFRoZSBtYXRjaGVkIGNoYXJhY3RlciB0byB1bmVzY2FwZS5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSB1bmVzY2FwZWQgY2hhcmFjdGVyLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVuZXNjYXBlSHRtbENoYXIobWF0Y2gpIHtcbiAgICAgIHJldHVybiBodG1sVW5lc2NhcGVzW21hdGNoXTtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGFuIGBhcmd1bWVudHNgIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RzXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBgdmFsdWVgIGlzIGFuIGBhcmd1bWVudHNgIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAoZnVuY3Rpb24oKSB7IHJldHVybiBfLmlzQXJndW1lbnRzKGFyZ3VtZW50cyk7IH0pKDEsIDIsIDMpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNBcmd1bWVudHMoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzQXJndW1lbnRzKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdmFsdWUgJiYgdHlwZW9mIHZhbHVlID09ICdvYmplY3QnICYmIHR5cGVvZiB2YWx1ZS5sZW5ndGggPT0gJ251bWJlcicgJiZcbiAgICAgICAgdG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gYXJnc0NsYXNzIHx8IGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGFuIGFycmF5LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHR5cGUgRnVuY3Rpb25cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0c1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgYHZhbHVlYCBpcyBhbiBhcnJheSwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAoZnVuY3Rpb24oKSB7IHJldHVybiBfLmlzQXJyYXkoYXJndW1lbnRzKTsgfSkoKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5KFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIHZhciBpc0FycmF5ID0gbmF0aXZlSXNBcnJheSB8fCBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PSAnb2JqZWN0JyAmJiB0eXBlb2YgdmFsdWUubGVuZ3RoID09ICdudW1iZXInICYmXG4gICAgICAgIHRvU3RyaW5nLmNhbGwodmFsdWUpID09IGFycmF5Q2xhc3MgfHwgZmFsc2U7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEEgZmFsbGJhY2sgaW1wbGVtZW50YXRpb24gb2YgYE9iamVjdC5rZXlzYCB3aGljaCBwcm9kdWNlcyBhbiBhcnJheSBvZiB0aGVcbiAgICAgKiBnaXZlbiBvYmplY3QncyBvd24gZW51bWVyYWJsZSBwcm9wZXJ0eSBuYW1lcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYW4gYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMuXG4gICAgICovXG4gICAgdmFyIHNoaW1LZXlzID0gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICB2YXIgaW5kZXgsIGl0ZXJhYmxlID0gb2JqZWN0LCByZXN1bHQgPSBbXTtcbiAgICAgIGlmICghaXRlcmFibGUpIHJldHVybiByZXN1bHQ7XG4gICAgICBpZiAoIShvYmplY3RUeXBlc1t0eXBlb2Ygb2JqZWN0XSkpIHJldHVybiByZXN1bHQ7XG4gICAgICAgIGZvciAoaW5kZXggaW4gaXRlcmFibGUpIHtcbiAgICAgICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChpdGVyYWJsZSwgaW5kZXgpKSB7XG4gICAgICAgICAgICByZXN1bHQucHVzaChpbmRleCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgY29tcG9zZWQgb2YgdGhlIG93biBlbnVtZXJhYmxlIHByb3BlcnR5IG5hbWVzIG9mIGFuIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RzXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGFuIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmtleXMoeyAnb25lJzogMSwgJ3R3byc6IDIsICd0aHJlZSc6IDMgfSk7XG4gICAgICogLy8gPT4gWydvbmUnLCAndHdvJywgJ3RocmVlJ10gKHByb3BlcnR5IG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkIGFjcm9zcyBlbnZpcm9ubWVudHMpXG4gICAgICovXG4gICAgdmFyIGtleXMgPSAhbmF0aXZlS2V5cyA/IHNoaW1LZXlzIDogZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICBpZiAoIWlzT2JqZWN0KG9iamVjdCkpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG5hdGl2ZUtleXMob2JqZWN0KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVXNlZCB0byBjb252ZXJ0IGNoYXJhY3RlcnMgdG8gSFRNTCBlbnRpdGllczpcbiAgICAgKlxuICAgICAqIFRob3VnaCB0aGUgYD5gIGNoYXJhY3RlciBpcyBlc2NhcGVkIGZvciBzeW1tZXRyeSwgY2hhcmFjdGVycyBsaWtlIGA+YCBhbmQgYC9gXG4gICAgICogZG9uJ3QgcmVxdWlyZSBlc2NhcGluZyBpbiBIVE1MIGFuZCBoYXZlIG5vIHNwZWNpYWwgbWVhbmluZyB1bmxlc3MgdGhleSdyZSBwYXJ0XG4gICAgICogb2YgYSB0YWcgb3IgYW4gdW5xdW90ZWQgYXR0cmlidXRlIHZhbHVlLlxuICAgICAqIGh0dHA6Ly9tYXRoaWFzYnluZW5zLmJlL25vdGVzL2FtYmlndW91cy1hbXBlcnNhbmRzICh1bmRlciBcInNlbWktcmVsYXRlZCBmdW4gZmFjdFwiKVxuICAgICAqL1xuICAgIHZhciBodG1sRXNjYXBlcyA9IHtcbiAgICAgICcmJzogJyZhbXA7JyxcbiAgICAgICc8JzogJyZsdDsnLFxuICAgICAgJz4nOiAnJmd0OycsXG4gICAgICAnXCInOiAnJnF1b3Q7JyxcbiAgICAgIFwiJ1wiOiAnJiMzOTsnXG4gICAgfTtcblxuICAgIC8qKiBVc2VkIHRvIGNvbnZlcnQgSFRNTCBlbnRpdGllcyB0byBjaGFyYWN0ZXJzICovXG4gICAgdmFyIGh0bWxVbmVzY2FwZXMgPSBpbnZlcnQoaHRtbEVzY2FwZXMpO1xuXG4gICAgLyoqIFVzZWQgdG8gbWF0Y2ggSFRNTCBlbnRpdGllcyBhbmQgSFRNTCBjaGFyYWN0ZXJzICovXG4gICAgdmFyIHJlRXNjYXBlZEh0bWwgPSBSZWdFeHAoJygnICsga2V5cyhodG1sVW5lc2NhcGVzKS5qb2luKCd8JykgKyAnKScsICdnJyksXG4gICAgICAgIHJlVW5lc2NhcGVkSHRtbCA9IFJlZ0V4cCgnWycgKyBrZXlzKGh0bWxFc2NhcGVzKS5qb2luKCcnKSArICddJywgJ2cnKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQXNzaWducyBvd24gZW51bWVyYWJsZSBwcm9wZXJ0aWVzIG9mIHNvdXJjZSBvYmplY3QocykgdG8gdGhlIGRlc3RpbmF0aW9uXG4gICAgICogb2JqZWN0LiBTdWJzZXF1ZW50IHNvdXJjZXMgd2lsbCBvdmVyd3JpdGUgcHJvcGVydHkgYXNzaWdubWVudHMgb2YgcHJldmlvdXNcbiAgICAgKiBzb3VyY2VzLiBJZiBhIGNhbGxiYWNrIGlzIHByb3ZpZGVkIGl0IHdpbGwgYmUgZXhlY3V0ZWQgdG8gcHJvZHVjZSB0aGVcbiAgICAgKiBhc3NpZ25lZCB2YWx1ZXMuIFRoZSBjYWxsYmFjayBpcyBib3VuZCB0byBgdGhpc0FyZ2AgYW5kIGludm9rZWQgd2l0aCB0d29cbiAgICAgKiBhcmd1bWVudHM7IChvYmplY3RWYWx1ZSwgc291cmNlVmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHR5cGUgRnVuY3Rpb25cbiAgICAgKiBAYWxpYXMgZXh0ZW5kXG4gICAgICogQGNhdGVnb3J5IE9iamVjdHNcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHsuLi5PYmplY3R9IFtzb3VyY2VdIFRoZSBzb3VyY2Ugb2JqZWN0cy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY2FsbGJhY2tdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgYXNzaWduaW5nIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGNhbGxiYWNrYC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uYXNzaWduKHsgJ25hbWUnOiAnZnJlZCcgfSwgeyAnZW1wbG95ZXInOiAnc2xhdGUnIH0pO1xuICAgICAqIC8vID0+IHsgJ25hbWUnOiAnZnJlZCcsICdlbXBsb3llcic6ICdzbGF0ZScgfVxuICAgICAqXG4gICAgICogdmFyIGRlZmF1bHRzID0gXy5wYXJ0aWFsUmlnaHQoXy5hc3NpZ24sIGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgKiAgIHJldHVybiB0eXBlb2YgYSA9PSAndW5kZWZpbmVkJyA/IGIgOiBhO1xuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ25hbWUnOiAnYmFybmV5JyB9O1xuICAgICAqIGRlZmF1bHRzKG9iamVjdCwgeyAnbmFtZSc6ICdmcmVkJywgJ2VtcGxveWVyJzogJ3NsYXRlJyB9KTtcbiAgICAgKiAvLyA9PiB7ICduYW1lJzogJ2Jhcm5leScsICdlbXBsb3llcic6ICdzbGF0ZScgfVxuICAgICAqL1xuICAgIHZhciBhc3NpZ24gPSBmdW5jdGlvbihvYmplY3QsIHNvdXJjZSwgZ3VhcmQpIHtcbiAgICAgIHZhciBpbmRleCwgaXRlcmFibGUgPSBvYmplY3QsIHJlc3VsdCA9IGl0ZXJhYmxlO1xuICAgICAgaWYgKCFpdGVyYWJsZSkgcmV0dXJuIHJlc3VsdDtcbiAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzLFxuICAgICAgICAgIGFyZ3NJbmRleCA9IDAsXG4gICAgICAgICAgYXJnc0xlbmd0aCA9IHR5cGVvZiBndWFyZCA9PSAnbnVtYmVyJyA/IDIgOiBhcmdzLmxlbmd0aDtcbiAgICAgIGlmIChhcmdzTGVuZ3RoID4gMyAmJiB0eXBlb2YgYXJnc1thcmdzTGVuZ3RoIC0gMl0gPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB2YXIgY2FsbGJhY2sgPSBiYXNlQ3JlYXRlQ2FsbGJhY2soYXJnc1stLWFyZ3NMZW5ndGggLSAxXSwgYXJnc1thcmdzTGVuZ3RoLS1dLCAyKTtcbiAgICAgIH0gZWxzZSBpZiAoYXJnc0xlbmd0aCA+IDIgJiYgdHlwZW9mIGFyZ3NbYXJnc0xlbmd0aCAtIDFdID09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgY2FsbGJhY2sgPSBhcmdzWy0tYXJnc0xlbmd0aF07XG4gICAgICB9XG4gICAgICB3aGlsZSAoKythcmdzSW5kZXggPCBhcmdzTGVuZ3RoKSB7XG4gICAgICAgIGl0ZXJhYmxlID0gYXJnc1thcmdzSW5kZXhdO1xuICAgICAgICBpZiAoaXRlcmFibGUgJiYgb2JqZWN0VHlwZXNbdHlwZW9mIGl0ZXJhYmxlXSkge1xuICAgICAgICB2YXIgb3duSW5kZXggPSAtMSxcbiAgICAgICAgICAgIG93blByb3BzID0gb2JqZWN0VHlwZXNbdHlwZW9mIGl0ZXJhYmxlXSAmJiBrZXlzKGl0ZXJhYmxlKSxcbiAgICAgICAgICAgIGxlbmd0aCA9IG93blByb3BzID8gb3duUHJvcHMubGVuZ3RoIDogMDtcblxuICAgICAgICB3aGlsZSAoKytvd25JbmRleCA8IGxlbmd0aCkge1xuICAgICAgICAgIGluZGV4ID0gb3duUHJvcHNbb3duSW5kZXhdO1xuICAgICAgICAgIHJlc3VsdFtpbmRleF0gPSBjYWxsYmFjayA/IGNhbGxiYWNrKHJlc3VsdFtpbmRleF0sIGl0ZXJhYmxlW2luZGV4XSkgOiBpdGVyYWJsZVtpbmRleF07XG4gICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdFxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgY2xvbmUgb2YgYHZhbHVlYC4gSWYgYGlzRGVlcGAgaXMgYHRydWVgIG5lc3RlZCBvYmplY3RzIHdpbGwgYWxzb1xuICAgICAqIGJlIGNsb25lZCwgb3RoZXJ3aXNlIHRoZXkgd2lsbCBiZSBhc3NpZ25lZCBieSByZWZlcmVuY2UuIElmIGEgY2FsbGJhY2tcbiAgICAgKiBpcyBwcm92aWRlZCBpdCB3aWxsIGJlIGV4ZWN1dGVkIHRvIHByb2R1Y2UgdGhlIGNsb25lZCB2YWx1ZXMuIElmIHRoZVxuICAgICAqIGNhbGxiYWNrIHJldHVybnMgYHVuZGVmaW5lZGAgY2xvbmluZyB3aWxsIGJlIGhhbmRsZWQgYnkgdGhlIG1ldGhvZCBpbnN0ZWFkLlxuICAgICAqIFRoZSBjYWxsYmFjayBpcyBib3VuZCB0byBgdGhpc0FyZ2AgYW5kIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ7ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0c1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNsb25lLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzRGVlcD1mYWxzZV0gU3BlY2lmeSBhIGRlZXAgY2xvbmUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2NhbGxiYWNrXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNsb25pbmcgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY2FsbGJhY2tgLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBjbG9uZWQgdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBjaGFyYWN0ZXJzID0gW1xuICAgICAqICAgeyAnbmFtZSc6ICdiYXJuZXknLCAnYWdlJzogMzYgfSxcbiAgICAgKiAgIHsgJ25hbWUnOiAnZnJlZCcsICAgJ2FnZSc6IDQwIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogdmFyIHNoYWxsb3cgPSBfLmNsb25lKGNoYXJhY3RlcnMpO1xuICAgICAqIHNoYWxsb3dbMF0gPT09IGNoYXJhY3RlcnNbMF07XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogdmFyIGRlZXAgPSBfLmNsb25lKGNoYXJhY3RlcnMsIHRydWUpO1xuICAgICAqIGRlZXBbMF0gPT09IGNoYXJhY3RlcnNbMF07XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8ubWl4aW4oe1xuICAgICAqICAgJ2Nsb25lJzogXy5wYXJ0aWFsUmlnaHQoXy5jbG9uZSwgZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgKiAgICAgcmV0dXJuIF8uaXNFbGVtZW50KHZhbHVlKSA/IHZhbHVlLmNsb25lTm9kZShmYWxzZSkgOiB1bmRlZmluZWQ7XG4gICAgICogICB9KVxuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogdmFyIGNsb25lID0gXy5jbG9uZShkb2N1bWVudC5ib2R5KTtcbiAgICAgKiBjbG9uZS5jaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgKiAvLyA9PiAwXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2xvbmUodmFsdWUsIGlzRGVlcCwgY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICAgIC8vIGFsbG93cyB3b3JraW5nIHdpdGggXCJDb2xsZWN0aW9uc1wiIG1ldGhvZHMgd2l0aG91dCB1c2luZyB0aGVpciBgaW5kZXhgXG4gICAgICAvLyBhbmQgYGNvbGxlY3Rpb25gIGFyZ3VtZW50cyBmb3IgYGlzRGVlcGAgYW5kIGBjYWxsYmFja2BcbiAgICAgIGlmICh0eXBlb2YgaXNEZWVwICE9ICdib29sZWFuJyAmJiBpc0RlZXAgIT0gbnVsbCkge1xuICAgICAgICB0aGlzQXJnID0gY2FsbGJhY2s7XG4gICAgICAgIGNhbGxiYWNrID0gaXNEZWVwO1xuICAgICAgICBpc0RlZXAgPSBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlQ2xvbmUodmFsdWUsIGlzRGVlcCwgdHlwZW9mIGNhbGxiYWNrID09ICdmdW5jdGlvbicgJiYgYmFzZUNyZWF0ZUNhbGxiYWNrKGNhbGxiYWNrLCB0aGlzQXJnLCAxKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGRlZXAgY2xvbmUgb2YgYHZhbHVlYC4gSWYgYSBjYWxsYmFjayBpcyBwcm92aWRlZCBpdCB3aWxsIGJlXG4gICAgICogZXhlY3V0ZWQgdG8gcHJvZHVjZSB0aGUgY2xvbmVkIHZhbHVlcy4gSWYgdGhlIGNhbGxiYWNrIHJldHVybnMgYHVuZGVmaW5lZGBcbiAgICAgKiBjbG9uaW5nIHdpbGwgYmUgaGFuZGxlZCBieSB0aGUgbWV0aG9kIGluc3RlYWQuIFRoZSBjYWxsYmFjayBpcyBib3VuZCB0b1xuICAgICAqIGB0aGlzQXJnYCBhbmQgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDsgKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIE5vdGU6IFRoaXMgbWV0aG9kIGlzIGxvb3NlbHkgYmFzZWQgb24gdGhlIHN0cnVjdHVyZWQgY2xvbmUgYWxnb3JpdGhtLiBGdW5jdGlvbnNcbiAgICAgKiBhbmQgRE9NIG5vZGVzIGFyZSAqKm5vdCoqIGNsb25lZC4gVGhlIGVudW1lcmFibGUgcHJvcGVydGllcyBvZiBgYXJndW1lbnRzYCBvYmplY3RzIGFuZFxuICAgICAqIG9iamVjdHMgY3JlYXRlZCBieSBjb25zdHJ1Y3RvcnMgb3RoZXIgdGhhbiBgT2JqZWN0YCBhcmUgY2xvbmVkIHRvIHBsYWluIGBPYmplY3RgIG9iamVjdHMuXG4gICAgICogU2VlIGh0dHA6Ly93d3cudzMub3JnL1RSL2h0bWw1L2luZnJhc3RydWN0dXJlLmh0bWwjaW50ZXJuYWwtc3RydWN0dXJlZC1jbG9uaW5nLWFsZ29yaXRobS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RzXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gZGVlcCBjbG9uZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY2FsbGJhY2tdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY2xvbmluZyB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBjYWxsYmFja2AuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGRlZXAgY2xvbmVkIHZhbHVlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgY2hhcmFjdGVycyA9IFtcbiAgICAgKiAgIHsgJ25hbWUnOiAnYmFybmV5JywgJ2FnZSc6IDM2IH0sXG4gICAgICogICB7ICduYW1lJzogJ2ZyZWQnLCAgICdhZ2UnOiA0MCB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIHZhciBkZWVwID0gXy5jbG9uZURlZXAoY2hhcmFjdGVycyk7XG4gICAgICogZGVlcFswXSA9PT0gY2hhcmFjdGVyc1swXTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogdmFyIHZpZXcgPSB7XG4gICAgICogICAnbGFiZWwnOiAnZG9jcycsXG4gICAgICogICAnbm9kZSc6IGVsZW1lbnRcbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogdmFyIGNsb25lID0gXy5jbG9uZURlZXAodmlldywgZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgKiAgIHJldHVybiBfLmlzRWxlbWVudCh2YWx1ZSkgPyB2YWx1ZS5jbG9uZU5vZGUodHJ1ZSkgOiB1bmRlZmluZWQ7XG4gICAgICogfSk7XG4gICAgICpcbiAgICAgKiBjbG9uZS5ub2RlID09IHZpZXcubm9kZTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsb25lRGVlcCh2YWx1ZSwgY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICAgIHJldHVybiBiYXNlQ2xvbmUodmFsdWUsIHRydWUsIHR5cGVvZiBjYWxsYmFjayA9PSAnZnVuY3Rpb24nICYmIGJhc2VDcmVhdGVDYWxsYmFjayhjYWxsYmFjaywgdGhpc0FyZywgMSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gb2JqZWN0IHRoYXQgaW5oZXJpdHMgZnJvbSB0aGUgZ2l2ZW4gYHByb3RvdHlwZWAgb2JqZWN0LiBJZiBhXG4gICAgICogYHByb3BlcnRpZXNgIG9iamVjdCBpcyBwcm92aWRlZCBpdHMgb3duIGVudW1lcmFibGUgcHJvcGVydGllcyBhcmUgYXNzaWduZWRcbiAgICAgKiB0byB0aGUgY3JlYXRlZCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0c1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwcm90b3R5cGUgVGhlIG9iamVjdCB0byBpbmhlcml0IGZyb20uXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtwcm9wZXJ0aWVzXSBUaGUgcHJvcGVydGllcyB0byBhc3NpZ24gdG8gdGhlIG9iamVjdC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBTaGFwZSgpIHtcbiAgICAgKiAgIHRoaXMueCA9IDA7XG4gICAgICogICB0aGlzLnkgPSAwO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIENpcmNsZSgpIHtcbiAgICAgKiAgIFNoYXBlLmNhbGwodGhpcyk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogQ2lyY2xlLnByb3RvdHlwZSA9IF8uY3JlYXRlKFNoYXBlLnByb3RvdHlwZSwgeyAnY29uc3RydWN0b3InOiBDaXJjbGUgfSk7XG4gICAgICpcbiAgICAgKiB2YXIgY2lyY2xlID0gbmV3IENpcmNsZTtcbiAgICAgKiBjaXJjbGUgaW5zdGFuY2VvZiBDaXJjbGU7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogY2lyY2xlIGluc3RhbmNlb2YgU2hhcGU7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZShwcm90b3R5cGUsIHByb3BlcnRpZXMpIHtcbiAgICAgIHZhciByZXN1bHQgPSBiYXNlQ3JlYXRlKHByb3RvdHlwZSk7XG4gICAgICByZXR1cm4gcHJvcGVydGllcyA/IGFzc2lnbihyZXN1bHQsIHByb3BlcnRpZXMpIDogcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFzc2lnbnMgb3duIGVudW1lcmFibGUgcHJvcGVydGllcyBvZiBzb3VyY2Ugb2JqZWN0KHMpIHRvIHRoZSBkZXN0aW5hdGlvblxuICAgICAqIG9iamVjdCBmb3IgYWxsIGRlc3RpbmF0aW9uIHByb3BlcnRpZXMgdGhhdCByZXNvbHZlIHRvIGB1bmRlZmluZWRgLiBPbmNlIGFcbiAgICAgKiBwcm9wZXJ0eSBpcyBzZXQsIGFkZGl0aW9uYWwgZGVmYXVsdHMgb2YgdGhlIHNhbWUgcHJvcGVydHkgd2lsbCBiZSBpZ25vcmVkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHR5cGUgRnVuY3Rpb25cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0c1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0gey4uLk9iamVjdH0gW3NvdXJjZV0gVGhlIHNvdXJjZSBvYmplY3RzLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBBbGxvd3Mgd29ya2luZyB3aXRoIGBfLnJlZHVjZWAgd2l0aG91dCB1c2luZyBpdHNcbiAgICAgKiAgYGtleWAgYW5kIGBvYmplY3RgIGFyZ3VtZW50cyBhcyBzb3VyY2VzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ25hbWUnOiAnYmFybmV5JyB9O1xuICAgICAqIF8uZGVmYXVsdHMob2JqZWN0LCB7ICduYW1lJzogJ2ZyZWQnLCAnZW1wbG95ZXInOiAnc2xhdGUnIH0pO1xuICAgICAqIC8vID0+IHsgJ25hbWUnOiAnYmFybmV5JywgJ2VtcGxveWVyJzogJ3NsYXRlJyB9XG4gICAgICovXG4gICAgdmFyIGRlZmF1bHRzID0gZnVuY3Rpb24ob2JqZWN0LCBzb3VyY2UsIGd1YXJkKSB7XG4gICAgICB2YXIgaW5kZXgsIGl0ZXJhYmxlID0gb2JqZWN0LCByZXN1bHQgPSBpdGVyYWJsZTtcbiAgICAgIGlmICghaXRlcmFibGUpIHJldHVybiByZXN1bHQ7XG4gICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cyxcbiAgICAgICAgICBhcmdzSW5kZXggPSAwLFxuICAgICAgICAgIGFyZ3NMZW5ndGggPSB0eXBlb2YgZ3VhcmQgPT0gJ251bWJlcicgPyAyIDogYXJncy5sZW5ndGg7XG4gICAgICB3aGlsZSAoKythcmdzSW5kZXggPCBhcmdzTGVuZ3RoKSB7XG4gICAgICAgIGl0ZXJhYmxlID0gYXJnc1thcmdzSW5kZXhdO1xuICAgICAgICBpZiAoaXRlcmFibGUgJiYgb2JqZWN0VHlwZXNbdHlwZW9mIGl0ZXJhYmxlXSkge1xuICAgICAgICB2YXIgb3duSW5kZXggPSAtMSxcbiAgICAgICAgICAgIG93blByb3BzID0gb2JqZWN0VHlwZXNbdHlwZW9mIGl0ZXJhYmxlXSAmJiBrZXlzKGl0ZXJhYmxlKSxcbiAgICAgICAgICAgIGxlbmd0aCA9IG93blByb3BzID8gb3duUHJvcHMubGVuZ3RoIDogMDtcblxuICAgICAgICB3aGlsZSAoKytvd25JbmRleCA8IGxlbmd0aCkge1xuICAgICAgICAgIGluZGV4ID0gb3duUHJvcHNbb3duSW5kZXhdO1xuICAgICAgICAgIGlmICh0eXBlb2YgcmVzdWx0W2luZGV4XSA9PSAndW5kZWZpbmVkJykgcmVzdWx0W2luZGV4XSA9IGl0ZXJhYmxlW2luZGV4XTtcbiAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZmluZEluZGV4YCBleGNlcHQgdGhhdCBpdCByZXR1cm5zIHRoZSBrZXkgb2YgdGhlXG4gICAgICogZmlyc3QgZWxlbWVudCB0aGF0IHBhc3NlcyB0aGUgY2FsbGJhY2sgY2hlY2ssIGluc3RlYWQgb2YgdGhlIGVsZW1lbnQgaXRzZWxmLlxuICAgICAqXG4gICAgICogSWYgYSBwcm9wZXJ0eSBuYW1lIGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy5wbHVja1wiIHN0eWxlXG4gICAgICogY2FsbGJhY2sgd2lsbCByZXR1cm4gdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqXG4gICAgICogSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy53aGVyZVwiIHN0eWxlIGNhbGxiYWNrXG4gICAgICogd2lsbCByZXR1cm4gYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuIG9iamVjdCxcbiAgICAgKiBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0c1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBzZWFyY2guXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbY2FsbGJhY2s9aWRlbnRpdHldIFRoZSBmdW5jdGlvbiBjYWxsZWQgcGVyXG4gICAgICogIGl0ZXJhdGlvbi4gSWYgYSBwcm9wZXJ0eSBuYW1lIG9yIG9iamVjdCBpcyBwcm92aWRlZCBpdCB3aWxsIGJlIHVzZWQgdG9cbiAgICAgKiAgY3JlYXRlIGEgXCJfLnBsdWNrXCIgb3IgXCJfLndoZXJlXCIgc3R5bGUgY2FsbGJhY2ssIHJlc3BlY3RpdmVseS5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGNhbGxiYWNrYC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfHVuZGVmaW5lZH0gUmV0dXJucyB0aGUga2V5IG9mIHRoZSBmb3VuZCBlbGVtZW50LCBlbHNlIGB1bmRlZmluZWRgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgY2hhcmFjdGVycyA9IHtcbiAgICAgKiAgICdiYXJuZXknOiB7ICAnYWdlJzogMzYsICdibG9ja2VkJzogZmFsc2UgfSxcbiAgICAgKiAgICdmcmVkJzogeyAgICAnYWdlJzogNDAsICdibG9ja2VkJzogdHJ1ZSB9LFxuICAgICAqICAgJ3BlYmJsZXMnOiB7ICdhZ2UnOiAxLCAgJ2Jsb2NrZWQnOiBmYWxzZSB9XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIF8uZmluZEtleShjaGFyYWN0ZXJzLCBmdW5jdGlvbihjaHIpIHtcbiAgICAgKiAgIHJldHVybiBjaHIuYWdlIDwgNDA7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gJ2Jhcm5leScgKHByb3BlcnR5IG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkIGFjcm9zcyBlbnZpcm9ubWVudHMpXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyBcIl8ud2hlcmVcIiBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLmZpbmRLZXkoY2hhcmFjdGVycywgeyAnYWdlJzogMSB9KTtcbiAgICAgKiAvLyA9PiAncGViYmxlcydcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIFwiXy5wbHVja1wiIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8uZmluZEtleShjaGFyYWN0ZXJzLCAnYmxvY2tlZCcpO1xuICAgICAqIC8vID0+ICdmcmVkJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZpbmRLZXkob2JqZWN0LCBjYWxsYmFjaywgdGhpc0FyZykge1xuICAgICAgdmFyIHJlc3VsdDtcbiAgICAgIGNhbGxiYWNrID0gbG9kYXNoLmNyZWF0ZUNhbGxiYWNrKGNhbGxiYWNrLCB0aGlzQXJnLCAzKTtcbiAgICAgIGZvck93bihvYmplY3QsIGZ1bmN0aW9uKHZhbHVlLCBrZXksIG9iamVjdCkge1xuICAgICAgICBpZiAoY2FsbGJhY2sodmFsdWUsIGtleSwgb2JqZWN0KSkge1xuICAgICAgICAgIHJlc3VsdCA9IGtleTtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZpbmRLZXlgIGV4Y2VwdCB0aGF0IGl0IGl0ZXJhdGVzIG92ZXIgZWxlbWVudHNcbiAgICAgKiBvZiBhIGBjb2xsZWN0aW9uYCBpbiB0aGUgb3Bwb3NpdGUgb3JkZXIuXG4gICAgICpcbiAgICAgKiBJZiBhIHByb3BlcnR5IG5hbWUgaXMgcHJvdmlkZWQgZm9yIGBjYWxsYmFja2AgdGhlIGNyZWF0ZWQgXCJfLnBsdWNrXCIgc3R5bGVcbiAgICAgKiBjYWxsYmFjayB3aWxsIHJldHVybiB0aGUgcHJvcGVydHkgdmFsdWUgb2YgdGhlIGdpdmVuIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiBhbiBvYmplY3QgaXMgcHJvdmlkZWQgZm9yIGBjYWxsYmFja2AgdGhlIGNyZWF0ZWQgXCJfLndoZXJlXCIgc3R5bGUgY2FsbGJhY2tcbiAgICAgKiB3aWxsIHJldHVybiBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSB0aGUgcHJvcGVydGllcyBvZiB0aGUgZ2l2ZW4gb2JqZWN0LFxuICAgICAqIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RzXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHNlYXJjaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtjYWxsYmFjaz1pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGNhbGxlZCBwZXJcbiAgICAgKiAgaXRlcmF0aW9uLiBJZiBhIHByb3BlcnR5IG5hbWUgb3Igb2JqZWN0IGlzIHByb3ZpZGVkIGl0IHdpbGwgYmUgdXNlZCB0b1xuICAgICAqICBjcmVhdGUgYSBcIl8ucGx1Y2tcIiBvciBcIl8ud2hlcmVcIiBzdHlsZSBjYWxsYmFjaywgcmVzcGVjdGl2ZWx5LlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY2FsbGJhY2tgLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8dW5kZWZpbmVkfSBSZXR1cm5zIHRoZSBrZXkgb2YgdGhlIGZvdW5kIGVsZW1lbnQsIGVsc2UgYHVuZGVmaW5lZGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBjaGFyYWN0ZXJzID0ge1xuICAgICAqICAgJ2Jhcm5leSc6IHsgICdhZ2UnOiAzNiwgJ2Jsb2NrZWQnOiB0cnVlIH0sXG4gICAgICogICAnZnJlZCc6IHsgICAgJ2FnZSc6IDQwLCAnYmxvY2tlZCc6IGZhbHNlIH0sXG4gICAgICogICAncGViYmxlcyc6IHsgJ2FnZSc6IDEsICAnYmxvY2tlZCc6IHRydWUgfVxuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBfLmZpbmRMYXN0S2V5KGNoYXJhY3RlcnMsIGZ1bmN0aW9uKGNocikge1xuICAgICAqICAgcmV0dXJuIGNoci5hZ2UgPCA0MDtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiByZXR1cm5zIGBwZWJibGVzYCwgYXNzdW1pbmcgYF8uZmluZEtleWAgcmV0dXJucyBgYmFybmV5YFxuICAgICAqXG4gICAgICogLy8gdXNpbmcgXCJfLndoZXJlXCIgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5maW5kTGFzdEtleShjaGFyYWN0ZXJzLCB7ICdhZ2UnOiA0MCB9KTtcbiAgICAgKiAvLyA9PiAnZnJlZCdcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIFwiXy5wbHVja1wiIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8uZmluZExhc3RLZXkoY2hhcmFjdGVycywgJ2Jsb2NrZWQnKTtcbiAgICAgKiAvLyA9PiAncGViYmxlcydcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmaW5kTGFzdEtleShvYmplY3QsIGNhbGxiYWNrLCB0aGlzQXJnKSB7XG4gICAgICB2YXIgcmVzdWx0O1xuICAgICAgY2FsbGJhY2sgPSBsb2Rhc2guY3JlYXRlQ2FsbGJhY2soY2FsbGJhY2ssIHRoaXNBcmcsIDMpO1xuICAgICAgZm9yT3duUmlnaHQob2JqZWN0LCBmdW5jdGlvbih2YWx1ZSwga2V5LCBvYmplY3QpIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrKHZhbHVlLCBrZXksIG9iamVjdCkpIHtcbiAgICAgICAgICByZXN1bHQgPSBrZXk7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSXRlcmF0ZXMgb3ZlciBvd24gYW5kIGluaGVyaXRlZCBlbnVtZXJhYmxlIHByb3BlcnRpZXMgb2YgYW4gb2JqZWN0LFxuICAgICAqIGV4ZWN1dGluZyB0aGUgY2FsbGJhY2sgZm9yIGVhY2ggcHJvcGVydHkuIFRoZSBjYWxsYmFjayBpcyBib3VuZCB0byBgdGhpc0FyZ2BcbiAgICAgKiBhbmQgaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czsgKHZhbHVlLCBrZXksIG9iamVjdCkuIENhbGxiYWNrcyBtYXkgZXhpdFxuICAgICAqIGl0ZXJhdGlvbiBlYXJseSBieSBleHBsaWNpdGx5IHJldHVybmluZyBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHR5cGUgRnVuY3Rpb25cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0c1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2NhbGxiYWNrPWlkZW50aXR5XSBUaGUgZnVuY3Rpb24gY2FsbGVkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBjYWxsYmFja2AuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gU2hhcGUoKSB7XG4gICAgICogICB0aGlzLnggPSAwO1xuICAgICAqICAgdGhpcy55ID0gMDtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBTaGFwZS5wcm90b3R5cGUubW92ZSA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgKiAgIHRoaXMueCArPSB4O1xuICAgICAqICAgdGhpcy55ICs9IHk7XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIF8uZm9ySW4obmV3IFNoYXBlLCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG4gICAgICogICBjb25zb2xlLmxvZyhrZXkpO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IGxvZ3MgJ3gnLCAneScsIGFuZCAnbW92ZScgKHByb3BlcnR5IG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkIGFjcm9zcyBlbnZpcm9ubWVudHMpXG4gICAgICovXG4gICAgdmFyIGZvckluID0gZnVuY3Rpb24oY29sbGVjdGlvbiwgY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICAgIHZhciBpbmRleCwgaXRlcmFibGUgPSBjb2xsZWN0aW9uLCByZXN1bHQgPSBpdGVyYWJsZTtcbiAgICAgIGlmICghaXRlcmFibGUpIHJldHVybiByZXN1bHQ7XG4gICAgICBpZiAoIW9iamVjdFR5cGVzW3R5cGVvZiBpdGVyYWJsZV0pIHJldHVybiByZXN1bHQ7XG4gICAgICBjYWxsYmFjayA9IGNhbGxiYWNrICYmIHR5cGVvZiB0aGlzQXJnID09ICd1bmRlZmluZWQnID8gY2FsbGJhY2sgOiBiYXNlQ3JlYXRlQ2FsbGJhY2soY2FsbGJhY2ssIHRoaXNBcmcsIDMpO1xuICAgICAgICBmb3IgKGluZGV4IGluIGl0ZXJhYmxlKSB7XG4gICAgICAgICAgaWYgKGNhbGxiYWNrKGl0ZXJhYmxlW2luZGV4XSwgaW5kZXgsIGNvbGxlY3Rpb24pID09PSBmYWxzZSkgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdFxuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZvckluYCBleGNlcHQgdGhhdCBpdCBpdGVyYXRlcyBvdmVyIGVsZW1lbnRzXG4gICAgICogb2YgYSBgY29sbGVjdGlvbmAgaW4gdGhlIG9wcG9zaXRlIG9yZGVyLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdHNcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjYWxsYmFjaz1pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGNhbGxlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY2FsbGJhY2tgLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIFNoYXBlKCkge1xuICAgICAqICAgdGhpcy54ID0gMDtcbiAgICAgKiAgIHRoaXMueSA9IDA7XG4gICAgICogfVxuICAgICAqXG4gICAgICogU2hhcGUucHJvdG90eXBlLm1vdmUgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgICogICB0aGlzLnggKz0geDtcbiAgICAgKiAgIHRoaXMueSArPSB5O1xuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBfLmZvckluUmlnaHQobmV3IFNoYXBlLCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG4gICAgICogICBjb25zb2xlLmxvZyhrZXkpO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IGxvZ3MgJ21vdmUnLCAneScsIGFuZCAneCcgYXNzdW1pbmcgYF8uZm9ySW4gYCBsb2dzICd4JywgJ3knLCBhbmQgJ21vdmUnXG4gICAgICovXG4gICAgZnVuY3Rpb24gZm9ySW5SaWdodChvYmplY3QsIGNhbGxiYWNrLCB0aGlzQXJnKSB7XG4gICAgICB2YXIgcGFpcnMgPSBbXTtcblxuICAgICAgZm9ySW4ob2JqZWN0LCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG4gICAgICAgIHBhaXJzLnB1c2goa2V5LCB2YWx1ZSk7XG4gICAgICB9KTtcblxuICAgICAgdmFyIGxlbmd0aCA9IHBhaXJzLmxlbmd0aDtcbiAgICAgIGNhbGxiYWNrID0gYmFzZUNyZWF0ZUNhbGxiYWNrKGNhbGxiYWNrLCB0aGlzQXJnLCAzKTtcbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICBpZiAoY2FsbGJhY2socGFpcnNbbGVuZ3RoLS1dLCBwYWlyc1tsZW5ndGhdLCBvYmplY3QpID09PSBmYWxzZSkge1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gb2JqZWN0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEl0ZXJhdGVzIG92ZXIgb3duIGVudW1lcmFibGUgcHJvcGVydGllcyBvZiBhbiBvYmplY3QsIGV4ZWN1dGluZyB0aGUgY2FsbGJhY2tcbiAgICAgKiBmb3IgZWFjaCBwcm9wZXJ0eS4gVGhlIGNhbGxiYWNrIGlzIGJvdW5kIHRvIGB0aGlzQXJnYCBhbmQgaW52b2tlZCB3aXRoIHRocmVlXG4gICAgICogYXJndW1lbnRzOyAodmFsdWUsIGtleSwgb2JqZWN0KS4gQ2FsbGJhY2tzIG1heSBleGl0IGl0ZXJhdGlvbiBlYXJseSBieVxuICAgICAqIGV4cGxpY2l0bHkgcmV0dXJuaW5nIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAdHlwZSBGdW5jdGlvblxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RzXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY2FsbGJhY2s9aWRlbnRpdHldIFRoZSBmdW5jdGlvbiBjYWxsZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGNhbGxiYWNrYC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmZvck93bih7ICcwJzogJ3plcm8nLCAnMSc6ICdvbmUnLCAnbGVuZ3RoJzogMiB9LCBmdW5jdGlvbihudW0sIGtleSkge1xuICAgICAqICAgY29uc29sZS5sb2coa2V5KTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBsb2dzICcwJywgJzEnLCBhbmQgJ2xlbmd0aCcgKHByb3BlcnR5IG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkIGFjcm9zcyBlbnZpcm9ubWVudHMpXG4gICAgICovXG4gICAgdmFyIGZvck93biA9IGZ1bmN0aW9uKGNvbGxlY3Rpb24sIGNhbGxiYWNrLCB0aGlzQXJnKSB7XG4gICAgICB2YXIgaW5kZXgsIGl0ZXJhYmxlID0gY29sbGVjdGlvbiwgcmVzdWx0ID0gaXRlcmFibGU7XG4gICAgICBpZiAoIWl0ZXJhYmxlKSByZXR1cm4gcmVzdWx0O1xuICAgICAgaWYgKCFvYmplY3RUeXBlc1t0eXBlb2YgaXRlcmFibGVdKSByZXR1cm4gcmVzdWx0O1xuICAgICAgY2FsbGJhY2sgPSBjYWxsYmFjayAmJiB0eXBlb2YgdGhpc0FyZyA9PSAndW5kZWZpbmVkJyA/IGNhbGxiYWNrIDogYmFzZUNyZWF0ZUNhbGxiYWNrKGNhbGxiYWNrLCB0aGlzQXJnLCAzKTtcbiAgICAgICAgdmFyIG93bkluZGV4ID0gLTEsXG4gICAgICAgICAgICBvd25Qcm9wcyA9IG9iamVjdFR5cGVzW3R5cGVvZiBpdGVyYWJsZV0gJiYga2V5cyhpdGVyYWJsZSksXG4gICAgICAgICAgICBsZW5ndGggPSBvd25Qcm9wcyA/IG93blByb3BzLmxlbmd0aCA6IDA7XG5cbiAgICAgICAgd2hpbGUgKCsrb3duSW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICBpbmRleCA9IG93blByb3BzW293bkluZGV4XTtcbiAgICAgICAgICBpZiAoY2FsbGJhY2soaXRlcmFibGVbaW5kZXhdLCBpbmRleCwgY29sbGVjdGlvbikgPT09IGZhbHNlKSByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZm9yT3duYCBleGNlcHQgdGhhdCBpdCBpdGVyYXRlcyBvdmVyIGVsZW1lbnRzXG4gICAgICogb2YgYSBgY29sbGVjdGlvbmAgaW4gdGhlIG9wcG9zaXRlIG9yZGVyLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdHNcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjYWxsYmFjaz1pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGNhbGxlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY2FsbGJhY2tgLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZm9yT3duUmlnaHQoeyAnMCc6ICd6ZXJvJywgJzEnOiAnb25lJywgJ2xlbmd0aCc6IDIgfSwgZnVuY3Rpb24obnVtLCBrZXkpIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKGtleSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gbG9ncyAnbGVuZ3RoJywgJzEnLCBhbmQgJzAnIGFzc3VtaW5nIGBfLmZvck93bmAgbG9ncyAnMCcsICcxJywgYW5kICdsZW5ndGgnXG4gICAgICovXG4gICAgZnVuY3Rpb24gZm9yT3duUmlnaHQob2JqZWN0LCBjYWxsYmFjaywgdGhpc0FyZykge1xuICAgICAgdmFyIHByb3BzID0ga2V5cyhvYmplY3QpLFxuICAgICAgICAgIGxlbmd0aCA9IHByb3BzLmxlbmd0aDtcblxuICAgICAgY2FsbGJhY2sgPSBiYXNlQ3JlYXRlQ2FsbGJhY2soY2FsbGJhY2ssIHRoaXNBcmcsIDMpO1xuICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgIHZhciBrZXkgPSBwcm9wc1tsZW5ndGhdO1xuICAgICAgICBpZiAoY2FsbGJhY2sob2JqZWN0W2tleV0sIGtleSwgb2JqZWN0KSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc29ydGVkIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzIG9mIGFsbCBlbnVtZXJhYmxlIHByb3BlcnRpZXMsXG4gICAgICogb3duIGFuZCBpbmhlcml0ZWQsIG9mIGBvYmplY3RgIHRoYXQgaGF2ZSBmdW5jdGlvbiB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAYWxpYXMgbWV0aG9kc1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RzXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGFuIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzIHRoYXQgaGF2ZSBmdW5jdGlvbiB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZnVuY3Rpb25zKF8pO1xuICAgICAqIC8vID0+IFsnYWxsJywgJ2FueScsICdiaW5kJywgJ2JpbmRBbGwnLCAnY2xvbmUnLCAnY29tcGFjdCcsICdjb21wb3NlJywgLi4uXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZ1bmN0aW9ucyhvYmplY3QpIHtcbiAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgIGZvckluKG9iamVjdCwgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAgICBpZiAoaXNGdW5jdGlvbih2YWx1ZSkpIHtcbiAgICAgICAgICByZXN1bHQucHVzaChrZXkpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJldHVybiByZXN1bHQuc29ydCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiB0aGUgc3BlY2lmaWVkIHByb3BlcnR5IG5hbWUgZXhpc3RzIGFzIGEgZGlyZWN0IHByb3BlcnR5IG9mIGBvYmplY3RgLFxuICAgICAqIGluc3RlYWQgb2YgYW4gaW5oZXJpdGVkIHByb3BlcnR5LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdHNcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYga2V5IGlzIGEgZGlyZWN0IHByb3BlcnR5LCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaGFzKHsgJ2EnOiAxLCAnYic6IDIsICdjJzogMyB9LCAnYicpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBoYXMob2JqZWN0LCBrZXkpIHtcbiAgICAgIHJldHVybiBvYmplY3QgPyBoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSA6IGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gb2JqZWN0IGNvbXBvc2VkIG9mIHRoZSBpbnZlcnRlZCBrZXlzIGFuZCB2YWx1ZXMgb2YgdGhlIGdpdmVuIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RzXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGludmVydC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjcmVhdGVkIGludmVydGVkIG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pbnZlcnQoeyAnZmlyc3QnOiAnZnJlZCcsICdzZWNvbmQnOiAnYmFybmV5JyB9KTtcbiAgICAgKiAvLyA9PiB7ICdmcmVkJzogJ2ZpcnN0JywgJ2Jhcm5leSc6ICdzZWNvbmQnIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbnZlcnQob2JqZWN0KSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBwcm9wcyA9IGtleXMob2JqZWN0KSxcbiAgICAgICAgICBsZW5ndGggPSBwcm9wcy5sZW5ndGgsXG4gICAgICAgICAgcmVzdWx0ID0ge307XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBrZXkgPSBwcm9wc1tpbmRleF07XG4gICAgICAgIHJlc3VsdFtvYmplY3Rba2V5XV0gPSBrZXk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgYm9vbGVhbiB2YWx1ZS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RzXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBgdmFsdWVgIGlzIGEgYm9vbGVhbiB2YWx1ZSwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzQm9vbGVhbihudWxsKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzQm9vbGVhbih2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlID09PSB0cnVlIHx8IHZhbHVlID09PSBmYWxzZSB8fFxuICAgICAgICB2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT0gJ29iamVjdCcgJiYgdG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gYm9vbENsYXNzIHx8IGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgZGF0ZS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RzXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBgdmFsdWVgIGlzIGEgZGF0ZSwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzRGF0ZShuZXcgRGF0ZSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzRGF0ZSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PSAnb2JqZWN0JyAmJiB0b1N0cmluZy5jYWxsKHZhbHVlKSA9PSBkYXRlQ2xhc3MgfHwgZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYSBET00gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RzXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBgdmFsdWVgIGlzIGEgRE9NIGVsZW1lbnQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0VsZW1lbnQoZG9jdW1lbnQuYm9keSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzRWxlbWVudCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlICYmIHZhbHVlLm5vZGVUeXBlID09PSAxIHx8IGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGVtcHR5LiBBcnJheXMsIHN0cmluZ3MsIG9yIGBhcmd1bWVudHNgIG9iamVjdHMgd2l0aCBhXG4gICAgICogbGVuZ3RoIG9mIGAwYCBhbmQgb2JqZWN0cyB3aXRoIG5vIG93biBlbnVtZXJhYmxlIHByb3BlcnRpZXMgYXJlIGNvbnNpZGVyZWRcbiAgICAgKiBcImVtcHR5XCIuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0c1xuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gdmFsdWUgVGhlIHZhbHVlIHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBgdmFsdWVgIGlzIGVtcHR5LCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNFbXB0eShbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzRW1wdHkoe30pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNFbXB0eSgnJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzRW1wdHkodmFsdWUpIHtcbiAgICAgIHZhciByZXN1bHQgPSB0cnVlO1xuICAgICAgaWYgKCF2YWx1ZSkge1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgICAgdmFyIGNsYXNzTmFtZSA9IHRvU3RyaW5nLmNhbGwodmFsdWUpLFxuICAgICAgICAgIGxlbmd0aCA9IHZhbHVlLmxlbmd0aDtcblxuICAgICAgaWYgKChjbGFzc05hbWUgPT0gYXJyYXlDbGFzcyB8fCBjbGFzc05hbWUgPT0gc3RyaW5nQ2xhc3MgfHwgY2xhc3NOYW1lID09IGFyZ3NDbGFzcyApIHx8XG4gICAgICAgICAgKGNsYXNzTmFtZSA9PSBvYmplY3RDbGFzcyAmJiB0eXBlb2YgbGVuZ3RoID09ICdudW1iZXInICYmIGlzRnVuY3Rpb24odmFsdWUuc3BsaWNlKSkpIHtcbiAgICAgICAgcmV0dXJuICFsZW5ndGg7XG4gICAgICB9XG4gICAgICBmb3JPd24odmFsdWUsIGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gKHJlc3VsdCA9IGZhbHNlKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQZXJmb3JtcyBhIGRlZXAgY29tcGFyaXNvbiBiZXR3ZWVuIHR3byB2YWx1ZXMgdG8gZGV0ZXJtaW5lIGlmIHRoZXkgYXJlXG4gICAgICogZXF1aXZhbGVudCB0byBlYWNoIG90aGVyLiBJZiBhIGNhbGxiYWNrIGlzIHByb3ZpZGVkIGl0IHdpbGwgYmUgZXhlY3V0ZWRcbiAgICAgKiB0byBjb21wYXJlIHZhbHVlcy4gSWYgdGhlIGNhbGxiYWNrIHJldHVybnMgYHVuZGVmaW5lZGAgY29tcGFyaXNvbnMgd2lsbFxuICAgICAqIGJlIGhhbmRsZWQgYnkgdGhlIG1ldGhvZCBpbnN0ZWFkLiBUaGUgY2FsbGJhY2sgaXMgYm91bmQgdG8gYHRoaXNBcmdgIGFuZFxuICAgICAqIGludm9rZWQgd2l0aCB0d28gYXJndW1lbnRzOyAoYSwgYikuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0c1xuICAgICAqIEBwYXJhbSB7Kn0gYSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0geyp9IGIgVGhlIG90aGVyIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2NhbGxiYWNrXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNvbXBhcmluZyB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBjYWxsYmFja2AuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSB2YWx1ZXMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ25hbWUnOiAnZnJlZCcgfTtcbiAgICAgKiB2YXIgY29weSA9IHsgJ25hbWUnOiAnZnJlZCcgfTtcbiAgICAgKlxuICAgICAqIG9iamVjdCA9PSBjb3B5O1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzRXF1YWwob2JqZWN0LCBjb3B5KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiB2YXIgd29yZHMgPSBbJ2hlbGxvJywgJ2dvb2RieWUnXTtcbiAgICAgKiB2YXIgb3RoZXJXb3JkcyA9IFsnaGknLCAnZ29vZGJ5ZSddO1xuICAgICAqXG4gICAgICogXy5pc0VxdWFsKHdvcmRzLCBvdGhlcldvcmRzLCBmdW5jdGlvbihhLCBiKSB7XG4gICAgICogICB2YXIgcmVHcmVldCA9IC9eKD86aGVsbG98aGkpJC9pLFxuICAgICAqICAgICAgIGFHcmVldCA9IF8uaXNTdHJpbmcoYSkgJiYgcmVHcmVldC50ZXN0KGEpLFxuICAgICAqICAgICAgIGJHcmVldCA9IF8uaXNTdHJpbmcoYikgJiYgcmVHcmVldC50ZXN0KGIpO1xuICAgICAqXG4gICAgICogICByZXR1cm4gKGFHcmVldCB8fCBiR3JlZXQpID8gKGFHcmVldCA9PSBiR3JlZXQpIDogdW5kZWZpbmVkO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0VxdWFsKGEsIGIsIGNhbGxiYWNrLCB0aGlzQXJnKSB7XG4gICAgICByZXR1cm4gYmFzZUlzRXF1YWwoYSwgYiwgdHlwZW9mIGNhbGxiYWNrID09ICdmdW5jdGlvbicgJiYgYmFzZUNyZWF0ZUNhbGxiYWNrKGNhbGxiYWNrLCB0aGlzQXJnLCAyKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMsIG9yIGNhbiBiZSBjb2VyY2VkIHRvLCBhIGZpbml0ZSBudW1iZXIuXG4gICAgICpcbiAgICAgKiBOb3RlOiBUaGlzIGlzIG5vdCB0aGUgc2FtZSBhcyBuYXRpdmUgYGlzRmluaXRlYCB3aGljaCB3aWxsIHJldHVybiB0cnVlIGZvclxuICAgICAqIGJvb2xlYW5zIGFuZCBlbXB0eSBzdHJpbmdzLiBTZWUgaHR0cDovL2VzNS5naXRodWIuaW8vI3gxNS4xLjIuNS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RzXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBgdmFsdWVgIGlzIGZpbml0ZSwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzRmluaXRlKC0xMDEpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNGaW5pdGUoJzEwJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0Zpbml0ZSh0cnVlKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc0Zpbml0ZSgnJyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNGaW5pdGUoSW5maW5pdHkpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNGaW5pdGUodmFsdWUpIHtcbiAgICAgIHJldHVybiBuYXRpdmVJc0Zpbml0ZSh2YWx1ZSkgJiYgIW5hdGl2ZUlzTmFOKHBhcnNlRmxvYXQodmFsdWUpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdHNcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGB2YWx1ZWAgaXMgYSBmdW5jdGlvbiwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzRnVuY3Rpb24oXyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzRnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gJ2Z1bmN0aW9uJztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyB0aGUgbGFuZ3VhZ2UgdHlwZSBvZiBPYmplY3QuXG4gICAgICogKGUuZy4gYXJyYXlzLCBmdW5jdGlvbnMsIG9iamVjdHMsIHJlZ2V4ZXMsIGBuZXcgTnVtYmVyKDApYCwgYW5kIGBuZXcgU3RyaW5nKCcnKWApXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0c1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgYHZhbHVlYCBpcyBhbiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc09iamVjdCh7fSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc09iamVjdChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNPYmplY3QoMSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc09iamVjdCh2YWx1ZSkge1xuICAgICAgLy8gY2hlY2sgaWYgdGhlIHZhbHVlIGlzIHRoZSBFQ01BU2NyaXB0IGxhbmd1YWdlIHR5cGUgb2YgT2JqZWN0XG4gICAgICAvLyBodHRwOi8vZXM1LmdpdGh1Yi5pby8jeDhcbiAgICAgIC8vIGFuZCBhdm9pZCBhIFY4IGJ1Z1xuICAgICAgLy8gaHR0cDovL2NvZGUuZ29vZ2xlLmNvbS9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9MjI5MVxuICAgICAgcmV0dXJuICEhKHZhbHVlICYmIG9iamVjdFR5cGVzW3R5cGVvZiB2YWx1ZV0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGBOYU5gLlxuICAgICAqXG4gICAgICogTm90ZTogVGhpcyBpcyBub3QgdGhlIHNhbWUgYXMgbmF0aXZlIGBpc05hTmAgd2hpY2ggd2lsbCByZXR1cm4gYHRydWVgIGZvclxuICAgICAqIGB1bmRlZmluZWRgIGFuZCBvdGhlciBub24tbnVtZXJpYyB2YWx1ZXMuIFNlZSBodHRwOi8vZXM1LmdpdGh1Yi5pby8jeDE1LjEuMi40LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdHNcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGB2YWx1ZWAgaXMgYE5hTmAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc05hTihOYU4pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNOYU4obmV3IE51bWJlcihOYU4pKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBpc05hTih1bmRlZmluZWQpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNOYU4odW5kZWZpbmVkKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTmFOKHZhbHVlKSB7XG4gICAgICAvLyBgTmFOYCBhcyBhIHByaW1pdGl2ZSBpcyB0aGUgb25seSB2YWx1ZSB0aGF0IGlzIG5vdCBlcXVhbCB0byBpdHNlbGZcbiAgICAgIC8vIChwZXJmb3JtIHRoZSBbW0NsYXNzXV0gY2hlY2sgZmlyc3QgdG8gYXZvaWQgZXJyb3JzIHdpdGggc29tZSBob3N0IG9iamVjdHMgaW4gSUUpXG4gICAgICByZXR1cm4gaXNOdW1iZXIodmFsdWUpICYmIHZhbHVlICE9ICt2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBgbnVsbGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0c1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgYHZhbHVlYCBpcyBgbnVsbGAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc051bGwobnVsbCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc051bGwodW5kZWZpbmVkKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTnVsbCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlID09PSBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgbnVtYmVyLlxuICAgICAqXG4gICAgICogTm90ZTogYE5hTmAgaXMgY29uc2lkZXJlZCBhIG51bWJlci4gU2VlIGh0dHA6Ly9lczUuZ2l0aHViLmlvLyN4OC41LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdHNcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGB2YWx1ZWAgaXMgYSBudW1iZXIsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc051bWJlcig4LjQgKiA1KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNOdW1iZXIodmFsdWUpIHtcbiAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gJ251bWJlcicgfHxcbiAgICAgICAgdmFsdWUgJiYgdHlwZW9mIHZhbHVlID09ICdvYmplY3QnICYmIHRvU3RyaW5nLmNhbGwodmFsdWUpID09IG51bWJlckNsYXNzIHx8IGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGFuIG9iamVjdCBjcmVhdGVkIGJ5IHRoZSBgT2JqZWN0YCBjb25zdHJ1Y3Rvci5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RzXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBwbGFpbiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gU2hhcGUoKSB7XG4gICAgICogICB0aGlzLnggPSAwO1xuICAgICAqICAgdGhpcy55ID0gMDtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBfLmlzUGxhaW5PYmplY3QobmV3IFNoYXBlKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc1BsYWluT2JqZWN0KFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNQbGFpbk9iamVjdCh7ICd4JzogMCwgJ3knOiAwIH0pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICB2YXIgaXNQbGFpbk9iamVjdCA9ICFnZXRQcm90b3R5cGVPZiA/IHNoaW1Jc1BsYWluT2JqZWN0IDogZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIGlmICghKHZhbHVlICYmIHRvU3RyaW5nLmNhbGwodmFsdWUpID09IG9iamVjdENsYXNzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICB2YXIgdmFsdWVPZiA9IHZhbHVlLnZhbHVlT2YsXG4gICAgICAgICAgb2JqUHJvdG8gPSBpc05hdGl2ZSh2YWx1ZU9mKSAmJiAob2JqUHJvdG8gPSBnZXRQcm90b3R5cGVPZih2YWx1ZU9mKSkgJiYgZ2V0UHJvdG90eXBlT2Yob2JqUHJvdG8pO1xuXG4gICAgICByZXR1cm4gb2JqUHJvdG9cbiAgICAgICAgPyAodmFsdWUgPT0gb2JqUHJvdG8gfHwgZ2V0UHJvdG90eXBlT2YodmFsdWUpID09IG9ialByb3RvKVxuICAgICAgICA6IHNoaW1Jc1BsYWluT2JqZWN0KHZhbHVlKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0c1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgYHZhbHVlYCBpcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbiwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzUmVnRXhwKC9mcmVkLyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzUmVnRXhwKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdmFsdWUgJiYgdHlwZW9mIHZhbHVlID09ICdvYmplY3QnICYmIHRvU3RyaW5nLmNhbGwodmFsdWUpID09IHJlZ2V4cENsYXNzIHx8IGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgc3RyaW5nLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdHNcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGB2YWx1ZWAgaXMgYSBzdHJpbmcsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc1N0cmluZygnZnJlZCcpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc1N0cmluZyh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJyB8fFxuICAgICAgICB2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT0gJ29iamVjdCcgJiYgdG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gc3RyaW5nQ2xhc3MgfHwgZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYHVuZGVmaW5lZGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0c1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgYHZhbHVlYCBpcyBgdW5kZWZpbmVkYCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzVW5kZWZpbmVkKHZvaWQgMCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzVW5kZWZpbmVkKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09ICd1bmRlZmluZWQnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gb2JqZWN0IHdpdGggdGhlIHNhbWUga2V5cyBhcyBgb2JqZWN0YCBhbmQgdmFsdWVzIGdlbmVyYXRlZCBieVxuICAgICAqIHJ1bm5pbmcgZWFjaCBvd24gZW51bWVyYWJsZSBwcm9wZXJ0eSBvZiBgb2JqZWN0YCB0aHJvdWdoIHRoZSBjYWxsYmFjay5cbiAgICAgKiBUaGUgY2FsbGJhY2sgaXMgYm91bmQgdG8gYHRoaXNBcmdgIGFuZCBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzO1xuICAgICAqICh2YWx1ZSwga2V5LCBvYmplY3QpLlxuICAgICAqXG4gICAgICogSWYgYSBwcm9wZXJ0eSBuYW1lIGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy5wbHVja1wiIHN0eWxlXG4gICAgICogY2FsbGJhY2sgd2lsbCByZXR1cm4gdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqXG4gICAgICogSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy53aGVyZVwiIHN0eWxlIGNhbGxiYWNrXG4gICAgICogd2lsbCByZXR1cm4gYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuIG9iamVjdCxcbiAgICAgKiBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0c1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbY2FsbGJhY2s9aWRlbnRpdHldIFRoZSBmdW5jdGlvbiBjYWxsZWRcbiAgICAgKiAgcGVyIGl0ZXJhdGlvbi4gSWYgYSBwcm9wZXJ0eSBuYW1lIG9yIG9iamVjdCBpcyBwcm92aWRlZCBpdCB3aWxsIGJlIHVzZWRcbiAgICAgKiAgdG8gY3JlYXRlIGEgXCJfLnBsdWNrXCIgb3IgXCJfLndoZXJlXCIgc3R5bGUgY2FsbGJhY2ssIHJlc3BlY3RpdmVseS5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGNhbGxiYWNrYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYSBuZXcgb2JqZWN0IHdpdGggdmFsdWVzIG9mIHRoZSByZXN1bHRzIG9mIGVhY2ggYGNhbGxiYWNrYCBleGVjdXRpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubWFwVmFsdWVzKHsgJ2EnOiAxLCAnYic6IDIsICdjJzogM30gLCBmdW5jdGlvbihudW0pIHsgcmV0dXJuIG51bSAqIDM7IH0pO1xuICAgICAqIC8vID0+IHsgJ2EnOiAzLCAnYic6IDYsICdjJzogOSB9XG4gICAgICpcbiAgICAgKiB2YXIgY2hhcmFjdGVycyA9IHtcbiAgICAgKiAgICdmcmVkJzogeyAnbmFtZSc6ICdmcmVkJywgJ2FnZSc6IDQwIH0sXG4gICAgICogICAncGViYmxlcyc6IHsgJ25hbWUnOiAncGViYmxlcycsICdhZ2UnOiAxIH1cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogLy8gdXNpbmcgXCJfLnBsdWNrXCIgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5tYXBWYWx1ZXMoY2hhcmFjdGVycywgJ2FnZScpO1xuICAgICAqIC8vID0+IHsgJ2ZyZWQnOiA0MCwgJ3BlYmJsZXMnOiAxIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYXBWYWx1ZXMob2JqZWN0LCBjYWxsYmFjaywgdGhpc0FyZykge1xuICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgY2FsbGJhY2sgPSBsb2Rhc2guY3JlYXRlQ2FsbGJhY2soY2FsbGJhY2ssIHRoaXNBcmcsIDMpO1xuXG4gICAgICBmb3JPd24ob2JqZWN0LCBmdW5jdGlvbih2YWx1ZSwga2V5LCBvYmplY3QpIHtcbiAgICAgICAgcmVzdWx0W2tleV0gPSBjYWxsYmFjayh2YWx1ZSwga2V5LCBvYmplY3QpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlY3Vyc2l2ZWx5IG1lcmdlcyBvd24gZW51bWVyYWJsZSBwcm9wZXJ0aWVzIG9mIHRoZSBzb3VyY2Ugb2JqZWN0KHMpLCB0aGF0XG4gICAgICogZG9uJ3QgcmVzb2x2ZSB0byBgdW5kZWZpbmVkYCBpbnRvIHRoZSBkZXN0aW5hdGlvbiBvYmplY3QuIFN1YnNlcXVlbnQgc291cmNlc1xuICAgICAqIHdpbGwgb3ZlcndyaXRlIHByb3BlcnR5IGFzc2lnbm1lbnRzIG9mIHByZXZpb3VzIHNvdXJjZXMuIElmIGEgY2FsbGJhY2sgaXNcbiAgICAgKiBwcm92aWRlZCBpdCB3aWxsIGJlIGV4ZWN1dGVkIHRvIHByb2R1Y2UgdGhlIG1lcmdlZCB2YWx1ZXMgb2YgdGhlIGRlc3RpbmF0aW9uXG4gICAgICogYW5kIHNvdXJjZSBwcm9wZXJ0aWVzLiBJZiB0aGUgY2FsbGJhY2sgcmV0dXJucyBgdW5kZWZpbmVkYCBtZXJnaW5nIHdpbGxcbiAgICAgKiBiZSBoYW5kbGVkIGJ5IHRoZSBtZXRob2QgaW5zdGVhZC4gVGhlIGNhbGxiYWNrIGlzIGJvdW5kIHRvIGB0aGlzQXJnYCBhbmRcbiAgICAgKiBpbnZva2VkIHdpdGggdHdvIGFyZ3VtZW50czsgKG9iamVjdFZhbHVlLCBzb3VyY2VWYWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0c1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0gey4uLk9iamVjdH0gW3NvdXJjZV0gVGhlIHNvdXJjZSBvYmplY3RzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjYWxsYmFja10gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBtZXJnaW5nIHByb3BlcnRpZXMuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBjYWxsYmFja2AuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgbmFtZXMgPSB7XG4gICAgICogICAnY2hhcmFjdGVycyc6IFtcbiAgICAgKiAgICAgeyAnbmFtZSc6ICdiYXJuZXknIH0sXG4gICAgICogICAgIHsgJ25hbWUnOiAnZnJlZCcgfVxuICAgICAqICAgXVxuICAgICAqIH07XG4gICAgICpcbiAgICAgKiB2YXIgYWdlcyA9IHtcbiAgICAgKiAgICdjaGFyYWN0ZXJzJzogW1xuICAgICAqICAgICB7ICdhZ2UnOiAzNiB9LFxuICAgICAqICAgICB7ICdhZ2UnOiA0MCB9XG4gICAgICogICBdXG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIF8ubWVyZ2UobmFtZXMsIGFnZXMpO1xuICAgICAqIC8vID0+IHsgJ2NoYXJhY3RlcnMnOiBbeyAnbmFtZSc6ICdiYXJuZXknLCAnYWdlJzogMzYgfSwgeyAnbmFtZSc6ICdmcmVkJywgJ2FnZSc6IDQwIH1dIH1cbiAgICAgKlxuICAgICAqIHZhciBmb29kID0ge1xuICAgICAqICAgJ2ZydWl0cyc6IFsnYXBwbGUnXSxcbiAgICAgKiAgICd2ZWdldGFibGVzJzogWydiZWV0J11cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogdmFyIG90aGVyRm9vZCA9IHtcbiAgICAgKiAgICdmcnVpdHMnOiBbJ2JhbmFuYSddLFxuICAgICAqICAgJ3ZlZ2V0YWJsZXMnOiBbJ2NhcnJvdCddXG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIF8ubWVyZ2UoZm9vZCwgb3RoZXJGb29kLCBmdW5jdGlvbihhLCBiKSB7XG4gICAgICogICByZXR1cm4gXy5pc0FycmF5KGEpID8gYS5jb25jYXQoYikgOiB1bmRlZmluZWQ7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4geyAnZnJ1aXRzJzogWydhcHBsZScsICdiYW5hbmEnXSwgJ3ZlZ2V0YWJsZXMnOiBbJ2JlZXQnLCAnY2Fycm90XSB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gbWVyZ2Uob2JqZWN0KSB7XG4gICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cyxcbiAgICAgICAgICBsZW5ndGggPSAyO1xuXG4gICAgICBpZiAoIWlzT2JqZWN0KG9iamVjdCkpIHtcbiAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgIH1cbiAgICAgIC8vIGFsbG93cyB3b3JraW5nIHdpdGggYF8ucmVkdWNlYCBhbmQgYF8ucmVkdWNlUmlnaHRgIHdpdGhvdXQgdXNpbmdcbiAgICAgIC8vIHRoZWlyIGBpbmRleGAgYW5kIGBjb2xsZWN0aW9uYCBhcmd1bWVudHNcbiAgICAgIGlmICh0eXBlb2YgYXJnc1syXSAhPSAnbnVtYmVyJykge1xuICAgICAgICBsZW5ndGggPSBhcmdzLmxlbmd0aDtcbiAgICAgIH1cbiAgICAgIGlmIChsZW5ndGggPiAzICYmIHR5cGVvZiBhcmdzW2xlbmd0aCAtIDJdID09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdmFyIGNhbGxiYWNrID0gYmFzZUNyZWF0ZUNhbGxiYWNrKGFyZ3NbLS1sZW5ndGggLSAxXSwgYXJnc1tsZW5ndGgtLV0sIDIpO1xuICAgICAgfSBlbHNlIGlmIChsZW5ndGggPiAyICYmIHR5cGVvZiBhcmdzW2xlbmd0aCAtIDFdID09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgY2FsbGJhY2sgPSBhcmdzWy0tbGVuZ3RoXTtcbiAgICAgIH1cbiAgICAgIHZhciBzb3VyY2VzID0gc2xpY2UoYXJndW1lbnRzLCAxLCBsZW5ndGgpLFxuICAgICAgICAgIGluZGV4ID0gLTEsXG4gICAgICAgICAgc3RhY2tBID0gZ2V0QXJyYXkoKSxcbiAgICAgICAgICBzdGFja0IgPSBnZXRBcnJheSgpO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICBiYXNlTWVyZ2Uob2JqZWN0LCBzb3VyY2VzW2luZGV4XSwgY2FsbGJhY2ssIHN0YWNrQSwgc3RhY2tCKTtcbiAgICAgIH1cbiAgICAgIHJlbGVhc2VBcnJheShzdGFja0EpO1xuICAgICAgcmVsZWFzZUFycmF5KHN0YWNrQik7XG4gICAgICByZXR1cm4gb2JqZWN0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBzaGFsbG93IGNsb25lIG9mIGBvYmplY3RgIGV4Y2x1ZGluZyB0aGUgc3BlY2lmaWVkIHByb3BlcnRpZXMuXG4gICAgICogUHJvcGVydHkgbmFtZXMgbWF5IGJlIHNwZWNpZmllZCBhcyBpbmRpdmlkdWFsIGFyZ3VtZW50cyBvciBhcyBhcnJheXMgb2ZcbiAgICAgKiBwcm9wZXJ0eSBuYW1lcy4gSWYgYSBjYWxsYmFjayBpcyBwcm92aWRlZCBpdCB3aWxsIGJlIGV4ZWN1dGVkIGZvciBlYWNoXG4gICAgICogcHJvcGVydHkgb2YgYG9iamVjdGAgb21pdHRpbmcgdGhlIHByb3BlcnRpZXMgdGhlIGNhbGxiYWNrIHJldHVybnMgdHJ1ZXlcbiAgICAgKiBmb3IuIFRoZSBjYWxsYmFjayBpcyBib3VuZCB0byBgdGhpc0FyZ2AgYW5kIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM7XG4gICAgICogKHZhbHVlLCBrZXksIG9iamVjdCkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0c1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIHNvdXJjZSBvYmplY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnwuLi5zdHJpbmd8c3RyaW5nW119IFtjYWxsYmFja10gVGhlIHByb3BlcnRpZXMgdG8gb21pdCBvciB0aGVcbiAgICAgKiAgZnVuY3Rpb24gY2FsbGVkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBjYWxsYmFja2AuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBhbiBvYmplY3Qgd2l0aG91dCB0aGUgb21pdHRlZCBwcm9wZXJ0aWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLm9taXQoeyAnbmFtZSc6ICdmcmVkJywgJ2FnZSc6IDQwIH0sICdhZ2UnKTtcbiAgICAgKiAvLyA9PiB7ICduYW1lJzogJ2ZyZWQnIH1cbiAgICAgKlxuICAgICAqIF8ub21pdCh7ICduYW1lJzogJ2ZyZWQnLCAnYWdlJzogNDAgfSwgZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgKiAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gJ251bWJlcic7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4geyAnbmFtZSc6ICdmcmVkJyB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gb21pdChvYmplY3QsIGNhbGxiYWNrLCB0aGlzQXJnKSB7XG4gICAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgICBpZiAodHlwZW9mIGNhbGxiYWNrICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdmFyIHByb3BzID0gW107XG4gICAgICAgIGZvckluKG9iamVjdCwgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAgICAgIHByb3BzLnB1c2goa2V5KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHByb3BzID0gYmFzZURpZmZlcmVuY2UocHJvcHMsIGJhc2VGbGF0dGVuKGFyZ3VtZW50cywgdHJ1ZSwgZmFsc2UsIDEpKTtcblxuICAgICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICAgIGxlbmd0aCA9IHByb3BzLmxlbmd0aDtcblxuICAgICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICAgIHZhciBrZXkgPSBwcm9wc1tpbmRleF07XG4gICAgICAgICAgcmVzdWx0W2tleV0gPSBvYmplY3Rba2V5XTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2FsbGJhY2sgPSBsb2Rhc2guY3JlYXRlQ2FsbGJhY2soY2FsbGJhY2ssIHRoaXNBcmcsIDMpO1xuICAgICAgICBmb3JJbihvYmplY3QsIGZ1bmN0aW9uKHZhbHVlLCBrZXksIG9iamVjdCkge1xuICAgICAgICAgIGlmICghY2FsbGJhY2sodmFsdWUsIGtleSwgb2JqZWN0KSkge1xuICAgICAgICAgICAgcmVzdWx0W2tleV0gPSB2YWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgdHdvIGRpbWVuc2lvbmFsIGFycmF5IG9mIGFuIG9iamVjdCdzIGtleS12YWx1ZSBwYWlycyxcbiAgICAgKiBpLmUuIGBbW2tleTEsIHZhbHVlMV0sIFtrZXkyLCB2YWx1ZTJdXWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0c1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpbnNwZWN0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBuZXcgYXJyYXkgb2Yga2V5LXZhbHVlIHBhaXJzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnBhaXJzKHsgJ2Jhcm5leSc6IDM2LCAnZnJlZCc6IDQwIH0pO1xuICAgICAqIC8vID0+IFtbJ2Jhcm5leScsIDM2XSwgWydmcmVkJywgNDBdXSAocHJvcGVydHkgb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQgYWNyb3NzIGVudmlyb25tZW50cylcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwYWlycyhvYmplY3QpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIHByb3BzID0ga2V5cyhvYmplY3QpLFxuICAgICAgICAgIGxlbmd0aCA9IHByb3BzLmxlbmd0aCxcbiAgICAgICAgICByZXN1bHQgPSBBcnJheShsZW5ndGgpO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIga2V5ID0gcHJvcHNbaW5kZXhdO1xuICAgICAgICByZXN1bHRbaW5kZXhdID0gW2tleSwgb2JqZWN0W2tleV1dO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc2hhbGxvdyBjbG9uZSBvZiBgb2JqZWN0YCBjb21wb3NlZCBvZiB0aGUgc3BlY2lmaWVkIHByb3BlcnRpZXMuXG4gICAgICogUHJvcGVydHkgbmFtZXMgbWF5IGJlIHNwZWNpZmllZCBhcyBpbmRpdmlkdWFsIGFyZ3VtZW50cyBvciBhcyBhcnJheXMgb2ZcbiAgICAgKiBwcm9wZXJ0eSBuYW1lcy4gSWYgYSBjYWxsYmFjayBpcyBwcm92aWRlZCBpdCB3aWxsIGJlIGV4ZWN1dGVkIGZvciBlYWNoXG4gICAgICogcHJvcGVydHkgb2YgYG9iamVjdGAgcGlja2luZyB0aGUgcHJvcGVydGllcyB0aGUgY2FsbGJhY2sgcmV0dXJucyB0cnVleVxuICAgICAqIGZvci4gVGhlIGNhbGxiYWNrIGlzIGJvdW5kIHRvIGB0aGlzQXJnYCBhbmQgaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50cztcbiAgICAgKiAodmFsdWUsIGtleSwgb2JqZWN0KS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RzXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufC4uLnN0cmluZ3xzdHJpbmdbXX0gW2NhbGxiYWNrXSBUaGUgZnVuY3Rpb24gY2FsbGVkIHBlclxuICAgICAqICBpdGVyYXRpb24gb3IgcHJvcGVydHkgbmFtZXMgdG8gcGljaywgc3BlY2lmaWVkIGFzIGluZGl2aWR1YWwgcHJvcGVydHlcbiAgICAgKiAgbmFtZXMgb3IgYXJyYXlzIG9mIHByb3BlcnR5IG5hbWVzLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY2FsbGJhY2tgLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYW4gb2JqZWN0IGNvbXBvc2VkIG9mIHRoZSBwaWNrZWQgcHJvcGVydGllcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5waWNrKHsgJ25hbWUnOiAnZnJlZCcsICdfdXNlcmlkJzogJ2ZyZWQxJyB9LCAnbmFtZScpO1xuICAgICAqIC8vID0+IHsgJ25hbWUnOiAnZnJlZCcgfVxuICAgICAqXG4gICAgICogXy5waWNrKHsgJ25hbWUnOiAnZnJlZCcsICdfdXNlcmlkJzogJ2ZyZWQxJyB9LCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG4gICAgICogICByZXR1cm4ga2V5LmNoYXJBdCgwKSAhPSAnXyc7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4geyAnbmFtZSc6ICdmcmVkJyB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gcGljayhvYmplY3QsIGNhbGxiYWNrLCB0aGlzQXJnKSB7XG4gICAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgICBpZiAodHlwZW9mIGNhbGxiYWNrICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgICBwcm9wcyA9IGJhc2VGbGF0dGVuKGFyZ3VtZW50cywgdHJ1ZSwgZmFsc2UsIDEpLFxuICAgICAgICAgICAgbGVuZ3RoID0gaXNPYmplY3Qob2JqZWN0KSA/IHByb3BzLmxlbmd0aCA6IDA7XG5cbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICB2YXIga2V5ID0gcHJvcHNbaW5kZXhdO1xuICAgICAgICAgIGlmIChrZXkgaW4gb2JqZWN0KSB7XG4gICAgICAgICAgICByZXN1bHRba2V5XSA9IG9iamVjdFtrZXldO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2FsbGJhY2sgPSBsb2Rhc2guY3JlYXRlQ2FsbGJhY2soY2FsbGJhY2ssIHRoaXNBcmcsIDMpO1xuICAgICAgICBmb3JJbihvYmplY3QsIGZ1bmN0aW9uKHZhbHVlLCBrZXksIG9iamVjdCkge1xuICAgICAgICAgIGlmIChjYWxsYmFjayh2YWx1ZSwga2V5LCBvYmplY3QpKSB7XG4gICAgICAgICAgICByZXN1bHRba2V5XSA9IHZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFuIGFsdGVybmF0aXZlIHRvIGBfLnJlZHVjZWAgdGhpcyBtZXRob2QgdHJhbnNmb3JtcyBgb2JqZWN0YCB0byBhIG5ld1xuICAgICAqIGBhY2N1bXVsYXRvcmAgb2JqZWN0IHdoaWNoIGlzIHRoZSByZXN1bHQgb2YgcnVubmluZyBlYWNoIG9mIGl0cyBvd25cbiAgICAgKiBlbnVtZXJhYmxlIHByb3BlcnRpZXMgdGhyb3VnaCBhIGNhbGxiYWNrLCB3aXRoIGVhY2ggY2FsbGJhY2sgZXhlY3V0aW9uXG4gICAgICogcG90ZW50aWFsbHkgbXV0YXRpbmcgdGhlIGBhY2N1bXVsYXRvcmAgb2JqZWN0LiBUaGUgY2FsbGJhY2sgaXMgYm91bmQgdG9cbiAgICAgKiBgdGhpc0FyZ2AgYW5kIGludm9rZWQgd2l0aCBmb3VyIGFyZ3VtZW50czsgKGFjY3VtdWxhdG9yLCB2YWx1ZSwga2V5LCBvYmplY3QpLlxuICAgICAqIENhbGxiYWNrcyBtYXkgZXhpdCBpdGVyYXRpb24gZWFybHkgYnkgZXhwbGljaXRseSByZXR1cm5pbmcgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RzXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY2FsbGJhY2s9aWRlbnRpdHldIFRoZSBmdW5jdGlvbiBjYWxsZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFthY2N1bXVsYXRvcl0gVGhlIGN1c3RvbSBhY2N1bXVsYXRvciB2YWx1ZS5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGNhbGxiYWNrYC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgYWNjdW11bGF0ZWQgdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBzcXVhcmVzID0gXy50cmFuc2Zvcm0oWzEsIDIsIDMsIDQsIDUsIDYsIDcsIDgsIDksIDEwXSwgZnVuY3Rpb24ocmVzdWx0LCBudW0pIHtcbiAgICAgKiAgIG51bSAqPSBudW07XG4gICAgICogICBpZiAobnVtICUgMikge1xuICAgICAqICAgICByZXR1cm4gcmVzdWx0LnB1c2gobnVtKSA8IDM7XG4gICAgICogICB9XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gWzEsIDksIDI1XVxuICAgICAqXG4gICAgICogdmFyIG1hcHBlZCA9IF8udHJhbnNmb3JtKHsgJ2EnOiAxLCAnYic6IDIsICdjJzogMyB9LCBmdW5jdGlvbihyZXN1bHQsIG51bSwga2V5KSB7XG4gICAgICogICByZXN1bHRba2V5XSA9IG51bSAqIDM7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4geyAnYSc6IDMsICdiJzogNiwgJ2MnOiA5IH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0cmFuc2Zvcm0ob2JqZWN0LCBjYWxsYmFjaywgYWNjdW11bGF0b3IsIHRoaXNBcmcpIHtcbiAgICAgIHZhciBpc0FyciA9IGlzQXJyYXkob2JqZWN0KTtcbiAgICAgIGlmIChhY2N1bXVsYXRvciA9PSBudWxsKSB7XG4gICAgICAgIGlmIChpc0Fycikge1xuICAgICAgICAgIGFjY3VtdWxhdG9yID0gW107XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIGN0b3IgPSBvYmplY3QgJiYgb2JqZWN0LmNvbnN0cnVjdG9yLFxuICAgICAgICAgICAgICBwcm90byA9IGN0b3IgJiYgY3Rvci5wcm90b3R5cGU7XG5cbiAgICAgICAgICBhY2N1bXVsYXRvciA9IGJhc2VDcmVhdGUocHJvdG8pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgY2FsbGJhY2sgPSBsb2Rhc2guY3JlYXRlQ2FsbGJhY2soY2FsbGJhY2ssIHRoaXNBcmcsIDQpO1xuICAgICAgICAoaXNBcnIgPyBmb3JFYWNoIDogZm9yT3duKShvYmplY3QsIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgb2JqZWN0KSB7XG4gICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGFjY3VtdWxhdG9yLCB2YWx1ZSwgaW5kZXgsIG9iamVjdCk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgY29tcG9zZWQgb2YgdGhlIG93biBlbnVtZXJhYmxlIHByb3BlcnR5IHZhbHVlcyBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RzXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGFuIGFycmF5IG9mIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy52YWx1ZXMoeyAnb25lJzogMSwgJ3R3byc6IDIsICd0aHJlZSc6IDMgfSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdIChwcm9wZXJ0eSBvcmRlciBpcyBub3QgZ3VhcmFudGVlZCBhY3Jvc3MgZW52aXJvbm1lbnRzKVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHZhbHVlcyhvYmplY3QpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIHByb3BzID0ga2V5cyhvYmplY3QpLFxuICAgICAgICAgIGxlbmd0aCA9IHByb3BzLmxlbmd0aCxcbiAgICAgICAgICByZXN1bHQgPSBBcnJheShsZW5ndGgpO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICByZXN1bHRbaW5kZXhdID0gb2JqZWN0W3Byb3BzW2luZGV4XV07XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBlbGVtZW50cyBmcm9tIHRoZSBzcGVjaWZpZWQgaW5kZXhlcywgb3Iga2V5cywgb2YgdGhlXG4gICAgICogYGNvbGxlY3Rpb25gLiBJbmRleGVzIG1heSBiZSBzcGVjaWZpZWQgYXMgaW5kaXZpZHVhbCBhcmd1bWVudHMgb3IgYXMgYXJyYXlzXG4gICAgICogb2YgaW5kZXhlcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uc1xuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHsuLi4obnVtYmVyfG51bWJlcltdfHN0cmluZ3xzdHJpbmdbXSl9IFtpbmRleF0gVGhlIGluZGV4ZXMgb2YgYGNvbGxlY3Rpb25gXG4gICAgICogICB0byByZXRyaWV2ZSwgc3BlY2lmaWVkIGFzIGluZGl2aWR1YWwgaW5kZXhlcyBvciBhcnJheXMgb2YgaW5kZXhlcy5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYSBuZXcgYXJyYXkgb2YgZWxlbWVudHMgY29ycmVzcG9uZGluZyB0byB0aGVcbiAgICAgKiAgcHJvdmlkZWQgaW5kZXhlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5hdChbJ2EnLCAnYicsICdjJywgJ2QnLCAnZSddLCBbMCwgMiwgNF0pO1xuICAgICAqIC8vID0+IFsnYScsICdjJywgJ2UnXVxuICAgICAqXG4gICAgICogXy5hdChbJ2ZyZWQnLCAnYmFybmV5JywgJ3BlYmJsZXMnXSwgMCwgMik7XG4gICAgICogLy8gPT4gWydmcmVkJywgJ3BlYmJsZXMnXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGF0KGNvbGxlY3Rpb24pIHtcbiAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzLFxuICAgICAgICAgIGluZGV4ID0gLTEsXG4gICAgICAgICAgcHJvcHMgPSBiYXNlRmxhdHRlbihhcmdzLCB0cnVlLCBmYWxzZSwgMSksXG4gICAgICAgICAgbGVuZ3RoID0gKGFyZ3NbMl0gJiYgYXJnc1syXVthcmdzWzFdXSA9PT0gY29sbGVjdGlvbikgPyAxIDogcHJvcHMubGVuZ3RoLFxuICAgICAgICAgIHJlc3VsdCA9IEFycmF5KGxlbmd0aCk7XG5cbiAgICAgIHdoaWxlKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgcmVzdWx0W2luZGV4XSA9IGNvbGxlY3Rpb25bcHJvcHNbaW5kZXhdXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGEgZ2l2ZW4gdmFsdWUgaXMgcHJlc2VudCBpbiBhIGNvbGxlY3Rpb24gdXNpbmcgc3RyaWN0IGVxdWFsaXR5XG4gICAgICogZm9yIGNvbXBhcmlzb25zLCBpLmUuIGA9PT1gLiBJZiBgZnJvbUluZGV4YCBpcyBuZWdhdGl2ZSwgaXQgaXMgdXNlZCBhcyB0aGVcbiAgICAgKiBvZmZzZXQgZnJvbSB0aGUgZW5kIG9mIHRoZSBjb2xsZWN0aW9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGFsaWFzIGluY2x1ZGVcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvbnNcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7Kn0gdGFyZ2V0IFRoZSB2YWx1ZSB0byBjaGVjayBmb3IuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtmcm9tSW5kZXg9MF0gVGhlIGluZGV4IHRvIHNlYXJjaCBmcm9tLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgYHRhcmdldGAgZWxlbWVudCBpcyBmb3VuZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmNvbnRhaW5zKFsxLCAyLCAzXSwgMSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5jb250YWlucyhbMSwgMiwgM10sIDEsIDIpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmNvbnRhaW5zKHsgJ25hbWUnOiAnZnJlZCcsICdhZ2UnOiA0MCB9LCAnZnJlZCcpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uY29udGFpbnMoJ3BlYmJsZXMnLCAnZWInKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29udGFpbnMoY29sbGVjdGlvbiwgdGFyZ2V0LCBmcm9tSW5kZXgpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGluZGV4T2YgPSBnZXRJbmRleE9mKCksXG4gICAgICAgICAgbGVuZ3RoID0gY29sbGVjdGlvbiA/IGNvbGxlY3Rpb24ubGVuZ3RoIDogMCxcbiAgICAgICAgICByZXN1bHQgPSBmYWxzZTtcblxuICAgICAgZnJvbUluZGV4ID0gKGZyb21JbmRleCA8IDAgPyBuYXRpdmVNYXgoMCwgbGVuZ3RoICsgZnJvbUluZGV4KSA6IGZyb21JbmRleCkgfHwgMDtcbiAgICAgIGlmIChpc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICAgIHJlc3VsdCA9IGluZGV4T2YoY29sbGVjdGlvbiwgdGFyZ2V0LCBmcm9tSW5kZXgpID4gLTE7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBsZW5ndGggPT0gJ251bWJlcicpIHtcbiAgICAgICAgcmVzdWx0ID0gKGlzU3RyaW5nKGNvbGxlY3Rpb24pID8gY29sbGVjdGlvbi5pbmRleE9mKHRhcmdldCwgZnJvbUluZGV4KSA6IGluZGV4T2YoY29sbGVjdGlvbiwgdGFyZ2V0LCBmcm9tSW5kZXgpKSA+IC0xO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZm9yT3duKGNvbGxlY3Rpb24sIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgICAgaWYgKCsraW5kZXggPj0gZnJvbUluZGV4KSB7XG4gICAgICAgICAgICByZXR1cm4gIShyZXN1bHQgPSB2YWx1ZSA9PT0gdGFyZ2V0KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIG9iamVjdCBjb21wb3NlZCBvZiBrZXlzIGdlbmVyYXRlZCBmcm9tIHRoZSByZXN1bHRzIG9mIHJ1bm5pbmdcbiAgICAgKiBlYWNoIGVsZW1lbnQgb2YgYGNvbGxlY3Rpb25gIHRocm91Z2ggdGhlIGNhbGxiYWNrLiBUaGUgY29ycmVzcG9uZGluZyB2YWx1ZVxuICAgICAqIG9mIGVhY2gga2V5IGlzIHRoZSBudW1iZXIgb2YgdGltZXMgdGhlIGtleSB3YXMgcmV0dXJuZWQgYnkgdGhlIGNhbGxiYWNrLlxuICAgICAqIFRoZSBjYWxsYmFjayBpcyBib3VuZCB0byBgdGhpc0FyZ2AgYW5kIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM7XG4gICAgICogKHZhbHVlLCBpbmRleHxrZXksIGNvbGxlY3Rpb24pLlxuICAgICAqXG4gICAgICogSWYgYSBwcm9wZXJ0eSBuYW1lIGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy5wbHVja1wiIHN0eWxlXG4gICAgICogY2FsbGJhY2sgd2lsbCByZXR1cm4gdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqXG4gICAgICogSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy53aGVyZVwiIHN0eWxlIGNhbGxiYWNrXG4gICAgICogd2lsbCByZXR1cm4gYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuIG9iamVjdCxcbiAgICAgKiBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvbnNcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW2NhbGxiYWNrPWlkZW50aXR5XSBUaGUgZnVuY3Rpb24gY2FsbGVkXG4gICAgICogIHBlciBpdGVyYXRpb24uIElmIGEgcHJvcGVydHkgbmFtZSBvciBvYmplY3QgaXMgcHJvdmlkZWQgaXQgd2lsbCBiZSB1c2VkXG4gICAgICogIHRvIGNyZWF0ZSBhIFwiXy5wbHVja1wiIG9yIFwiXy53aGVyZVwiIHN0eWxlIGNhbGxiYWNrLCByZXNwZWN0aXZlbHkuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBjYWxsYmFja2AuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY29tcG9zZWQgYWdncmVnYXRlIG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5jb3VudEJ5KFs0LjMsIDYuMSwgNi40XSwgZnVuY3Rpb24obnVtKSB7IHJldHVybiBNYXRoLmZsb29yKG51bSk7IH0pO1xuICAgICAqIC8vID0+IHsgJzQnOiAxLCAnNic6IDIgfVxuICAgICAqXG4gICAgICogXy5jb3VudEJ5KFs0LjMsIDYuMSwgNi40XSwgZnVuY3Rpb24obnVtKSB7IHJldHVybiB0aGlzLmZsb29yKG51bSk7IH0sIE1hdGgpO1xuICAgICAqIC8vID0+IHsgJzQnOiAxLCAnNic6IDIgfVxuICAgICAqXG4gICAgICogXy5jb3VudEJ5KFsnb25lJywgJ3R3bycsICd0aHJlZSddLCAnbGVuZ3RoJyk7XG4gICAgICogLy8gPT4geyAnMyc6IDIsICc1JzogMSB9XG4gICAgICovXG4gICAgdmFyIGNvdW50QnkgPSBjcmVhdGVBZ2dyZWdhdG9yKGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgKGhhc093blByb3BlcnR5LmNhbGwocmVzdWx0LCBrZXkpID8gcmVzdWx0W2tleV0rKyA6IHJlc3VsdFtrZXldID0gMSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgdGhlIGdpdmVuIGNhbGxiYWNrIHJldHVybnMgdHJ1ZXkgdmFsdWUgZm9yICoqYWxsKiogZWxlbWVudHMgb2ZcbiAgICAgKiBhIGNvbGxlY3Rpb24uIFRoZSBjYWxsYmFjayBpcyBib3VuZCB0byBgdGhpc0FyZ2AgYW5kIGludm9rZWQgd2l0aCB0aHJlZVxuICAgICAqIGFyZ3VtZW50czsgKHZhbHVlLCBpbmRleHxrZXksIGNvbGxlY3Rpb24pLlxuICAgICAqXG4gICAgICogSWYgYSBwcm9wZXJ0eSBuYW1lIGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy5wbHVja1wiIHN0eWxlXG4gICAgICogY2FsbGJhY2sgd2lsbCByZXR1cm4gdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqXG4gICAgICogSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy53aGVyZVwiIHN0eWxlIGNhbGxiYWNrXG4gICAgICogd2lsbCByZXR1cm4gYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuIG9iamVjdCxcbiAgICAgKiBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAYWxpYXMgYWxsXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25zXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtjYWxsYmFjaz1pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGNhbGxlZFxuICAgICAqICBwZXIgaXRlcmF0aW9uLiBJZiBhIHByb3BlcnR5IG5hbWUgb3Igb2JqZWN0IGlzIHByb3ZpZGVkIGl0IHdpbGwgYmUgdXNlZFxuICAgICAqICB0byBjcmVhdGUgYSBcIl8ucGx1Y2tcIiBvciBcIl8ud2hlcmVcIiBzdHlsZSBjYWxsYmFjaywgcmVzcGVjdGl2ZWx5LlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY2FsbGJhY2tgLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbGwgZWxlbWVudHMgcGFzc2VkIHRoZSBjYWxsYmFjayBjaGVjayxcbiAgICAgKiAgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmV2ZXJ5KFt0cnVlLCAxLCBudWxsLCAneWVzJ10pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiB2YXIgY2hhcmFjdGVycyA9IFtcbiAgICAgKiAgIHsgJ25hbWUnOiAnYmFybmV5JywgJ2FnZSc6IDM2IH0sXG4gICAgICogICB7ICduYW1lJzogJ2ZyZWQnLCAgICdhZ2UnOiA0MCB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIFwiXy5wbHVja1wiIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8uZXZlcnkoY2hhcmFjdGVycywgJ2FnZScpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIFwiXy53aGVyZVwiIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8uZXZlcnkoY2hhcmFjdGVycywgeyAnYWdlJzogMzYgfSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBldmVyeShjb2xsZWN0aW9uLCBjYWxsYmFjaywgdGhpc0FyZykge1xuICAgICAgdmFyIHJlc3VsdCA9IHRydWU7XG4gICAgICBjYWxsYmFjayA9IGxvZGFzaC5jcmVhdGVDYWxsYmFjayhjYWxsYmFjaywgdGhpc0FyZywgMyk7XG5cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGNvbGxlY3Rpb24gPyBjb2xsZWN0aW9uLmxlbmd0aCA6IDA7XG5cbiAgICAgIGlmICh0eXBlb2YgbGVuZ3RoID09ICdudW1iZXInKSB7XG4gICAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgICAgaWYgKCEocmVzdWx0ID0gISFjYWxsYmFjayhjb2xsZWN0aW9uW2luZGV4XSwgaW5kZXgsIGNvbGxlY3Rpb24pKSkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBmb3JPd24oY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgICAgcmV0dXJuIChyZXN1bHQgPSAhIWNhbGxiYWNrKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSXRlcmF0ZXMgb3ZlciBlbGVtZW50cyBvZiBhIGNvbGxlY3Rpb24sIHJldHVybmluZyBhbiBhcnJheSBvZiBhbGwgZWxlbWVudHNcbiAgICAgKiB0aGUgY2FsbGJhY2sgcmV0dXJucyB0cnVleSBmb3IuIFRoZSBjYWxsYmFjayBpcyBib3VuZCB0byBgdGhpc0FyZ2AgYW5kXG4gICAgICogaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czsgKHZhbHVlLCBpbmRleHxrZXksIGNvbGxlY3Rpb24pLlxuICAgICAqXG4gICAgICogSWYgYSBwcm9wZXJ0eSBuYW1lIGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy5wbHVja1wiIHN0eWxlXG4gICAgICogY2FsbGJhY2sgd2lsbCByZXR1cm4gdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqXG4gICAgICogSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy53aGVyZVwiIHN0eWxlIGNhbGxiYWNrXG4gICAgICogd2lsbCByZXR1cm4gYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuIG9iamVjdCxcbiAgICAgKiBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAYWxpYXMgc2VsZWN0XG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25zXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtjYWxsYmFjaz1pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGNhbGxlZFxuICAgICAqICBwZXIgaXRlcmF0aW9uLiBJZiBhIHByb3BlcnR5IG5hbWUgb3Igb2JqZWN0IGlzIHByb3ZpZGVkIGl0IHdpbGwgYmUgdXNlZFxuICAgICAqICB0byBjcmVhdGUgYSBcIl8ucGx1Y2tcIiBvciBcIl8ud2hlcmVcIiBzdHlsZSBjYWxsYmFjaywgcmVzcGVjdGl2ZWx5LlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY2FsbGJhY2tgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBhIG5ldyBhcnJheSBvZiBlbGVtZW50cyB0aGF0IHBhc3NlZCB0aGUgY2FsbGJhY2sgY2hlY2suXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBldmVucyA9IF8uZmlsdGVyKFsxLCAyLCAzLCA0LCA1LCA2XSwgZnVuY3Rpb24obnVtKSB7IHJldHVybiBudW0gJSAyID09IDA7IH0pO1xuICAgICAqIC8vID0+IFsyLCA0LCA2XVxuICAgICAqXG4gICAgICogdmFyIGNoYXJhY3RlcnMgPSBbXG4gICAgICogICB7ICduYW1lJzogJ2Jhcm5leScsICdhZ2UnOiAzNiwgJ2Jsb2NrZWQnOiBmYWxzZSB9LFxuICAgICAqICAgeyAnbmFtZSc6ICdmcmVkJywgICAnYWdlJzogNDAsICdibG9ja2VkJzogdHJ1ZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIFwiXy5wbHVja1wiIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8uZmlsdGVyKGNoYXJhY3RlcnMsICdibG9ja2VkJyk7XG4gICAgICogLy8gPT4gW3sgJ25hbWUnOiAnZnJlZCcsICdhZ2UnOiA0MCwgJ2Jsb2NrZWQnOiB0cnVlIH1dXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyBcIl8ud2hlcmVcIiBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLmZpbHRlcihjaGFyYWN0ZXJzLCB7ICdhZ2UnOiAzNiB9KTtcbiAgICAgKiAvLyA9PiBbeyAnbmFtZSc6ICdiYXJuZXknLCAnYWdlJzogMzYsICdibG9ja2VkJzogZmFsc2UgfV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmaWx0ZXIoY29sbGVjdGlvbiwgY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgIGNhbGxiYWNrID0gbG9kYXNoLmNyZWF0ZUNhbGxiYWNrKGNhbGxiYWNrLCB0aGlzQXJnLCAzKTtcblxuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gY29sbGVjdGlvbiA/IGNvbGxlY3Rpb24ubGVuZ3RoIDogMDtcblxuICAgICAgaWYgKHR5cGVvZiBsZW5ndGggPT0gJ251bWJlcicpIHtcbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICB2YXIgdmFsdWUgPSBjb2xsZWN0aW9uW2luZGV4XTtcbiAgICAgICAgICBpZiAoY2FsbGJhY2sodmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSkge1xuICAgICAgICAgICAgcmVzdWx0LnB1c2godmFsdWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZm9yT3duKGNvbGxlY3Rpb24sIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikge1xuICAgICAgICAgIGlmIChjYWxsYmFjayh2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pKSB7XG4gICAgICAgICAgICByZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSXRlcmF0ZXMgb3ZlciBlbGVtZW50cyBvZiBhIGNvbGxlY3Rpb24sIHJldHVybmluZyB0aGUgZmlyc3QgZWxlbWVudCB0aGF0XG4gICAgICogdGhlIGNhbGxiYWNrIHJldHVybnMgdHJ1ZXkgZm9yLiBUaGUgY2FsbGJhY2sgaXMgYm91bmQgdG8gYHRoaXNBcmdgIGFuZFxuICAgICAqIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM7ICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYGNhbGxiYWNrYCB0aGUgY3JlYXRlZCBcIl8ucGx1Y2tcIiBzdHlsZVxuICAgICAqIGNhbGxiYWNrIHdpbGwgcmV0dXJuIHRoZSBwcm9wZXJ0eSB2YWx1ZSBvZiB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYGNhbGxiYWNrYCB0aGUgY3JlYXRlZCBcIl8ud2hlcmVcIiBzdHlsZSBjYWxsYmFja1xuICAgICAqIHdpbGwgcmV0dXJuIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBnaXZlbiBvYmplY3QsXG4gICAgICogZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGFsaWFzIGRldGVjdCwgZmluZFdoZXJlXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25zXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtjYWxsYmFjaz1pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGNhbGxlZFxuICAgICAqICBwZXIgaXRlcmF0aW9uLiBJZiBhIHByb3BlcnR5IG5hbWUgb3Igb2JqZWN0IGlzIHByb3ZpZGVkIGl0IHdpbGwgYmUgdXNlZFxuICAgICAqICB0byBjcmVhdGUgYSBcIl8ucGx1Y2tcIiBvciBcIl8ud2hlcmVcIiBzdHlsZSBjYWxsYmFjaywgcmVzcGVjdGl2ZWx5LlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY2FsbGJhY2tgLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBmb3VuZCBlbGVtZW50LCBlbHNlIGB1bmRlZmluZWRgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgY2hhcmFjdGVycyA9IFtcbiAgICAgKiAgIHsgJ25hbWUnOiAnYmFybmV5JywgICdhZ2UnOiAzNiwgJ2Jsb2NrZWQnOiBmYWxzZSB9LFxuICAgICAqICAgeyAnbmFtZSc6ICdmcmVkJywgICAgJ2FnZSc6IDQwLCAnYmxvY2tlZCc6IHRydWUgfSxcbiAgICAgKiAgIHsgJ25hbWUnOiAncGViYmxlcycsICdhZ2UnOiAxLCAgJ2Jsb2NrZWQnOiBmYWxzZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8uZmluZChjaGFyYWN0ZXJzLCBmdW5jdGlvbihjaHIpIHtcbiAgICAgKiAgIHJldHVybiBjaHIuYWdlIDwgNDA7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4geyAnbmFtZSc6ICdiYXJuZXknLCAnYWdlJzogMzYsICdibG9ja2VkJzogZmFsc2UgfVxuICAgICAqXG4gICAgICogLy8gdXNpbmcgXCJfLndoZXJlXCIgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5maW5kKGNoYXJhY3RlcnMsIHsgJ2FnZSc6IDEgfSk7XG4gICAgICogLy8gPT4gIHsgJ25hbWUnOiAncGViYmxlcycsICdhZ2UnOiAxLCAnYmxvY2tlZCc6IGZhbHNlIH1cbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIFwiXy5wbHVja1wiIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8uZmluZChjaGFyYWN0ZXJzLCAnYmxvY2tlZCcpO1xuICAgICAqIC8vID0+IHsgJ25hbWUnOiAnZnJlZCcsICdhZ2UnOiA0MCwgJ2Jsb2NrZWQnOiB0cnVlIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmaW5kKGNvbGxlY3Rpb24sIGNhbGxiYWNrLCB0aGlzQXJnKSB7XG4gICAgICBjYWxsYmFjayA9IGxvZGFzaC5jcmVhdGVDYWxsYmFjayhjYWxsYmFjaywgdGhpc0FyZywgMyk7XG5cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGNvbGxlY3Rpb24gPyBjb2xsZWN0aW9uLmxlbmd0aCA6IDA7XG5cbiAgICAgIGlmICh0eXBlb2YgbGVuZ3RoID09ICdudW1iZXInKSB7XG4gICAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgICAgdmFyIHZhbHVlID0gY29sbGVjdGlvbltpbmRleF07XG4gICAgICAgICAgaWYgKGNhbGxiYWNrKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciByZXN1bHQ7XG4gICAgICAgIGZvck93bihjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgICBpZiAoY2FsbGJhY2sodmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWU7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZpbmRgIGV4Y2VwdCB0aGF0IGl0IGl0ZXJhdGVzIG92ZXIgZWxlbWVudHNcbiAgICAgKiBvZiBhIGBjb2xsZWN0aW9uYCBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvbnNcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW2NhbGxiYWNrPWlkZW50aXR5XSBUaGUgZnVuY3Rpb24gY2FsbGVkXG4gICAgICogIHBlciBpdGVyYXRpb24uIElmIGEgcHJvcGVydHkgbmFtZSBvciBvYmplY3QgaXMgcHJvdmlkZWQgaXQgd2lsbCBiZSB1c2VkXG4gICAgICogIHRvIGNyZWF0ZSBhIFwiXy5wbHVja1wiIG9yIFwiXy53aGVyZVwiIHN0eWxlIGNhbGxiYWNrLCByZXNwZWN0aXZlbHkuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBjYWxsYmFja2AuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGZvdW5kIGVsZW1lbnQsIGVsc2UgYHVuZGVmaW5lZGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZmluZExhc3QoWzEsIDIsIDMsIDRdLCBmdW5jdGlvbihudW0pIHtcbiAgICAgKiAgIHJldHVybiBudW0gJSAyID09IDE7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gM1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZpbmRMYXN0KGNvbGxlY3Rpb24sIGNhbGxiYWNrLCB0aGlzQXJnKSB7XG4gICAgICB2YXIgcmVzdWx0O1xuICAgICAgY2FsbGJhY2sgPSBsb2Rhc2guY3JlYXRlQ2FsbGJhY2soY2FsbGJhY2ssIHRoaXNBcmcsIDMpO1xuICAgICAgZm9yRWFjaFJpZ2h0KGNvbGxlY3Rpb24sIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikge1xuICAgICAgICBpZiAoY2FsbGJhY2sodmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSkge1xuICAgICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEl0ZXJhdGVzIG92ZXIgZWxlbWVudHMgb2YgYSBjb2xsZWN0aW9uLCBleGVjdXRpbmcgdGhlIGNhbGxiYWNrIGZvciBlYWNoXG4gICAgICogZWxlbWVudC4gVGhlIGNhbGxiYWNrIGlzIGJvdW5kIHRvIGB0aGlzQXJnYCBhbmQgaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50cztcbiAgICAgKiAodmFsdWUsIGluZGV4fGtleSwgY29sbGVjdGlvbikuIENhbGxiYWNrcyBtYXkgZXhpdCBpdGVyYXRpb24gZWFybHkgYnlcbiAgICAgKiBleHBsaWNpdGx5IHJldHVybmluZyBgZmFsc2VgLlxuICAgICAqXG4gICAgICogTm90ZTogQXMgd2l0aCBvdGhlciBcIkNvbGxlY3Rpb25zXCIgbWV0aG9kcywgb2JqZWN0cyB3aXRoIGEgYGxlbmd0aGAgcHJvcGVydHlcbiAgICAgKiBhcmUgaXRlcmF0ZWQgbGlrZSBhcnJheXMuIFRvIGF2b2lkIHRoaXMgYmVoYXZpb3IgYF8uZm9ySW5gIG9yIGBfLmZvck93bmBcbiAgICAgKiBtYXkgYmUgdXNlZCBmb3Igb2JqZWN0IGl0ZXJhdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBhbGlhcyBlYWNoXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25zXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY2FsbGJhY2s9aWRlbnRpdHldIFRoZSBmdW5jdGlvbiBjYWxsZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGNhbGxiYWNrYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl8T2JqZWN0fHN0cmluZ30gUmV0dXJucyBgY29sbGVjdGlvbmAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8oWzEsIDIsIDNdKS5mb3JFYWNoKGZ1bmN0aW9uKG51bSkgeyBjb25zb2xlLmxvZyhudW0pOyB9KS5qb2luKCcsJyk7XG4gICAgICogLy8gPT4gbG9ncyBlYWNoIG51bWJlciBhbmQgcmV0dXJucyAnMSwyLDMnXG4gICAgICpcbiAgICAgKiBfLmZvckVhY2goeyAnb25lJzogMSwgJ3R3byc6IDIsICd0aHJlZSc6IDMgfSwgZnVuY3Rpb24obnVtKSB7IGNvbnNvbGUubG9nKG51bSk7IH0pO1xuICAgICAqIC8vID0+IGxvZ3MgZWFjaCBudW1iZXIgYW5kIHJldHVybnMgdGhlIG9iamVjdCAocHJvcGVydHkgb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQgYWNyb3NzIGVudmlyb25tZW50cylcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmb3JFYWNoKGNvbGxlY3Rpb24sIGNhbGxiYWNrLCB0aGlzQXJnKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBjb2xsZWN0aW9uID8gY29sbGVjdGlvbi5sZW5ndGggOiAwO1xuXG4gICAgICBjYWxsYmFjayA9IGNhbGxiYWNrICYmIHR5cGVvZiB0aGlzQXJnID09ICd1bmRlZmluZWQnID8gY2FsbGJhY2sgOiBiYXNlQ3JlYXRlQ2FsbGJhY2soY2FsbGJhY2ssIHRoaXNBcmcsIDMpO1xuICAgICAgaWYgKHR5cGVvZiBsZW5ndGggPT0gJ251bWJlcicpIHtcbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICBpZiAoY2FsbGJhY2soY29sbGVjdGlvbltpbmRleF0sIGluZGV4LCBjb2xsZWN0aW9uKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZm9yT3duKGNvbGxlY3Rpb24sIGNhbGxiYWNrKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZm9yRWFjaGAgZXhjZXB0IHRoYXQgaXQgaXRlcmF0ZXMgb3ZlciBlbGVtZW50c1xuICAgICAqIG9mIGEgYGNvbGxlY3Rpb25gIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBhbGlhcyBlYWNoUmlnaHRcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvbnNcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjYWxsYmFjaz1pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGNhbGxlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY2FsbGJhY2tgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheXxPYmplY3R8c3RyaW5nfSBSZXR1cm5zIGBjb2xsZWN0aW9uYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXyhbMSwgMiwgM10pLmZvckVhY2hSaWdodChmdW5jdGlvbihudW0pIHsgY29uc29sZS5sb2cobnVtKTsgfSkuam9pbignLCcpO1xuICAgICAqIC8vID0+IGxvZ3MgZWFjaCBudW1iZXIgZnJvbSByaWdodCB0byBsZWZ0IGFuZCByZXR1cm5zICczLDIsMSdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmb3JFYWNoUmlnaHQoY29sbGVjdGlvbiwgY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICAgIHZhciBsZW5ndGggPSBjb2xsZWN0aW9uID8gY29sbGVjdGlvbi5sZW5ndGggOiAwO1xuICAgICAgY2FsbGJhY2sgPSBjYWxsYmFjayAmJiB0eXBlb2YgdGhpc0FyZyA9PSAndW5kZWZpbmVkJyA/IGNhbGxiYWNrIDogYmFzZUNyZWF0ZUNhbGxiYWNrKGNhbGxiYWNrLCB0aGlzQXJnLCAzKTtcbiAgICAgIGlmICh0eXBlb2YgbGVuZ3RoID09ICdudW1iZXInKSB7XG4gICAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICAgIGlmIChjYWxsYmFjayhjb2xsZWN0aW9uW2xlbmd0aF0sIGxlbmd0aCwgY29sbGVjdGlvbikgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBwcm9wcyA9IGtleXMoY29sbGVjdGlvbik7XG4gICAgICAgIGxlbmd0aCA9IHByb3BzLmxlbmd0aDtcbiAgICAgICAgZm9yT3duKGNvbGxlY3Rpb24sIGZ1bmN0aW9uKHZhbHVlLCBrZXksIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgICBrZXkgPSBwcm9wcyA/IHByb3BzWy0tbGVuZ3RoXSA6IC0tbGVuZ3RoO1xuICAgICAgICAgIHJldHVybiBjYWxsYmFjayhjb2xsZWN0aW9uW2tleV0sIGtleSwgY29sbGVjdGlvbik7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBvYmplY3QgY29tcG9zZWQgb2Yga2V5cyBnZW5lcmF0ZWQgZnJvbSB0aGUgcmVzdWx0cyBvZiBydW5uaW5nXG4gICAgICogZWFjaCBlbGVtZW50IG9mIGEgY29sbGVjdGlvbiB0aHJvdWdoIHRoZSBjYWxsYmFjay4gVGhlIGNvcnJlc3BvbmRpbmcgdmFsdWVcbiAgICAgKiBvZiBlYWNoIGtleSBpcyBhbiBhcnJheSBvZiB0aGUgZWxlbWVudHMgcmVzcG9uc2libGUgZm9yIGdlbmVyYXRpbmcgdGhlIGtleS5cbiAgICAgKiBUaGUgY2FsbGJhY2sgaXMgYm91bmQgdG8gYHRoaXNBcmdgIGFuZCBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzO1xuICAgICAqICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYGNhbGxiYWNrYCB0aGUgY3JlYXRlZCBcIl8ucGx1Y2tcIiBzdHlsZVxuICAgICAqIGNhbGxiYWNrIHdpbGwgcmV0dXJuIHRoZSBwcm9wZXJ0eSB2YWx1ZSBvZiB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYGNhbGxiYWNrYCB0aGUgY3JlYXRlZCBcIl8ud2hlcmVcIiBzdHlsZSBjYWxsYmFja1xuICAgICAqIHdpbGwgcmV0dXJuIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBnaXZlbiBvYmplY3QsXG4gICAgICogZWxzZSBgZmFsc2VgXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvbnNcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW2NhbGxiYWNrPWlkZW50aXR5XSBUaGUgZnVuY3Rpb24gY2FsbGVkXG4gICAgICogIHBlciBpdGVyYXRpb24uIElmIGEgcHJvcGVydHkgbmFtZSBvciBvYmplY3QgaXMgcHJvdmlkZWQgaXQgd2lsbCBiZSB1c2VkXG4gICAgICogIHRvIGNyZWF0ZSBhIFwiXy5wbHVja1wiIG9yIFwiXy53aGVyZVwiIHN0eWxlIGNhbGxiYWNrLCByZXNwZWN0aXZlbHkuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBjYWxsYmFja2AuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY29tcG9zZWQgYWdncmVnYXRlIG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5ncm91cEJ5KFs0LjIsIDYuMSwgNi40XSwgZnVuY3Rpb24obnVtKSB7IHJldHVybiBNYXRoLmZsb29yKG51bSk7IH0pO1xuICAgICAqIC8vID0+IHsgJzQnOiBbNC4yXSwgJzYnOiBbNi4xLCA2LjRdIH1cbiAgICAgKlxuICAgICAqIF8uZ3JvdXBCeShbNC4yLCA2LjEsIDYuNF0sIGZ1bmN0aW9uKG51bSkgeyByZXR1cm4gdGhpcy5mbG9vcihudW0pOyB9LCBNYXRoKTtcbiAgICAgKiAvLyA9PiB7ICc0JzogWzQuMl0sICc2JzogWzYuMSwgNi40XSB9XG4gICAgICpcbiAgICAgKiAvLyB1c2luZyBcIl8ucGx1Y2tcIiBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLmdyb3VwQnkoWydvbmUnLCAndHdvJywgJ3RocmVlJ10sICdsZW5ndGgnKTtcbiAgICAgKiAvLyA9PiB7ICczJzogWydvbmUnLCAndHdvJ10sICc1JzogWyd0aHJlZSddIH1cbiAgICAgKi9cbiAgICB2YXIgZ3JvdXBCeSA9IGNyZWF0ZUFnZ3JlZ2F0b3IoZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgICAoaGFzT3duUHJvcGVydHkuY2FsbChyZXN1bHQsIGtleSkgPyByZXN1bHRba2V5XSA6IHJlc3VsdFtrZXldID0gW10pLnB1c2godmFsdWUpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBvYmplY3QgY29tcG9zZWQgb2Yga2V5cyBnZW5lcmF0ZWQgZnJvbSB0aGUgcmVzdWx0cyBvZiBydW5uaW5nXG4gICAgICogZWFjaCBlbGVtZW50IG9mIHRoZSBjb2xsZWN0aW9uIHRocm91Z2ggdGhlIGdpdmVuIGNhbGxiYWNrLiBUaGUgY29ycmVzcG9uZGluZ1xuICAgICAqIHZhbHVlIG9mIGVhY2gga2V5IGlzIHRoZSBsYXN0IGVsZW1lbnQgcmVzcG9uc2libGUgZm9yIGdlbmVyYXRpbmcgdGhlIGtleS5cbiAgICAgKiBUaGUgY2FsbGJhY2sgaXMgYm91bmQgdG8gYHRoaXNBcmdgIGFuZCBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzO1xuICAgICAqICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYGNhbGxiYWNrYCB0aGUgY3JlYXRlZCBcIl8ucGx1Y2tcIiBzdHlsZVxuICAgICAqIGNhbGxiYWNrIHdpbGwgcmV0dXJuIHRoZSBwcm9wZXJ0eSB2YWx1ZSBvZiB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYGNhbGxiYWNrYCB0aGUgY3JlYXRlZCBcIl8ud2hlcmVcIiBzdHlsZSBjYWxsYmFja1xuICAgICAqIHdpbGwgcmV0dXJuIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBnaXZlbiBvYmplY3QsXG4gICAgICogZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25zXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtjYWxsYmFjaz1pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGNhbGxlZFxuICAgICAqICBwZXIgaXRlcmF0aW9uLiBJZiBhIHByb3BlcnR5IG5hbWUgb3Igb2JqZWN0IGlzIHByb3ZpZGVkIGl0IHdpbGwgYmUgdXNlZFxuICAgICAqICB0byBjcmVhdGUgYSBcIl8ucGx1Y2tcIiBvciBcIl8ud2hlcmVcIiBzdHlsZSBjYWxsYmFjaywgcmVzcGVjdGl2ZWx5LlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY2FsbGJhY2tgLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNvbXBvc2VkIGFnZ3JlZ2F0ZSBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBrZXlzID0gW1xuICAgICAqICAgeyAnZGlyJzogJ2xlZnQnLCAnY29kZSc6IDk3IH0sXG4gICAgICogICB7ICdkaXInOiAncmlnaHQnLCAnY29kZSc6IDEwMCB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8uaW5kZXhCeShrZXlzLCAnZGlyJyk7XG4gICAgICogLy8gPT4geyAnbGVmdCc6IHsgJ2Rpcic6ICdsZWZ0JywgJ2NvZGUnOiA5NyB9LCAncmlnaHQnOiB7ICdkaXInOiAncmlnaHQnLCAnY29kZSc6IDEwMCB9IH1cbiAgICAgKlxuICAgICAqIF8uaW5kZXhCeShrZXlzLCBmdW5jdGlvbihrZXkpIHsgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoa2V5LmNvZGUpOyB9KTtcbiAgICAgKiAvLyA9PiB7ICdhJzogeyAnZGlyJzogJ2xlZnQnLCAnY29kZSc6IDk3IH0sICdkJzogeyAnZGlyJzogJ3JpZ2h0JywgJ2NvZGUnOiAxMDAgfSB9XG4gICAgICpcbiAgICAgKiBfLmluZGV4QnkoY2hhcmFjdGVycywgZnVuY3Rpb24oa2V5KSB7IHRoaXMuZnJvbUNoYXJDb2RlKGtleS5jb2RlKTsgfSwgU3RyaW5nKTtcbiAgICAgKiAvLyA9PiB7ICdhJzogeyAnZGlyJzogJ2xlZnQnLCAnY29kZSc6IDk3IH0sICdkJzogeyAnZGlyJzogJ3JpZ2h0JywgJ2NvZGUnOiAxMDAgfSB9XG4gICAgICovXG4gICAgdmFyIGluZGV4QnkgPSBjcmVhdGVBZ2dyZWdhdG9yKGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgcmVzdWx0W2tleV0gPSB2YWx1ZTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIEludm9rZXMgdGhlIG1ldGhvZCBuYW1lZCBieSBgbWV0aG9kTmFtZWAgb24gZWFjaCBlbGVtZW50IGluIHRoZSBgY29sbGVjdGlvbmBcbiAgICAgKiByZXR1cm5pbmcgYW4gYXJyYXkgb2YgdGhlIHJlc3VsdHMgb2YgZWFjaCBpbnZva2VkIG1ldGhvZC4gQWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICAgKiB3aWxsIGJlIHByb3ZpZGVkIHRvIGVhY2ggaW52b2tlZCBtZXRob2QuIElmIGBtZXRob2ROYW1lYCBpcyBhIGZ1bmN0aW9uIGl0XG4gICAgICogd2lsbCBiZSBpbnZva2VkIGZvciwgYW5kIGB0aGlzYCBib3VuZCB0bywgZWFjaCBlbGVtZW50IGluIHRoZSBgY29sbGVjdGlvbmAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvbnNcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258c3RyaW5nfSBtZXRob2ROYW1lIFRoZSBuYW1lIG9mIHRoZSBtZXRob2QgdG8gaW52b2tlIG9yXG4gICAgICogIHRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsuLi4qfSBbYXJnXSBBcmd1bWVudHMgdG8gaW52b2tlIHRoZSBtZXRob2Qgd2l0aC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYSBuZXcgYXJyYXkgb2YgdGhlIHJlc3VsdHMgb2YgZWFjaCBpbnZva2VkIG1ldGhvZC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pbnZva2UoW1s1LCAxLCA3XSwgWzMsIDIsIDFdXSwgJ3NvcnQnKTtcbiAgICAgKiAvLyA9PiBbWzEsIDUsIDddLCBbMSwgMiwgM11dXG4gICAgICpcbiAgICAgKiBfLmludm9rZShbMTIzLCA0NTZdLCBTdHJpbmcucHJvdG90eXBlLnNwbGl0LCAnJyk7XG4gICAgICogLy8gPT4gW1snMScsICcyJywgJzMnXSwgWyc0JywgJzUnLCAnNiddXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGludm9rZShjb2xsZWN0aW9uLCBtZXRob2ROYW1lKSB7XG4gICAgICB2YXIgYXJncyA9IHNsaWNlKGFyZ3VtZW50cywgMiksXG4gICAgICAgICAgaW5kZXggPSAtMSxcbiAgICAgICAgICBpc0Z1bmMgPSB0eXBlb2YgbWV0aG9kTmFtZSA9PSAnZnVuY3Rpb24nLFxuICAgICAgICAgIGxlbmd0aCA9IGNvbGxlY3Rpb24gPyBjb2xsZWN0aW9uLmxlbmd0aCA6IDAsXG4gICAgICAgICAgcmVzdWx0ID0gQXJyYXkodHlwZW9mIGxlbmd0aCA9PSAnbnVtYmVyJyA/IGxlbmd0aCA6IDApO1xuXG4gICAgICBmb3JFYWNoKGNvbGxlY3Rpb24sIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIHJlc3VsdFsrK2luZGV4XSA9IChpc0Z1bmMgPyBtZXRob2ROYW1lIDogdmFsdWVbbWV0aG9kTmFtZV0pLmFwcGx5KHZhbHVlLCBhcmdzKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIHZhbHVlcyBieSBydW5uaW5nIGVhY2ggZWxlbWVudCBpbiB0aGUgY29sbGVjdGlvblxuICAgICAqIHRocm91Z2ggdGhlIGNhbGxiYWNrLiBUaGUgY2FsbGJhY2sgaXMgYm91bmQgdG8gYHRoaXNBcmdgIGFuZCBpbnZva2VkIHdpdGhcbiAgICAgKiB0aHJlZSBhcmd1bWVudHM7ICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYGNhbGxiYWNrYCB0aGUgY3JlYXRlZCBcIl8ucGx1Y2tcIiBzdHlsZVxuICAgICAqIGNhbGxiYWNrIHdpbGwgcmV0dXJuIHRoZSBwcm9wZXJ0eSB2YWx1ZSBvZiB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYGNhbGxiYWNrYCB0aGUgY3JlYXRlZCBcIl8ud2hlcmVcIiBzdHlsZSBjYWxsYmFja1xuICAgICAqIHdpbGwgcmV0dXJuIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBnaXZlbiBvYmplY3QsXG4gICAgICogZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGFsaWFzIGNvbGxlY3RcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvbnNcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW2NhbGxiYWNrPWlkZW50aXR5XSBUaGUgZnVuY3Rpb24gY2FsbGVkXG4gICAgICogIHBlciBpdGVyYXRpb24uIElmIGEgcHJvcGVydHkgbmFtZSBvciBvYmplY3QgaXMgcHJvdmlkZWQgaXQgd2lsbCBiZSB1c2VkXG4gICAgICogIHRvIGNyZWF0ZSBhIFwiXy5wbHVja1wiIG9yIFwiXy53aGVyZVwiIHN0eWxlIGNhbGxiYWNrLCByZXNwZWN0aXZlbHkuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBjYWxsYmFja2AuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGEgbmV3IGFycmF5IG9mIHRoZSByZXN1bHRzIG9mIGVhY2ggYGNhbGxiYWNrYCBleGVjdXRpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubWFwKFsxLCAyLCAzXSwgZnVuY3Rpb24obnVtKSB7IHJldHVybiBudW0gKiAzOyB9KTtcbiAgICAgKiAvLyA9PiBbMywgNiwgOV1cbiAgICAgKlxuICAgICAqIF8ubWFwKHsgJ29uZSc6IDEsICd0d28nOiAyLCAndGhyZWUnOiAzIH0sIGZ1bmN0aW9uKG51bSkgeyByZXR1cm4gbnVtICogMzsgfSk7XG4gICAgICogLy8gPT4gWzMsIDYsIDldIChwcm9wZXJ0eSBvcmRlciBpcyBub3QgZ3VhcmFudGVlZCBhY3Jvc3MgZW52aXJvbm1lbnRzKVxuICAgICAqXG4gICAgICogdmFyIGNoYXJhY3RlcnMgPSBbXG4gICAgICogICB7ICduYW1lJzogJ2Jhcm5leScsICdhZ2UnOiAzNiB9LFxuICAgICAqICAgeyAnbmFtZSc6ICdmcmVkJywgICAnYWdlJzogNDAgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiAvLyB1c2luZyBcIl8ucGx1Y2tcIiBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLm1hcChjaGFyYWN0ZXJzLCAnbmFtZScpO1xuICAgICAqIC8vID0+IFsnYmFybmV5JywgJ2ZyZWQnXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1hcChjb2xsZWN0aW9uLCBjYWxsYmFjaywgdGhpc0FyZykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gY29sbGVjdGlvbiA/IGNvbGxlY3Rpb24ubGVuZ3RoIDogMDtcblxuICAgICAgY2FsbGJhY2sgPSBsb2Rhc2guY3JlYXRlQ2FsbGJhY2soY2FsbGJhY2ssIHRoaXNBcmcsIDMpO1xuICAgICAgaWYgKHR5cGVvZiBsZW5ndGggPT0gJ251bWJlcicpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IEFycmF5KGxlbmd0aCk7XG4gICAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgICAgcmVzdWx0W2luZGV4XSA9IGNhbGxiYWNrKGNvbGxlY3Rpb25baW5kZXhdLCBpbmRleCwgY29sbGVjdGlvbik7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdCA9IFtdO1xuICAgICAgICBmb3JPd24oY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGtleSwgY29sbGVjdGlvbikge1xuICAgICAgICAgIHJlc3VsdFsrK2luZGV4XSA9IGNhbGxiYWNrKHZhbHVlLCBrZXksIGNvbGxlY3Rpb24pO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIHRoZSBtYXhpbXVtIHZhbHVlIG9mIGEgY29sbGVjdGlvbi4gSWYgdGhlIGNvbGxlY3Rpb24gaXMgZW1wdHkgb3JcbiAgICAgKiBmYWxzZXkgYC1JbmZpbml0eWAgaXMgcmV0dXJuZWQuIElmIGEgY2FsbGJhY2sgaXMgcHJvdmlkZWQgaXQgd2lsbCBiZSBleGVjdXRlZFxuICAgICAqIGZvciBlYWNoIHZhbHVlIGluIHRoZSBjb2xsZWN0aW9uIHRvIGdlbmVyYXRlIHRoZSBjcml0ZXJpb24gYnkgd2hpY2ggdGhlIHZhbHVlXG4gICAgICogaXMgcmFua2VkLiBUaGUgY2FsbGJhY2sgaXMgYm91bmQgdG8gYHRoaXNBcmdgIGFuZCBpbnZva2VkIHdpdGggdGhyZWVcbiAgICAgKiBhcmd1bWVudHM7ICh2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pLlxuICAgICAqXG4gICAgICogSWYgYSBwcm9wZXJ0eSBuYW1lIGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy5wbHVja1wiIHN0eWxlXG4gICAgICogY2FsbGJhY2sgd2lsbCByZXR1cm4gdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqXG4gICAgICogSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy53aGVyZVwiIHN0eWxlIGNhbGxiYWNrXG4gICAgICogd2lsbCByZXR1cm4gYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuIG9iamVjdCxcbiAgICAgKiBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvbnNcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW2NhbGxiYWNrPWlkZW50aXR5XSBUaGUgZnVuY3Rpb24gY2FsbGVkXG4gICAgICogIHBlciBpdGVyYXRpb24uIElmIGEgcHJvcGVydHkgbmFtZSBvciBvYmplY3QgaXMgcHJvdmlkZWQgaXQgd2lsbCBiZSB1c2VkXG4gICAgICogIHRvIGNyZWF0ZSBhIFwiXy5wbHVja1wiIG9yIFwiXy53aGVyZVwiIHN0eWxlIGNhbGxiYWNrLCByZXNwZWN0aXZlbHkuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBjYWxsYmFja2AuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG1heGltdW0gdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubWF4KFs0LCAyLCA4LCA2XSk7XG4gICAgICogLy8gPT4gOFxuICAgICAqXG4gICAgICogdmFyIGNoYXJhY3RlcnMgPSBbXG4gICAgICogICB7ICduYW1lJzogJ2Jhcm5leScsICdhZ2UnOiAzNiB9LFxuICAgICAqICAgeyAnbmFtZSc6ICdmcmVkJywgICAnYWdlJzogNDAgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLm1heChjaGFyYWN0ZXJzLCBmdW5jdGlvbihjaHIpIHsgcmV0dXJuIGNoci5hZ2U7IH0pO1xuICAgICAqIC8vID0+IHsgJ25hbWUnOiAnZnJlZCcsICdhZ2UnOiA0MCB9O1xuICAgICAqXG4gICAgICogLy8gdXNpbmcgXCJfLnBsdWNrXCIgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5tYXgoY2hhcmFjdGVycywgJ2FnZScpO1xuICAgICAqIC8vID0+IHsgJ25hbWUnOiAnZnJlZCcsICdhZ2UnOiA0MCB9O1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1heChjb2xsZWN0aW9uLCBjYWxsYmFjaywgdGhpc0FyZykge1xuICAgICAgdmFyIGNvbXB1dGVkID0gLUluZmluaXR5LFxuICAgICAgICAgIHJlc3VsdCA9IGNvbXB1dGVkO1xuXG4gICAgICAvLyBhbGxvd3Mgd29ya2luZyB3aXRoIGZ1bmN0aW9ucyBsaWtlIGBfLm1hcGAgd2l0aG91dCB1c2luZ1xuICAgICAgLy8gdGhlaXIgYGluZGV4YCBhcmd1bWVudCBhcyBhIGNhbGxiYWNrXG4gICAgICBpZiAodHlwZW9mIGNhbGxiYWNrICE9ICdmdW5jdGlvbicgJiYgdGhpc0FyZyAmJiB0aGlzQXJnW2NhbGxiYWNrXSA9PT0gY29sbGVjdGlvbikge1xuICAgICAgICBjYWxsYmFjayA9IG51bGw7XG4gICAgICB9XG4gICAgICBpZiAoY2FsbGJhY2sgPT0gbnVsbCAmJiBpc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgICAgbGVuZ3RoID0gY29sbGVjdGlvbi5sZW5ndGg7XG5cbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICB2YXIgdmFsdWUgPSBjb2xsZWN0aW9uW2luZGV4XTtcbiAgICAgICAgICBpZiAodmFsdWUgPiByZXN1bHQpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2FsbGJhY2sgPSAoY2FsbGJhY2sgPT0gbnVsbCAmJiBpc1N0cmluZyhjb2xsZWN0aW9uKSlcbiAgICAgICAgICA/IGNoYXJBdENhbGxiYWNrXG4gICAgICAgICAgOiBsb2Rhc2guY3JlYXRlQ2FsbGJhY2soY2FsbGJhY2ssIHRoaXNBcmcsIDMpO1xuXG4gICAgICAgIGZvckVhY2goY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgICAgdmFyIGN1cnJlbnQgPSBjYWxsYmFjayh2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pO1xuICAgICAgICAgIGlmIChjdXJyZW50ID4gY29tcHV0ZWQpIHtcbiAgICAgICAgICAgIGNvbXB1dGVkID0gY3VycmVudDtcbiAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyB0aGUgbWluaW11bSB2YWx1ZSBvZiBhIGNvbGxlY3Rpb24uIElmIHRoZSBjb2xsZWN0aW9uIGlzIGVtcHR5IG9yXG4gICAgICogZmFsc2V5IGBJbmZpbml0eWAgaXMgcmV0dXJuZWQuIElmIGEgY2FsbGJhY2sgaXMgcHJvdmlkZWQgaXQgd2lsbCBiZSBleGVjdXRlZFxuICAgICAqIGZvciBlYWNoIHZhbHVlIGluIHRoZSBjb2xsZWN0aW9uIHRvIGdlbmVyYXRlIHRoZSBjcml0ZXJpb24gYnkgd2hpY2ggdGhlIHZhbHVlXG4gICAgICogaXMgcmFua2VkLiBUaGUgY2FsbGJhY2sgaXMgYm91bmQgdG8gYHRoaXNBcmdgIGFuZCBpbnZva2VkIHdpdGggdGhyZWVcbiAgICAgKiBhcmd1bWVudHM7ICh2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pLlxuICAgICAqXG4gICAgICogSWYgYSBwcm9wZXJ0eSBuYW1lIGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy5wbHVja1wiIHN0eWxlXG4gICAgICogY2FsbGJhY2sgd2lsbCByZXR1cm4gdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqXG4gICAgICogSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy53aGVyZVwiIHN0eWxlIGNhbGxiYWNrXG4gICAgICogd2lsbCByZXR1cm4gYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuIG9iamVjdCxcbiAgICAgKiBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvbnNcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fHN0cmluZ30gW2NhbGxiYWNrPWlkZW50aXR5XSBUaGUgZnVuY3Rpb24gY2FsbGVkXG4gICAgICogIHBlciBpdGVyYXRpb24uIElmIGEgcHJvcGVydHkgbmFtZSBvciBvYmplY3QgaXMgcHJvdmlkZWQgaXQgd2lsbCBiZSB1c2VkXG4gICAgICogIHRvIGNyZWF0ZSBhIFwiXy5wbHVja1wiIG9yIFwiXy53aGVyZVwiIHN0eWxlIGNhbGxiYWNrLCByZXNwZWN0aXZlbHkuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBjYWxsYmFja2AuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG1pbmltdW0gdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubWluKFs0LCAyLCA4LCA2XSk7XG4gICAgICogLy8gPT4gMlxuICAgICAqXG4gICAgICogdmFyIGNoYXJhY3RlcnMgPSBbXG4gICAgICogICB7ICduYW1lJzogJ2Jhcm5leScsICdhZ2UnOiAzNiB9LFxuICAgICAqICAgeyAnbmFtZSc6ICdmcmVkJywgICAnYWdlJzogNDAgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLm1pbihjaGFyYWN0ZXJzLCBmdW5jdGlvbihjaHIpIHsgcmV0dXJuIGNoci5hZ2U7IH0pO1xuICAgICAqIC8vID0+IHsgJ25hbWUnOiAnYmFybmV5JywgJ2FnZSc6IDM2IH07XG4gICAgICpcbiAgICAgKiAvLyB1c2luZyBcIl8ucGx1Y2tcIiBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLm1pbihjaGFyYWN0ZXJzLCAnYWdlJyk7XG4gICAgICogLy8gPT4geyAnbmFtZSc6ICdiYXJuZXknLCAnYWdlJzogMzYgfTtcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtaW4oY29sbGVjdGlvbiwgY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICAgIHZhciBjb21wdXRlZCA9IEluZmluaXR5LFxuICAgICAgICAgIHJlc3VsdCA9IGNvbXB1dGVkO1xuXG4gICAgICAvLyBhbGxvd3Mgd29ya2luZyB3aXRoIGZ1bmN0aW9ucyBsaWtlIGBfLm1hcGAgd2l0aG91dCB1c2luZ1xuICAgICAgLy8gdGhlaXIgYGluZGV4YCBhcmd1bWVudCBhcyBhIGNhbGxiYWNrXG4gICAgICBpZiAodHlwZW9mIGNhbGxiYWNrICE9ICdmdW5jdGlvbicgJiYgdGhpc0FyZyAmJiB0aGlzQXJnW2NhbGxiYWNrXSA9PT0gY29sbGVjdGlvbikge1xuICAgICAgICBjYWxsYmFjayA9IG51bGw7XG4gICAgICB9XG4gICAgICBpZiAoY2FsbGJhY2sgPT0gbnVsbCAmJiBpc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgICAgbGVuZ3RoID0gY29sbGVjdGlvbi5sZW5ndGg7XG5cbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICB2YXIgdmFsdWUgPSBjb2xsZWN0aW9uW2luZGV4XTtcbiAgICAgICAgICBpZiAodmFsdWUgPCByZXN1bHQpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2FsbGJhY2sgPSAoY2FsbGJhY2sgPT0gbnVsbCAmJiBpc1N0cmluZyhjb2xsZWN0aW9uKSlcbiAgICAgICAgICA/IGNoYXJBdENhbGxiYWNrXG4gICAgICAgICAgOiBsb2Rhc2guY3JlYXRlQ2FsbGJhY2soY2FsbGJhY2ssIHRoaXNBcmcsIDMpO1xuXG4gICAgICAgIGZvckVhY2goY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgICAgdmFyIGN1cnJlbnQgPSBjYWxsYmFjayh2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pO1xuICAgICAgICAgIGlmIChjdXJyZW50IDwgY29tcHV0ZWQpIHtcbiAgICAgICAgICAgIGNvbXB1dGVkID0gY3VycmVudDtcbiAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyB0aGUgdmFsdWUgb2YgYSBzcGVjaWZpZWQgcHJvcGVydHkgZnJvbSBhbGwgZWxlbWVudHMgaW4gdGhlIGNvbGxlY3Rpb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAdHlwZSBGdW5jdGlvblxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uc1xuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHByb3BlcnR5IFRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eSB0byBwbHVjay5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYSBuZXcgYXJyYXkgb2YgcHJvcGVydHkgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgY2hhcmFjdGVycyA9IFtcbiAgICAgKiAgIHsgJ25hbWUnOiAnYmFybmV5JywgJ2FnZSc6IDM2IH0sXG4gICAgICogICB7ICduYW1lJzogJ2ZyZWQnLCAgICdhZ2UnOiA0MCB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8ucGx1Y2soY2hhcmFjdGVycywgJ25hbWUnKTtcbiAgICAgKiAvLyA9PiBbJ2Jhcm5leScsICdmcmVkJ11cbiAgICAgKi9cbiAgICB2YXIgcGx1Y2sgPSBtYXA7XG5cbiAgICAvKipcbiAgICAgKiBSZWR1Y2VzIGEgY29sbGVjdGlvbiB0byBhIHZhbHVlIHdoaWNoIGlzIHRoZSBhY2N1bXVsYXRlZCByZXN1bHQgb2YgcnVubmluZ1xuICAgICAqIGVhY2ggZWxlbWVudCBpbiB0aGUgY29sbGVjdGlvbiB0aHJvdWdoIHRoZSBjYWxsYmFjaywgd2hlcmUgZWFjaCBzdWNjZXNzaXZlXG4gICAgICogY2FsbGJhY2sgZXhlY3V0aW9uIGNvbnN1bWVzIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlIHByZXZpb3VzIGV4ZWN1dGlvbi4gSWZcbiAgICAgKiBgYWNjdW11bGF0b3JgIGlzIG5vdCBwcm92aWRlZCB0aGUgZmlyc3QgZWxlbWVudCBvZiB0aGUgY29sbGVjdGlvbiB3aWxsIGJlXG4gICAgICogdXNlZCBhcyB0aGUgaW5pdGlhbCBgYWNjdW11bGF0b3JgIHZhbHVlLiBUaGUgY2FsbGJhY2sgaXMgYm91bmQgdG8gYHRoaXNBcmdgXG4gICAgICogYW5kIGludm9rZWQgd2l0aCBmb3VyIGFyZ3VtZW50czsgKGFjY3VtdWxhdG9yLCB2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBhbGlhcyBmb2xkbCwgaW5qZWN0XG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25zXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY2FsbGJhY2s9aWRlbnRpdHldIFRoZSBmdW5jdGlvbiBjYWxsZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFthY2N1bXVsYXRvcl0gSW5pdGlhbCB2YWx1ZSBvZiB0aGUgYWNjdW11bGF0b3IuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBjYWxsYmFja2AuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGFjY3VtdWxhdGVkIHZhbHVlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgc3VtID0gXy5yZWR1Y2UoWzEsIDIsIDNdLCBmdW5jdGlvbihzdW0sIG51bSkge1xuICAgICAqICAgcmV0dXJuIHN1bSArIG51bTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiA2XG4gICAgICpcbiAgICAgKiB2YXIgbWFwcGVkID0gXy5yZWR1Y2UoeyAnYSc6IDEsICdiJzogMiwgJ2MnOiAzIH0sIGZ1bmN0aW9uKHJlc3VsdCwgbnVtLCBrZXkpIHtcbiAgICAgKiAgIHJlc3VsdFtrZXldID0gbnVtICogMztcbiAgICAgKiAgIHJldHVybiByZXN1bHQ7XG4gICAgICogfSwge30pO1xuICAgICAqIC8vID0+IHsgJ2EnOiAzLCAnYic6IDYsICdjJzogOSB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gcmVkdWNlKGNvbGxlY3Rpb24sIGNhbGxiYWNrLCBhY2N1bXVsYXRvciwgdGhpc0FyZykge1xuICAgICAgaWYgKCFjb2xsZWN0aW9uKSByZXR1cm4gYWNjdW11bGF0b3I7XG4gICAgICB2YXIgbm9hY2N1bSA9IGFyZ3VtZW50cy5sZW5ndGggPCAzO1xuICAgICAgY2FsbGJhY2sgPSBsb2Rhc2guY3JlYXRlQ2FsbGJhY2soY2FsbGJhY2ssIHRoaXNBcmcsIDQpO1xuXG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBjb2xsZWN0aW9uLmxlbmd0aDtcblxuICAgICAgaWYgKHR5cGVvZiBsZW5ndGggPT0gJ251bWJlcicpIHtcbiAgICAgICAgaWYgKG5vYWNjdW0pIHtcbiAgICAgICAgICBhY2N1bXVsYXRvciA9IGNvbGxlY3Rpb25bKytpbmRleF07XG4gICAgICAgIH1cbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICBhY2N1bXVsYXRvciA9IGNhbGxiYWNrKGFjY3VtdWxhdG9yLCBjb2xsZWN0aW9uW2luZGV4XSwgaW5kZXgsIGNvbGxlY3Rpb24pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBmb3JPd24oY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgICAgYWNjdW11bGF0b3IgPSBub2FjY3VtXG4gICAgICAgICAgICA/IChub2FjY3VtID0gZmFsc2UsIHZhbHVlKVxuICAgICAgICAgICAgOiBjYWxsYmFjayhhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnJlZHVjZWAgZXhjZXB0IHRoYXQgaXQgaXRlcmF0ZXMgb3ZlciBlbGVtZW50c1xuICAgICAqIG9mIGEgYGNvbGxlY3Rpb25gIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBhbGlhcyBmb2xkclxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uc1xuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2NhbGxiYWNrPWlkZW50aXR5XSBUaGUgZnVuY3Rpb24gY2FsbGVkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbYWNjdW11bGF0b3JdIEluaXRpYWwgdmFsdWUgb2YgdGhlIGFjY3VtdWxhdG9yLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY2FsbGJhY2tgLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBhY2N1bXVsYXRlZCB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGxpc3QgPSBbWzAsIDFdLCBbMiwgM10sIFs0LCA1XV07XG4gICAgICogdmFyIGZsYXQgPSBfLnJlZHVjZVJpZ2h0KGxpc3QsIGZ1bmN0aW9uKGEsIGIpIHsgcmV0dXJuIGEuY29uY2F0KGIpOyB9LCBbXSk7XG4gICAgICogLy8gPT4gWzQsIDUsIDIsIDMsIDAsIDFdXG4gICAgICovXG4gICAgZnVuY3Rpb24gcmVkdWNlUmlnaHQoY29sbGVjdGlvbiwgY2FsbGJhY2ssIGFjY3VtdWxhdG9yLCB0aGlzQXJnKSB7XG4gICAgICB2YXIgbm9hY2N1bSA9IGFyZ3VtZW50cy5sZW5ndGggPCAzO1xuICAgICAgY2FsbGJhY2sgPSBsb2Rhc2guY3JlYXRlQ2FsbGJhY2soY2FsbGJhY2ssIHRoaXNBcmcsIDQpO1xuICAgICAgZm9yRWFjaFJpZ2h0KGNvbGxlY3Rpb24sIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikge1xuICAgICAgICBhY2N1bXVsYXRvciA9IG5vYWNjdW1cbiAgICAgICAgICA/IChub2FjY3VtID0gZmFsc2UsIHZhbHVlKVxuICAgICAgICAgIDogY2FsbGJhY2soYWNjdW11bGF0b3IsIHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbik7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb3Bwb3NpdGUgb2YgYF8uZmlsdGVyYCB0aGlzIG1ldGhvZCByZXR1cm5zIHRoZSBlbGVtZW50cyBvZiBhXG4gICAgICogY29sbGVjdGlvbiB0aGF0IHRoZSBjYWxsYmFjayBkb2VzICoqbm90KiogcmV0dXJuIHRydWV5IGZvci5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYGNhbGxiYWNrYCB0aGUgY3JlYXRlZCBcIl8ucGx1Y2tcIiBzdHlsZVxuICAgICAqIGNhbGxiYWNrIHdpbGwgcmV0dXJuIHRoZSBwcm9wZXJ0eSB2YWx1ZSBvZiB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYGNhbGxiYWNrYCB0aGUgY3JlYXRlZCBcIl8ud2hlcmVcIiBzdHlsZSBjYWxsYmFja1xuICAgICAqIHdpbGwgcmV0dXJuIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBnaXZlbiBvYmplY3QsXG4gICAgICogZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25zXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtjYWxsYmFjaz1pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGNhbGxlZFxuICAgICAqICBwZXIgaXRlcmF0aW9uLiBJZiBhIHByb3BlcnR5IG5hbWUgb3Igb2JqZWN0IGlzIHByb3ZpZGVkIGl0IHdpbGwgYmUgdXNlZFxuICAgICAqICB0byBjcmVhdGUgYSBcIl8ucGx1Y2tcIiBvciBcIl8ud2hlcmVcIiBzdHlsZSBjYWxsYmFjaywgcmVzcGVjdGl2ZWx5LlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY2FsbGJhY2tgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBhIG5ldyBhcnJheSBvZiBlbGVtZW50cyB0aGF0IGZhaWxlZCB0aGUgY2FsbGJhY2sgY2hlY2suXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvZGRzID0gXy5yZWplY3QoWzEsIDIsIDMsIDQsIDUsIDZdLCBmdW5jdGlvbihudW0pIHsgcmV0dXJuIG51bSAlIDIgPT0gMDsgfSk7XG4gICAgICogLy8gPT4gWzEsIDMsIDVdXG4gICAgICpcbiAgICAgKiB2YXIgY2hhcmFjdGVycyA9IFtcbiAgICAgKiAgIHsgJ25hbWUnOiAnYmFybmV5JywgJ2FnZSc6IDM2LCAnYmxvY2tlZCc6IGZhbHNlIH0sXG4gICAgICogICB7ICduYW1lJzogJ2ZyZWQnLCAgICdhZ2UnOiA0MCwgJ2Jsb2NrZWQnOiB0cnVlIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogLy8gdXNpbmcgXCJfLnBsdWNrXCIgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5yZWplY3QoY2hhcmFjdGVycywgJ2Jsb2NrZWQnKTtcbiAgICAgKiAvLyA9PiBbeyAnbmFtZSc6ICdiYXJuZXknLCAnYWdlJzogMzYsICdibG9ja2VkJzogZmFsc2UgfV1cbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIFwiXy53aGVyZVwiIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8ucmVqZWN0KGNoYXJhY3RlcnMsIHsgJ2FnZSc6IDM2IH0pO1xuICAgICAqIC8vID0+IFt7ICduYW1lJzogJ2ZyZWQnLCAnYWdlJzogNDAsICdibG9ja2VkJzogdHJ1ZSB9XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJlamVjdChjb2xsZWN0aW9uLCBjYWxsYmFjaywgdGhpc0FyZykge1xuICAgICAgY2FsbGJhY2sgPSBsb2Rhc2guY3JlYXRlQ2FsbGJhY2soY2FsbGJhY2ssIHRoaXNBcmcsIDMpO1xuICAgICAgcmV0dXJuIGZpbHRlcihjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgcmV0dXJuICFjYWxsYmFjayh2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIGEgcmFuZG9tIGVsZW1lbnQgb3IgYG5gIHJhbmRvbSBlbGVtZW50cyBmcm9tIGEgY29sbGVjdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uc1xuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBzYW1wbGUuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtuXSBUaGUgbnVtYmVyIG9mIGVsZW1lbnRzIHRvIHNhbXBsZS5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gQWxsb3dzIHdvcmtpbmcgd2l0aCBmdW5jdGlvbnMgbGlrZSBgXy5tYXBgXG4gICAgICogIHdpdGhvdXQgdXNpbmcgdGhlaXIgYGluZGV4YCBhcmd1bWVudHMgYXMgYG5gLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgcmFuZG9tIHNhbXBsZShzKSBvZiBgY29sbGVjdGlvbmAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc2FtcGxlKFsxLCAyLCAzLCA0XSk7XG4gICAgICogLy8gPT4gMlxuICAgICAqXG4gICAgICogXy5zYW1wbGUoWzEsIDIsIDMsIDRdLCAyKTtcbiAgICAgKiAvLyA9PiBbMywgMV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzYW1wbGUoY29sbGVjdGlvbiwgbiwgZ3VhcmQpIHtcbiAgICAgIGlmIChjb2xsZWN0aW9uICYmIHR5cGVvZiBjb2xsZWN0aW9uLmxlbmd0aCAhPSAnbnVtYmVyJykge1xuICAgICAgICBjb2xsZWN0aW9uID0gdmFsdWVzKGNvbGxlY3Rpb24pO1xuICAgICAgfVxuICAgICAgaWYgKG4gPT0gbnVsbCB8fCBndWFyZCkge1xuICAgICAgICByZXR1cm4gY29sbGVjdGlvbiA/IGNvbGxlY3Rpb25bYmFzZVJhbmRvbSgwLCBjb2xsZWN0aW9uLmxlbmd0aCAtIDEpXSA6IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHZhciByZXN1bHQgPSBzaHVmZmxlKGNvbGxlY3Rpb24pO1xuICAgICAgcmVzdWx0Lmxlbmd0aCA9IG5hdGl2ZU1pbihuYXRpdmVNYXgoMCwgbiksIHJlc3VsdC5sZW5ndGgpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIHNodWZmbGVkIHZhbHVlcywgdXNpbmcgYSB2ZXJzaW9uIG9mIHRoZSBGaXNoZXItWWF0ZXNcbiAgICAgKiBzaHVmZmxlLiBTZWUgaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9GaXNoZXItWWF0ZXNfc2h1ZmZsZS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uc1xuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBzaHVmZmxlLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBhIG5ldyBzaHVmZmxlZCBjb2xsZWN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNodWZmbGUoWzEsIDIsIDMsIDQsIDUsIDZdKTtcbiAgICAgKiAvLyA9PiBbNCwgMSwgNiwgMywgNSwgMl1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzaHVmZmxlKGNvbGxlY3Rpb24pIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGNvbGxlY3Rpb24gPyBjb2xsZWN0aW9uLmxlbmd0aCA6IDAsXG4gICAgICAgICAgcmVzdWx0ID0gQXJyYXkodHlwZW9mIGxlbmd0aCA9PSAnbnVtYmVyJyA/IGxlbmd0aCA6IDApO1xuXG4gICAgICBmb3JFYWNoKGNvbGxlY3Rpb24sIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIHZhciByYW5kID0gYmFzZVJhbmRvbSgwLCArK2luZGV4KTtcbiAgICAgICAgcmVzdWx0W2luZGV4XSA9IHJlc3VsdFtyYW5kXTtcbiAgICAgICAgcmVzdWx0W3JhbmRdID0gdmFsdWU7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgc2l6ZSBvZiB0aGUgYGNvbGxlY3Rpb25gIGJ5IHJldHVybmluZyBgY29sbGVjdGlvbi5sZW5ndGhgIGZvciBhcnJheXNcbiAgICAgKiBhbmQgYXJyYXktbGlrZSBvYmplY3RzIG9yIHRoZSBudW1iZXIgb2Ygb3duIGVudW1lcmFibGUgcHJvcGVydGllcyBmb3Igb2JqZWN0cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uc1xuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpbnNwZWN0LlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgYGNvbGxlY3Rpb24ubGVuZ3RoYCBvciBudW1iZXIgb2Ygb3duIGVudW1lcmFibGUgcHJvcGVydGllcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zaXplKFsxLCAyXSk7XG4gICAgICogLy8gPT4gMlxuICAgICAqXG4gICAgICogXy5zaXplKHsgJ29uZSc6IDEsICd0d28nOiAyLCAndGhyZWUnOiAzIH0pO1xuICAgICAqIC8vID0+IDNcbiAgICAgKlxuICAgICAqIF8uc2l6ZSgncGViYmxlcycpO1xuICAgICAqIC8vID0+IDdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzaXplKGNvbGxlY3Rpb24pIHtcbiAgICAgIHZhciBsZW5ndGggPSBjb2xsZWN0aW9uID8gY29sbGVjdGlvbi5sZW5ndGggOiAwO1xuICAgICAgcmV0dXJuIHR5cGVvZiBsZW5ndGggPT0gJ251bWJlcicgPyBsZW5ndGggOiBrZXlzKGNvbGxlY3Rpb24pLmxlbmd0aDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgdGhlIGNhbGxiYWNrIHJldHVybnMgYSB0cnVleSB2YWx1ZSBmb3IgKiphbnkqKiBlbGVtZW50IG9mIGFcbiAgICAgKiBjb2xsZWN0aW9uLiBUaGUgZnVuY3Rpb24gcmV0dXJucyBhcyBzb29uIGFzIGl0IGZpbmRzIGEgcGFzc2luZyB2YWx1ZSBhbmRcbiAgICAgKiBkb2VzIG5vdCBpdGVyYXRlIG92ZXIgdGhlIGVudGlyZSBjb2xsZWN0aW9uLiBUaGUgY2FsbGJhY2sgaXMgYm91bmQgdG9cbiAgICAgKiBgdGhpc0FyZ2AgYW5kIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM7ICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYGNhbGxiYWNrYCB0aGUgY3JlYXRlZCBcIl8ucGx1Y2tcIiBzdHlsZVxuICAgICAqIGNhbGxiYWNrIHdpbGwgcmV0dXJuIHRoZSBwcm9wZXJ0eSB2YWx1ZSBvZiB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYGNhbGxiYWNrYCB0aGUgY3JlYXRlZCBcIl8ud2hlcmVcIiBzdHlsZSBjYWxsYmFja1xuICAgICAqIHdpbGwgcmV0dXJuIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBnaXZlbiBvYmplY3QsXG4gICAgICogZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGFsaWFzIGFueVxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uc1xuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbY2FsbGJhY2s9aWRlbnRpdHldIFRoZSBmdW5jdGlvbiBjYWxsZWRcbiAgICAgKiAgcGVyIGl0ZXJhdGlvbi4gSWYgYSBwcm9wZXJ0eSBuYW1lIG9yIG9iamVjdCBpcyBwcm92aWRlZCBpdCB3aWxsIGJlIHVzZWRcbiAgICAgKiAgdG8gY3JlYXRlIGEgXCJfLnBsdWNrXCIgb3IgXCJfLndoZXJlXCIgc3R5bGUgY2FsbGJhY2ssIHJlc3BlY3RpdmVseS5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGNhbGxiYWNrYC5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYW55IGVsZW1lbnQgcGFzc2VkIHRoZSBjYWxsYmFjayBjaGVjayxcbiAgICAgKiAgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNvbWUoW251bGwsIDAsICd5ZXMnLCBmYWxzZV0sIEJvb2xlYW4pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIHZhciBjaGFyYWN0ZXJzID0gW1xuICAgICAqICAgeyAnbmFtZSc6ICdiYXJuZXknLCAnYWdlJzogMzYsICdibG9ja2VkJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ25hbWUnOiAnZnJlZCcsICAgJ2FnZSc6IDQwLCAnYmxvY2tlZCc6IHRydWUgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiAvLyB1c2luZyBcIl8ucGx1Y2tcIiBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLnNvbWUoY2hhcmFjdGVycywgJ2Jsb2NrZWQnKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyBcIl8ud2hlcmVcIiBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLnNvbWUoY2hhcmFjdGVycywgeyAnYWdlJzogMSB9KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNvbWUoY29sbGVjdGlvbiwgY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICAgIHZhciByZXN1bHQ7XG4gICAgICBjYWxsYmFjayA9IGxvZGFzaC5jcmVhdGVDYWxsYmFjayhjYWxsYmFjaywgdGhpc0FyZywgMyk7XG5cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGNvbGxlY3Rpb24gPyBjb2xsZWN0aW9uLmxlbmd0aCA6IDA7XG5cbiAgICAgIGlmICh0eXBlb2YgbGVuZ3RoID09ICdudW1iZXInKSB7XG4gICAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgICAgaWYgKChyZXN1bHQgPSBjYWxsYmFjayhjb2xsZWN0aW9uW2luZGV4XSwgaW5kZXgsIGNvbGxlY3Rpb24pKSkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBmb3JPd24oY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgICAgcmV0dXJuICEocmVzdWx0ID0gY2FsbGJhY2sodmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuICEhcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgZWxlbWVudHMsIHNvcnRlZCBpbiBhc2NlbmRpbmcgb3JkZXIgYnkgdGhlIHJlc3VsdHMgb2ZcbiAgICAgKiBydW5uaW5nIGVhY2ggZWxlbWVudCBpbiBhIGNvbGxlY3Rpb24gdGhyb3VnaCB0aGUgY2FsbGJhY2suIFRoaXMgbWV0aG9kXG4gICAgICogcGVyZm9ybXMgYSBzdGFibGUgc29ydCwgdGhhdCBpcywgaXQgd2lsbCBwcmVzZXJ2ZSB0aGUgb3JpZ2luYWwgc29ydCBvcmRlclxuICAgICAqIG9mIGVxdWFsIGVsZW1lbnRzLiBUaGUgY2FsbGJhY2sgaXMgYm91bmQgdG8gYHRoaXNBcmdgIGFuZCBpbnZva2VkIHdpdGhcbiAgICAgKiB0aHJlZSBhcmd1bWVudHM7ICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYGNhbGxiYWNrYCB0aGUgY3JlYXRlZCBcIl8ucGx1Y2tcIiBzdHlsZVxuICAgICAqIGNhbGxiYWNrIHdpbGwgcmV0dXJuIHRoZSBwcm9wZXJ0eSB2YWx1ZSBvZiB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIElmIGFuIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzIGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjb2xsZWN0aW9uXG4gICAgICogd2lsbCBiZSBzb3J0ZWQgYnkgZWFjaCBwcm9wZXJ0eSB2YWx1ZS5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYGNhbGxiYWNrYCB0aGUgY3JlYXRlZCBcIl8ud2hlcmVcIiBzdHlsZSBjYWxsYmFja1xuICAgICAqIHdpbGwgcmV0dXJuIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBnaXZlbiBvYmplY3QsXG4gICAgICogZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25zXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0FycmF5fEZ1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtjYWxsYmFjaz1pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGNhbGxlZFxuICAgICAqICBwZXIgaXRlcmF0aW9uLiBJZiBhIHByb3BlcnR5IG5hbWUgb3Igb2JqZWN0IGlzIHByb3ZpZGVkIGl0IHdpbGwgYmUgdXNlZFxuICAgICAqICB0byBjcmVhdGUgYSBcIl8ucGx1Y2tcIiBvciBcIl8ud2hlcmVcIiBzdHlsZSBjYWxsYmFjaywgcmVzcGVjdGl2ZWx5LlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY2FsbGJhY2tgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBhIG5ldyBhcnJheSBvZiBzb3J0ZWQgZWxlbWVudHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc29ydEJ5KFsxLCAyLCAzXSwgZnVuY3Rpb24obnVtKSB7IHJldHVybiBNYXRoLnNpbihudW0pOyB9KTtcbiAgICAgKiAvLyA9PiBbMywgMSwgMl1cbiAgICAgKlxuICAgICAqIF8uc29ydEJ5KFsxLCAyLCAzXSwgZnVuY3Rpb24obnVtKSB7IHJldHVybiB0aGlzLnNpbihudW0pOyB9LCBNYXRoKTtcbiAgICAgKiAvLyA9PiBbMywgMSwgMl1cbiAgICAgKlxuICAgICAqIHZhciBjaGFyYWN0ZXJzID0gW1xuICAgICAqICAgeyAnbmFtZSc6ICdiYXJuZXknLCAgJ2FnZSc6IDM2IH0sXG4gICAgICogICB7ICduYW1lJzogJ2ZyZWQnLCAgICAnYWdlJzogNDAgfSxcbiAgICAgKiAgIHsgJ25hbWUnOiAnYmFybmV5JywgICdhZ2UnOiAyNiB9LFxuICAgICAqICAgeyAnbmFtZSc6ICdmcmVkJywgICAgJ2FnZSc6IDMwIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogLy8gdXNpbmcgXCJfLnBsdWNrXCIgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5tYXAoXy5zb3J0QnkoY2hhcmFjdGVycywgJ2FnZScpLCBfLnZhbHVlcyk7XG4gICAgICogLy8gPT4gW1snYmFybmV5JywgMjZdLCBbJ2ZyZWQnLCAzMF0sIFsnYmFybmV5JywgMzZdLCBbJ2ZyZWQnLCA0MF1dXG4gICAgICpcbiAgICAgKiAvLyBzb3J0aW5nIGJ5IG11bHRpcGxlIHByb3BlcnRpZXNcbiAgICAgKiBfLm1hcChfLnNvcnRCeShjaGFyYWN0ZXJzLCBbJ25hbWUnLCAnYWdlJ10pLCBfLnZhbHVlcyk7XG4gICAgICogLy8gPSA+IFtbJ2Jhcm5leScsIDI2XSwgWydiYXJuZXknLCAzNl0sIFsnZnJlZCcsIDMwXSwgWydmcmVkJywgNDBdXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNvcnRCeShjb2xsZWN0aW9uLCBjYWxsYmFjaywgdGhpc0FyZykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgaXNBcnIgPSBpc0FycmF5KGNhbGxiYWNrKSxcbiAgICAgICAgICBsZW5ndGggPSBjb2xsZWN0aW9uID8gY29sbGVjdGlvbi5sZW5ndGggOiAwLFxuICAgICAgICAgIHJlc3VsdCA9IEFycmF5KHR5cGVvZiBsZW5ndGggPT0gJ251bWJlcicgPyBsZW5ndGggOiAwKTtcblxuICAgICAgaWYgKCFpc0Fycikge1xuICAgICAgICBjYWxsYmFjayA9IGxvZGFzaC5jcmVhdGVDYWxsYmFjayhjYWxsYmFjaywgdGhpc0FyZywgMyk7XG4gICAgICB9XG4gICAgICBmb3JFYWNoKGNvbGxlY3Rpb24sIGZ1bmN0aW9uKHZhbHVlLCBrZXksIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgdmFyIG9iamVjdCA9IHJlc3VsdFsrK2luZGV4XSA9IGdldE9iamVjdCgpO1xuICAgICAgICBpZiAoaXNBcnIpIHtcbiAgICAgICAgICBvYmplY3QuY3JpdGVyaWEgPSBtYXAoY2FsbGJhY2ssIGZ1bmN0aW9uKGtleSkgeyByZXR1cm4gdmFsdWVba2V5XTsgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgKG9iamVjdC5jcml0ZXJpYSA9IGdldEFycmF5KCkpWzBdID0gY2FsbGJhY2sodmFsdWUsIGtleSwgY29sbGVjdGlvbik7XG4gICAgICAgIH1cbiAgICAgICAgb2JqZWN0LmluZGV4ID0gaW5kZXg7XG4gICAgICAgIG9iamVjdC52YWx1ZSA9IHZhbHVlO1xuICAgICAgfSk7XG5cbiAgICAgIGxlbmd0aCA9IHJlc3VsdC5sZW5ndGg7XG4gICAgICByZXN1bHQuc29ydChjb21wYXJlQXNjZW5kaW5nKTtcbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICB2YXIgb2JqZWN0ID0gcmVzdWx0W2xlbmd0aF07XG4gICAgICAgIHJlc3VsdFtsZW5ndGhdID0gb2JqZWN0LnZhbHVlO1xuICAgICAgICBpZiAoIWlzQXJyKSB7XG4gICAgICAgICAgcmVsZWFzZUFycmF5KG9iamVjdC5jcml0ZXJpYSk7XG4gICAgICAgIH1cbiAgICAgICAgcmVsZWFzZU9iamVjdChvYmplY3QpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyB0aGUgYGNvbGxlY3Rpb25gIHRvIGFuIGFycmF5LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25zXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgY29udmVydGVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAoZnVuY3Rpb24oKSB7IHJldHVybiBfLnRvQXJyYXkoYXJndW1lbnRzKS5zbGljZSgxKTsgfSkoMSwgMiwgMywgNCk7XG4gICAgICogLy8gPT4gWzIsIDMsIDRdXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9BcnJheShjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoY29sbGVjdGlvbiAmJiB0eXBlb2YgY29sbGVjdGlvbi5sZW5ndGggPT0gJ251bWJlcicpIHtcbiAgICAgICAgcmV0dXJuIHNsaWNlKGNvbGxlY3Rpb24pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHZhbHVlcyhjb2xsZWN0aW9uKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQZXJmb3JtcyBhIGRlZXAgY29tcGFyaXNvbiBvZiBlYWNoIGVsZW1lbnQgaW4gYSBgY29sbGVjdGlvbmAgdG8gdGhlIGdpdmVuXG4gICAgICogYHByb3BlcnRpZXNgIG9iamVjdCwgcmV0dXJuaW5nIGFuIGFycmF5IG9mIGFsbCBlbGVtZW50cyB0aGF0IGhhdmUgZXF1aXZhbGVudFxuICAgICAqIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEB0eXBlIEZ1bmN0aW9uXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25zXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcHJvcHMgVGhlIG9iamVjdCBvZiBwcm9wZXJ0eSB2YWx1ZXMgdG8gZmlsdGVyIGJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBhIG5ldyBhcnJheSBvZiBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIGdpdmVuIHByb3BlcnRpZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBjaGFyYWN0ZXJzID0gW1xuICAgICAqICAgeyAnbmFtZSc6ICdiYXJuZXknLCAnYWdlJzogMzYsICdwZXRzJzogWydob3BweSddIH0sXG4gICAgICogICB7ICduYW1lJzogJ2ZyZWQnLCAgICdhZ2UnOiA0MCwgJ3BldHMnOiBbJ2JhYnkgcHVzcycsICdkaW5vJ10gfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLndoZXJlKGNoYXJhY3RlcnMsIHsgJ2FnZSc6IDM2IH0pO1xuICAgICAqIC8vID0+IFt7ICduYW1lJzogJ2Jhcm5leScsICdhZ2UnOiAzNiwgJ3BldHMnOiBbJ2hvcHB5J10gfV1cbiAgICAgKlxuICAgICAqIF8ud2hlcmUoY2hhcmFjdGVycywgeyAncGV0cyc6IFsnZGlubyddIH0pO1xuICAgICAqIC8vID0+IFt7ICduYW1lJzogJ2ZyZWQnLCAnYWdlJzogNDAsICdwZXRzJzogWydiYWJ5IHB1c3MnLCAnZGlubyddIH1dXG4gICAgICovXG4gICAgdmFyIHdoZXJlID0gZmlsdGVyO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IHdpdGggYWxsIGZhbHNleSB2YWx1ZXMgcmVtb3ZlZC4gVGhlIHZhbHVlcyBgZmFsc2VgLCBgbnVsbGAsXG4gICAgICogYDBgLCBgXCJcImAsIGB1bmRlZmluZWRgLCBhbmQgYE5hTmAgYXJlIGFsbCBmYWxzZXkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlzXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGNvbXBhY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGEgbmV3IGFycmF5IG9mIGZpbHRlcmVkIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5jb21wYWN0KFswLCAxLCBmYWxzZSwgMiwgJycsIDNdKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb21wYWN0KGFycmF5KSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDAsXG4gICAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XTtcbiAgICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgICAgcmVzdWx0LnB1c2godmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgZXhjbHVkaW5nIGFsbCB2YWx1ZXMgb2YgdGhlIHByb3ZpZGVkIGFycmF5cyB1c2luZyBzdHJpY3RcbiAgICAgKiBlcXVhbGl0eSBmb3IgY29tcGFyaXNvbnMsIGkuZS4gYD09PWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlzXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHByb2Nlc3MuXG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW3ZhbHVlc10gVGhlIGFycmF5cyBvZiB2YWx1ZXMgdG8gZXhjbHVkZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYSBuZXcgYXJyYXkgb2YgZmlsdGVyZWQgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRpZmZlcmVuY2UoWzEsIDIsIDMsIDQsIDVdLCBbNSwgMiwgMTBdKTtcbiAgICAgKiAvLyA9PiBbMSwgMywgNF1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBkaWZmZXJlbmNlKGFycmF5KSB7XG4gICAgICByZXR1cm4gYmFzZURpZmZlcmVuY2UoYXJyYXksIGJhc2VGbGF0dGVuKGFyZ3VtZW50cywgdHJ1ZSwgdHJ1ZSwgMSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZmluZGAgZXhjZXB0IHRoYXQgaXQgcmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIGZpcnN0XG4gICAgICogZWxlbWVudCB0aGF0IHBhc3NlcyB0aGUgY2FsbGJhY2sgY2hlY2ssIGluc3RlYWQgb2YgdGhlIGVsZW1lbnQgaXRzZWxmLlxuICAgICAqXG4gICAgICogSWYgYSBwcm9wZXJ0eSBuYW1lIGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy5wbHVja1wiIHN0eWxlXG4gICAgICogY2FsbGJhY2sgd2lsbCByZXR1cm4gdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqXG4gICAgICogSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy53aGVyZVwiIHN0eWxlIGNhbGxiYWNrXG4gICAgICogd2lsbCByZXR1cm4gYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuIG9iamVjdCxcbiAgICAgKiBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlzXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNlYXJjaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtjYWxsYmFjaz1pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGNhbGxlZFxuICAgICAqICBwZXIgaXRlcmF0aW9uLiBJZiBhIHByb3BlcnR5IG5hbWUgb3Igb2JqZWN0IGlzIHByb3ZpZGVkIGl0IHdpbGwgYmUgdXNlZFxuICAgICAqICB0byBjcmVhdGUgYSBcIl8ucGx1Y2tcIiBvciBcIl8ud2hlcmVcIiBzdHlsZSBjYWxsYmFjaywgcmVzcGVjdGl2ZWx5LlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY2FsbGJhY2tgLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBmb3VuZCBlbGVtZW50LCBlbHNlIGAtMWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBjaGFyYWN0ZXJzID0gW1xuICAgICAqICAgeyAnbmFtZSc6ICdiYXJuZXknLCAgJ2FnZSc6IDM2LCAnYmxvY2tlZCc6IGZhbHNlIH0sXG4gICAgICogICB7ICduYW1lJzogJ2ZyZWQnLCAgICAnYWdlJzogNDAsICdibG9ja2VkJzogdHJ1ZSB9LFxuICAgICAqICAgeyAnbmFtZSc6ICdwZWJibGVzJywgJ2FnZSc6IDEsICAnYmxvY2tlZCc6IGZhbHNlIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5maW5kSW5kZXgoY2hhcmFjdGVycywgZnVuY3Rpb24oY2hyKSB7XG4gICAgICogICByZXR1cm4gY2hyLmFnZSA8IDIwO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IDJcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIFwiXy53aGVyZVwiIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8uZmluZEluZGV4KGNoYXJhY3RlcnMsIHsgJ2FnZSc6IDM2IH0pO1xuICAgICAqIC8vID0+IDBcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIFwiXy5wbHVja1wiIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8uZmluZEluZGV4KGNoYXJhY3RlcnMsICdibG9ja2VkJyk7XG4gICAgICogLy8gPT4gMVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZpbmRJbmRleChhcnJheSwgY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5ID8gYXJyYXkubGVuZ3RoIDogMDtcblxuICAgICAgY2FsbGJhY2sgPSBsb2Rhc2guY3JlYXRlQ2FsbGJhY2soY2FsbGJhY2ssIHRoaXNBcmcsIDMpO1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrKGFycmF5W2luZGV4XSwgaW5kZXgsIGFycmF5KSkge1xuICAgICAgICAgIHJldHVybiBpbmRleDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIC0xO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZmluZEluZGV4YCBleGNlcHQgdGhhdCBpdCBpdGVyYXRlcyBvdmVyIGVsZW1lbnRzXG4gICAgICogb2YgYSBgY29sbGVjdGlvbmAgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgICAqXG4gICAgICogSWYgYSBwcm9wZXJ0eSBuYW1lIGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy5wbHVja1wiIHN0eWxlXG4gICAgICogY2FsbGJhY2sgd2lsbCByZXR1cm4gdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqXG4gICAgICogSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy53aGVyZVwiIHN0eWxlIGNhbGxiYWNrXG4gICAgICogd2lsbCByZXR1cm4gYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuIG9iamVjdCxcbiAgICAgKiBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlzXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNlYXJjaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtjYWxsYmFjaz1pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGNhbGxlZFxuICAgICAqICBwZXIgaXRlcmF0aW9uLiBJZiBhIHByb3BlcnR5IG5hbWUgb3Igb2JqZWN0IGlzIHByb3ZpZGVkIGl0IHdpbGwgYmUgdXNlZFxuICAgICAqICB0byBjcmVhdGUgYSBcIl8ucGx1Y2tcIiBvciBcIl8ud2hlcmVcIiBzdHlsZSBjYWxsYmFjaywgcmVzcGVjdGl2ZWx5LlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY2FsbGJhY2tgLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBmb3VuZCBlbGVtZW50LCBlbHNlIGAtMWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBjaGFyYWN0ZXJzID0gW1xuICAgICAqICAgeyAnbmFtZSc6ICdiYXJuZXknLCAgJ2FnZSc6IDM2LCAnYmxvY2tlZCc6IHRydWUgfSxcbiAgICAgKiAgIHsgJ25hbWUnOiAnZnJlZCcsICAgICdhZ2UnOiA0MCwgJ2Jsb2NrZWQnOiBmYWxzZSB9LFxuICAgICAqICAgeyAnbmFtZSc6ICdwZWJibGVzJywgJ2FnZSc6IDEsICAnYmxvY2tlZCc6IHRydWUgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLmZpbmRMYXN0SW5kZXgoY2hhcmFjdGVycywgZnVuY3Rpb24oY2hyKSB7XG4gICAgICogICByZXR1cm4gY2hyLmFnZSA+IDMwO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IDFcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIFwiXy53aGVyZVwiIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8uZmluZExhc3RJbmRleChjaGFyYWN0ZXJzLCB7ICdhZ2UnOiAzNiB9KTtcbiAgICAgKiAvLyA9PiAwXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyBcIl8ucGx1Y2tcIiBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLmZpbmRMYXN0SW5kZXgoY2hhcmFjdGVycywgJ2Jsb2NrZWQnKTtcbiAgICAgKiAvLyA9PiAyXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmluZExhc3RJbmRleChhcnJheSwgY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDA7XG4gICAgICBjYWxsYmFjayA9IGxvZGFzaC5jcmVhdGVDYWxsYmFjayhjYWxsYmFjaywgdGhpc0FyZywgMyk7XG4gICAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrKGFycmF5W2xlbmd0aF0sIGxlbmd0aCwgYXJyYXkpKSB7XG4gICAgICAgICAgcmV0dXJuIGxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIC0xO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGZpcnN0IGVsZW1lbnQgb3IgZmlyc3QgYG5gIGVsZW1lbnRzIG9mIGFuIGFycmF5LiBJZiBhIGNhbGxiYWNrXG4gICAgICogaXMgcHJvdmlkZWQgZWxlbWVudHMgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgYXJyYXkgYXJlIHJldHVybmVkIGFzIGxvbmdcbiAgICAgKiBhcyB0aGUgY2FsbGJhY2sgcmV0dXJucyB0cnVleS4gVGhlIGNhbGxiYWNrIGlzIGJvdW5kIHRvIGB0aGlzQXJnYCBhbmRcbiAgICAgKiBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzOyAodmFsdWUsIGluZGV4LCBhcnJheSkuXG4gICAgICpcbiAgICAgKiBJZiBhIHByb3BlcnR5IG5hbWUgaXMgcHJvdmlkZWQgZm9yIGBjYWxsYmFja2AgdGhlIGNyZWF0ZWQgXCJfLnBsdWNrXCIgc3R5bGVcbiAgICAgKiBjYWxsYmFjayB3aWxsIHJldHVybiB0aGUgcHJvcGVydHkgdmFsdWUgb2YgdGhlIGdpdmVuIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiBhbiBvYmplY3QgaXMgcHJvdmlkZWQgZm9yIGBjYWxsYmFja2AgdGhlIGNyZWF0ZWQgXCJfLndoZXJlXCIgc3R5bGUgY2FsbGJhY2tcbiAgICAgKiB3aWxsIHJldHVybiBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSB0aGUgcHJvcGVydGllcyBvZiB0aGUgZ2l2ZW4gb2JqZWN0LFxuICAgICAqIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBhbGlhcyBoZWFkLCB0YWtlXG4gICAgICogQGNhdGVnb3J5IEFycmF5c1xuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxudW1iZXJ8c3RyaW5nfSBbY2FsbGJhY2tdIFRoZSBmdW5jdGlvbiBjYWxsZWRcbiAgICAgKiAgcGVyIGVsZW1lbnQgb3IgdGhlIG51bWJlciBvZiBlbGVtZW50cyB0byByZXR1cm4uIElmIGEgcHJvcGVydHkgbmFtZSBvclxuICAgICAqICBvYmplY3QgaXMgcHJvdmlkZWQgaXQgd2lsbCBiZSB1c2VkIHRvIGNyZWF0ZSBhIFwiXy5wbHVja1wiIG9yIFwiXy53aGVyZVwiXG4gICAgICogIHN0eWxlIGNhbGxiYWNrLCByZXNwZWN0aXZlbHkuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBjYWxsYmFja2AuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGZpcnN0IGVsZW1lbnQocykgb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5maXJzdChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IDFcbiAgICAgKlxuICAgICAqIF8uZmlyc3QoWzEsIDIsIDNdLCAyKTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKlxuICAgICAqIF8uZmlyc3QoWzEsIDIsIDNdLCBmdW5jdGlvbihudW0pIHtcbiAgICAgKiAgIHJldHVybiBudW0gPCAzO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IFsxLCAyXVxuICAgICAqXG4gICAgICogdmFyIGNoYXJhY3RlcnMgPSBbXG4gICAgICogICB7ICduYW1lJzogJ2Jhcm5leScsICAnYmxvY2tlZCc6IHRydWUsICAnZW1wbG95ZXInOiAnc2xhdGUnIH0sXG4gICAgICogICB7ICduYW1lJzogJ2ZyZWQnLCAgICAnYmxvY2tlZCc6IGZhbHNlLCAnZW1wbG95ZXInOiAnc2xhdGUnIH0sXG4gICAgICogICB7ICduYW1lJzogJ3BlYmJsZXMnLCAnYmxvY2tlZCc6IHRydWUsICAnZW1wbG95ZXInOiAnbmEnIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogLy8gdXNpbmcgXCJfLnBsdWNrXCIgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5maXJzdChjaGFyYWN0ZXJzLCAnYmxvY2tlZCcpO1xuICAgICAqIC8vID0+IFt7ICduYW1lJzogJ2Jhcm5leScsICdibG9ja2VkJzogdHJ1ZSwgJ2VtcGxveWVyJzogJ3NsYXRlJyB9XVxuICAgICAqXG4gICAgICogLy8gdXNpbmcgXCJfLndoZXJlXCIgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5wbHVjayhfLmZpcnN0KGNoYXJhY3RlcnMsIHsgJ2VtcGxveWVyJzogJ3NsYXRlJyB9KSwgJ25hbWUnKTtcbiAgICAgKiAvLyA9PiBbJ2Jhcm5leScsICdmcmVkJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmaXJzdChhcnJheSwgY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICAgIHZhciBuID0gMCxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDA7XG5cbiAgICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgIT0gJ251bWJlcicgJiYgY2FsbGJhY2sgIT0gbnVsbCkge1xuICAgICAgICB2YXIgaW5kZXggPSAtMTtcbiAgICAgICAgY2FsbGJhY2sgPSBsb2Rhc2guY3JlYXRlQ2FsbGJhY2soY2FsbGJhY2ssIHRoaXNBcmcsIDMpO1xuICAgICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCAmJiBjYWxsYmFjayhhcnJheVtpbmRleF0sIGluZGV4LCBhcnJheSkpIHtcbiAgICAgICAgICBuKys7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG4gPSBjYWxsYmFjaztcbiAgICAgICAgaWYgKG4gPT0gbnVsbCB8fCB0aGlzQXJnKSB7XG4gICAgICAgICAgcmV0dXJuIGFycmF5ID8gYXJyYXlbMF0gOiB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBzbGljZShhcnJheSwgMCwgbmF0aXZlTWluKG5hdGl2ZU1heCgwLCBuKSwgbGVuZ3RoKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRmxhdHRlbnMgYSBuZXN0ZWQgYXJyYXkgKHRoZSBuZXN0aW5nIGNhbiBiZSB0byBhbnkgZGVwdGgpLiBJZiBgaXNTaGFsbG93YFxuICAgICAqIGlzIHRydWV5LCB0aGUgYXJyYXkgd2lsbCBvbmx5IGJlIGZsYXR0ZW5lZCBhIHNpbmdsZSBsZXZlbC4gSWYgYSBjYWxsYmFja1xuICAgICAqIGlzIHByb3ZpZGVkIGVhY2ggZWxlbWVudCBvZiB0aGUgYXJyYXkgaXMgcGFzc2VkIHRocm91Z2ggdGhlIGNhbGxiYWNrIGJlZm9yZVxuICAgICAqIGZsYXR0ZW5pbmcuIFRoZSBjYWxsYmFjayBpcyBib3VuZCB0byBgdGhpc0FyZ2AgYW5kIGludm9rZWQgd2l0aCB0aHJlZVxuICAgICAqIGFyZ3VtZW50czsgKHZhbHVlLCBpbmRleCwgYXJyYXkpLlxuICAgICAqXG4gICAgICogSWYgYSBwcm9wZXJ0eSBuYW1lIGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy5wbHVja1wiIHN0eWxlXG4gICAgICogY2FsbGJhY2sgd2lsbCByZXR1cm4gdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqXG4gICAgICogSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy53aGVyZVwiIHN0eWxlIGNhbGxiYWNrXG4gICAgICogd2lsbCByZXR1cm4gYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuIG9iamVjdCxcbiAgICAgKiBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlzXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGZsYXR0ZW4uXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbaXNTaGFsbG93PWZhbHNlXSBBIGZsYWcgdG8gcmVzdHJpY3QgZmxhdHRlbmluZyB0byBhIHNpbmdsZSBsZXZlbC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtjYWxsYmFjaz1pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGNhbGxlZFxuICAgICAqICBwZXIgaXRlcmF0aW9uLiBJZiBhIHByb3BlcnR5IG5hbWUgb3Igb2JqZWN0IGlzIHByb3ZpZGVkIGl0IHdpbGwgYmUgdXNlZFxuICAgICAqICB0byBjcmVhdGUgYSBcIl8ucGx1Y2tcIiBvciBcIl8ud2hlcmVcIiBzdHlsZSBjYWxsYmFjaywgcmVzcGVjdGl2ZWx5LlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY2FsbGJhY2tgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBhIG5ldyBmbGF0dGVuZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZmxhdHRlbihbMSwgWzJdLCBbMywgW1s0XV1dXSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDMsIDRdO1xuICAgICAqXG4gICAgICogXy5mbGF0dGVuKFsxLCBbMl0sIFszLCBbWzRdXV1dLCB0cnVlKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgMywgW1s0XV1dO1xuICAgICAqXG4gICAgICogdmFyIGNoYXJhY3RlcnMgPSBbXG4gICAgICogICB7ICduYW1lJzogJ2Jhcm5leScsICdhZ2UnOiAzMCwgJ3BldHMnOiBbJ2hvcHB5J10gfSxcbiAgICAgKiAgIHsgJ25hbWUnOiAnZnJlZCcsICAgJ2FnZSc6IDQwLCAncGV0cyc6IFsnYmFieSBwdXNzJywgJ2Rpbm8nXSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIFwiXy5wbHVja1wiIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8uZmxhdHRlbihjaGFyYWN0ZXJzLCAncGV0cycpO1xuICAgICAqIC8vID0+IFsnaG9wcHknLCAnYmFieSBwdXNzJywgJ2Rpbm8nXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZsYXR0ZW4oYXJyYXksIGlzU2hhbGxvdywgY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICAgIC8vIGp1Z2dsZSBhcmd1bWVudHNcbiAgICAgIGlmICh0eXBlb2YgaXNTaGFsbG93ICE9ICdib29sZWFuJyAmJiBpc1NoYWxsb3cgIT0gbnVsbCkge1xuICAgICAgICB0aGlzQXJnID0gY2FsbGJhY2s7XG4gICAgICAgIGNhbGxiYWNrID0gKHR5cGVvZiBpc1NoYWxsb3cgIT0gJ2Z1bmN0aW9uJyAmJiB0aGlzQXJnICYmIHRoaXNBcmdbaXNTaGFsbG93XSA9PT0gYXJyYXkpID8gbnVsbCA6IGlzU2hhbGxvdztcbiAgICAgICAgaXNTaGFsbG93ID0gZmFsc2U7XG4gICAgICB9XG4gICAgICBpZiAoY2FsbGJhY2sgIT0gbnVsbCkge1xuICAgICAgICBhcnJheSA9IG1hcChhcnJheSwgY2FsbGJhY2ssIHRoaXNBcmcpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VGbGF0dGVuKGFycmF5LCBpc1NoYWxsb3cpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGluZGV4IGF0IHdoaWNoIHRoZSBmaXJzdCBvY2N1cnJlbmNlIG9mIGB2YWx1ZWAgaXMgZm91bmQgdXNpbmdcbiAgICAgKiBzdHJpY3QgZXF1YWxpdHkgZm9yIGNvbXBhcmlzb25zLCBpLmUuIGA9PT1gLiBJZiB0aGUgYXJyYXkgaXMgYWxyZWFkeSBzb3J0ZWRcbiAgICAgKiBwcm92aWRpbmcgYHRydWVgIGZvciBgZnJvbUluZGV4YCB3aWxsIHJ1biBhIGZhc3RlciBiaW5hcnkgc2VhcmNoLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5c1xuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBzZWFyY2guXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2VhcmNoIGZvci5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW58bnVtYmVyfSBbZnJvbUluZGV4PTBdIFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbSBvciBgdHJ1ZWBcbiAgICAgKiAgdG8gcGVyZm9ybSBhIGJpbmFyeSBzZWFyY2ggb24gYSBzb3J0ZWQgYXJyYXkuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUgb3IgYC0xYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pbmRleE9mKFsxLCAyLCAzLCAxLCAyLCAzXSwgMik7XG4gICAgICogLy8gPT4gMVxuICAgICAqXG4gICAgICogXy5pbmRleE9mKFsxLCAyLCAzLCAxLCAyLCAzXSwgMiwgMyk7XG4gICAgICogLy8gPT4gNFxuICAgICAqXG4gICAgICogXy5pbmRleE9mKFsxLCAxLCAyLCAyLCAzLCAzXSwgMiwgdHJ1ZSk7XG4gICAgICogLy8gPT4gMlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluZGV4T2YoYXJyYXksIHZhbHVlLCBmcm9tSW5kZXgpIHtcbiAgICAgIGlmICh0eXBlb2YgZnJvbUluZGV4ID09ICdudW1iZXInKSB7XG4gICAgICAgIHZhciBsZW5ndGggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDA7XG4gICAgICAgIGZyb21JbmRleCA9IChmcm9tSW5kZXggPCAwID8gbmF0aXZlTWF4KDAsIGxlbmd0aCArIGZyb21JbmRleCkgOiBmcm9tSW5kZXggfHwgMCk7XG4gICAgICB9IGVsc2UgaWYgKGZyb21JbmRleCkge1xuICAgICAgICB2YXIgaW5kZXggPSBzb3J0ZWRJbmRleChhcnJheSwgdmFsdWUpO1xuICAgICAgICByZXR1cm4gYXJyYXlbaW5kZXhdID09PSB2YWx1ZSA/IGluZGV4IDogLTE7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZUluZGV4T2YoYXJyYXksIHZhbHVlLCBmcm9tSW5kZXgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgYWxsIGJ1dCB0aGUgbGFzdCBlbGVtZW50IG9yIGxhc3QgYG5gIGVsZW1lbnRzIG9mIGFuIGFycmF5LiBJZiBhXG4gICAgICogY2FsbGJhY2sgaXMgcHJvdmlkZWQgZWxlbWVudHMgYXQgdGhlIGVuZCBvZiB0aGUgYXJyYXkgYXJlIGV4Y2x1ZGVkIGZyb21cbiAgICAgKiB0aGUgcmVzdWx0IGFzIGxvbmcgYXMgdGhlIGNhbGxiYWNrIHJldHVybnMgdHJ1ZXkuIFRoZSBjYWxsYmFjayBpcyBib3VuZFxuICAgICAqIHRvIGB0aGlzQXJnYCBhbmQgaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czsgKHZhbHVlLCBpbmRleCwgYXJyYXkpLlxuICAgICAqXG4gICAgICogSWYgYSBwcm9wZXJ0eSBuYW1lIGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy5wbHVja1wiIHN0eWxlXG4gICAgICogY2FsbGJhY2sgd2lsbCByZXR1cm4gdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqXG4gICAgICogSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy53aGVyZVwiIHN0eWxlIGNhbGxiYWNrXG4gICAgICogd2lsbCByZXR1cm4gYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuIG9iamVjdCxcbiAgICAgKiBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlzXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fG51bWJlcnxzdHJpbmd9IFtjYWxsYmFjaz0xXSBUaGUgZnVuY3Rpb24gY2FsbGVkXG4gICAgICogIHBlciBlbGVtZW50IG9yIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgdG8gZXhjbHVkZS4gSWYgYSBwcm9wZXJ0eSBuYW1lIG9yXG4gICAgICogIG9iamVjdCBpcyBwcm92aWRlZCBpdCB3aWxsIGJlIHVzZWQgdG8gY3JlYXRlIGEgXCJfLnBsdWNrXCIgb3IgXCJfLndoZXJlXCJcbiAgICAgKiAgc3R5bGUgY2FsbGJhY2ssIHJlc3BlY3RpdmVseS5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGNhbGxiYWNrYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmluaXRpYWwoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKlxuICAgICAqIF8uaW5pdGlhbChbMSwgMiwgM10sIDIpO1xuICAgICAqIC8vID0+IFsxXVxuICAgICAqXG4gICAgICogXy5pbml0aWFsKFsxLCAyLCAzXSwgZnVuY3Rpb24obnVtKSB7XG4gICAgICogICByZXR1cm4gbnVtID4gMTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBbMV1cbiAgICAgKlxuICAgICAqIHZhciBjaGFyYWN0ZXJzID0gW1xuICAgICAqICAgeyAnbmFtZSc6ICdiYXJuZXknLCAgJ2Jsb2NrZWQnOiBmYWxzZSwgJ2VtcGxveWVyJzogJ3NsYXRlJyB9LFxuICAgICAqICAgeyAnbmFtZSc6ICdmcmVkJywgICAgJ2Jsb2NrZWQnOiB0cnVlLCAgJ2VtcGxveWVyJzogJ3NsYXRlJyB9LFxuICAgICAqICAgeyAnbmFtZSc6ICdwZWJibGVzJywgJ2Jsb2NrZWQnOiB0cnVlLCAgJ2VtcGxveWVyJzogJ25hJyB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIFwiXy5wbHVja1wiIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8uaW5pdGlhbChjaGFyYWN0ZXJzLCAnYmxvY2tlZCcpO1xuICAgICAqIC8vID0+IFt7ICduYW1lJzogJ2Jhcm5leScsICAnYmxvY2tlZCc6IGZhbHNlLCAnZW1wbG95ZXInOiAnc2xhdGUnIH1dXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyBcIl8ud2hlcmVcIiBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLnBsdWNrKF8uaW5pdGlhbChjaGFyYWN0ZXJzLCB7ICdlbXBsb3llcic6ICduYScgfSksICduYW1lJyk7XG4gICAgICogLy8gPT4gWydiYXJuZXknLCAnZnJlZCddXG4gICAgICovXG4gICAgZnVuY3Rpb24gaW5pdGlhbChhcnJheSwgY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICAgIHZhciBuID0gMCxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDA7XG5cbiAgICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgIT0gJ251bWJlcicgJiYgY2FsbGJhY2sgIT0gbnVsbCkge1xuICAgICAgICB2YXIgaW5kZXggPSBsZW5ndGg7XG4gICAgICAgIGNhbGxiYWNrID0gbG9kYXNoLmNyZWF0ZUNhbGxiYWNrKGNhbGxiYWNrLCB0aGlzQXJnLCAzKTtcbiAgICAgICAgd2hpbGUgKGluZGV4LS0gJiYgY2FsbGJhY2soYXJyYXlbaW5kZXhdLCBpbmRleCwgYXJyYXkpKSB7XG4gICAgICAgICAgbisrO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuID0gKGNhbGxiYWNrID09IG51bGwgfHwgdGhpc0FyZykgPyAxIDogY2FsbGJhY2sgfHwgbjtcbiAgICAgIH1cbiAgICAgIHJldHVybiBzbGljZShhcnJheSwgMCwgbmF0aXZlTWluKG5hdGl2ZU1heCgwLCBsZW5ndGggLSBuKSwgbGVuZ3RoKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB1bmlxdWUgdmFsdWVzIHByZXNlbnQgaW4gYWxsIHByb3ZpZGVkIGFycmF5cyB1c2luZ1xuICAgICAqIHN0cmljdCBlcXVhbGl0eSBmb3IgY29tcGFyaXNvbnMsIGkuZS4gYD09PWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlzXG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5XSBUaGUgYXJyYXlzIHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGFuIGFycmF5IG9mIHNoYXJlZCB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaW50ZXJzZWN0aW9uKFsxLCAyLCAzXSwgWzUsIDIsIDEsIDRdLCBbMiwgMV0pO1xuICAgICAqIC8vID0+IFsxLCAyXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGludGVyc2VjdGlvbigpIHtcbiAgICAgIHZhciBhcmdzID0gW10sXG4gICAgICAgICAgYXJnc0luZGV4ID0gLTEsXG4gICAgICAgICAgYXJnc0xlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGgsXG4gICAgICAgICAgY2FjaGVzID0gZ2V0QXJyYXkoKSxcbiAgICAgICAgICBpbmRleE9mID0gZ2V0SW5kZXhPZigpLFxuICAgICAgICAgIHRydXN0SW5kZXhPZiA9IGluZGV4T2YgPT09IGJhc2VJbmRleE9mLFxuICAgICAgICAgIHNlZW4gPSBnZXRBcnJheSgpO1xuXG4gICAgICB3aGlsZSAoKythcmdzSW5kZXggPCBhcmdzTGVuZ3RoKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGFyZ3VtZW50c1thcmdzSW5kZXhdO1xuICAgICAgICBpZiAoaXNBcnJheSh2YWx1ZSkgfHwgaXNBcmd1bWVudHModmFsdWUpKSB7XG4gICAgICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgICAgICBjYWNoZXMucHVzaCh0cnVzdEluZGV4T2YgJiYgdmFsdWUubGVuZ3RoID49IGxhcmdlQXJyYXlTaXplICYmXG4gICAgICAgICAgICBjcmVhdGVDYWNoZShhcmdzSW5kZXggPyBhcmdzW2FyZ3NJbmRleF0gOiBzZWVuKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHZhciBhcnJheSA9IGFyZ3NbMF0sXG4gICAgICAgICAgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDAsXG4gICAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICAgIG91dGVyOlxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIGNhY2hlID0gY2FjaGVzWzBdO1xuICAgICAgICB2YWx1ZSA9IGFycmF5W2luZGV4XTtcblxuICAgICAgICBpZiAoKGNhY2hlID8gY2FjaGVJbmRleE9mKGNhY2hlLCB2YWx1ZSkgOiBpbmRleE9mKHNlZW4sIHZhbHVlKSkgPCAwKSB7XG4gICAgICAgICAgYXJnc0luZGV4ID0gYXJnc0xlbmd0aDtcbiAgICAgICAgICAoY2FjaGUgfHwgc2VlbikucHVzaCh2YWx1ZSk7XG4gICAgICAgICAgd2hpbGUgKC0tYXJnc0luZGV4KSB7XG4gICAgICAgICAgICBjYWNoZSA9IGNhY2hlc1thcmdzSW5kZXhdO1xuICAgICAgICAgICAgaWYgKChjYWNoZSA/IGNhY2hlSW5kZXhPZihjYWNoZSwgdmFsdWUpIDogaW5kZXhPZihhcmdzW2FyZ3NJbmRleF0sIHZhbHVlKSkgPCAwKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlIG91dGVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHdoaWxlIChhcmdzTGVuZ3RoLS0pIHtcbiAgICAgICAgY2FjaGUgPSBjYWNoZXNbYXJnc0xlbmd0aF07XG4gICAgICAgIGlmIChjYWNoZSkge1xuICAgICAgICAgIHJlbGVhc2VPYmplY3QoY2FjaGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZWxlYXNlQXJyYXkoY2FjaGVzKTtcbiAgICAgIHJlbGVhc2VBcnJheShzZWVuKTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbGFzdCBlbGVtZW50IG9yIGxhc3QgYG5gIGVsZW1lbnRzIG9mIGFuIGFycmF5LiBJZiBhIGNhbGxiYWNrIGlzXG4gICAgICogcHJvdmlkZWQgZWxlbWVudHMgYXQgdGhlIGVuZCBvZiB0aGUgYXJyYXkgYXJlIHJldHVybmVkIGFzIGxvbmcgYXMgdGhlXG4gICAgICogY2FsbGJhY2sgcmV0dXJucyB0cnVleS4gVGhlIGNhbGxiYWNrIGlzIGJvdW5kIHRvIGB0aGlzQXJnYCBhbmQgaW52b2tlZFxuICAgICAqIHdpdGggdGhyZWUgYXJndW1lbnRzOyAodmFsdWUsIGluZGV4LCBhcnJheSkuXG4gICAgICpcbiAgICAgKiBJZiBhIHByb3BlcnR5IG5hbWUgaXMgcHJvdmlkZWQgZm9yIGBjYWxsYmFja2AgdGhlIGNyZWF0ZWQgXCJfLnBsdWNrXCIgc3R5bGVcbiAgICAgKiBjYWxsYmFjayB3aWxsIHJldHVybiB0aGUgcHJvcGVydHkgdmFsdWUgb2YgdGhlIGdpdmVuIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBJZiBhbiBvYmplY3QgaXMgcHJvdmlkZWQgZm9yIGBjYWxsYmFja2AgdGhlIGNyZWF0ZWQgXCJfLndoZXJlXCIgc3R5bGUgY2FsbGJhY2tcbiAgICAgKiB3aWxsIHJldHVybiBgdHJ1ZWAgZm9yIGVsZW1lbnRzIHRoYXQgaGF2ZSB0aGUgcHJvcGVydGllcyBvZiB0aGUgZ2l2ZW4gb2JqZWN0LFxuICAgICAqIGVsc2UgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheXNcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8bnVtYmVyfHN0cmluZ30gW2NhbGxiYWNrXSBUaGUgZnVuY3Rpb24gY2FsbGVkXG4gICAgICogIHBlciBlbGVtZW50IG9yIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgdG8gcmV0dXJuLiBJZiBhIHByb3BlcnR5IG5hbWUgb3JcbiAgICAgKiAgb2JqZWN0IGlzIHByb3ZpZGVkIGl0IHdpbGwgYmUgdXNlZCB0byBjcmVhdGUgYSBcIl8ucGx1Y2tcIiBvciBcIl8ud2hlcmVcIlxuICAgICAqICBzdHlsZSBjYWxsYmFjaywgcmVzcGVjdGl2ZWx5LlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY2FsbGJhY2tgLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBsYXN0IGVsZW1lbnQocykgb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5sYXN0KFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gM1xuICAgICAqXG4gICAgICogXy5sYXN0KFsxLCAyLCAzXSwgMik7XG4gICAgICogLy8gPT4gWzIsIDNdXG4gICAgICpcbiAgICAgKiBfLmxhc3QoWzEsIDIsIDNdLCBmdW5jdGlvbihudW0pIHtcbiAgICAgKiAgIHJldHVybiBudW0gPiAxO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IFsyLCAzXVxuICAgICAqXG4gICAgICogdmFyIGNoYXJhY3RlcnMgPSBbXG4gICAgICogICB7ICduYW1lJzogJ2Jhcm5leScsICAnYmxvY2tlZCc6IGZhbHNlLCAnZW1wbG95ZXInOiAnc2xhdGUnIH0sXG4gICAgICogICB7ICduYW1lJzogJ2ZyZWQnLCAgICAnYmxvY2tlZCc6IHRydWUsICAnZW1wbG95ZXInOiAnc2xhdGUnIH0sXG4gICAgICogICB7ICduYW1lJzogJ3BlYmJsZXMnLCAnYmxvY2tlZCc6IHRydWUsICAnZW1wbG95ZXInOiAnbmEnIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogLy8gdXNpbmcgXCJfLnBsdWNrXCIgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5wbHVjayhfLmxhc3QoY2hhcmFjdGVycywgJ2Jsb2NrZWQnKSwgJ25hbWUnKTtcbiAgICAgKiAvLyA9PiBbJ2ZyZWQnLCAncGViYmxlcyddXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyBcIl8ud2hlcmVcIiBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLmxhc3QoY2hhcmFjdGVycywgeyAnZW1wbG95ZXInOiAnbmEnIH0pO1xuICAgICAqIC8vID0+IFt7ICduYW1lJzogJ3BlYmJsZXMnLCAnYmxvY2tlZCc6IHRydWUsICdlbXBsb3llcic6ICduYScgfV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBsYXN0KGFycmF5LCBjYWxsYmFjaywgdGhpc0FyZykge1xuICAgICAgdmFyIG4gPSAwLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5ID8gYXJyYXkubGVuZ3RoIDogMDtcblxuICAgICAgaWYgKHR5cGVvZiBjYWxsYmFjayAhPSAnbnVtYmVyJyAmJiBjYWxsYmFjayAhPSBudWxsKSB7XG4gICAgICAgIHZhciBpbmRleCA9IGxlbmd0aDtcbiAgICAgICAgY2FsbGJhY2sgPSBsb2Rhc2guY3JlYXRlQ2FsbGJhY2soY2FsbGJhY2ssIHRoaXNBcmcsIDMpO1xuICAgICAgICB3aGlsZSAoaW5kZXgtLSAmJiBjYWxsYmFjayhhcnJheVtpbmRleF0sIGluZGV4LCBhcnJheSkpIHtcbiAgICAgICAgICBuKys7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG4gPSBjYWxsYmFjaztcbiAgICAgICAgaWYgKG4gPT0gbnVsbCB8fCB0aGlzQXJnKSB7XG4gICAgICAgICAgcmV0dXJuIGFycmF5ID8gYXJyYXlbbGVuZ3RoIC0gMV0gOiB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBzbGljZShhcnJheSwgbmF0aXZlTWF4KDAsIGxlbmd0aCAtIG4pKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBpbmRleCBhdCB3aGljaCB0aGUgbGFzdCBvY2N1cnJlbmNlIG9mIGB2YWx1ZWAgaXMgZm91bmQgdXNpbmcgc3RyaWN0XG4gICAgICogZXF1YWxpdHkgZm9yIGNvbXBhcmlzb25zLCBpLmUuIGA9PT1gLiBJZiBgZnJvbUluZGV4YCBpcyBuZWdhdGl2ZSwgaXQgaXMgdXNlZFxuICAgICAqIGFzIHRoZSBvZmZzZXQgZnJvbSB0aGUgZW5kIG9mIHRoZSBjb2xsZWN0aW9uLlxuICAgICAqXG4gICAgICogSWYgYSBwcm9wZXJ0eSBuYW1lIGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy5wbHVja1wiIHN0eWxlXG4gICAgICogY2FsbGJhY2sgd2lsbCByZXR1cm4gdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqXG4gICAgICogSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy53aGVyZVwiIHN0eWxlIGNhbGxiYWNrXG4gICAgICogd2lsbCByZXR1cm4gYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuIG9iamVjdCxcbiAgICAgKiBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlzXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNlYXJjaC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZnJvbUluZGV4PWFycmF5Lmxlbmd0aC0xXSBUaGUgaW5kZXggdG8gc2VhcmNoIGZyb20uXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUgb3IgYC0xYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5sYXN0SW5kZXhPZihbMSwgMiwgMywgMSwgMiwgM10sIDIpO1xuICAgICAqIC8vID0+IDRcbiAgICAgKlxuICAgICAqIF8ubGFzdEluZGV4T2YoWzEsIDIsIDMsIDEsIDIsIDNdLCAyLCAzKTtcbiAgICAgKiAvLyA9PiAxXG4gICAgICovXG4gICAgZnVuY3Rpb24gbGFzdEluZGV4T2YoYXJyYXksIHZhbHVlLCBmcm9tSW5kZXgpIHtcbiAgICAgIHZhciBpbmRleCA9IGFycmF5ID8gYXJyYXkubGVuZ3RoIDogMDtcbiAgICAgIGlmICh0eXBlb2YgZnJvbUluZGV4ID09ICdudW1iZXInKSB7XG4gICAgICAgIGluZGV4ID0gKGZyb21JbmRleCA8IDAgPyBuYXRpdmVNYXgoMCwgaW5kZXggKyBmcm9tSW5kZXgpIDogbmF0aXZlTWluKGZyb21JbmRleCwgaW5kZXggLSAxKSkgKyAxO1xuICAgICAgfVxuICAgICAgd2hpbGUgKGluZGV4LS0pIHtcbiAgICAgICAgaWYgKGFycmF5W2luZGV4XSA9PT0gdmFsdWUpIHtcbiAgICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiAtMTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFsbCBwcm92aWRlZCB2YWx1ZXMgZnJvbSB0aGUgZ2l2ZW4gYXJyYXkgdXNpbmcgc3RyaWN0IGVxdWFsaXR5IGZvclxuICAgICAqIGNvbXBhcmlzb25zLCBpLmUuIGA9PT1gLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5c1xuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHsuLi4qfSBbdmFsdWVdIFRoZSB2YWx1ZXMgdG8gcmVtb3ZlLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbMSwgMiwgMywgMSwgMiwgM107XG4gICAgICogXy5wdWxsKGFycmF5LCAyLCAzKTtcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheSk7XG4gICAgICogLy8gPT4gWzEsIDFdXG4gICAgICovXG4gICAgZnVuY3Rpb24gcHVsbChhcnJheSkge1xuICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHMsXG4gICAgICAgICAgYXJnc0luZGV4ID0gMCxcbiAgICAgICAgICBhcmdzTGVuZ3RoID0gYXJncy5sZW5ndGgsXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXkgPyBhcnJheS5sZW5ndGggOiAwO1xuXG4gICAgICB3aGlsZSAoKythcmdzSW5kZXggPCBhcmdzTGVuZ3RoKSB7XG4gICAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgICAgdmFsdWUgPSBhcmdzW2FyZ3NJbmRleF07XG4gICAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgICAgaWYgKGFycmF5W2luZGV4XSA9PT0gdmFsdWUpIHtcbiAgICAgICAgICAgIHNwbGljZS5jYWxsKGFycmF5LCBpbmRleC0tLCAxKTtcbiAgICAgICAgICAgIGxlbmd0aC0tO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGFycmF5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgbnVtYmVycyAocG9zaXRpdmUgYW5kL29yIG5lZ2F0aXZlKSBwcm9ncmVzc2luZyBmcm9tXG4gICAgICogYHN0YXJ0YCB1cCB0byBidXQgbm90IGluY2x1ZGluZyBgZW5kYC4gSWYgYHN0YXJ0YCBpcyBsZXNzIHRoYW4gYHN0b3BgIGFcbiAgICAgKiB6ZXJvLWxlbmd0aCByYW5nZSBpcyBjcmVhdGVkIHVubGVzcyBhIG5lZ2F0aXZlIGBzdGVwYCBpcyBzcGVjaWZpZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlzXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGFydD0wXSBUaGUgc3RhcnQgb2YgdGhlIHJhbmdlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgVGhlIGVuZCBvZiB0aGUgcmFuZ2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGVwPTFdIFRoZSB2YWx1ZSB0byBpbmNyZW1lbnQgb3IgZGVjcmVtZW50IGJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBhIG5ldyByYW5nZSBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5yYW5nZSg0KTtcbiAgICAgKiAvLyA9PiBbMCwgMSwgMiwgM11cbiAgICAgKlxuICAgICAqIF8ucmFuZ2UoMSwgNSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDMsIDRdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlKDAsIDIwLCA1KTtcbiAgICAgKiAvLyA9PiBbMCwgNSwgMTAsIDE1XVxuICAgICAqXG4gICAgICogXy5yYW5nZSgwLCAtNCwgLTEpO1xuICAgICAqIC8vID0+IFswLCAtMSwgLTIsIC0zXVxuICAgICAqXG4gICAgICogXy5yYW5nZSgxLCA0LCAwKTtcbiAgICAgKiAvLyA9PiBbMSwgMSwgMV1cbiAgICAgKlxuICAgICAqIF8ucmFuZ2UoMCk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiByYW5nZShzdGFydCwgZW5kLCBzdGVwKSB7XG4gICAgICBzdGFydCA9ICtzdGFydCB8fCAwO1xuICAgICAgc3RlcCA9IHR5cGVvZiBzdGVwID09ICdudW1iZXInID8gc3RlcCA6ICgrc3RlcCB8fCAxKTtcblxuICAgICAgaWYgKGVuZCA9PSBudWxsKSB7XG4gICAgICAgIGVuZCA9IHN0YXJ0O1xuICAgICAgICBzdGFydCA9IDA7XG4gICAgICB9XG4gICAgICAvLyB1c2UgYEFycmF5KGxlbmd0aClgIHNvIGVuZ2luZXMgbGlrZSBDaGFrcmEgYW5kIFY4IGF2b2lkIHNsb3dlciBtb2Rlc1xuICAgICAgLy8gaHR0cDovL3lvdXR1LmJlL1hBcUlwR1U4WlprI3Q9MTdtMjVzXG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBuYXRpdmVNYXgoMCwgY2VpbCgoZW5kIC0gc3RhcnQpIC8gKHN0ZXAgfHwgMSkpKSxcbiAgICAgICAgICByZXN1bHQgPSBBcnJheShsZW5ndGgpO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICByZXN1bHRbaW5kZXhdID0gc3RhcnQ7XG4gICAgICAgIHN0YXJ0ICs9IHN0ZXA7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGVsZW1lbnRzIGZyb20gYW4gYXJyYXkgdGhhdCB0aGUgY2FsbGJhY2sgcmV0dXJucyB0cnVleSBmb3JcbiAgICAgKiBhbmQgcmV0dXJucyBhbiBhcnJheSBvZiByZW1vdmVkIGVsZW1lbnRzLiBUaGUgY2FsbGJhY2sgaXMgYm91bmQgdG8gYHRoaXNBcmdgXG4gICAgICogYW5kIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM7ICh2YWx1ZSwgaW5kZXgsIGFycmF5KS5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYGNhbGxiYWNrYCB0aGUgY3JlYXRlZCBcIl8ucGx1Y2tcIiBzdHlsZVxuICAgICAqIGNhbGxiYWNrIHdpbGwgcmV0dXJuIHRoZSBwcm9wZXJ0eSB2YWx1ZSBvZiB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYGNhbGxiYWNrYCB0aGUgY3JlYXRlZCBcIl8ud2hlcmVcIiBzdHlsZSBjYWxsYmFja1xuICAgICAqIHdpbGwgcmV0dXJuIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBnaXZlbiBvYmplY3QsXG4gICAgICogZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEFycmF5c1xuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbY2FsbGJhY2s9aWRlbnRpdHldIFRoZSBmdW5jdGlvbiBjYWxsZWRcbiAgICAgKiAgcGVyIGl0ZXJhdGlvbi4gSWYgYSBwcm9wZXJ0eSBuYW1lIG9yIG9iamVjdCBpcyBwcm92aWRlZCBpdCB3aWxsIGJlIHVzZWRcbiAgICAgKiAgdG8gY3JlYXRlIGEgXCJfLnBsdWNrXCIgb3IgXCJfLndoZXJlXCIgc3R5bGUgY2FsbGJhY2ssIHJlc3BlY3RpdmVseS5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGNhbGxiYWNrYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYSBuZXcgYXJyYXkgb2YgcmVtb3ZlZCBlbGVtZW50cy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWzEsIDIsIDMsIDQsIDUsIDZdO1xuICAgICAqIHZhciBldmVucyA9IF8ucmVtb3ZlKGFycmF5LCBmdW5jdGlvbihudW0pIHsgcmV0dXJuIG51bSAlIDIgPT0gMDsgfSk7XG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheSk7XG4gICAgICogLy8gPT4gWzEsIDMsIDVdXG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhldmVucyk7XG4gICAgICogLy8gPT4gWzIsIDQsIDZdXG4gICAgICovXG4gICAgZnVuY3Rpb24gcmVtb3ZlKGFycmF5LCBjYWxsYmFjaywgdGhpc0FyZykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXkgPyBhcnJheS5sZW5ndGggOiAwLFxuICAgICAgICAgIHJlc3VsdCA9IFtdO1xuXG4gICAgICBjYWxsYmFjayA9IGxvZGFzaC5jcmVhdGVDYWxsYmFjayhjYWxsYmFjaywgdGhpc0FyZywgMyk7XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIgdmFsdWUgPSBhcnJheVtpbmRleF07XG4gICAgICAgIGlmIChjYWxsYmFjayh2YWx1ZSwgaW5kZXgsIGFycmF5KSkge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKHZhbHVlKTtcbiAgICAgICAgICBzcGxpY2UuY2FsbChhcnJheSwgaW5kZXgtLSwgMSk7XG4gICAgICAgICAgbGVuZ3RoLS07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIG9wcG9zaXRlIG9mIGBfLmluaXRpYWxgIHRoaXMgbWV0aG9kIGdldHMgYWxsIGJ1dCB0aGUgZmlyc3QgZWxlbWVudCBvclxuICAgICAqIGZpcnN0IGBuYCBlbGVtZW50cyBvZiBhbiBhcnJheS4gSWYgYSBjYWxsYmFjayBmdW5jdGlvbiBpcyBwcm92aWRlZCBlbGVtZW50c1xuICAgICAqIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGFycmF5IGFyZSBleGNsdWRlZCBmcm9tIHRoZSByZXN1bHQgYXMgbG9uZyBhcyB0aGVcbiAgICAgKiBjYWxsYmFjayByZXR1cm5zIHRydWV5LiBUaGUgY2FsbGJhY2sgaXMgYm91bmQgdG8gYHRoaXNBcmdgIGFuZCBpbnZva2VkXG4gICAgICogd2l0aCB0aHJlZSBhcmd1bWVudHM7ICh2YWx1ZSwgaW5kZXgsIGFycmF5KS5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYGNhbGxiYWNrYCB0aGUgY3JlYXRlZCBcIl8ucGx1Y2tcIiBzdHlsZVxuICAgICAqIGNhbGxiYWNrIHdpbGwgcmV0dXJuIHRoZSBwcm9wZXJ0eSB2YWx1ZSBvZiB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYGNhbGxiYWNrYCB0aGUgY3JlYXRlZCBcIl8ud2hlcmVcIiBzdHlsZSBjYWxsYmFja1xuICAgICAqIHdpbGwgcmV0dXJuIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBnaXZlbiBvYmplY3QsXG4gICAgICogZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGFsaWFzIGRyb3AsIHRhaWxcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlzXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fG51bWJlcnxzdHJpbmd9IFtjYWxsYmFjaz0xXSBUaGUgZnVuY3Rpb24gY2FsbGVkXG4gICAgICogIHBlciBlbGVtZW50IG9yIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgdG8gZXhjbHVkZS4gSWYgYSBwcm9wZXJ0eSBuYW1lIG9yXG4gICAgICogIG9iamVjdCBpcyBwcm92aWRlZCBpdCB3aWxsIGJlIHVzZWQgdG8gY3JlYXRlIGEgXCJfLnBsdWNrXCIgb3IgXCJfLndoZXJlXCJcbiAgICAgKiAgc3R5bGUgY2FsbGJhY2ssIHJlc3BlY3RpdmVseS5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGNhbGxiYWNrYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnJlc3QoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBbMiwgM11cbiAgICAgKlxuICAgICAqIF8ucmVzdChbMSwgMiwgM10sIDIpO1xuICAgICAqIC8vID0+IFszXVxuICAgICAqXG4gICAgICogXy5yZXN0KFsxLCAyLCAzXSwgZnVuY3Rpb24obnVtKSB7XG4gICAgICogICByZXR1cm4gbnVtIDwgMztcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBbM11cbiAgICAgKlxuICAgICAqIHZhciBjaGFyYWN0ZXJzID0gW1xuICAgICAqICAgeyAnbmFtZSc6ICdiYXJuZXknLCAgJ2Jsb2NrZWQnOiB0cnVlLCAgJ2VtcGxveWVyJzogJ3NsYXRlJyB9LFxuICAgICAqICAgeyAnbmFtZSc6ICdmcmVkJywgICAgJ2Jsb2NrZWQnOiBmYWxzZSwgICdlbXBsb3llcic6ICdzbGF0ZScgfSxcbiAgICAgKiAgIHsgJ25hbWUnOiAncGViYmxlcycsICdibG9ja2VkJzogdHJ1ZSwgJ2VtcGxveWVyJzogJ25hJyB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIFwiXy5wbHVja1wiIGNhbGxiYWNrIHNob3J0aGFuZFxuICAgICAqIF8ucGx1Y2soXy5yZXN0KGNoYXJhY3RlcnMsICdibG9ja2VkJyksICduYW1lJyk7XG4gICAgICogLy8gPT4gWydmcmVkJywgJ3BlYmJsZXMnXVxuICAgICAqXG4gICAgICogLy8gdXNpbmcgXCJfLndoZXJlXCIgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5yZXN0KGNoYXJhY3RlcnMsIHsgJ2VtcGxveWVyJzogJ3NsYXRlJyB9KTtcbiAgICAgKiAvLyA9PiBbeyAnbmFtZSc6ICdwZWJibGVzJywgJ2Jsb2NrZWQnOiB0cnVlLCAnZW1wbG95ZXInOiAnbmEnIH1dXG4gICAgICovXG4gICAgZnVuY3Rpb24gcmVzdChhcnJheSwgY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgIT0gJ251bWJlcicgJiYgY2FsbGJhY2sgIT0gbnVsbCkge1xuICAgICAgICB2YXIgbiA9IDAsXG4gICAgICAgICAgICBpbmRleCA9IC0xLFxuICAgICAgICAgICAgbGVuZ3RoID0gYXJyYXkgPyBhcnJheS5sZW5ndGggOiAwO1xuXG4gICAgICAgIGNhbGxiYWNrID0gbG9kYXNoLmNyZWF0ZUNhbGxiYWNrKGNhbGxiYWNrLCB0aGlzQXJnLCAzKTtcbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGggJiYgY2FsbGJhY2soYXJyYXlbaW5kZXhdLCBpbmRleCwgYXJyYXkpKSB7XG4gICAgICAgICAgbisrO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuID0gKGNhbGxiYWNrID09IG51bGwgfHwgdGhpc0FyZykgPyAxIDogbmF0aXZlTWF4KDAsIGNhbGxiYWNrKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBzbGljZShhcnJheSwgbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXNlcyBhIGJpbmFyeSBzZWFyY2ggdG8gZGV0ZXJtaW5lIHRoZSBzbWFsbGVzdCBpbmRleCBhdCB3aGljaCBhIHZhbHVlXG4gICAgICogc2hvdWxkIGJlIGluc2VydGVkIGludG8gYSBnaXZlbiBzb3J0ZWQgYXJyYXkgaW4gb3JkZXIgdG8gbWFpbnRhaW4gdGhlIHNvcnRcbiAgICAgKiBvcmRlciBvZiB0aGUgYXJyYXkuIElmIGEgY2FsbGJhY2sgaXMgcHJvdmlkZWQgaXQgd2lsbCBiZSBleGVjdXRlZCBmb3JcbiAgICAgKiBgdmFsdWVgIGFuZCBlYWNoIGVsZW1lbnQgb2YgYGFycmF5YCB0byBjb21wdXRlIHRoZWlyIHNvcnQgcmFua2luZy4gVGhlXG4gICAgICogY2FsbGJhY2sgaXMgYm91bmQgdG8gYHRoaXNBcmdgIGFuZCBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OyAodmFsdWUpLlxuICAgICAqXG4gICAgICogSWYgYSBwcm9wZXJ0eSBuYW1lIGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy5wbHVja1wiIHN0eWxlXG4gICAgICogY2FsbGJhY2sgd2lsbCByZXR1cm4gdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICAgICAqXG4gICAgICogSWYgYW4gb2JqZWN0IGlzIHByb3ZpZGVkIGZvciBgY2FsbGJhY2tgIHRoZSBjcmVhdGVkIFwiXy53aGVyZVwiIHN0eWxlIGNhbGxiYWNrXG4gICAgICogd2lsbCByZXR1cm4gYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuIG9iamVjdCxcbiAgICAgKiBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlzXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gZXZhbHVhdGUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbY2FsbGJhY2s9aWRlbnRpdHldIFRoZSBmdW5jdGlvbiBjYWxsZWRcbiAgICAgKiAgcGVyIGl0ZXJhdGlvbi4gSWYgYSBwcm9wZXJ0eSBuYW1lIG9yIG9iamVjdCBpcyBwcm92aWRlZCBpdCB3aWxsIGJlIHVzZWRcbiAgICAgKiAgdG8gY3JlYXRlIGEgXCJfLnBsdWNrXCIgb3IgXCJfLndoZXJlXCIgc3R5bGUgY2FsbGJhY2ssIHJlc3BlY3RpdmVseS5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGNhbGxiYWNrYC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBhdCB3aGljaCBgdmFsdWVgIHNob3VsZCBiZSBpbnNlcnRlZFxuICAgICAqICBpbnRvIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc29ydGVkSW5kZXgoWzIwLCAzMCwgNTBdLCA0MCk7XG4gICAgICogLy8gPT4gMlxuICAgICAqXG4gICAgICogLy8gdXNpbmcgXCJfLnBsdWNrXCIgY2FsbGJhY2sgc2hvcnRoYW5kXG4gICAgICogXy5zb3J0ZWRJbmRleChbeyAneCc6IDIwIH0sIHsgJ3gnOiAzMCB9LCB7ICd4JzogNTAgfV0sIHsgJ3gnOiA0MCB9LCAneCcpO1xuICAgICAqIC8vID0+IDJcbiAgICAgKlxuICAgICAqIHZhciBkaWN0ID0ge1xuICAgICAqICAgJ3dvcmRUb051bWJlcic6IHsgJ3R3ZW50eSc6IDIwLCAndGhpcnR5JzogMzAsICdmb3VydHknOiA0MCwgJ2ZpZnR5JzogNTAgfVxuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBfLnNvcnRlZEluZGV4KFsndHdlbnR5JywgJ3RoaXJ0eScsICdmaWZ0eSddLCAnZm91cnR5JywgZnVuY3Rpb24od29yZCkge1xuICAgICAqICAgcmV0dXJuIGRpY3Qud29yZFRvTnVtYmVyW3dvcmRdO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IDJcbiAgICAgKlxuICAgICAqIF8uc29ydGVkSW5kZXgoWyd0d2VudHknLCAndGhpcnR5JywgJ2ZpZnR5J10sICdmb3VydHknLCBmdW5jdGlvbih3b3JkKSB7XG4gICAgICogICByZXR1cm4gdGhpcy53b3JkVG9OdW1iZXJbd29yZF07XG4gICAgICogfSwgZGljdCk7XG4gICAgICogLy8gPT4gMlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNvcnRlZEluZGV4KGFycmF5LCB2YWx1ZSwgY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICAgIHZhciBsb3cgPSAwLFxuICAgICAgICAgIGhpZ2ggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IGxvdztcblxuICAgICAgLy8gZXhwbGljaXRseSByZWZlcmVuY2UgYGlkZW50aXR5YCBmb3IgYmV0dGVyIGlubGluaW5nIGluIEZpcmVmb3hcbiAgICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgPyBsb2Rhc2guY3JlYXRlQ2FsbGJhY2soY2FsbGJhY2ssIHRoaXNBcmcsIDEpIDogaWRlbnRpdHk7XG4gICAgICB2YWx1ZSA9IGNhbGxiYWNrKHZhbHVlKTtcblxuICAgICAgd2hpbGUgKGxvdyA8IGhpZ2gpIHtcbiAgICAgICAgdmFyIG1pZCA9IChsb3cgKyBoaWdoKSA+Pj4gMTtcbiAgICAgICAgKGNhbGxiYWNrKGFycmF5W21pZF0pIDwgdmFsdWUpXG4gICAgICAgICAgPyBsb3cgPSBtaWQgKyAxXG4gICAgICAgICAgOiBoaWdoID0gbWlkO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGxvdztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIHVuaXF1ZSB2YWx1ZXMsIGluIG9yZGVyLCBvZiB0aGUgcHJvdmlkZWQgYXJyYXlzIHVzaW5nXG4gICAgICogc3RyaWN0IGVxdWFsaXR5IGZvciBjb21wYXJpc29ucywgaS5lLiBgPT09YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheXNcbiAgICAgKiBAcGFyYW0gey4uLkFycmF5fSBbYXJyYXldIFRoZSBhcnJheXMgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYW4gYXJyYXkgb2YgY29tYmluZWQgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnVuaW9uKFsxLCAyLCAzXSwgWzUsIDIsIDEsIDRdLCBbMiwgMV0pO1xuICAgICAqIC8vID0+IFsxLCAyLCAzLCA1LCA0XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVuaW9uKCkge1xuICAgICAgcmV0dXJuIGJhc2VVbmlxKGJhc2VGbGF0dGVuKGFyZ3VtZW50cywgdHJ1ZSwgdHJ1ZSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBkdXBsaWNhdGUtdmFsdWUtZnJlZSB2ZXJzaW9uIG9mIGFuIGFycmF5IHVzaW5nIHN0cmljdCBlcXVhbGl0eVxuICAgICAqIGZvciBjb21wYXJpc29ucywgaS5lLiBgPT09YC4gSWYgdGhlIGFycmF5IGlzIHNvcnRlZCwgcHJvdmlkaW5nXG4gICAgICogYHRydWVgIGZvciBgaXNTb3J0ZWRgIHdpbGwgdXNlIGEgZmFzdGVyIGFsZ29yaXRobS4gSWYgYSBjYWxsYmFjayBpcyBwcm92aWRlZFxuICAgICAqIGVhY2ggZWxlbWVudCBvZiBgYXJyYXlgIGlzIHBhc3NlZCB0aHJvdWdoIHRoZSBjYWxsYmFjayBiZWZvcmUgdW5pcXVlbmVzc1xuICAgICAqIGlzIGNvbXB1dGVkLiBUaGUgY2FsbGJhY2sgaXMgYm91bmQgdG8gYHRoaXNBcmdgIGFuZCBpbnZva2VkIHdpdGggdGhyZWVcbiAgICAgKiBhcmd1bWVudHM7ICh2YWx1ZSwgaW5kZXgsIGFycmF5KS5cbiAgICAgKlxuICAgICAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYGNhbGxiYWNrYCB0aGUgY3JlYXRlZCBcIl8ucGx1Y2tcIiBzdHlsZVxuICAgICAqIGNhbGxiYWNrIHdpbGwgcmV0dXJuIHRoZSBwcm9wZXJ0eSB2YWx1ZSBvZiB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIElmIGFuIG9iamVjdCBpcyBwcm92aWRlZCBmb3IgYGNhbGxiYWNrYCB0aGUgY3JlYXRlZCBcIl8ud2hlcmVcIiBzdHlsZSBjYWxsYmFja1xuICAgICAqIHdpbGwgcmV0dXJuIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBnaXZlbiBvYmplY3QsXG4gICAgICogZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGFsaWFzIHVuaXF1ZVxuICAgICAqIEBjYXRlZ29yeSBBcnJheXNcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcHJvY2Vzcy5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc1NvcnRlZD1mYWxzZV0gQSBmbGFnIHRvIGluZGljYXRlIHRoYXQgYGFycmF5YCBpcyBzb3J0ZWQuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbY2FsbGJhY2s9aWRlbnRpdHldIFRoZSBmdW5jdGlvbiBjYWxsZWRcbiAgICAgKiAgcGVyIGl0ZXJhdGlvbi4gSWYgYSBwcm9wZXJ0eSBuYW1lIG9yIG9iamVjdCBpcyBwcm92aWRlZCBpdCB3aWxsIGJlIHVzZWRcbiAgICAgKiAgdG8gY3JlYXRlIGEgXCJfLnBsdWNrXCIgb3IgXCJfLndoZXJlXCIgc3R5bGUgY2FsbGJhY2ssIHJlc3BlY3RpdmVseS5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGNhbGxiYWNrYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYSBkdXBsaWNhdGUtdmFsdWUtZnJlZSBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy51bmlxKFsxLCAyLCAxLCAzLCAxXSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICpcbiAgICAgKiBfLnVuaXEoWzEsIDEsIDIsIDIsIDNdLCB0cnVlKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKlxuICAgICAqIF8udW5pcShbJ0EnLCAnYicsICdDJywgJ2EnLCAnQicsICdjJ10sIGZ1bmN0aW9uKGxldHRlcikgeyByZXR1cm4gbGV0dGVyLnRvTG93ZXJDYXNlKCk7IH0pO1xuICAgICAqIC8vID0+IFsnQScsICdiJywgJ0MnXVxuICAgICAqXG4gICAgICogXy51bmlxKFsxLCAyLjUsIDMsIDEuNSwgMiwgMy41XSwgZnVuY3Rpb24obnVtKSB7IHJldHVybiB0aGlzLmZsb29yKG51bSk7IH0sIE1hdGgpO1xuICAgICAqIC8vID0+IFsxLCAyLjUsIDNdXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyBcIl8ucGx1Y2tcIiBjYWxsYmFjayBzaG9ydGhhbmRcbiAgICAgKiBfLnVuaXEoW3sgJ3gnOiAxIH0sIHsgJ3gnOiAyIH0sIHsgJ3gnOiAxIH1dLCAneCcpO1xuICAgICAqIC8vID0+IFt7ICd4JzogMSB9LCB7ICd4JzogMiB9XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVuaXEoYXJyYXksIGlzU29ydGVkLCBjYWxsYmFjaywgdGhpc0FyZykge1xuICAgICAgLy8ganVnZ2xlIGFyZ3VtZW50c1xuICAgICAgaWYgKHR5cGVvZiBpc1NvcnRlZCAhPSAnYm9vbGVhbicgJiYgaXNTb3J0ZWQgIT0gbnVsbCkge1xuICAgICAgICB0aGlzQXJnID0gY2FsbGJhY2s7XG4gICAgICAgIGNhbGxiYWNrID0gKHR5cGVvZiBpc1NvcnRlZCAhPSAnZnVuY3Rpb24nICYmIHRoaXNBcmcgJiYgdGhpc0FyZ1tpc1NvcnRlZF0gPT09IGFycmF5KSA/IG51bGwgOiBpc1NvcnRlZDtcbiAgICAgICAgaXNTb3J0ZWQgPSBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGlmIChjYWxsYmFjayAhPSBudWxsKSB7XG4gICAgICAgIGNhbGxiYWNrID0gbG9kYXNoLmNyZWF0ZUNhbGxiYWNrKGNhbGxiYWNrLCB0aGlzQXJnLCAzKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlVW5pcShhcnJheSwgaXNTb3J0ZWQsIGNhbGxiYWNrKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IGV4Y2x1ZGluZyBhbGwgcHJvdmlkZWQgdmFsdWVzIHVzaW5nIHN0cmljdCBlcXVhbGl0eSBmb3JcbiAgICAgKiBjb21wYXJpc29ucywgaS5lLiBgPT09YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBBcnJheXNcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gZmlsdGVyLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW3ZhbHVlXSBUaGUgdmFsdWVzIHRvIGV4Y2x1ZGUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGEgbmV3IGFycmF5IG9mIGZpbHRlcmVkIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy53aXRob3V0KFsxLCAyLCAxLCAwLCAzLCAxLCA0XSwgMCwgMSk7XG4gICAgICogLy8gPT4gWzIsIDMsIDRdXG4gICAgICovXG4gICAgZnVuY3Rpb24gd2l0aG91dChhcnJheSkge1xuICAgICAgcmV0dXJuIGJhc2VEaWZmZXJlbmNlKGFycmF5LCBzbGljZShhcmd1bWVudHMsIDEpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IHRoYXQgaXMgdGhlIHN5bW1ldHJpYyBkaWZmZXJlbmNlIG9mIHRoZSBwcm92aWRlZCBhcnJheXMuXG4gICAgICogU2VlIGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU3ltbWV0cmljX2RpZmZlcmVuY2UuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlzXG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5XSBUaGUgYXJyYXlzIHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGFuIGFycmF5IG9mIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy54b3IoWzEsIDIsIDNdLCBbNSwgMiwgMSwgNF0pO1xuICAgICAqIC8vID0+IFszLCA1LCA0XVxuICAgICAqXG4gICAgICogXy54b3IoWzEsIDIsIDVdLCBbMiwgMywgNV0sIFszLCA0LCA1XSk7XG4gICAgICogLy8gPT4gWzEsIDQsIDVdXG4gICAgICovXG4gICAgZnVuY3Rpb24geG9yKCkge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gYXJndW1lbnRzLmxlbmd0aDtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIGFycmF5ID0gYXJndW1lbnRzW2luZGV4XTtcbiAgICAgICAgaWYgKGlzQXJyYXkoYXJyYXkpIHx8IGlzQXJndW1lbnRzKGFycmF5KSkge1xuICAgICAgICAgIHZhciByZXN1bHQgPSByZXN1bHRcbiAgICAgICAgICAgID8gYmFzZVVuaXEoYmFzZURpZmZlcmVuY2UocmVzdWx0LCBhcnJheSkuY29uY2F0KGJhc2VEaWZmZXJlbmNlKGFycmF5LCByZXN1bHQpKSlcbiAgICAgICAgICAgIDogYXJyYXk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQgfHwgW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBncm91cGVkIGVsZW1lbnRzLCB0aGUgZmlyc3Qgb2Ygd2hpY2ggY29udGFpbnMgdGhlIGZpcnN0XG4gICAgICogZWxlbWVudHMgb2YgdGhlIGdpdmVuIGFycmF5cywgdGhlIHNlY29uZCBvZiB3aGljaCBjb250YWlucyB0aGUgc2Vjb25kXG4gICAgICogZWxlbWVudHMgb2YgdGhlIGdpdmVuIGFycmF5cywgYW5kIHNvIG9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGFsaWFzIHVuemlwXG4gICAgICogQGNhdGVnb3J5IEFycmF5c1xuICAgICAqIEBwYXJhbSB7Li4uQXJyYXl9IFthcnJheV0gQXJyYXlzIHRvIHByb2Nlc3MuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGEgbmV3IGFycmF5IG9mIGdyb3VwZWQgZWxlbWVudHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uemlwKFsnZnJlZCcsICdiYXJuZXknXSwgWzMwLCA0MF0sIFt0cnVlLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IFtbJ2ZyZWQnLCAzMCwgdHJ1ZV0sIFsnYmFybmV5JywgNDAsIGZhbHNlXV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB6aXAoKSB7XG4gICAgICB2YXIgYXJyYXkgPSBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50cyA6IGFyZ3VtZW50c1swXSxcbiAgICAgICAgICBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5ID8gbWF4KHBsdWNrKGFycmF5LCAnbGVuZ3RoJykpIDogMCxcbiAgICAgICAgICByZXN1bHQgPSBBcnJheShsZW5ndGggPCAwID8gMCA6IGxlbmd0aCk7XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHJlc3VsdFtpbmRleF0gPSBwbHVjayhhcnJheSwgaW5kZXgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIG9iamVjdCBjb21wb3NlZCBmcm9tIGFycmF5cyBvZiBga2V5c2AgYW5kIGB2YWx1ZXNgLiBQcm92aWRlXG4gICAgICogZWl0aGVyIGEgc2luZ2xlIHR3byBkaW1lbnNpb25hbCBhcnJheSwgaS5lLiBgW1trZXkxLCB2YWx1ZTFdLCBba2V5MiwgdmFsdWUyXV1gXG4gICAgICogb3IgdHdvIGFycmF5cywgb25lIG9mIGBrZXlzYCBhbmQgb25lIG9mIGNvcnJlc3BvbmRpbmcgYHZhbHVlc2AuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAYWxpYXMgb2JqZWN0XG4gICAgICogQGNhdGVnb3J5IEFycmF5c1xuICAgICAqIEBwYXJhbSB7QXJyYXl9IGtleXMgVGhlIGFycmF5IG9mIGtleXMuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW3ZhbHVlcz1bXV0gVGhlIGFycmF5IG9mIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGFuIG9iamVjdCBjb21wb3NlZCBvZiB0aGUgZ2l2ZW4ga2V5cyBhbmRcbiAgICAgKiAgY29ycmVzcG9uZGluZyB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uemlwT2JqZWN0KFsnZnJlZCcsICdiYXJuZXknXSwgWzMwLCA0MF0pO1xuICAgICAqIC8vID0+IHsgJ2ZyZWQnOiAzMCwgJ2Jhcm5leSc6IDQwIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB6aXBPYmplY3Qoa2V5cywgdmFsdWVzKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBrZXlzID8ga2V5cy5sZW5ndGggOiAwLFxuICAgICAgICAgIHJlc3VsdCA9IHt9O1xuXG4gICAgICBpZiAoIXZhbHVlcyAmJiBsZW5ndGggJiYgIWlzQXJyYXkoa2V5c1swXSkpIHtcbiAgICAgICAgdmFsdWVzID0gW107XG4gICAgICB9XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIga2V5ID0ga2V5c1tpbmRleF07XG4gICAgICAgIGlmICh2YWx1ZXMpIHtcbiAgICAgICAgICByZXN1bHRba2V5XSA9IHZhbHVlc1tpbmRleF07XG4gICAgICAgIH0gZWxzZSBpZiAoa2V5KSB7XG4gICAgICAgICAgcmVzdWx0W2tleVswXV0gPSBrZXlbMV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBleGVjdXRlcyBgZnVuY2AsIHdpdGggIHRoZSBgdGhpc2AgYmluZGluZyBhbmRcbiAgICAgKiBhcmd1bWVudHMgb2YgdGhlIGNyZWF0ZWQgZnVuY3Rpb24sIG9ubHkgYWZ0ZXIgYmVpbmcgY2FsbGVkIGBuYCB0aW1lcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvbnNcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbiBUaGUgbnVtYmVyIG9mIHRpbWVzIHRoZSBmdW5jdGlvbiBtdXN0IGJlIGNhbGxlZCBiZWZvcmVcbiAgICAgKiAgYGZ1bmNgIGlzIGV4ZWN1dGVkLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHJlc3RyaWN0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHJlc3RyaWN0ZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBzYXZlcyA9IFsncHJvZmlsZScsICdzZXR0aW5ncyddO1xuICAgICAqXG4gICAgICogdmFyIGRvbmUgPSBfLmFmdGVyKHNhdmVzLmxlbmd0aCwgZnVuY3Rpb24oKSB7XG4gICAgICogICBjb25zb2xlLmxvZygnRG9uZSBzYXZpbmchJyk7XG4gICAgICogfSk7XG4gICAgICpcbiAgICAgKiBfLmZvckVhY2goc2F2ZXMsIGZ1bmN0aW9uKHR5cGUpIHtcbiAgICAgKiAgIGFzeW5jU2F2ZSh7ICd0eXBlJzogdHlwZSwgJ2NvbXBsZXRlJzogZG9uZSB9KTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBsb2dzICdEb25lIHNhdmluZyEnLCBhZnRlciBhbGwgc2F2ZXMgaGF2ZSBjb21wbGV0ZWRcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhZnRlcihuLCBmdW5jKSB7XG4gICAgICBpZiAoIWlzRnVuY3Rpb24oZnVuYykpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcjtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKC0tbiA8IDEpIHtcbiAgICAgICAgICByZXR1cm4gZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0LCB3aGVuIGNhbGxlZCwgaW52b2tlcyBgZnVuY2Agd2l0aCB0aGUgYHRoaXNgXG4gICAgICogYmluZGluZyBvZiBgdGhpc0FyZ2AgYW5kIHByZXBlbmRzIGFueSBhZGRpdGlvbmFsIGBiaW5kYCBhcmd1bWVudHMgdG8gdGhvc2VcbiAgICAgKiBwcm92aWRlZCB0byB0aGUgYm91bmQgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25zXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gYmluZC5cbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW2FyZ10gQXJndW1lbnRzIHRvIGJlIHBhcnRpYWxseSBhcHBsaWVkLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGJvdW5kIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgZnVuYyA9IGZ1bmN0aW9uKGdyZWV0aW5nKSB7XG4gICAgICogICByZXR1cm4gZ3JlZXRpbmcgKyAnICcgKyB0aGlzLm5hbWU7XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIGZ1bmMgPSBfLmJpbmQoZnVuYywgeyAnbmFtZSc6ICdmcmVkJyB9LCAnaGknKTtcbiAgICAgKiBmdW5jKCk7XG4gICAgICogLy8gPT4gJ2hpIGZyZWQnXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmluZChmdW5jLCB0aGlzQXJnKSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA+IDJcbiAgICAgICAgPyBjcmVhdGVXcmFwcGVyKGZ1bmMsIDE3LCBzbGljZShhcmd1bWVudHMsIDIpLCBudWxsLCB0aGlzQXJnKVxuICAgICAgICA6IGNyZWF0ZVdyYXBwZXIoZnVuYywgMSwgbnVsbCwgbnVsbCwgdGhpc0FyZyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQmluZHMgbWV0aG9kcyBvZiBhbiBvYmplY3QgdG8gdGhlIG9iamVjdCBpdHNlbGYsIG92ZXJ3cml0aW5nIHRoZSBleGlzdGluZ1xuICAgICAqIG1ldGhvZC4gTWV0aG9kIG5hbWVzIG1heSBiZSBzcGVjaWZpZWQgYXMgaW5kaXZpZHVhbCBhcmd1bWVudHMgb3IgYXMgYXJyYXlzXG4gICAgICogb2YgbWV0aG9kIG5hbWVzLiBJZiBubyBtZXRob2QgbmFtZXMgYXJlIHByb3ZpZGVkIGFsbCB0aGUgZnVuY3Rpb24gcHJvcGVydGllc1xuICAgICAqIG9mIGBvYmplY3RgIHdpbGwgYmUgYm91bmQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25zXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGJpbmQgYW5kIGFzc2lnbiB0aGUgYm91bmQgbWV0aG9kcyB0by5cbiAgICAgKiBAcGFyYW0gey4uLnN0cmluZ30gW21ldGhvZE5hbWVdIFRoZSBvYmplY3QgbWV0aG9kIG5hbWVzIHRvXG4gICAgICogIGJpbmQsIHNwZWNpZmllZCBhcyBpbmRpdmlkdWFsIG1ldGhvZCBuYW1lcyBvciBhcnJheXMgb2YgbWV0aG9kIG5hbWVzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB2aWV3ID0ge1xuICAgICAqICAgJ2xhYmVsJzogJ2RvY3MnLFxuICAgICAqICAgJ29uQ2xpY2snOiBmdW5jdGlvbigpIHsgY29uc29sZS5sb2coJ2NsaWNrZWQgJyArIHRoaXMubGFiZWwpOyB9XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIF8uYmluZEFsbCh2aWV3KTtcbiAgICAgKiBqUXVlcnkoJyNkb2NzJykub24oJ2NsaWNrJywgdmlldy5vbkNsaWNrKTtcbiAgICAgKiAvLyA9PiBsb2dzICdjbGlja2VkIGRvY3MnLCB3aGVuIHRoZSBidXR0b24gaXMgY2xpY2tlZFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJpbmRBbGwob2JqZWN0KSB7XG4gICAgICB2YXIgZnVuY3MgPSBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGJhc2VGbGF0dGVuKGFyZ3VtZW50cywgdHJ1ZSwgZmFsc2UsIDEpIDogZnVuY3Rpb25zKG9iamVjdCksXG4gICAgICAgICAgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBmdW5jcy5sZW5ndGg7XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBrZXkgPSBmdW5jc1tpbmRleF07XG4gICAgICAgIG9iamVjdFtrZXldID0gY3JlYXRlV3JhcHBlcihvYmplY3Rba2V5XSwgMSwgbnVsbCwgbnVsbCwgb2JqZWN0KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQsIHdoZW4gY2FsbGVkLCBpbnZva2VzIHRoZSBtZXRob2QgYXQgYG9iamVjdFtrZXldYFxuICAgICAqIGFuZCBwcmVwZW5kcyBhbnkgYWRkaXRpb25hbCBgYmluZEtleWAgYXJndW1lbnRzIHRvIHRob3NlIHByb3ZpZGVkIHRvIHRoZSBib3VuZFxuICAgICAqIGZ1bmN0aW9uLiBUaGlzIG1ldGhvZCBkaWZmZXJzIGZyb20gYF8uYmluZGAgYnkgYWxsb3dpbmcgYm91bmQgZnVuY3Rpb25zIHRvXG4gICAgICogcmVmZXJlbmNlIG1ldGhvZHMgdGhhdCB3aWxsIGJlIHJlZGVmaW5lZCBvciBkb24ndCB5ZXQgZXhpc3QuXG4gICAgICogU2VlIGh0dHA6Ly9taWNoYXV4LmNhL2FydGljbGVzL2xhenktZnVuY3Rpb24tZGVmaW5pdGlvbi1wYXR0ZXJuLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uc1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0aGUgbWV0aG9kIGJlbG9uZ3MgdG8uXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBtZXRob2QuXG4gICAgICogQHBhcmFtIHsuLi4qfSBbYXJnXSBBcmd1bWVudHMgdG8gYmUgcGFydGlhbGx5IGFwcGxpZWQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYm91bmQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7XG4gICAgICogICAnbmFtZSc6ICdmcmVkJyxcbiAgICAgKiAgICdncmVldCc6IGZ1bmN0aW9uKGdyZWV0aW5nKSB7XG4gICAgICogICAgIHJldHVybiBncmVldGluZyArICcgJyArIHRoaXMubmFtZTtcbiAgICAgKiAgIH1cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogdmFyIGZ1bmMgPSBfLmJpbmRLZXkob2JqZWN0LCAnZ3JlZXQnLCAnaGknKTtcbiAgICAgKiBmdW5jKCk7XG4gICAgICogLy8gPT4gJ2hpIGZyZWQnXG4gICAgICpcbiAgICAgKiBvYmplY3QuZ3JlZXQgPSBmdW5jdGlvbihncmVldGluZykge1xuICAgICAqICAgcmV0dXJuIGdyZWV0aW5nICsgJ3lhICcgKyB0aGlzLm5hbWUgKyAnISc7XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIGZ1bmMoKTtcbiAgICAgKiAvLyA9PiAnaGl5YSBmcmVkISdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiaW5kS2V5KG9iamVjdCwga2V5KSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA+IDJcbiAgICAgICAgPyBjcmVhdGVXcmFwcGVyKGtleSwgMTksIHNsaWNlKGFyZ3VtZW50cywgMiksIG51bGwsIG9iamVjdClcbiAgICAgICAgOiBjcmVhdGVXcmFwcGVyKGtleSwgMywgbnVsbCwgbnVsbCwgb2JqZWN0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpcyB0aGUgY29tcG9zaXRpb24gb2YgdGhlIHByb3ZpZGVkIGZ1bmN0aW9ucyxcbiAgICAgKiB3aGVyZSBlYWNoIGZ1bmN0aW9uIGNvbnN1bWVzIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlIGZ1bmN0aW9uIHRoYXQgZm9sbG93cy5cbiAgICAgKiBGb3IgZXhhbXBsZSwgY29tcG9zaW5nIHRoZSBmdW5jdGlvbnMgYGYoKWAsIGBnKClgLCBhbmQgYGgoKWAgcHJvZHVjZXMgYGYoZyhoKCkpKWAuXG4gICAgICogRWFjaCBmdW5jdGlvbiBpcyBleGVjdXRlZCB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBvZiB0aGUgY29tcG9zZWQgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25zXG4gICAgICogQHBhcmFtIHsuLi5GdW5jdGlvbn0gW2Z1bmNdIEZ1bmN0aW9ucyB0byBjb21wb3NlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGNvbXBvc2VkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgcmVhbE5hbWVNYXAgPSB7XG4gICAgICogICAncGViYmxlcyc6ICdwZW5lbG9wZSdcbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogdmFyIGZvcm1hdCA9IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgKiAgIG5hbWUgPSByZWFsTmFtZU1hcFtuYW1lLnRvTG93ZXJDYXNlKCldIHx8IG5hbWU7XG4gICAgICogICByZXR1cm4gbmFtZS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIG5hbWUuc2xpY2UoMSkudG9Mb3dlckNhc2UoKTtcbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogdmFyIGdyZWV0ID0gZnVuY3Rpb24oZm9ybWF0dGVkKSB7XG4gICAgICogICByZXR1cm4gJ0hpeWEgJyArIGZvcm1hdHRlZCArICchJztcbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogdmFyIHdlbGNvbWUgPSBfLmNvbXBvc2UoZ3JlZXQsIGZvcm1hdCk7XG4gICAgICogd2VsY29tZSgncGViYmxlcycpO1xuICAgICAqIC8vID0+ICdIaXlhIFBlbmVsb3BlISdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb21wb3NlKCkge1xuICAgICAgdmFyIGZ1bmNzID0gYXJndW1lbnRzLFxuICAgICAgICAgIGxlbmd0aCA9IGZ1bmNzLmxlbmd0aDtcblxuICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgIGlmICghaXNGdW5jdGlvbihmdW5jc1tsZW5ndGhdKSkge1xuICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3I7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHMsXG4gICAgICAgICAgICBsZW5ndGggPSBmdW5jcy5sZW5ndGg7XG5cbiAgICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgICAgYXJncyA9IFtmdW5jc1tsZW5ndGhdLmFwcGx5KHRoaXMsIGFyZ3MpXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYXJnc1swXTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHdoaWNoIGFjY2VwdHMgb25lIG9yIG1vcmUgYXJndW1lbnRzIG9mIGBmdW5jYCB0aGF0IHdoZW5cbiAgICAgKiBpbnZva2VkIGVpdGhlciBleGVjdXRlcyBgZnVuY2AgcmV0dXJuaW5nIGl0cyByZXN1bHQsIGlmIGFsbCBgZnVuY2AgYXJndW1lbnRzXG4gICAgICogaGF2ZSBiZWVuIHByb3ZpZGVkLCBvciByZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCBhY2NlcHRzIG9uZSBvciBtb3JlIG9mIHRoZVxuICAgICAqIHJlbWFpbmluZyBgZnVuY2AgYXJndW1lbnRzLCBhbmQgc28gb24uIFRoZSBhcml0eSBvZiBgZnVuY2AgY2FuIGJlIHNwZWNpZmllZFxuICAgICAqIGlmIGBmdW5jLmxlbmd0aGAgaXMgbm90IHN1ZmZpY2llbnQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25zXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gY3VycnkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFthcml0eT1mdW5jLmxlbmd0aF0gVGhlIGFyaXR5IG9mIGBmdW5jYC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBjdXJyaWVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgY3VycmllZCA9IF8uY3VycnkoZnVuY3Rpb24oYSwgYiwgYykge1xuICAgICAqICAgY29uc29sZS5sb2coYSArIGIgKyBjKTtcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIGN1cnJpZWQoMSkoMikoMyk7XG4gICAgICogLy8gPT4gNlxuICAgICAqXG4gICAgICogY3VycmllZCgxLCAyKSgzKTtcbiAgICAgKiAvLyA9PiA2XG4gICAgICpcbiAgICAgKiBjdXJyaWVkKDEsIDIsIDMpO1xuICAgICAqIC8vID0+IDZcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjdXJyeShmdW5jLCBhcml0eSkge1xuICAgICAgYXJpdHkgPSB0eXBlb2YgYXJpdHkgPT0gJ251bWJlcicgPyBhcml0eSA6ICgrYXJpdHkgfHwgZnVuYy5sZW5ndGgpO1xuICAgICAgcmV0dXJuIGNyZWF0ZVdyYXBwZXIoZnVuYywgNCwgbnVsbCwgbnVsbCwgbnVsbCwgYXJpdHkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHdpbGwgZGVsYXkgdGhlIGV4ZWN1dGlvbiBvZiBgZnVuY2AgdW50aWwgYWZ0ZXJcbiAgICAgKiBgd2FpdGAgbWlsbGlzZWNvbmRzIGhhdmUgZWxhcHNlZCBzaW5jZSB0aGUgbGFzdCB0aW1lIGl0IHdhcyBpbnZva2VkLlxuICAgICAqIFByb3ZpZGUgYW4gb3B0aW9ucyBvYmplY3QgdG8gaW5kaWNhdGUgdGhhdCBgZnVuY2Agc2hvdWxkIGJlIGludm9rZWQgb25cbiAgICAgKiB0aGUgbGVhZGluZyBhbmQvb3IgdHJhaWxpbmcgZWRnZSBvZiB0aGUgYHdhaXRgIHRpbWVvdXQuIFN1YnNlcXVlbnQgY2FsbHNcbiAgICAgKiB0byB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uIHdpbGwgcmV0dXJuIHRoZSByZXN1bHQgb2YgdGhlIGxhc3QgYGZ1bmNgIGNhbGwuXG4gICAgICpcbiAgICAgKiBOb3RlOiBJZiBgbGVhZGluZ2AgYW5kIGB0cmFpbGluZ2Agb3B0aW9ucyBhcmUgYHRydWVgIGBmdW5jYCB3aWxsIGJlIGNhbGxlZFxuICAgICAqIG9uIHRoZSB0cmFpbGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0IG9ubHkgaWYgdGhlIHRoZSBkZWJvdW5jZWQgZnVuY3Rpb24gaXNcbiAgICAgKiBpbnZva2VkIG1vcmUgdGhhbiBvbmNlIGR1cmluZyB0aGUgYHdhaXRgIHRpbWVvdXQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25zXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gZGVib3VuY2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHdhaXQgVGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gZGVsYXkuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXSBUaGUgb3B0aW9ucyBvYmplY3QuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5sZWFkaW5nPWZhbHNlXSBTcGVjaWZ5IGV4ZWN1dGlvbiBvbiB0aGUgbGVhZGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy5tYXhXYWl0XSBUaGUgbWF4aW11bSB0aW1lIGBmdW5jYCBpcyBhbGxvd2VkIHRvIGJlIGRlbGF5ZWQgYmVmb3JlIGl0J3MgY2FsbGVkLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMudHJhaWxpbmc9dHJ1ZV0gU3BlY2lmeSBleGVjdXRpb24gb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZGVib3VuY2VkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAvLyBhdm9pZCBjb3N0bHkgY2FsY3VsYXRpb25zIHdoaWxlIHRoZSB3aW5kb3cgc2l6ZSBpcyBpbiBmbHV4XG4gICAgICogdmFyIGxhenlMYXlvdXQgPSBfLmRlYm91bmNlKGNhbGN1bGF0ZUxheW91dCwgMTUwKTtcbiAgICAgKiBqUXVlcnkod2luZG93KS5vbigncmVzaXplJywgbGF6eUxheW91dCk7XG4gICAgICpcbiAgICAgKiAvLyBleGVjdXRlIGBzZW5kTWFpbGAgd2hlbiB0aGUgY2xpY2sgZXZlbnQgaXMgZmlyZWQsIGRlYm91bmNpbmcgc3Vic2VxdWVudCBjYWxsc1xuICAgICAqIGpRdWVyeSgnI3Bvc3Rib3gnKS5vbignY2xpY2snLCBfLmRlYm91bmNlKHNlbmRNYWlsLCAzMDAsIHtcbiAgICAgKiAgICdsZWFkaW5nJzogdHJ1ZSxcbiAgICAgKiAgICd0cmFpbGluZyc6IGZhbHNlXG4gICAgICogfSk7XG4gICAgICpcbiAgICAgKiAvLyBlbnN1cmUgYGJhdGNoTG9nYCBpcyBleGVjdXRlZCBvbmNlIGFmdGVyIDEgc2Vjb25kIG9mIGRlYm91bmNlZCBjYWxsc1xuICAgICAqIHZhciBzb3VyY2UgPSBuZXcgRXZlbnRTb3VyY2UoJy9zdHJlYW0nKTtcbiAgICAgKiBzb3VyY2UuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIF8uZGVib3VuY2UoYmF0Y2hMb2csIDI1MCwge1xuICAgICAqICAgJ21heFdhaXQnOiAxMDAwXG4gICAgICogfSwgZmFsc2UpO1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGRlYm91bmNlKGZ1bmMsIHdhaXQsIG9wdGlvbnMpIHtcbiAgICAgIHZhciBhcmdzLFxuICAgICAgICAgIG1heFRpbWVvdXRJZCxcbiAgICAgICAgICByZXN1bHQsXG4gICAgICAgICAgc3RhbXAsXG4gICAgICAgICAgdGhpc0FyZyxcbiAgICAgICAgICB0aW1lb3V0SWQsXG4gICAgICAgICAgdHJhaWxpbmdDYWxsLFxuICAgICAgICAgIGxhc3RDYWxsZWQgPSAwLFxuICAgICAgICAgIG1heFdhaXQgPSBmYWxzZSxcbiAgICAgICAgICB0cmFpbGluZyA9IHRydWU7XG5cbiAgICAgIGlmICghaXNGdW5jdGlvbihmdW5jKSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yO1xuICAgICAgfVxuICAgICAgd2FpdCA9IG5hdGl2ZU1heCgwLCB3YWl0KSB8fCAwO1xuICAgICAgaWYgKG9wdGlvbnMgPT09IHRydWUpIHtcbiAgICAgICAgdmFyIGxlYWRpbmcgPSB0cnVlO1xuICAgICAgICB0cmFpbGluZyA9IGZhbHNlO1xuICAgICAgfSBlbHNlIGlmIChpc09iamVjdChvcHRpb25zKSkge1xuICAgICAgICBsZWFkaW5nID0gb3B0aW9ucy5sZWFkaW5nO1xuICAgICAgICBtYXhXYWl0ID0gJ21heFdhaXQnIGluIG9wdGlvbnMgJiYgKG5hdGl2ZU1heCh3YWl0LCBvcHRpb25zLm1heFdhaXQpIHx8IDApO1xuICAgICAgICB0cmFpbGluZyA9ICd0cmFpbGluZycgaW4gb3B0aW9ucyA/IG9wdGlvbnMudHJhaWxpbmcgOiB0cmFpbGluZztcbiAgICAgIH1cbiAgICAgIHZhciBkZWxheWVkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciByZW1haW5pbmcgPSB3YWl0IC0gKG5vdygpIC0gc3RhbXApO1xuICAgICAgICBpZiAocmVtYWluaW5nIDw9IDApIHtcbiAgICAgICAgICBpZiAobWF4VGltZW91dElkKSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQobWF4VGltZW91dElkKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIGlzQ2FsbGVkID0gdHJhaWxpbmdDYWxsO1xuICAgICAgICAgIG1heFRpbWVvdXRJZCA9IHRpbWVvdXRJZCA9IHRyYWlsaW5nQ2FsbCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICBpZiAoaXNDYWxsZWQpIHtcbiAgICAgICAgICAgIGxhc3RDYWxsZWQgPSBub3coKTtcbiAgICAgICAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkodGhpc0FyZywgYXJncyk7XG4gICAgICAgICAgICBpZiAoIXRpbWVvdXRJZCAmJiAhbWF4VGltZW91dElkKSB7XG4gICAgICAgICAgICAgIGFyZ3MgPSB0aGlzQXJnID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGltZW91dElkID0gc2V0VGltZW91dChkZWxheWVkLCByZW1haW5pbmcpO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICB2YXIgbWF4RGVsYXllZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGltZW91dElkKSB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXRJZCk7XG4gICAgICAgIH1cbiAgICAgICAgbWF4VGltZW91dElkID0gdGltZW91dElkID0gdHJhaWxpbmdDYWxsID0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAodHJhaWxpbmcgfHwgKG1heFdhaXQgIT09IHdhaXQpKSB7XG4gICAgICAgICAgbGFzdENhbGxlZCA9IG5vdygpO1xuICAgICAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkodGhpc0FyZywgYXJncyk7XG4gICAgICAgICAgaWYgKCF0aW1lb3V0SWQgJiYgIW1heFRpbWVvdXRJZCkge1xuICAgICAgICAgICAgYXJncyA9IHRoaXNBcmcgPSBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgICBzdGFtcCA9IG5vdygpO1xuICAgICAgICB0aGlzQXJnID0gdGhpcztcbiAgICAgICAgdHJhaWxpbmdDYWxsID0gdHJhaWxpbmcgJiYgKHRpbWVvdXRJZCB8fCAhbGVhZGluZyk7XG5cbiAgICAgICAgaWYgKG1heFdhaXQgPT09IGZhbHNlKSB7XG4gICAgICAgICAgdmFyIGxlYWRpbmdDYWxsID0gbGVhZGluZyAmJiAhdGltZW91dElkO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICghbWF4VGltZW91dElkICYmICFsZWFkaW5nKSB7XG4gICAgICAgICAgICBsYXN0Q2FsbGVkID0gc3RhbXA7XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhciByZW1haW5pbmcgPSBtYXhXYWl0IC0gKHN0YW1wIC0gbGFzdENhbGxlZCksXG4gICAgICAgICAgICAgIGlzQ2FsbGVkID0gcmVtYWluaW5nIDw9IDA7XG5cbiAgICAgICAgICBpZiAoaXNDYWxsZWQpIHtcbiAgICAgICAgICAgIGlmIChtYXhUaW1lb3V0SWQpIHtcbiAgICAgICAgICAgICAgbWF4VGltZW91dElkID0gY2xlYXJUaW1lb3V0KG1heFRpbWVvdXRJZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsYXN0Q2FsbGVkID0gc3RhbXA7XG4gICAgICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KHRoaXNBcmcsIGFyZ3MpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIGlmICghbWF4VGltZW91dElkKSB7XG4gICAgICAgICAgICBtYXhUaW1lb3V0SWQgPSBzZXRUaW1lb3V0KG1heERlbGF5ZWQsIHJlbWFpbmluZyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChpc0NhbGxlZCAmJiB0aW1lb3V0SWQpIHtcbiAgICAgICAgICB0aW1lb3V0SWQgPSBjbGVhclRpbWVvdXQodGltZW91dElkKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICghdGltZW91dElkICYmIHdhaXQgIT09IG1heFdhaXQpIHtcbiAgICAgICAgICB0aW1lb3V0SWQgPSBzZXRUaW1lb3V0KGRlbGF5ZWQsIHdhaXQpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChsZWFkaW5nQ2FsbCkge1xuICAgICAgICAgIGlzQ2FsbGVkID0gdHJ1ZTtcbiAgICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KHRoaXNBcmcsIGFyZ3MpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc0NhbGxlZCAmJiAhdGltZW91dElkICYmICFtYXhUaW1lb3V0SWQpIHtcbiAgICAgICAgICBhcmdzID0gdGhpc0FyZyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGVmZXJzIGV4ZWN1dGluZyB0aGUgYGZ1bmNgIGZ1bmN0aW9uIHVudGlsIHRoZSBjdXJyZW50IGNhbGwgc3RhY2sgaGFzIGNsZWFyZWQuXG4gICAgICogQWRkaXRpb25hbCBhcmd1bWVudHMgd2lsbCBiZSBwcm92aWRlZCB0byBgZnVuY2Agd2hlbiBpdCBpcyBpbnZva2VkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uc1xuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRlZmVyLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW2FyZ10gQXJndW1lbnRzIHRvIGludm9rZSB0aGUgZnVuY3Rpb24gd2l0aC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSB0aW1lciBpZC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5kZWZlcihmdW5jdGlvbih0ZXh0KSB7IGNvbnNvbGUubG9nKHRleHQpOyB9LCAnZGVmZXJyZWQnKTtcbiAgICAgKiAvLyBsb2dzICdkZWZlcnJlZCcgYWZ0ZXIgb25lIG9yIG1vcmUgbWlsbGlzZWNvbmRzXG4gICAgICovXG4gICAgZnVuY3Rpb24gZGVmZXIoZnVuYykge1xuICAgICAgaWYgKCFpc0Z1bmN0aW9uKGZ1bmMpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3I7XG4gICAgICB9XG4gICAgICB2YXIgYXJncyA9IHNsaWNlKGFyZ3VtZW50cywgMSk7XG4gICAgICByZXR1cm4gc2V0VGltZW91dChmdW5jdGlvbigpIHsgZnVuYy5hcHBseSh1bmRlZmluZWQsIGFyZ3MpOyB9LCAxKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFeGVjdXRlcyB0aGUgYGZ1bmNgIGZ1bmN0aW9uIGFmdGVyIGB3YWl0YCBtaWxsaXNlY29uZHMuIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAgICogd2lsbCBiZSBwcm92aWRlZCB0byBgZnVuY2Agd2hlbiBpdCBpcyBpbnZva2VkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uc1xuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRlbGF5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB3YWl0IFRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIGRlbGF5IGV4ZWN1dGlvbi5cbiAgICAgKiBAcGFyYW0gey4uLip9IFthcmddIEFyZ3VtZW50cyB0byBpbnZva2UgdGhlIGZ1bmN0aW9uIHdpdGguXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgdGltZXIgaWQuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZGVsYXkoZnVuY3Rpb24odGV4dCkgeyBjb25zb2xlLmxvZyh0ZXh0KTsgfSwgMTAwMCwgJ2xhdGVyJyk7XG4gICAgICogLy8gPT4gbG9ncyAnbGF0ZXInIGFmdGVyIG9uZSBzZWNvbmRcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBkZWxheShmdW5jLCB3YWl0KSB7XG4gICAgICBpZiAoIWlzRnVuY3Rpb24oZnVuYykpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcjtcbiAgICAgIH1cbiAgICAgIHZhciBhcmdzID0gc2xpY2UoYXJndW1lbnRzLCAyKTtcbiAgICAgIHJldHVybiBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgeyBmdW5jLmFwcGx5KHVuZGVmaW5lZCwgYXJncyk7IH0sIHdhaXQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IG1lbW9pemVzIHRoZSByZXN1bHQgb2YgYGZ1bmNgLiBJZiBgcmVzb2x2ZXJgIGlzXG4gICAgICogcHJvdmlkZWQgaXQgd2lsbCBiZSB1c2VkIHRvIGRldGVybWluZSB0aGUgY2FjaGUga2V5IGZvciBzdG9yaW5nIHRoZSByZXN1bHRcbiAgICAgKiBiYXNlZCBvbiB0aGUgYXJndW1lbnRzIHByb3ZpZGVkIHRvIHRoZSBtZW1vaXplZCBmdW5jdGlvbi4gQnkgZGVmYXVsdCwgdGhlXG4gICAgICogZmlyc3QgYXJndW1lbnQgcHJvdmlkZWQgdG8gdGhlIG1lbW9pemVkIGZ1bmN0aW9uIGlzIHVzZWQgYXMgdGhlIGNhY2hlIGtleS5cbiAgICAgKiBUaGUgYGZ1bmNgIGlzIGV4ZWN1dGVkIHdpdGggdGhlIGB0aGlzYCBiaW5kaW5nIG9mIHRoZSBtZW1vaXplZCBmdW5jdGlvbi5cbiAgICAgKiBUaGUgcmVzdWx0IGNhY2hlIGlzIGV4cG9zZWQgYXMgdGhlIGBjYWNoZWAgcHJvcGVydHkgb24gdGhlIG1lbW9pemVkIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uc1xuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGhhdmUgaXRzIG91dHB1dCBtZW1vaXplZC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcmVzb2x2ZXJdIEEgZnVuY3Rpb24gdXNlZCB0byByZXNvbHZlIHRoZSBjYWNoZSBrZXkuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgbWVtb2l6aW5nIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgZmlib25hY2NpID0gXy5tZW1vaXplKGZ1bmN0aW9uKG4pIHtcbiAgICAgKiAgIHJldHVybiBuIDwgMiA/IG4gOiBmaWJvbmFjY2kobiAtIDEpICsgZmlib25hY2NpKG4gLSAyKTtcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIGZpYm9uYWNjaSg5KVxuICAgICAqIC8vID0+IDM0XG4gICAgICpcbiAgICAgKiB2YXIgZGF0YSA9IHtcbiAgICAgKiAgICdmcmVkJzogeyAnbmFtZSc6ICdmcmVkJywgJ2FnZSc6IDQwIH0sXG4gICAgICogICAncGViYmxlcyc6IHsgJ25hbWUnOiAncGViYmxlcycsICdhZ2UnOiAxIH1cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogLy8gbW9kaWZ5aW5nIHRoZSByZXN1bHQgY2FjaGVcbiAgICAgKiB2YXIgZ2V0ID0gXy5tZW1vaXplKGZ1bmN0aW9uKG5hbWUpIHsgcmV0dXJuIGRhdGFbbmFtZV07IH0sIF8uaWRlbnRpdHkpO1xuICAgICAqIGdldCgncGViYmxlcycpO1xuICAgICAqIC8vID0+IHsgJ25hbWUnOiAncGViYmxlcycsICdhZ2UnOiAxIH1cbiAgICAgKlxuICAgICAqIGdldC5jYWNoZS5wZWJibGVzLm5hbWUgPSAncGVuZWxvcGUnO1xuICAgICAqIGdldCgncGViYmxlcycpO1xuICAgICAqIC8vID0+IHsgJ25hbWUnOiAncGVuZWxvcGUnLCAnYWdlJzogMSB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gbWVtb2l6ZShmdW5jLCByZXNvbHZlcikge1xuICAgICAgaWYgKCFpc0Z1bmN0aW9uKGZ1bmMpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3I7XG4gICAgICB9XG4gICAgICB2YXIgbWVtb2l6ZWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGNhY2hlID0gbWVtb2l6ZWQuY2FjaGUsXG4gICAgICAgICAgICBrZXkgPSByZXNvbHZlciA/IHJlc29sdmVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgOiBrZXlQcmVmaXggKyBhcmd1bWVudHNbMF07XG5cbiAgICAgICAgcmV0dXJuIGhhc093blByb3BlcnR5LmNhbGwoY2FjaGUsIGtleSlcbiAgICAgICAgICA/IGNhY2hlW2tleV1cbiAgICAgICAgICA6IChjYWNoZVtrZXldID0gZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpKTtcbiAgICAgIH1cbiAgICAgIG1lbW9pemVkLmNhY2hlID0ge307XG4gICAgICByZXR1cm4gbWVtb2l6ZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaXMgcmVzdHJpY3RlZCB0byBleGVjdXRlIGBmdW5jYCBvbmNlLiBSZXBlYXQgY2FsbHMgdG9cbiAgICAgKiB0aGUgZnVuY3Rpb24gd2lsbCByZXR1cm4gdGhlIHZhbHVlIG9mIHRoZSBmaXJzdCBjYWxsLiBUaGUgYGZ1bmNgIGlzIGV4ZWN1dGVkXG4gICAgICogd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgb2YgdGhlIGNyZWF0ZWQgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25zXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcmVzdHJpY3QuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgcmVzdHJpY3RlZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGluaXRpYWxpemUgPSBfLm9uY2UoY3JlYXRlQXBwbGljYXRpb24pO1xuICAgICAqIGluaXRpYWxpemUoKTtcbiAgICAgKiBpbml0aWFsaXplKCk7XG4gICAgICogLy8gYGluaXRpYWxpemVgIGV4ZWN1dGVzIGBjcmVhdGVBcHBsaWNhdGlvbmAgb25jZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG9uY2UoZnVuYykge1xuICAgICAgdmFyIHJhbixcbiAgICAgICAgICByZXN1bHQ7XG5cbiAgICAgIGlmICghaXNGdW5jdGlvbihmdW5jKSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAocmFuKSB7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICByYW4gPSB0cnVlO1xuICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG5cbiAgICAgICAgLy8gY2xlYXIgdGhlIGBmdW5jYCB2YXJpYWJsZSBzbyB0aGUgZnVuY3Rpb24gbWF5IGJlIGdhcmJhZ2UgY29sbGVjdGVkXG4gICAgICAgIGZ1bmMgPSBudWxsO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCwgd2hlbiBjYWxsZWQsIGludm9rZXMgYGZ1bmNgIHdpdGggYW55IGFkZGl0aW9uYWxcbiAgICAgKiBgcGFydGlhbGAgYXJndW1lbnRzIHByZXBlbmRlZCB0byB0aG9zZSBwcm92aWRlZCB0byB0aGUgbmV3IGZ1bmN0aW9uLiBUaGlzXG4gICAgICogbWV0aG9kIGlzIHNpbWlsYXIgdG8gYF8uYmluZGAgZXhjZXB0IGl0IGRvZXMgKipub3QqKiBhbHRlciB0aGUgYHRoaXNgIGJpbmRpbmcuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25zXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcGFydGlhbGx5IGFwcGx5IGFyZ3VtZW50cyB0by5cbiAgICAgKiBAcGFyYW0gey4uLip9IFthcmddIEFyZ3VtZW50cyB0byBiZSBwYXJ0aWFsbHkgYXBwbGllZC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBwYXJ0aWFsbHkgYXBwbGllZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGdyZWV0ID0gZnVuY3Rpb24oZ3JlZXRpbmcsIG5hbWUpIHsgcmV0dXJuIGdyZWV0aW5nICsgJyAnICsgbmFtZTsgfTtcbiAgICAgKiB2YXIgaGkgPSBfLnBhcnRpYWwoZ3JlZXQsICdoaScpO1xuICAgICAqIGhpKCdmcmVkJyk7XG4gICAgICogLy8gPT4gJ2hpIGZyZWQnXG4gICAgICovXG4gICAgZnVuY3Rpb24gcGFydGlhbChmdW5jKSB7XG4gICAgICByZXR1cm4gY3JlYXRlV3JhcHBlcihmdW5jLCAxNiwgc2xpY2UoYXJndW1lbnRzLCAxKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5wYXJ0aWFsYCBleGNlcHQgdGhhdCBgcGFydGlhbGAgYXJndW1lbnRzIGFyZVxuICAgICAqIGFwcGVuZGVkIHRvIHRob3NlIHByb3ZpZGVkIHRvIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25zXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcGFydGlhbGx5IGFwcGx5IGFyZ3VtZW50cyB0by5cbiAgICAgKiBAcGFyYW0gey4uLip9IFthcmddIEFyZ3VtZW50cyB0byBiZSBwYXJ0aWFsbHkgYXBwbGllZC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBwYXJ0aWFsbHkgYXBwbGllZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGRlZmF1bHRzRGVlcCA9IF8ucGFydGlhbFJpZ2h0KF8ubWVyZ2UsIF8uZGVmYXVsdHMpO1xuICAgICAqXG4gICAgICogdmFyIG9wdGlvbnMgPSB7XG4gICAgICogICAndmFyaWFibGUnOiAnZGF0YScsXG4gICAgICogICAnaW1wb3J0cyc6IHsgJ2pxJzogJCB9XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIGRlZmF1bHRzRGVlcChvcHRpb25zLCBfLnRlbXBsYXRlU2V0dGluZ3MpO1xuICAgICAqXG4gICAgICogb3B0aW9ucy52YXJpYWJsZVxuICAgICAqIC8vID0+ICdkYXRhJ1xuICAgICAqXG4gICAgICogb3B0aW9ucy5pbXBvcnRzXG4gICAgICogLy8gPT4geyAnXyc6IF8sICdqcSc6ICQgfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHBhcnRpYWxSaWdodChmdW5jKSB7XG4gICAgICByZXR1cm4gY3JlYXRlV3JhcHBlcihmdW5jLCAzMiwgbnVsbCwgc2xpY2UoYXJndW1lbnRzLCAxKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQsIHdoZW4gZXhlY3V0ZWQsIHdpbGwgb25seSBjYWxsIHRoZSBgZnVuY2AgZnVuY3Rpb25cbiAgICAgKiBhdCBtb3N0IG9uY2UgcGVyIGV2ZXJ5IGB3YWl0YCBtaWxsaXNlY29uZHMuIFByb3ZpZGUgYW4gb3B0aW9ucyBvYmplY3QgdG9cbiAgICAgKiBpbmRpY2F0ZSB0aGF0IGBmdW5jYCBzaG91bGQgYmUgaW52b2tlZCBvbiB0aGUgbGVhZGluZyBhbmQvb3IgdHJhaWxpbmcgZWRnZVxuICAgICAqIG9mIHRoZSBgd2FpdGAgdGltZW91dC4gU3Vic2VxdWVudCBjYWxscyB0byB0aGUgdGhyb3R0bGVkIGZ1bmN0aW9uIHdpbGxcbiAgICAgKiByZXR1cm4gdGhlIHJlc3VsdCBvZiB0aGUgbGFzdCBgZnVuY2AgY2FsbC5cbiAgICAgKlxuICAgICAqIE5vdGU6IElmIGBsZWFkaW5nYCBhbmQgYHRyYWlsaW5nYCBvcHRpb25zIGFyZSBgdHJ1ZWAgYGZ1bmNgIHdpbGwgYmUgY2FsbGVkXG4gICAgICogb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQgb25seSBpZiB0aGUgdGhlIHRocm90dGxlZCBmdW5jdGlvbiBpc1xuICAgICAqIGludm9rZWQgbW9yZSB0aGFuIG9uY2UgZHVyaW5nIHRoZSBgd2FpdGAgdGltZW91dC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvbnNcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byB0aHJvdHRsZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gd2FpdCBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byB0aHJvdHRsZSBleGVjdXRpb25zIHRvLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc10gVGhlIG9wdGlvbnMgb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMubGVhZGluZz10cnVlXSBTcGVjaWZ5IGV4ZWN1dGlvbiBvbiB0aGUgbGVhZGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0LlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMudHJhaWxpbmc9dHJ1ZV0gU3BlY2lmeSBleGVjdXRpb24gb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgdGhyb3R0bGVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiAvLyBhdm9pZCBleGNlc3NpdmVseSB1cGRhdGluZyB0aGUgcG9zaXRpb24gd2hpbGUgc2Nyb2xsaW5nXG4gICAgICogdmFyIHRocm90dGxlZCA9IF8udGhyb3R0bGUodXBkYXRlUG9zaXRpb24sIDEwMCk7XG4gICAgICogalF1ZXJ5KHdpbmRvdykub24oJ3Njcm9sbCcsIHRocm90dGxlZCk7XG4gICAgICpcbiAgICAgKiAvLyBleGVjdXRlIGByZW5ld1Rva2VuYCB3aGVuIHRoZSBjbGljayBldmVudCBpcyBmaXJlZCwgYnV0IG5vdCBtb3JlIHRoYW4gb25jZSBldmVyeSA1IG1pbnV0ZXNcbiAgICAgKiBqUXVlcnkoJy5pbnRlcmFjdGl2ZScpLm9uKCdjbGljaycsIF8udGhyb3R0bGUocmVuZXdUb2tlbiwgMzAwMDAwLCB7XG4gICAgICogICAndHJhaWxpbmcnOiBmYWxzZVxuICAgICAqIH0pKTtcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0aHJvdHRsZShmdW5jLCB3YWl0LCBvcHRpb25zKSB7XG4gICAgICB2YXIgbGVhZGluZyA9IHRydWUsXG4gICAgICAgICAgdHJhaWxpbmcgPSB0cnVlO1xuXG4gICAgICBpZiAoIWlzRnVuY3Rpb24oZnVuYykpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcjtcbiAgICAgIH1cbiAgICAgIGlmIChvcHRpb25zID09PSBmYWxzZSkge1xuICAgICAgICBsZWFkaW5nID0gZmFsc2U7XG4gICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KG9wdGlvbnMpKSB7XG4gICAgICAgIGxlYWRpbmcgPSAnbGVhZGluZycgaW4gb3B0aW9ucyA/IG9wdGlvbnMubGVhZGluZyA6IGxlYWRpbmc7XG4gICAgICAgIHRyYWlsaW5nID0gJ3RyYWlsaW5nJyBpbiBvcHRpb25zID8gb3B0aW9ucy50cmFpbGluZyA6IHRyYWlsaW5nO1xuICAgICAgfVxuICAgICAgZGVib3VuY2VPcHRpb25zLmxlYWRpbmcgPSBsZWFkaW5nO1xuICAgICAgZGVib3VuY2VPcHRpb25zLm1heFdhaXQgPSB3YWl0O1xuICAgICAgZGVib3VuY2VPcHRpb25zLnRyYWlsaW5nID0gdHJhaWxpbmc7XG5cbiAgICAgIHJldHVybiBkZWJvdW5jZShmdW5jLCB3YWl0LCBkZWJvdW5jZU9wdGlvbnMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHByb3ZpZGVzIGB2YWx1ZWAgdG8gdGhlIHdyYXBwZXIgZnVuY3Rpb24gYXMgaXRzXG4gICAgICogZmlyc3QgYXJndW1lbnQuIEFkZGl0aW9uYWwgYXJndW1lbnRzIHByb3ZpZGVkIHRvIHRoZSBmdW5jdGlvbiBhcmUgYXBwZW5kZWRcbiAgICAgKiB0byB0aG9zZSBwcm92aWRlZCB0byB0aGUgd3JhcHBlciBmdW5jdGlvbi4gVGhlIHdyYXBwZXIgaXMgZXhlY3V0ZWQgd2l0aFxuICAgICAqIHRoZSBgdGhpc2AgYmluZGluZyBvZiB0aGUgY3JlYXRlZCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvbnNcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byB3cmFwLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHdyYXBwZXIgVGhlIHdyYXBwZXIgZnVuY3Rpb24uXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBwID0gXy53cmFwKF8uZXNjYXBlLCBmdW5jdGlvbihmdW5jLCB0ZXh0KSB7XG4gICAgICogICByZXR1cm4gJzxwPicgKyBmdW5jKHRleHQpICsgJzwvcD4nO1xuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogcCgnRnJlZCwgV2lsbWEsICYgUGViYmxlcycpO1xuICAgICAqIC8vID0+ICc8cD5GcmVkLCBXaWxtYSwgJmFtcDsgUGViYmxlczwvcD4nXG4gICAgICovXG4gICAgZnVuY3Rpb24gd3JhcCh2YWx1ZSwgd3JhcHBlcikge1xuICAgICAgcmV0dXJuIGNyZWF0ZVdyYXBwZXIod3JhcHBlciwgMTYsIFt2YWx1ZV0pO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxpdGllc1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHJldHVybiBmcm9tIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICduYW1lJzogJ2ZyZWQnIH07XG4gICAgICogdmFyIGdldHRlciA9IF8uY29uc3RhbnQob2JqZWN0KTtcbiAgICAgKiBnZXR0ZXIoKSA9PT0gb2JqZWN0O1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb25zdGFudCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFByb2R1Y2VzIGEgY2FsbGJhY2sgYm91bmQgdG8gYW4gb3B0aW9uYWwgYHRoaXNBcmdgLiBJZiBgZnVuY2AgaXMgYSBwcm9wZXJ0eVxuICAgICAqIG5hbWUgdGhlIGNyZWF0ZWQgY2FsbGJhY2sgd2lsbCByZXR1cm4gdGhlIHByb3BlcnR5IHZhbHVlIGZvciBhIGdpdmVuIGVsZW1lbnQuXG4gICAgICogSWYgYGZ1bmNgIGlzIGFuIG9iamVjdCB0aGUgY3JlYXRlZCBjYWxsYmFjayB3aWxsIHJldHVybiBgdHJ1ZWAgZm9yIGVsZW1lbnRzXG4gICAgICogdGhhdCBjb250YWluIHRoZSBlcXVpdmFsZW50IG9iamVjdCBwcm9wZXJ0aWVzLCBvdGhlcndpc2UgaXQgd2lsbCByZXR1cm4gYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsaXRpZXNcbiAgICAgKiBAcGFyYW0geyp9IFtmdW5jPWlkZW50aXR5XSBUaGUgdmFsdWUgdG8gY29udmVydCB0byBhIGNhbGxiYWNrLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiB0aGUgY3JlYXRlZCBjYWxsYmFjay5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2FyZ0NvdW50XSBUaGUgbnVtYmVyIG9mIGFyZ3VtZW50cyB0aGUgY2FsbGJhY2sgYWNjZXB0cy5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgYSBjYWxsYmFjayBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGNoYXJhY3RlcnMgPSBbXG4gICAgICogICB7ICduYW1lJzogJ2Jhcm5leScsICdhZ2UnOiAzNiB9LFxuICAgICAqICAgeyAnbmFtZSc6ICdmcmVkJywgICAnYWdlJzogNDAgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiAvLyB3cmFwIHRvIGNyZWF0ZSBjdXN0b20gY2FsbGJhY2sgc2hvcnRoYW5kc1xuICAgICAqIF8uY3JlYXRlQ2FsbGJhY2sgPSBfLndyYXAoXy5jcmVhdGVDYWxsYmFjaywgZnVuY3Rpb24oZnVuYywgY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgICAgKiAgIHZhciBtYXRjaCA9IC9eKC4rPylfXyhbZ2xddCkoLispJC8uZXhlYyhjYWxsYmFjayk7XG4gICAgICogICByZXR1cm4gIW1hdGNoID8gZnVuYyhjYWxsYmFjaywgdGhpc0FyZykgOiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgKiAgICAgcmV0dXJuIG1hdGNoWzJdID09ICdndCcgPyBvYmplY3RbbWF0Y2hbMV1dID4gbWF0Y2hbM10gOiBvYmplY3RbbWF0Y2hbMV1dIDwgbWF0Y2hbM107XG4gICAgICogICB9O1xuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogXy5maWx0ZXIoY2hhcmFjdGVycywgJ2FnZV9fZ3QzOCcpO1xuICAgICAqIC8vID0+IFt7ICduYW1lJzogJ2ZyZWQnLCAnYWdlJzogNDAgfV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVDYWxsYmFjayhmdW5jLCB0aGlzQXJnLCBhcmdDb3VudCkge1xuICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgZnVuYztcbiAgICAgIGlmIChmdW5jID09IG51bGwgfHwgdHlwZSA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBiYXNlQ3JlYXRlQ2FsbGJhY2soZnVuYywgdGhpc0FyZywgYXJnQ291bnQpO1xuICAgICAgfVxuICAgICAgLy8gaGFuZGxlIFwiXy5wbHVja1wiIHN0eWxlIGNhbGxiYWNrIHNob3J0aGFuZHNcbiAgICAgIGlmICh0eXBlICE9ICdvYmplY3QnKSB7XG4gICAgICAgIHJldHVybiBwcm9wZXJ0eShmdW5jKTtcbiAgICAgIH1cbiAgICAgIHZhciBwcm9wcyA9IGtleXMoZnVuYyksXG4gICAgICAgICAga2V5ID0gcHJvcHNbMF0sXG4gICAgICAgICAgYSA9IGZ1bmNba2V5XTtcblxuICAgICAgLy8gaGFuZGxlIFwiXy53aGVyZVwiIHN0eWxlIGNhbGxiYWNrIHNob3J0aGFuZHNcbiAgICAgIGlmIChwcm9wcy5sZW5ndGggPT0gMSAmJiBhID09PSBhICYmICFpc09iamVjdChhKSkge1xuICAgICAgICAvLyBmYXN0IHBhdGggdGhlIGNvbW1vbiBjYXNlIG9mIHByb3ZpZGluZyBhbiBvYmplY3Qgd2l0aCBhIHNpbmdsZVxuICAgICAgICAvLyBwcm9wZXJ0eSBjb250YWluaW5nIGEgcHJpbWl0aXZlIHZhbHVlXG4gICAgICAgIHJldHVybiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgICAgICB2YXIgYiA9IG9iamVjdFtrZXldO1xuICAgICAgICAgIHJldHVybiBhID09PSBiICYmIChhICE9PSAwIHx8ICgxIC8gYSA9PSAxIC8gYikpO1xuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgICB2YXIgbGVuZ3RoID0gcHJvcHMubGVuZ3RoLFxuICAgICAgICAgICAgcmVzdWx0ID0gZmFsc2U7XG5cbiAgICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgICAgaWYgKCEocmVzdWx0ID0gYmFzZUlzRXF1YWwob2JqZWN0W3Byb3BzW2xlbmd0aF1dLCBmdW5jW3Byb3BzW2xlbmd0aF1dLCBudWxsLCB0cnVlKSkpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyB0aGUgY2hhcmFjdGVycyBgJmAsIGA8YCwgYD5gLCBgXCJgLCBhbmQgYCdgIGluIGBzdHJpbmdgIHRvIHRoZWlyXG4gICAgICogY29ycmVzcG9uZGluZyBIVE1MIGVudGl0aWVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxpdGllc1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBlc2NhcGUuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgZXNjYXBlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZXNjYXBlKCdGcmVkLCBXaWxtYSwgJiBQZWJibGVzJyk7XG4gICAgICogLy8gPT4gJ0ZyZWQsIFdpbG1hLCAmYW1wOyBQZWJibGVzJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGVzY2FwZShzdHJpbmcpIHtcbiAgICAgIHJldHVybiBzdHJpbmcgPT0gbnVsbCA/ICcnIDogU3RyaW5nKHN0cmluZykucmVwbGFjZShyZVVuZXNjYXBlZEh0bWwsIGVzY2FwZUh0bWxDaGFyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCByZXR1cm5zIHRoZSBmaXJzdCBhcmd1bWVudCBwcm92aWRlZCB0byBpdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsaXRpZXNcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIEFueSB2YWx1ZS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyBgdmFsdWVgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnbmFtZSc6ICdmcmVkJyB9O1xuICAgICAqIF8uaWRlbnRpdHkob2JqZWN0KSA9PT0gb2JqZWN0O1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpZGVudGl0eSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZHMgZnVuY3Rpb24gcHJvcGVydGllcyBvZiBhIHNvdXJjZSBvYmplY3QgdG8gdGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBJZiBgb2JqZWN0YCBpcyBhIGZ1bmN0aW9uIG1ldGhvZHMgd2lsbCBiZSBhZGRlZCB0byBpdHMgcHJvdG90eXBlIGFzIHdlbGwuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbGl0aWVzXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R9IFtvYmplY3Q9bG9kYXNoXSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBvYmplY3Qgb2YgZnVuY3Rpb25zIHRvIGFkZC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIFRoZSBvcHRpb25zIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmNoYWluPXRydWVdIFNwZWNpZnkgd2hldGhlciB0aGUgZnVuY3Rpb25zIGFkZGVkIGFyZSBjaGFpbmFibGUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGNhcGl0YWxpemUoc3RyaW5nKSB7XG4gICAgICogICByZXR1cm4gc3RyaW5nLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgc3RyaW5nLnNsaWNlKDEpLnRvTG93ZXJDYXNlKCk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogXy5taXhpbih7ICdjYXBpdGFsaXplJzogY2FwaXRhbGl6ZSB9KTtcbiAgICAgKiBfLmNhcGl0YWxpemUoJ2ZyZWQnKTtcbiAgICAgKiAvLyA9PiAnRnJlZCdcbiAgICAgKlxuICAgICAqIF8oJ2ZyZWQnKS5jYXBpdGFsaXplKCkudmFsdWUoKTtcbiAgICAgKiAvLyA9PiAnRnJlZCdcbiAgICAgKlxuICAgICAqIF8ubWl4aW4oeyAnY2FwaXRhbGl6ZSc6IGNhcGl0YWxpemUgfSwgeyAnY2hhaW4nOiBmYWxzZSB9KTtcbiAgICAgKiBfKCdmcmVkJykuY2FwaXRhbGl6ZSgpO1xuICAgICAqIC8vID0+ICdGcmVkJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1peGluKG9iamVjdCwgc291cmNlLCBvcHRpb25zKSB7XG4gICAgICB2YXIgY2hhaW4gPSB0cnVlLFxuICAgICAgICAgIG1ldGhvZE5hbWVzID0gc291cmNlICYmIGZ1bmN0aW9ucyhzb3VyY2UpO1xuXG4gICAgICBpZiAoIXNvdXJjZSB8fCAoIW9wdGlvbnMgJiYgIW1ldGhvZE5hbWVzLmxlbmd0aCkpIHtcbiAgICAgICAgaWYgKG9wdGlvbnMgPT0gbnVsbCkge1xuICAgICAgICAgIG9wdGlvbnMgPSBzb3VyY2U7XG4gICAgICAgIH1cbiAgICAgICAgY3RvciA9IGxvZGFzaFdyYXBwZXI7XG4gICAgICAgIHNvdXJjZSA9IG9iamVjdDtcbiAgICAgICAgb2JqZWN0ID0gbG9kYXNoO1xuICAgICAgICBtZXRob2ROYW1lcyA9IGZ1bmN0aW9ucyhzb3VyY2UpO1xuICAgICAgfVxuICAgICAgaWYgKG9wdGlvbnMgPT09IGZhbHNlKSB7XG4gICAgICAgIGNoYWluID0gZmFsc2U7XG4gICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KG9wdGlvbnMpICYmICdjaGFpbicgaW4gb3B0aW9ucykge1xuICAgICAgICBjaGFpbiA9IG9wdGlvbnMuY2hhaW47XG4gICAgICB9XG4gICAgICB2YXIgY3RvciA9IG9iamVjdCxcbiAgICAgICAgICBpc0Z1bmMgPSBpc0Z1bmN0aW9uKGN0b3IpO1xuXG4gICAgICBmb3JFYWNoKG1ldGhvZE5hbWVzLCBmdW5jdGlvbihtZXRob2ROYW1lKSB7XG4gICAgICAgIHZhciBmdW5jID0gb2JqZWN0W21ldGhvZE5hbWVdID0gc291cmNlW21ldGhvZE5hbWVdO1xuICAgICAgICBpZiAoaXNGdW5jKSB7XG4gICAgICAgICAgY3Rvci5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBjaGFpbkFsbCA9IHRoaXMuX19jaGFpbl9fLFxuICAgICAgICAgICAgICAgIHZhbHVlID0gdGhpcy5fX3dyYXBwZWRfXyxcbiAgICAgICAgICAgICAgICBhcmdzID0gW3ZhbHVlXTtcblxuICAgICAgICAgICAgcHVzaC5hcHBseShhcmdzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IGZ1bmMuYXBwbHkob2JqZWN0LCBhcmdzKTtcbiAgICAgICAgICAgIGlmIChjaGFpbiB8fCBjaGFpbkFsbCkge1xuICAgICAgICAgICAgICBpZiAodmFsdWUgPT09IHJlc3VsdCAmJiBpc09iamVjdChyZXN1bHQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmVzdWx0ID0gbmV3IGN0b3IocmVzdWx0KTtcbiAgICAgICAgICAgICAgcmVzdWx0Ll9fY2hhaW5fXyA9IGNoYWluQWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXZlcnRzIHRoZSAnXycgdmFyaWFibGUgdG8gaXRzIHByZXZpb3VzIHZhbHVlIGFuZCByZXR1cm5zIGEgcmVmZXJlbmNlIHRvXG4gICAgICogdGhlIGBsb2Rhc2hgIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxpdGllc1xuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgYGxvZGFzaGAgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBsb2Rhc2ggPSBfLm5vQ29uZmxpY3QoKTtcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBub0NvbmZsaWN0KCkge1xuICAgICAgY29udGV4dC5fID0gb2xkRGFzaDtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgbm8tb3BlcmF0aW9uIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxpdGllc1xuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnbmFtZSc6ICdmcmVkJyB9O1xuICAgICAqIF8ubm9vcChvYmplY3QpID09PSB1bmRlZmluZWQ7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG5vb3AoKSB7XG4gICAgICAvLyBubyBvcGVyYXRpb24gcGVyZm9ybWVkXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0aGF0IGhhdmUgZWxhcHNlZCBzaW5jZSB0aGUgVW5peCBlcG9jaFxuICAgICAqICgxIEphbnVhcnkgMTk3MCAwMDowMDowMCBVVEMpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxpdGllc1xuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgc3RhbXAgPSBfLm5vdygpO1xuICAgICAqIF8uZGVmZXIoZnVuY3Rpb24oKSB7IGNvbnNvbGUubG9nKF8ubm93KCkgLSBzdGFtcCk7IH0pO1xuICAgICAqIC8vID0+IGxvZ3MgdGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgaXQgdG9vayBmb3IgdGhlIGRlZmVycmVkIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZFxuICAgICAqL1xuICAgIHZhciBub3cgPSBpc05hdGl2ZShub3cgPSBEYXRlLm5vdykgJiYgbm93IHx8IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyB0aGUgZ2l2ZW4gdmFsdWUgaW50byBhbiBpbnRlZ2VyIG9mIHRoZSBzcGVjaWZpZWQgcmFkaXguXG4gICAgICogSWYgYHJhZGl4YCBpcyBgdW5kZWZpbmVkYCBvciBgMGAgYSBgcmFkaXhgIG9mIGAxMGAgaXMgdXNlZCB1bmxlc3MgdGhlXG4gICAgICogYHZhbHVlYCBpcyBhIGhleGFkZWNpbWFsLCBpbiB3aGljaCBjYXNlIGEgYHJhZGl4YCBvZiBgMTZgIGlzIHVzZWQuXG4gICAgICpcbiAgICAgKiBOb3RlOiBUaGlzIG1ldGhvZCBhdm9pZHMgZGlmZmVyZW5jZXMgaW4gbmF0aXZlIEVTMyBhbmQgRVM1IGBwYXJzZUludGBcbiAgICAgKiBpbXBsZW1lbnRhdGlvbnMuIFNlZSBodHRwOi8vZXM1LmdpdGh1Yi5pby8jRS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsaXRpZXNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgVGhlIHZhbHVlIHRvIHBhcnNlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbcmFkaXhdIFRoZSByYWRpeCB1c2VkIHRvIGludGVycHJldCB0aGUgdmFsdWUgdG8gcGFyc2UuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgbmV3IGludGVnZXIgdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ucGFyc2VJbnQoJzA4Jyk7XG4gICAgICogLy8gPT4gOFxuICAgICAqL1xuICAgIHZhciBwYXJzZUludCA9IG5hdGl2ZVBhcnNlSW50KHdoaXRlc3BhY2UgKyAnMDgnKSA9PSA4ID8gbmF0aXZlUGFyc2VJbnQgOiBmdW5jdGlvbih2YWx1ZSwgcmFkaXgpIHtcbiAgICAgIC8vIEZpcmVmb3ggPCAyMSBhbmQgT3BlcmEgPCAxNSBmb2xsb3cgdGhlIEVTMyBzcGVjaWZpZWQgaW1wbGVtZW50YXRpb24gb2YgYHBhcnNlSW50YFxuICAgICAgcmV0dXJuIG5hdGl2ZVBhcnNlSW50KGlzU3RyaW5nKHZhbHVlKSA/IHZhbHVlLnJlcGxhY2UocmVMZWFkaW5nU3BhY2VzQW5kWmVyb3MsICcnKSA6IHZhbHVlLCByYWRpeCB8fCAwKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIFwiXy5wbHVja1wiIHN0eWxlIGZ1bmN0aW9uLCB3aGljaCByZXR1cm5zIHRoZSBga2V5YCB2YWx1ZSBvZiBhXG4gICAgICogZ2l2ZW4gb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxpdGllc1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5IHRvIHJldHJpZXZlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgY2hhcmFjdGVycyA9IFtcbiAgICAgKiAgIHsgJ25hbWUnOiAnZnJlZCcsICAgJ2FnZSc6IDQwIH0sXG4gICAgICogICB7ICduYW1lJzogJ2Jhcm5leScsICdhZ2UnOiAzNiB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIHZhciBnZXROYW1lID0gXy5wcm9wZXJ0eSgnbmFtZScpO1xuICAgICAqXG4gICAgICogXy5tYXAoY2hhcmFjdGVycywgZ2V0TmFtZSk7XG4gICAgICogLy8gPT4gWydiYXJuZXknLCAnZnJlZCddXG4gICAgICpcbiAgICAgKiBfLnNvcnRCeShjaGFyYWN0ZXJzLCBnZXROYW1lKTtcbiAgICAgKiAvLyA9PiBbeyAnbmFtZSc6ICdiYXJuZXknLCAnYWdlJzogMzYgfSwgeyAnbmFtZSc6ICdmcmVkJywgICAnYWdlJzogNDAgfV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwcm9wZXJ0eShrZXkpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgICAgcmV0dXJuIG9iamVjdFtrZXldO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcm9kdWNlcyBhIHJhbmRvbSBudW1iZXIgYmV0d2VlbiBgbWluYCBhbmQgYG1heGAgKGluY2x1c2l2ZSkuIElmIG9ubHkgb25lXG4gICAgICogYXJndW1lbnQgaXMgcHJvdmlkZWQgYSBudW1iZXIgYmV0d2VlbiBgMGAgYW5kIHRoZSBnaXZlbiBudW1iZXIgd2lsbCBiZVxuICAgICAqIHJldHVybmVkLiBJZiBgZmxvYXRpbmdgIGlzIHRydWV5IG9yIGVpdGhlciBgbWluYCBvciBgbWF4YCBhcmUgZmxvYXRzIGFcbiAgICAgKiBmbG9hdGluZy1wb2ludCBudW1iZXIgd2lsbCBiZSByZXR1cm5lZCBpbnN0ZWFkIG9mIGFuIGludGVnZXIuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbGl0aWVzXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFttaW49MF0gVGhlIG1pbmltdW0gcG9zc2libGUgdmFsdWUuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFttYXg9MV0gVGhlIG1heGltdW0gcG9zc2libGUgdmFsdWUuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbZmxvYXRpbmc9ZmFsc2VdIFNwZWNpZnkgcmV0dXJuaW5nIGEgZmxvYXRpbmctcG9pbnQgbnVtYmVyLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgYSByYW5kb20gbnVtYmVyLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnJhbmRvbSgwLCA1KTtcbiAgICAgKiAvLyA9PiBhbiBpbnRlZ2VyIGJldHdlZW4gMCBhbmQgNVxuICAgICAqXG4gICAgICogXy5yYW5kb20oNSk7XG4gICAgICogLy8gPT4gYWxzbyBhbiBpbnRlZ2VyIGJldHdlZW4gMCBhbmQgNVxuICAgICAqXG4gICAgICogXy5yYW5kb20oNSwgdHJ1ZSk7XG4gICAgICogLy8gPT4gYSBmbG9hdGluZy1wb2ludCBudW1iZXIgYmV0d2VlbiAwIGFuZCA1XG4gICAgICpcbiAgICAgKiBfLnJhbmRvbSgxLjIsIDUuMik7XG4gICAgICogLy8gPT4gYSBmbG9hdGluZy1wb2ludCBudW1iZXIgYmV0d2VlbiAxLjIgYW5kIDUuMlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJhbmRvbShtaW4sIG1heCwgZmxvYXRpbmcpIHtcbiAgICAgIHZhciBub01pbiA9IG1pbiA9PSBudWxsLFxuICAgICAgICAgIG5vTWF4ID0gbWF4ID09IG51bGw7XG5cbiAgICAgIGlmIChmbG9hdGluZyA9PSBudWxsKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbWluID09ICdib29sZWFuJyAmJiBub01heCkge1xuICAgICAgICAgIGZsb2F0aW5nID0gbWluO1xuICAgICAgICAgIG1pbiA9IDE7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoIW5vTWF4ICYmIHR5cGVvZiBtYXggPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgZmxvYXRpbmcgPSBtYXg7XG4gICAgICAgICAgbm9NYXggPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAobm9NaW4gJiYgbm9NYXgpIHtcbiAgICAgICAgbWF4ID0gMTtcbiAgICAgIH1cbiAgICAgIG1pbiA9ICttaW4gfHwgMDtcbiAgICAgIGlmIChub01heCkge1xuICAgICAgICBtYXggPSBtaW47XG4gICAgICAgIG1pbiA9IDA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBtYXggPSArbWF4IHx8IDA7XG4gICAgICB9XG4gICAgICBpZiAoZmxvYXRpbmcgfHwgbWluICUgMSB8fCBtYXggJSAxKSB7XG4gICAgICAgIHZhciByYW5kID0gbmF0aXZlUmFuZG9tKCk7XG4gICAgICAgIHJldHVybiBuYXRpdmVNaW4obWluICsgKHJhbmQgKiAobWF4IC0gbWluICsgcGFyc2VGbG9hdCgnMWUtJyArICgocmFuZCArJycpLmxlbmd0aCAtIDEpKSkpLCBtYXgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VSYW5kb20obWluLCBtYXgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc29sdmVzIHRoZSB2YWx1ZSBvZiBwcm9wZXJ0eSBga2V5YCBvbiBgb2JqZWN0YC4gSWYgYGtleWAgaXMgYSBmdW5jdGlvblxuICAgICAqIGl0IHdpbGwgYmUgaW52b2tlZCB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBvZiBgb2JqZWN0YCBhbmQgaXRzIHJlc3VsdCByZXR1cm5lZCxcbiAgICAgKiBlbHNlIHRoZSBwcm9wZXJ0eSB2YWx1ZSBpcyByZXR1cm5lZC4gSWYgYG9iamVjdGAgaXMgZmFsc2V5IHRoZW4gYHVuZGVmaW5lZGBcbiAgICAgKiBpcyByZXR1cm5lZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsaXRpZXNcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eSB0byByZXNvbHZlLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSByZXNvbHZlZCB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHtcbiAgICAgKiAgICdjaGVlc2UnOiAnY3J1bXBldHMnLFxuICAgICAqICAgJ3N0dWZmJzogZnVuY3Rpb24oKSB7XG4gICAgICogICAgIHJldHVybiAnbm9uc2Vuc2UnO1xuICAgICAqICAgfVxuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBfLnJlc3VsdChvYmplY3QsICdjaGVlc2UnKTtcbiAgICAgKiAvLyA9PiAnY3J1bXBldHMnXG4gICAgICpcbiAgICAgKiBfLnJlc3VsdChvYmplY3QsICdzdHVmZicpO1xuICAgICAqIC8vID0+ICdub25zZW5zZSdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZXN1bHQob2JqZWN0LCBrZXkpIHtcbiAgICAgIGlmIChvYmplY3QpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gb2JqZWN0W2tleV07XG4gICAgICAgIHJldHVybiBpc0Z1bmN0aW9uKHZhbHVlKSA/IG9iamVjdFtrZXldKCkgOiB2YWx1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIG1pY3JvLXRlbXBsYXRpbmcgbWV0aG9kIHRoYXQgaGFuZGxlcyBhcmJpdHJhcnkgZGVsaW1pdGVycywgcHJlc2VydmVzXG4gICAgICogd2hpdGVzcGFjZSwgYW5kIGNvcnJlY3RseSBlc2NhcGVzIHF1b3RlcyB3aXRoaW4gaW50ZXJwb2xhdGVkIGNvZGUuXG4gICAgICpcbiAgICAgKiBOb3RlOiBJbiB0aGUgZGV2ZWxvcG1lbnQgYnVpbGQsIGBfLnRlbXBsYXRlYCB1dGlsaXplcyBzb3VyY2VVUkxzIGZvciBlYXNpZXJcbiAgICAgKiBkZWJ1Z2dpbmcuIFNlZSBodHRwOi8vd3d3Lmh0bWw1cm9ja3MuY29tL2VuL3R1dG9yaWFscy9kZXZlbG9wZXJ0b29scy9zb3VyY2VtYXBzLyN0b2Mtc291cmNldXJsXG4gICAgICpcbiAgICAgKiBGb3IgbW9yZSBpbmZvcm1hdGlvbiBvbiBwcmVjb21waWxpbmcgdGVtcGxhdGVzIHNlZTpcbiAgICAgKiBodHRwOi8vbG9kYXNoLmNvbS9jdXN0b20tYnVpbGRzXG4gICAgICpcbiAgICAgKiBGb3IgbW9yZSBpbmZvcm1hdGlvbiBvbiBDaHJvbWUgZXh0ZW5zaW9uIHNhbmRib3hlcyBzZWU6XG4gICAgICogaHR0cDovL2RldmVsb3Blci5jaHJvbWUuY29tL3N0YWJsZS9leHRlbnNpb25zL3NhbmRib3hpbmdFdmFsLmh0bWxcbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsaXRpZXNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdGV4dCBUaGUgdGVtcGxhdGUgdGV4dC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gZGF0YSBUaGUgZGF0YSBvYmplY3QgdXNlZCB0byBwb3B1bGF0ZSB0aGUgdGV4dC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIFRoZSBvcHRpb25zIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge1JlZ0V4cH0gW29wdGlvbnMuZXNjYXBlXSBUaGUgXCJlc2NhcGVcIiBkZWxpbWl0ZXIuXG4gICAgICogQHBhcmFtIHtSZWdFeHB9IFtvcHRpb25zLmV2YWx1YXRlXSBUaGUgXCJldmFsdWF0ZVwiIGRlbGltaXRlci5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMuaW1wb3J0c10gQW4gb2JqZWN0IHRvIGltcG9ydCBpbnRvIHRoZSB0ZW1wbGF0ZSBhcyBsb2NhbCB2YXJpYWJsZXMuXG4gICAgICogQHBhcmFtIHtSZWdFeHB9IFtvcHRpb25zLmludGVycG9sYXRlXSBUaGUgXCJpbnRlcnBvbGF0ZVwiIGRlbGltaXRlci5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3NvdXJjZVVSTF0gVGhlIHNvdXJjZVVSTCBvZiB0aGUgdGVtcGxhdGUncyBjb21waWxlZCBzb3VyY2UuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFt2YXJpYWJsZV0gVGhlIGRhdGEgb2JqZWN0IHZhcmlhYmxlIG5hbWUuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufHN0cmluZ30gUmV0dXJucyBhIGNvbXBpbGVkIGZ1bmN0aW9uIHdoZW4gbm8gYGRhdGFgIG9iamVjdFxuICAgICAqICBpcyBnaXZlbiwgZWxzZSBpdCByZXR1cm5zIHRoZSBpbnRlcnBvbGF0ZWQgdGV4dC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIFwiaW50ZXJwb2xhdGVcIiBkZWxpbWl0ZXIgdG8gY3JlYXRlIGEgY29tcGlsZWQgdGVtcGxhdGVcbiAgICAgKiB2YXIgY29tcGlsZWQgPSBfLnRlbXBsYXRlKCdoZWxsbyA8JT0gbmFtZSAlPicpO1xuICAgICAqIGNvbXBpbGVkKHsgJ25hbWUnOiAnZnJlZCcgfSk7XG4gICAgICogLy8gPT4gJ2hlbGxvIGZyZWQnXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgXCJlc2NhcGVcIiBkZWxpbWl0ZXIgdG8gZXNjYXBlIEhUTUwgaW4gZGF0YSBwcm9wZXJ0eSB2YWx1ZXNcbiAgICAgKiBfLnRlbXBsYXRlKCc8Yj48JS0gdmFsdWUgJT48L2I+JywgeyAndmFsdWUnOiAnPHNjcmlwdD4nIH0pO1xuICAgICAqIC8vID0+ICc8Yj4mbHQ7c2NyaXB0Jmd0OzwvYj4nXG4gICAgICpcbiAgICAgKiAvLyB1c2luZyB0aGUgXCJldmFsdWF0ZVwiIGRlbGltaXRlciB0byBnZW5lcmF0ZSBIVE1MXG4gICAgICogdmFyIGxpc3QgPSAnPCUgXy5mb3JFYWNoKHBlb3BsZSwgZnVuY3Rpb24obmFtZSkgeyAlPjxsaT48JS0gbmFtZSAlPjwvbGk+PCUgfSk7ICU+JztcbiAgICAgKiBfLnRlbXBsYXRlKGxpc3QsIHsgJ3Blb3BsZSc6IFsnZnJlZCcsICdiYXJuZXknXSB9KTtcbiAgICAgKiAvLyA9PiAnPGxpPmZyZWQ8L2xpPjxsaT5iYXJuZXk8L2xpPidcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBFUzYgZGVsaW1pdGVyIGFzIGFuIGFsdGVybmF0aXZlIHRvIHRoZSBkZWZhdWx0IFwiaW50ZXJwb2xhdGVcIiBkZWxpbWl0ZXJcbiAgICAgKiBfLnRlbXBsYXRlKCdoZWxsbyAkeyBuYW1lIH0nLCB7ICduYW1lJzogJ3BlYmJsZXMnIH0pO1xuICAgICAqIC8vID0+ICdoZWxsbyBwZWJibGVzJ1xuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGludGVybmFsIGBwcmludGAgZnVuY3Rpb24gaW4gXCJldmFsdWF0ZVwiIGRlbGltaXRlcnNcbiAgICAgKiBfLnRlbXBsYXRlKCc8JSBwcmludChcImhlbGxvIFwiICsgbmFtZSk7ICU+IScsIHsgJ25hbWUnOiAnYmFybmV5JyB9KTtcbiAgICAgKiAvLyA9PiAnaGVsbG8gYmFybmV5ISdcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIGEgY3VzdG9tIHRlbXBsYXRlIGRlbGltaXRlcnNcbiAgICAgKiBfLnRlbXBsYXRlU2V0dGluZ3MgPSB7XG4gICAgICogICAnaW50ZXJwb2xhdGUnOiAve3soW1xcc1xcU10rPyl9fS9nXG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIF8udGVtcGxhdGUoJ2hlbGxvIHt7IG5hbWUgfX0hJywgeyAnbmFtZSc6ICdtdXN0YWNoZScgfSk7XG4gICAgICogLy8gPT4gJ2hlbGxvIG11c3RhY2hlISdcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBgaW1wb3J0c2Agb3B0aW9uIHRvIGltcG9ydCBqUXVlcnlcbiAgICAgKiB2YXIgbGlzdCA9ICc8JSBqcS5lYWNoKHBlb3BsZSwgZnVuY3Rpb24obmFtZSkgeyAlPjxsaT48JS0gbmFtZSAlPjwvbGk+PCUgfSk7ICU+JztcbiAgICAgKiBfLnRlbXBsYXRlKGxpc3QsIHsgJ3Blb3BsZSc6IFsnZnJlZCcsICdiYXJuZXknXSB9LCB7ICdpbXBvcnRzJzogeyAnanEnOiBqUXVlcnkgfSB9KTtcbiAgICAgKiAvLyA9PiAnPGxpPmZyZWQ8L2xpPjxsaT5iYXJuZXk8L2xpPidcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBgc291cmNlVVJMYCBvcHRpb24gdG8gc3BlY2lmeSBhIGN1c3RvbSBzb3VyY2VVUkwgZm9yIHRoZSB0ZW1wbGF0ZVxuICAgICAqIHZhciBjb21waWxlZCA9IF8udGVtcGxhdGUoJ2hlbGxvIDwlPSBuYW1lICU+JywgbnVsbCwgeyAnc291cmNlVVJMJzogJy9iYXNpYy9ncmVldGluZy5qc3QnIH0pO1xuICAgICAqIGNvbXBpbGVkKGRhdGEpO1xuICAgICAqIC8vID0+IGZpbmQgdGhlIHNvdXJjZSBvZiBcImdyZWV0aW5nLmpzdFwiIHVuZGVyIHRoZSBTb3VyY2VzIHRhYiBvciBSZXNvdXJjZXMgcGFuZWwgb2YgdGhlIHdlYiBpbnNwZWN0b3JcbiAgICAgKlxuICAgICAqIC8vIHVzaW5nIHRoZSBgdmFyaWFibGVgIG9wdGlvbiB0byBlbnN1cmUgYSB3aXRoLXN0YXRlbWVudCBpc24ndCB1c2VkIGluIHRoZSBjb21waWxlZCB0ZW1wbGF0ZVxuICAgICAqIHZhciBjb21waWxlZCA9IF8udGVtcGxhdGUoJ2hpIDwlPSBkYXRhLm5hbWUgJT4hJywgbnVsbCwgeyAndmFyaWFibGUnOiAnZGF0YScgfSk7XG4gICAgICogY29tcGlsZWQuc291cmNlO1xuICAgICAqIC8vID0+IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgKiAgIHZhciBfX3QsIF9fcCA9ICcnLCBfX2UgPSBfLmVzY2FwZTtcbiAgICAgKiAgIF9fcCArPSAnaGkgJyArICgoX190ID0gKCBkYXRhLm5hbWUgKSkgPT0gbnVsbCA/ICcnIDogX190KSArICchJztcbiAgICAgKiAgIHJldHVybiBfX3A7XG4gICAgICogfVxuICAgICAqXG4gICAgICogLy8gdXNpbmcgdGhlIGBzb3VyY2VgIHByb3BlcnR5IHRvIGlubGluZSBjb21waWxlZCB0ZW1wbGF0ZXMgZm9yIG1lYW5pbmdmdWxcbiAgICAgKiAvLyBsaW5lIG51bWJlcnMgaW4gZXJyb3IgbWVzc2FnZXMgYW5kIGEgc3RhY2sgdHJhY2VcbiAgICAgKiBmcy53cml0ZUZpbGVTeW5jKHBhdGguam9pbihjd2QsICdqc3QuanMnKSwgJ1xcXG4gICAgICogICB2YXIgSlNUID0ge1xcXG4gICAgICogICAgIFwibWFpblwiOiAnICsgXy50ZW1wbGF0ZShtYWluVGV4dCkuc291cmNlICsgJ1xcXG4gICAgICogICB9O1xcXG4gICAgICogJyk7XG4gICAgICovXG4gICAgZnVuY3Rpb24gdGVtcGxhdGUodGV4dCwgZGF0YSwgb3B0aW9ucykge1xuICAgICAgLy8gYmFzZWQgb24gSm9obiBSZXNpZydzIGB0bXBsYCBpbXBsZW1lbnRhdGlvblxuICAgICAgLy8gaHR0cDovL2Vqb2huLm9yZy9ibG9nL2phdmFzY3JpcHQtbWljcm8tdGVtcGxhdGluZy9cbiAgICAgIC8vIGFuZCBMYXVyYSBEb2t0b3JvdmEncyBkb1QuanNcbiAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9vbGFkby9kb1RcbiAgICAgIHZhciBzZXR0aW5ncyA9IGxvZGFzaC50ZW1wbGF0ZVNldHRpbmdzO1xuICAgICAgdGV4dCA9IFN0cmluZyh0ZXh0IHx8ICcnKTtcblxuICAgICAgLy8gYXZvaWQgbWlzc2luZyBkZXBlbmRlbmNpZXMgd2hlbiBgaXRlcmF0b3JUZW1wbGF0ZWAgaXMgbm90IGRlZmluZWRcbiAgICAgIG9wdGlvbnMgPSBkZWZhdWx0cyh7fSwgb3B0aW9ucywgc2V0dGluZ3MpO1xuXG4gICAgICB2YXIgaW1wb3J0cyA9IGRlZmF1bHRzKHt9LCBvcHRpb25zLmltcG9ydHMsIHNldHRpbmdzLmltcG9ydHMpLFxuICAgICAgICAgIGltcG9ydHNLZXlzID0ga2V5cyhpbXBvcnRzKSxcbiAgICAgICAgICBpbXBvcnRzVmFsdWVzID0gdmFsdWVzKGltcG9ydHMpO1xuXG4gICAgICB2YXIgaXNFdmFsdWF0aW5nLFxuICAgICAgICAgIGluZGV4ID0gMCxcbiAgICAgICAgICBpbnRlcnBvbGF0ZSA9IG9wdGlvbnMuaW50ZXJwb2xhdGUgfHwgcmVOb01hdGNoLFxuICAgICAgICAgIHNvdXJjZSA9IFwiX19wICs9ICdcIjtcblxuICAgICAgLy8gY29tcGlsZSB0aGUgcmVnZXhwIHRvIG1hdGNoIGVhY2ggZGVsaW1pdGVyXG4gICAgICB2YXIgcmVEZWxpbWl0ZXJzID0gUmVnRXhwKFxuICAgICAgICAob3B0aW9ucy5lc2NhcGUgfHwgcmVOb01hdGNoKS5zb3VyY2UgKyAnfCcgK1xuICAgICAgICBpbnRlcnBvbGF0ZS5zb3VyY2UgKyAnfCcgK1xuICAgICAgICAoaW50ZXJwb2xhdGUgPT09IHJlSW50ZXJwb2xhdGUgPyByZUVzVGVtcGxhdGUgOiByZU5vTWF0Y2gpLnNvdXJjZSArICd8JyArXG4gICAgICAgIChvcHRpb25zLmV2YWx1YXRlIHx8IHJlTm9NYXRjaCkuc291cmNlICsgJ3wkJ1xuICAgICAgLCAnZycpO1xuXG4gICAgICB0ZXh0LnJlcGxhY2UocmVEZWxpbWl0ZXJzLCBmdW5jdGlvbihtYXRjaCwgZXNjYXBlVmFsdWUsIGludGVycG9sYXRlVmFsdWUsIGVzVGVtcGxhdGVWYWx1ZSwgZXZhbHVhdGVWYWx1ZSwgb2Zmc2V0KSB7XG4gICAgICAgIGludGVycG9sYXRlVmFsdWUgfHwgKGludGVycG9sYXRlVmFsdWUgPSBlc1RlbXBsYXRlVmFsdWUpO1xuXG4gICAgICAgIC8vIGVzY2FwZSBjaGFyYWN0ZXJzIHRoYXQgY2Fubm90IGJlIGluY2x1ZGVkIGluIHN0cmluZyBsaXRlcmFsc1xuICAgICAgICBzb3VyY2UgKz0gdGV4dC5zbGljZShpbmRleCwgb2Zmc2V0KS5yZXBsYWNlKHJlVW5lc2NhcGVkU3RyaW5nLCBlc2NhcGVTdHJpbmdDaGFyKTtcblxuICAgICAgICAvLyByZXBsYWNlIGRlbGltaXRlcnMgd2l0aCBzbmlwcGV0c1xuICAgICAgICBpZiAoZXNjYXBlVmFsdWUpIHtcbiAgICAgICAgICBzb3VyY2UgKz0gXCInICtcXG5fX2UoXCIgKyBlc2NhcGVWYWx1ZSArIFwiKSArXFxuJ1wiO1xuICAgICAgICB9XG4gICAgICAgIGlmIChldmFsdWF0ZVZhbHVlKSB7XG4gICAgICAgICAgaXNFdmFsdWF0aW5nID0gdHJ1ZTtcbiAgICAgICAgICBzb3VyY2UgKz0gXCInO1xcblwiICsgZXZhbHVhdGVWYWx1ZSArIFwiO1xcbl9fcCArPSAnXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGludGVycG9sYXRlVmFsdWUpIHtcbiAgICAgICAgICBzb3VyY2UgKz0gXCInICtcXG4oKF9fdCA9IChcIiArIGludGVycG9sYXRlVmFsdWUgKyBcIikpID09IG51bGwgPyAnJyA6IF9fdCkgK1xcbidcIjtcbiAgICAgICAgfVxuICAgICAgICBpbmRleCA9IG9mZnNldCArIG1hdGNoLmxlbmd0aDtcblxuICAgICAgICAvLyB0aGUgSlMgZW5naW5lIGVtYmVkZGVkIGluIEFkb2JlIHByb2R1Y3RzIHJlcXVpcmVzIHJldHVybmluZyB0aGUgYG1hdGNoYFxuICAgICAgICAvLyBzdHJpbmcgaW4gb3JkZXIgdG8gcHJvZHVjZSB0aGUgY29ycmVjdCBgb2Zmc2V0YCB2YWx1ZVxuICAgICAgICByZXR1cm4gbWF0Y2g7XG4gICAgICB9KTtcblxuICAgICAgc291cmNlICs9IFwiJztcXG5cIjtcblxuICAgICAgLy8gaWYgYHZhcmlhYmxlYCBpcyBub3Qgc3BlY2lmaWVkLCB3cmFwIGEgd2l0aC1zdGF0ZW1lbnQgYXJvdW5kIHRoZSBnZW5lcmF0ZWRcbiAgICAgIC8vIGNvZGUgdG8gYWRkIHRoZSBkYXRhIG9iamVjdCB0byB0aGUgdG9wIG9mIHRoZSBzY29wZSBjaGFpblxuICAgICAgdmFyIHZhcmlhYmxlID0gb3B0aW9ucy52YXJpYWJsZSxcbiAgICAgICAgICBoYXNWYXJpYWJsZSA9IHZhcmlhYmxlO1xuXG4gICAgICBpZiAoIWhhc1ZhcmlhYmxlKSB7XG4gICAgICAgIHZhcmlhYmxlID0gJ29iaic7XG4gICAgICAgIHNvdXJjZSA9ICd3aXRoICgnICsgdmFyaWFibGUgKyAnKSB7XFxuJyArIHNvdXJjZSArICdcXG59XFxuJztcbiAgICAgIH1cbiAgICAgIC8vIGNsZWFudXAgY29kZSBieSBzdHJpcHBpbmcgZW1wdHkgc3RyaW5nc1xuICAgICAgc291cmNlID0gKGlzRXZhbHVhdGluZyA/IHNvdXJjZS5yZXBsYWNlKHJlRW1wdHlTdHJpbmdMZWFkaW5nLCAnJykgOiBzb3VyY2UpXG4gICAgICAgIC5yZXBsYWNlKHJlRW1wdHlTdHJpbmdNaWRkbGUsICckMScpXG4gICAgICAgIC5yZXBsYWNlKHJlRW1wdHlTdHJpbmdUcmFpbGluZywgJyQxOycpO1xuXG4gICAgICAvLyBmcmFtZSBjb2RlIGFzIHRoZSBmdW5jdGlvbiBib2R5XG4gICAgICBzb3VyY2UgPSAnZnVuY3Rpb24oJyArIHZhcmlhYmxlICsgJykge1xcbicgK1xuICAgICAgICAoaGFzVmFyaWFibGUgPyAnJyA6IHZhcmlhYmxlICsgJyB8fCAoJyArIHZhcmlhYmxlICsgJyA9IHt9KTtcXG4nKSArXG4gICAgICAgIFwidmFyIF9fdCwgX19wID0gJycsIF9fZSA9IF8uZXNjYXBlXCIgK1xuICAgICAgICAoaXNFdmFsdWF0aW5nXG4gICAgICAgICAgPyAnLCBfX2ogPSBBcnJheS5wcm90b3R5cGUuam9pbjtcXG4nICtcbiAgICAgICAgICAgIFwiZnVuY3Rpb24gcHJpbnQoKSB7IF9fcCArPSBfX2ouY2FsbChhcmd1bWVudHMsICcnKSB9XFxuXCJcbiAgICAgICAgICA6ICc7XFxuJ1xuICAgICAgICApICtcbiAgICAgICAgc291cmNlICtcbiAgICAgICAgJ3JldHVybiBfX3BcXG59JztcblxuICAgICAgLy8gVXNlIGEgc291cmNlVVJMIGZvciBlYXNpZXIgZGVidWdnaW5nLlxuICAgICAgLy8gaHR0cDovL3d3dy5odG1sNXJvY2tzLmNvbS9lbi90dXRvcmlhbHMvZGV2ZWxvcGVydG9vbHMvc291cmNlbWFwcy8jdG9jLXNvdXJjZXVybFxuICAgICAgdmFyIHNvdXJjZVVSTCA9ICdcXG4vKlxcbi8vIyBzb3VyY2VVUkw9JyArIChvcHRpb25zLnNvdXJjZVVSTCB8fCAnL2xvZGFzaC90ZW1wbGF0ZS9zb3VyY2VbJyArICh0ZW1wbGF0ZUNvdW50ZXIrKykgKyAnXScpICsgJ1xcbiovJztcblxuICAgICAgdHJ5IHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IEZ1bmN0aW9uKGltcG9ydHNLZXlzLCAncmV0dXJuICcgKyBzb3VyY2UgKyBzb3VyY2VVUkwpLmFwcGx5KHVuZGVmaW5lZCwgaW1wb3J0c1ZhbHVlcyk7XG4gICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgZS5zb3VyY2UgPSBzb3VyY2U7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgICBpZiAoZGF0YSkge1xuICAgICAgICByZXR1cm4gcmVzdWx0KGRhdGEpO1xuICAgICAgfVxuICAgICAgLy8gcHJvdmlkZSB0aGUgY29tcGlsZWQgZnVuY3Rpb24ncyBzb3VyY2UgYnkgaXRzIGB0b1N0cmluZ2AgbWV0aG9kLCBpblxuICAgICAgLy8gc3VwcG9ydGVkIGVudmlyb25tZW50cywgb3IgdGhlIGBzb3VyY2VgIHByb3BlcnR5IGFzIGEgY29udmVuaWVuY2UgZm9yXG4gICAgICAvLyBpbmxpbmluZyBjb21waWxlZCB0ZW1wbGF0ZXMgZHVyaW5nIHRoZSBidWlsZCBwcm9jZXNzXG4gICAgICByZXN1bHQuc291cmNlID0gc291cmNlO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFeGVjdXRlcyB0aGUgY2FsbGJhY2sgYG5gIHRpbWVzLCByZXR1cm5pbmcgYW4gYXJyYXkgb2YgdGhlIHJlc3VsdHNcbiAgICAgKiBvZiBlYWNoIGNhbGxiYWNrIGV4ZWN1dGlvbi4gVGhlIGNhbGxiYWNrIGlzIGJvdW5kIHRvIGB0aGlzQXJnYCBhbmQgaW52b2tlZFxuICAgICAqIHdpdGggb25lIGFyZ3VtZW50OyAoaW5kZXgpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxpdGllc1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBuIFRoZSBudW1iZXIgb2YgdGltZXMgdG8gZXhlY3V0ZSB0aGUgY2FsbGJhY2suXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIGNhbGxlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgY2FsbGJhY2tgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBhbiBhcnJheSBvZiB0aGUgcmVzdWx0cyBvZiBlYWNoIGBjYWxsYmFja2AgZXhlY3V0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgZGljZVJvbGxzID0gXy50aW1lcygzLCBfLnBhcnRpYWwoXy5yYW5kb20sIDEsIDYpKTtcbiAgICAgKiAvLyA9PiBbMywgNiwgNF1cbiAgICAgKlxuICAgICAqIF8udGltZXMoMywgZnVuY3Rpb24obikgeyBtYWdlLmNhc3RTcGVsbChuKTsgfSk7XG4gICAgICogLy8gPT4gY2FsbHMgYG1hZ2UuY2FzdFNwZWxsKG4pYCB0aHJlZSB0aW1lcywgcGFzc2luZyBgbmAgb2YgYDBgLCBgMWAsIGFuZCBgMmAgcmVzcGVjdGl2ZWx5XG4gICAgICpcbiAgICAgKiBfLnRpbWVzKDMsIGZ1bmN0aW9uKG4pIHsgdGhpcy5jYXN0KG4pOyB9LCBtYWdlKTtcbiAgICAgKiAvLyA9PiBhbHNvIGNhbGxzIGBtYWdlLmNhc3RTcGVsbChuKWAgdGhyZWUgdGltZXNcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0aW1lcyhuLCBjYWxsYmFjaywgdGhpc0FyZykge1xuICAgICAgbiA9IChuID0gK24pID4gLTEgPyBuIDogMDtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIHJlc3VsdCA9IEFycmF5KG4pO1xuXG4gICAgICBjYWxsYmFjayA9IGJhc2VDcmVhdGVDYWxsYmFjayhjYWxsYmFjaywgdGhpc0FyZywgMSk7XG4gICAgICB3aGlsZSAoKytpbmRleCA8IG4pIHtcbiAgICAgICAgcmVzdWx0W2luZGV4XSA9IGNhbGxiYWNrKGluZGV4KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGludmVyc2Ugb2YgYF8uZXNjYXBlYCB0aGlzIG1ldGhvZCBjb252ZXJ0cyB0aGUgSFRNTCBlbnRpdGllc1xuICAgICAqIGAmYW1wO2AsIGAmbHQ7YCwgYCZndDtgLCBgJnF1b3Q7YCwgYW5kIGAmIzM5O2AgaW4gYHN0cmluZ2AgdG8gdGhlaXJcbiAgICAgKiBjb3JyZXNwb25kaW5nIGNoYXJhY3RlcnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbGl0aWVzXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIHVuZXNjYXBlLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHVuZXNjYXBlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udW5lc2NhcGUoJ0ZyZWQsIEJhcm5leSAmYW1wOyBQZWJibGVzJyk7XG4gICAgICogLy8gPT4gJ0ZyZWQsIEJhcm5leSAmIFBlYmJsZXMnXG4gICAgICovXG4gICAgZnVuY3Rpb24gdW5lc2NhcGUoc3RyaW5nKSB7XG4gICAgICByZXR1cm4gc3RyaW5nID09IG51bGwgPyAnJyA6IFN0cmluZyhzdHJpbmcpLnJlcGxhY2UocmVFc2NhcGVkSHRtbCwgdW5lc2NhcGVIdG1sQ2hhcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGVzIGEgdW5pcXVlIElELiBJZiBgcHJlZml4YCBpcyBwcm92aWRlZCB0aGUgSUQgd2lsbCBiZSBhcHBlbmRlZCB0byBpdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsaXRpZXNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3ByZWZpeF0gVGhlIHZhbHVlIHRvIHByZWZpeCB0aGUgSUQgd2l0aC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSB1bmlxdWUgSUQuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udW5pcXVlSWQoJ2NvbnRhY3RfJyk7XG4gICAgICogLy8gPT4gJ2NvbnRhY3RfMTA0J1xuICAgICAqXG4gICAgICogXy51bmlxdWVJZCgpO1xuICAgICAqIC8vID0+ICcxMDUnXG4gICAgICovXG4gICAgZnVuY3Rpb24gdW5pcXVlSWQocHJlZml4KSB7XG4gICAgICB2YXIgaWQgPSArK2lkQ291bnRlcjtcbiAgICAgIHJldHVybiBTdHJpbmcocHJlZml4ID09IG51bGwgPyAnJyA6IHByZWZpeCkgKyBpZDtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBgbG9kYXNoYCBvYmplY3QgdGhhdCB3cmFwcyB0aGUgZ2l2ZW4gdmFsdWUgd2l0aCBleHBsaWNpdFxuICAgICAqIG1ldGhvZCBjaGFpbmluZyBlbmFibGVkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IENoYWluaW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gd3JhcC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSB3cmFwcGVyIG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGNoYXJhY3RlcnMgPSBbXG4gICAgICogICB7ICduYW1lJzogJ2Jhcm5leScsICAnYWdlJzogMzYgfSxcbiAgICAgKiAgIHsgJ25hbWUnOiAnZnJlZCcsICAgICdhZ2UnOiA0MCB9LFxuICAgICAqICAgeyAnbmFtZSc6ICdwZWJibGVzJywgJ2FnZSc6IDEgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiB2YXIgeW91bmdlc3QgPSBfLmNoYWluKGNoYXJhY3RlcnMpXG4gICAgICogICAgIC5zb3J0QnkoJ2FnZScpXG4gICAgICogICAgIC5tYXAoZnVuY3Rpb24oY2hyKSB7IHJldHVybiBjaHIubmFtZSArICcgaXMgJyArIGNoci5hZ2U7IH0pXG4gICAgICogICAgIC5maXJzdCgpXG4gICAgICogICAgIC52YWx1ZSgpO1xuICAgICAqIC8vID0+ICdwZWJibGVzIGlzIDEnXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2hhaW4odmFsdWUpIHtcbiAgICAgIHZhbHVlID0gbmV3IGxvZGFzaFdyYXBwZXIodmFsdWUpO1xuICAgICAgdmFsdWUuX19jaGFpbl9fID0gdHJ1ZTtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnZva2VzIGBpbnRlcmNlcHRvcmAgd2l0aCB0aGUgYHZhbHVlYCBhcyB0aGUgZmlyc3QgYXJndW1lbnQgYW5kIHRoZW5cbiAgICAgKiByZXR1cm5zIGB2YWx1ZWAuIFRoZSBwdXJwb3NlIG9mIHRoaXMgbWV0aG9kIGlzIHRvIFwidGFwIGludG9cIiBhIG1ldGhvZFxuICAgICAqIGNoYWluIGluIG9yZGVyIHRvIHBlcmZvcm0gb3BlcmF0aW9ucyBvbiBpbnRlcm1lZGlhdGUgcmVzdWx0cyB3aXRoaW5cbiAgICAgKiB0aGUgY2hhaW4uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgQ2hhaW5pbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBwcm92aWRlIHRvIGBpbnRlcmNlcHRvcmAuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaW50ZXJjZXB0b3IgVGhlIGZ1bmN0aW9uIHRvIGludm9rZS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyBgdmFsdWVgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfKFsxLCAyLCAzLCA0XSlcbiAgICAgKiAgLnRhcChmdW5jdGlvbihhcnJheSkgeyBhcnJheS5wb3AoKTsgfSlcbiAgICAgKiAgLnJldmVyc2UoKVxuICAgICAqICAudmFsdWUoKTtcbiAgICAgKiAvLyA9PiBbMywgMiwgMV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0YXAodmFsdWUsIGludGVyY2VwdG9yKSB7XG4gICAgICBpbnRlcmNlcHRvcih2YWx1ZSk7XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRW5hYmxlcyBleHBsaWNpdCBtZXRob2QgY2hhaW5pbmcgb24gdGhlIHdyYXBwZXIgb2JqZWN0LlxuICAgICAqXG4gICAgICogQG5hbWUgY2hhaW5cbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBDaGFpbmluZ1xuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSB3cmFwcGVyIG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGNoYXJhY3RlcnMgPSBbXG4gICAgICogICB7ICduYW1lJzogJ2Jhcm5leScsICdhZ2UnOiAzNiB9LFxuICAgICAqICAgeyAnbmFtZSc6ICdmcmVkJywgICAnYWdlJzogNDAgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiAvLyB3aXRob3V0IGV4cGxpY2l0IGNoYWluaW5nXG4gICAgICogXyhjaGFyYWN0ZXJzKS5maXJzdCgpO1xuICAgICAqIC8vID0+IHsgJ25hbWUnOiAnYmFybmV5JywgJ2FnZSc6IDM2IH1cbiAgICAgKlxuICAgICAqIC8vIHdpdGggZXhwbGljaXQgY2hhaW5pbmdcbiAgICAgKiBfKGNoYXJhY3RlcnMpLmNoYWluKClcbiAgICAgKiAgIC5maXJzdCgpXG4gICAgICogICAucGljaygnYWdlJylcbiAgICAgKiAgIC52YWx1ZSgpO1xuICAgICAqIC8vID0+IHsgJ2FnZSc6IDM2IH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB3cmFwcGVyQ2hhaW4oKSB7XG4gICAgICB0aGlzLl9fY2hhaW5fXyA9IHRydWU7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcm9kdWNlcyB0aGUgYHRvU3RyaW5nYCByZXN1bHQgb2YgdGhlIHdyYXBwZWQgdmFsdWUuXG4gICAgICpcbiAgICAgKiBAbmFtZSB0b1N0cmluZ1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IENoYWluaW5nXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgc3RyaW5nIHJlc3VsdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXyhbMSwgMiwgM10pLnRvU3RyaW5nKCk7XG4gICAgICogLy8gPT4gJzEsMiwzJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdyYXBwZXJUb1N0cmluZygpIHtcbiAgICAgIHJldHVybiBTdHJpbmcodGhpcy5fX3dyYXBwZWRfXyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXh0cmFjdHMgdGhlIHdyYXBwZWQgdmFsdWUuXG4gICAgICpcbiAgICAgKiBAbmFtZSB2YWx1ZU9mXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAYWxpYXMgdmFsdWVcbiAgICAgKiBAY2F0ZWdvcnkgQ2hhaW5pbmdcbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgd3JhcHBlZCB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXyhbMSwgMiwgM10pLnZhbHVlT2YoKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB3cmFwcGVyVmFsdWVPZigpIHtcbiAgICAgIHJldHVybiB0aGlzLl9fd3JhcHBlZF9fO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLy8gYWRkIGZ1bmN0aW9ucyB0aGF0IHJldHVybiB3cmFwcGVkIHZhbHVlcyB3aGVuIGNoYWluaW5nXG4gICAgbG9kYXNoLmFmdGVyID0gYWZ0ZXI7XG4gICAgbG9kYXNoLmFzc2lnbiA9IGFzc2lnbjtcbiAgICBsb2Rhc2guYXQgPSBhdDtcbiAgICBsb2Rhc2guYmluZCA9IGJpbmQ7XG4gICAgbG9kYXNoLmJpbmRBbGwgPSBiaW5kQWxsO1xuICAgIGxvZGFzaC5iaW5kS2V5ID0gYmluZEtleTtcbiAgICBsb2Rhc2guY2hhaW4gPSBjaGFpbjtcbiAgICBsb2Rhc2guY29tcGFjdCA9IGNvbXBhY3Q7XG4gICAgbG9kYXNoLmNvbXBvc2UgPSBjb21wb3NlO1xuICAgIGxvZGFzaC5jb25zdGFudCA9IGNvbnN0YW50O1xuICAgIGxvZGFzaC5jb3VudEJ5ID0gY291bnRCeTtcbiAgICBsb2Rhc2guY3JlYXRlID0gY3JlYXRlO1xuICAgIGxvZGFzaC5jcmVhdGVDYWxsYmFjayA9IGNyZWF0ZUNhbGxiYWNrO1xuICAgIGxvZGFzaC5jdXJyeSA9IGN1cnJ5O1xuICAgIGxvZGFzaC5kZWJvdW5jZSA9IGRlYm91bmNlO1xuICAgIGxvZGFzaC5kZWZhdWx0cyA9IGRlZmF1bHRzO1xuICAgIGxvZGFzaC5kZWZlciA9IGRlZmVyO1xuICAgIGxvZGFzaC5kZWxheSA9IGRlbGF5O1xuICAgIGxvZGFzaC5kaWZmZXJlbmNlID0gZGlmZmVyZW5jZTtcbiAgICBsb2Rhc2guZmlsdGVyID0gZmlsdGVyO1xuICAgIGxvZGFzaC5mbGF0dGVuID0gZmxhdHRlbjtcbiAgICBsb2Rhc2guZm9yRWFjaCA9IGZvckVhY2g7XG4gICAgbG9kYXNoLmZvckVhY2hSaWdodCA9IGZvckVhY2hSaWdodDtcbiAgICBsb2Rhc2guZm9ySW4gPSBmb3JJbjtcbiAgICBsb2Rhc2guZm9ySW5SaWdodCA9IGZvckluUmlnaHQ7XG4gICAgbG9kYXNoLmZvck93biA9IGZvck93bjtcbiAgICBsb2Rhc2guZm9yT3duUmlnaHQgPSBmb3JPd25SaWdodDtcbiAgICBsb2Rhc2guZnVuY3Rpb25zID0gZnVuY3Rpb25zO1xuICAgIGxvZGFzaC5ncm91cEJ5ID0gZ3JvdXBCeTtcbiAgICBsb2Rhc2guaW5kZXhCeSA9IGluZGV4Qnk7XG4gICAgbG9kYXNoLmluaXRpYWwgPSBpbml0aWFsO1xuICAgIGxvZGFzaC5pbnRlcnNlY3Rpb24gPSBpbnRlcnNlY3Rpb247XG4gICAgbG9kYXNoLmludmVydCA9IGludmVydDtcbiAgICBsb2Rhc2guaW52b2tlID0gaW52b2tlO1xuICAgIGxvZGFzaC5rZXlzID0ga2V5cztcbiAgICBsb2Rhc2gubWFwID0gbWFwO1xuICAgIGxvZGFzaC5tYXBWYWx1ZXMgPSBtYXBWYWx1ZXM7XG4gICAgbG9kYXNoLm1heCA9IG1heDtcbiAgICBsb2Rhc2gubWVtb2l6ZSA9IG1lbW9pemU7XG4gICAgbG9kYXNoLm1lcmdlID0gbWVyZ2U7XG4gICAgbG9kYXNoLm1pbiA9IG1pbjtcbiAgICBsb2Rhc2gub21pdCA9IG9taXQ7XG4gICAgbG9kYXNoLm9uY2UgPSBvbmNlO1xuICAgIGxvZGFzaC5wYWlycyA9IHBhaXJzO1xuICAgIGxvZGFzaC5wYXJ0aWFsID0gcGFydGlhbDtcbiAgICBsb2Rhc2gucGFydGlhbFJpZ2h0ID0gcGFydGlhbFJpZ2h0O1xuICAgIGxvZGFzaC5waWNrID0gcGljaztcbiAgICBsb2Rhc2gucGx1Y2sgPSBwbHVjaztcbiAgICBsb2Rhc2gucHJvcGVydHkgPSBwcm9wZXJ0eTtcbiAgICBsb2Rhc2gucHVsbCA9IHB1bGw7XG4gICAgbG9kYXNoLnJhbmdlID0gcmFuZ2U7XG4gICAgbG9kYXNoLnJlamVjdCA9IHJlamVjdDtcbiAgICBsb2Rhc2gucmVtb3ZlID0gcmVtb3ZlO1xuICAgIGxvZGFzaC5yZXN0ID0gcmVzdDtcbiAgICBsb2Rhc2guc2h1ZmZsZSA9IHNodWZmbGU7XG4gICAgbG9kYXNoLnNvcnRCeSA9IHNvcnRCeTtcbiAgICBsb2Rhc2gudGFwID0gdGFwO1xuICAgIGxvZGFzaC50aHJvdHRsZSA9IHRocm90dGxlO1xuICAgIGxvZGFzaC50aW1lcyA9IHRpbWVzO1xuICAgIGxvZGFzaC50b0FycmF5ID0gdG9BcnJheTtcbiAgICBsb2Rhc2gudHJhbnNmb3JtID0gdHJhbnNmb3JtO1xuICAgIGxvZGFzaC51bmlvbiA9IHVuaW9uO1xuICAgIGxvZGFzaC51bmlxID0gdW5pcTtcbiAgICBsb2Rhc2gudmFsdWVzID0gdmFsdWVzO1xuICAgIGxvZGFzaC53aGVyZSA9IHdoZXJlO1xuICAgIGxvZGFzaC53aXRob3V0ID0gd2l0aG91dDtcbiAgICBsb2Rhc2gud3JhcCA9IHdyYXA7XG4gICAgbG9kYXNoLnhvciA9IHhvcjtcbiAgICBsb2Rhc2guemlwID0gemlwO1xuICAgIGxvZGFzaC56aXBPYmplY3QgPSB6aXBPYmplY3Q7XG5cbiAgICAvLyBhZGQgYWxpYXNlc1xuICAgIGxvZGFzaC5jb2xsZWN0ID0gbWFwO1xuICAgIGxvZGFzaC5kcm9wID0gcmVzdDtcbiAgICBsb2Rhc2guZWFjaCA9IGZvckVhY2g7XG4gICAgbG9kYXNoLmVhY2hSaWdodCA9IGZvckVhY2hSaWdodDtcbiAgICBsb2Rhc2guZXh0ZW5kID0gYXNzaWduO1xuICAgIGxvZGFzaC5tZXRob2RzID0gZnVuY3Rpb25zO1xuICAgIGxvZGFzaC5vYmplY3QgPSB6aXBPYmplY3Q7XG4gICAgbG9kYXNoLnNlbGVjdCA9IGZpbHRlcjtcbiAgICBsb2Rhc2gudGFpbCA9IHJlc3Q7XG4gICAgbG9kYXNoLnVuaXF1ZSA9IHVuaXE7XG4gICAgbG9kYXNoLnVuemlwID0gemlwO1xuXG4gICAgLy8gYWRkIGZ1bmN0aW9ucyB0byBgbG9kYXNoLnByb3RvdHlwZWBcbiAgICBtaXhpbihsb2Rhc2gpO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvLyBhZGQgZnVuY3Rpb25zIHRoYXQgcmV0dXJuIHVud3JhcHBlZCB2YWx1ZXMgd2hlbiBjaGFpbmluZ1xuICAgIGxvZGFzaC5jbG9uZSA9IGNsb25lO1xuICAgIGxvZGFzaC5jbG9uZURlZXAgPSBjbG9uZURlZXA7XG4gICAgbG9kYXNoLmNvbnRhaW5zID0gY29udGFpbnM7XG4gICAgbG9kYXNoLmVzY2FwZSA9IGVzY2FwZTtcbiAgICBsb2Rhc2guZXZlcnkgPSBldmVyeTtcbiAgICBsb2Rhc2guZmluZCA9IGZpbmQ7XG4gICAgbG9kYXNoLmZpbmRJbmRleCA9IGZpbmRJbmRleDtcbiAgICBsb2Rhc2guZmluZEtleSA9IGZpbmRLZXk7XG4gICAgbG9kYXNoLmZpbmRMYXN0ID0gZmluZExhc3Q7XG4gICAgbG9kYXNoLmZpbmRMYXN0SW5kZXggPSBmaW5kTGFzdEluZGV4O1xuICAgIGxvZGFzaC5maW5kTGFzdEtleSA9IGZpbmRMYXN0S2V5O1xuICAgIGxvZGFzaC5oYXMgPSBoYXM7XG4gICAgbG9kYXNoLmlkZW50aXR5ID0gaWRlbnRpdHk7XG4gICAgbG9kYXNoLmluZGV4T2YgPSBpbmRleE9mO1xuICAgIGxvZGFzaC5pc0FyZ3VtZW50cyA9IGlzQXJndW1lbnRzO1xuICAgIGxvZGFzaC5pc0FycmF5ID0gaXNBcnJheTtcbiAgICBsb2Rhc2guaXNCb29sZWFuID0gaXNCb29sZWFuO1xuICAgIGxvZGFzaC5pc0RhdGUgPSBpc0RhdGU7XG4gICAgbG9kYXNoLmlzRWxlbWVudCA9IGlzRWxlbWVudDtcbiAgICBsb2Rhc2guaXNFbXB0eSA9IGlzRW1wdHk7XG4gICAgbG9kYXNoLmlzRXF1YWwgPSBpc0VxdWFsO1xuICAgIGxvZGFzaC5pc0Zpbml0ZSA9IGlzRmluaXRlO1xuICAgIGxvZGFzaC5pc0Z1bmN0aW9uID0gaXNGdW5jdGlvbjtcbiAgICBsb2Rhc2guaXNOYU4gPSBpc05hTjtcbiAgICBsb2Rhc2guaXNOdWxsID0gaXNOdWxsO1xuICAgIGxvZGFzaC5pc051bWJlciA9IGlzTnVtYmVyO1xuICAgIGxvZGFzaC5pc09iamVjdCA9IGlzT2JqZWN0O1xuICAgIGxvZGFzaC5pc1BsYWluT2JqZWN0ID0gaXNQbGFpbk9iamVjdDtcbiAgICBsb2Rhc2guaXNSZWdFeHAgPSBpc1JlZ0V4cDtcbiAgICBsb2Rhc2guaXNTdHJpbmcgPSBpc1N0cmluZztcbiAgICBsb2Rhc2guaXNVbmRlZmluZWQgPSBpc1VuZGVmaW5lZDtcbiAgICBsb2Rhc2gubGFzdEluZGV4T2YgPSBsYXN0SW5kZXhPZjtcbiAgICBsb2Rhc2gubWl4aW4gPSBtaXhpbjtcbiAgICBsb2Rhc2gubm9Db25mbGljdCA9IG5vQ29uZmxpY3Q7XG4gICAgbG9kYXNoLm5vb3AgPSBub29wO1xuICAgIGxvZGFzaC5ub3cgPSBub3c7XG4gICAgbG9kYXNoLnBhcnNlSW50ID0gcGFyc2VJbnQ7XG4gICAgbG9kYXNoLnJhbmRvbSA9IHJhbmRvbTtcbiAgICBsb2Rhc2gucmVkdWNlID0gcmVkdWNlO1xuICAgIGxvZGFzaC5yZWR1Y2VSaWdodCA9IHJlZHVjZVJpZ2h0O1xuICAgIGxvZGFzaC5yZXN1bHQgPSByZXN1bHQ7XG4gICAgbG9kYXNoLnJ1bkluQ29udGV4dCA9IHJ1bkluQ29udGV4dDtcbiAgICBsb2Rhc2guc2l6ZSA9IHNpemU7XG4gICAgbG9kYXNoLnNvbWUgPSBzb21lO1xuICAgIGxvZGFzaC5zb3J0ZWRJbmRleCA9IHNvcnRlZEluZGV4O1xuICAgIGxvZGFzaC50ZW1wbGF0ZSA9IHRlbXBsYXRlO1xuICAgIGxvZGFzaC51bmVzY2FwZSA9IHVuZXNjYXBlO1xuICAgIGxvZGFzaC51bmlxdWVJZCA9IHVuaXF1ZUlkO1xuXG4gICAgLy8gYWRkIGFsaWFzZXNcbiAgICBsb2Rhc2guYWxsID0gZXZlcnk7XG4gICAgbG9kYXNoLmFueSA9IHNvbWU7XG4gICAgbG9kYXNoLmRldGVjdCA9IGZpbmQ7XG4gICAgbG9kYXNoLmZpbmRXaGVyZSA9IGZpbmQ7XG4gICAgbG9kYXNoLmZvbGRsID0gcmVkdWNlO1xuICAgIGxvZGFzaC5mb2xkciA9IHJlZHVjZVJpZ2h0O1xuICAgIGxvZGFzaC5pbmNsdWRlID0gY29udGFpbnM7XG4gICAgbG9kYXNoLmluamVjdCA9IHJlZHVjZTtcblxuICAgIG1peGluKGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHNvdXJjZSA9IHt9XG4gICAgICBmb3JPd24obG9kYXNoLCBmdW5jdGlvbihmdW5jLCBtZXRob2ROYW1lKSB7XG4gICAgICAgIGlmICghbG9kYXNoLnByb3RvdHlwZVttZXRob2ROYW1lXSkge1xuICAgICAgICAgIHNvdXJjZVttZXRob2ROYW1lXSA9IGZ1bmM7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICB9KCksIGZhbHNlKTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLy8gYWRkIGZ1bmN0aW9ucyBjYXBhYmxlIG9mIHJldHVybmluZyB3cmFwcGVkIGFuZCB1bndyYXBwZWQgdmFsdWVzIHdoZW4gY2hhaW5pbmdcbiAgICBsb2Rhc2guZmlyc3QgPSBmaXJzdDtcbiAgICBsb2Rhc2gubGFzdCA9IGxhc3Q7XG4gICAgbG9kYXNoLnNhbXBsZSA9IHNhbXBsZTtcblxuICAgIC8vIGFkZCBhbGlhc2VzXG4gICAgbG9kYXNoLnRha2UgPSBmaXJzdDtcbiAgICBsb2Rhc2guaGVhZCA9IGZpcnN0O1xuXG4gICAgZm9yT3duKGxvZGFzaCwgZnVuY3Rpb24oZnVuYywgbWV0aG9kTmFtZSkge1xuICAgICAgdmFyIGNhbGxiYWNrYWJsZSA9IG1ldGhvZE5hbWUgIT09ICdzYW1wbGUnO1xuICAgICAgaWYgKCFsb2Rhc2gucHJvdG90eXBlW21ldGhvZE5hbWVdKSB7XG4gICAgICAgIGxvZGFzaC5wcm90b3R5cGVbbWV0aG9kTmFtZV09IGZ1bmN0aW9uKG4sIGd1YXJkKSB7XG4gICAgICAgICAgdmFyIGNoYWluQWxsID0gdGhpcy5fX2NoYWluX18sXG4gICAgICAgICAgICAgIHJlc3VsdCA9IGZ1bmModGhpcy5fX3dyYXBwZWRfXywgbiwgZ3VhcmQpO1xuXG4gICAgICAgICAgcmV0dXJuICFjaGFpbkFsbCAmJiAobiA9PSBudWxsIHx8IChndWFyZCAmJiAhKGNhbGxiYWNrYWJsZSAmJiB0eXBlb2YgbiA9PSAnZnVuY3Rpb24nKSkpXG4gICAgICAgICAgICA/IHJlc3VsdFxuICAgICAgICAgICAgOiBuZXcgbG9kYXNoV3JhcHBlcihyZXN1bHQsIGNoYWluQWxsKTtcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogVGhlIHNlbWFudGljIHZlcnNpb24gbnVtYmVyLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHR5cGUgc3RyaW5nXG4gICAgICovXG4gICAgbG9kYXNoLlZFUlNJT04gPSAnMi40LjEnO1xuXG4gICAgLy8gYWRkIFwiQ2hhaW5pbmdcIiBmdW5jdGlvbnMgdG8gdGhlIHdyYXBwZXJcbiAgICBsb2Rhc2gucHJvdG90eXBlLmNoYWluID0gd3JhcHBlckNoYWluO1xuICAgIGxvZGFzaC5wcm90b3R5cGUudG9TdHJpbmcgPSB3cmFwcGVyVG9TdHJpbmc7XG4gICAgbG9kYXNoLnByb3RvdHlwZS52YWx1ZSA9IHdyYXBwZXJWYWx1ZU9mO1xuICAgIGxvZGFzaC5wcm90b3R5cGUudmFsdWVPZiA9IHdyYXBwZXJWYWx1ZU9mO1xuXG4gICAgLy8gYWRkIGBBcnJheWAgZnVuY3Rpb25zIHRoYXQgcmV0dXJuIHVud3JhcHBlZCB2YWx1ZXNcbiAgICBmb3JFYWNoKFsnam9pbicsICdwb3AnLCAnc2hpZnQnXSwgZnVuY3Rpb24obWV0aG9kTmFtZSkge1xuICAgICAgdmFyIGZ1bmMgPSBhcnJheVJlZlttZXRob2ROYW1lXTtcbiAgICAgIGxvZGFzaC5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGNoYWluQWxsID0gdGhpcy5fX2NoYWluX18sXG4gICAgICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KHRoaXMuX193cmFwcGVkX18sIGFyZ3VtZW50cyk7XG5cbiAgICAgICAgcmV0dXJuIGNoYWluQWxsXG4gICAgICAgICAgPyBuZXcgbG9kYXNoV3JhcHBlcihyZXN1bHQsIGNoYWluQWxsKVxuICAgICAgICAgIDogcmVzdWx0O1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIGFkZCBgQXJyYXlgIGZ1bmN0aW9ucyB0aGF0IHJldHVybiB0aGUgZXhpc3Rpbmcgd3JhcHBlZCB2YWx1ZVxuICAgIGZvckVhY2goWydwdXNoJywgJ3JldmVyc2UnLCAnc29ydCcsICd1bnNoaWZ0J10sIGZ1bmN0aW9uKG1ldGhvZE5hbWUpIHtcbiAgICAgIHZhciBmdW5jID0gYXJyYXlSZWZbbWV0aG9kTmFtZV07XG4gICAgICBsb2Rhc2gucHJvdG90eXBlW21ldGhvZE5hbWVdID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIGZ1bmMuYXBwbHkodGhpcy5fX3dyYXBwZWRfXywgYXJndW1lbnRzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgLy8gYWRkIGBBcnJheWAgZnVuY3Rpb25zIHRoYXQgcmV0dXJuIG5ldyB3cmFwcGVkIHZhbHVlc1xuICAgIGZvckVhY2goWydjb25jYXQnLCAnc2xpY2UnLCAnc3BsaWNlJ10sIGZ1bmN0aW9uKG1ldGhvZE5hbWUpIHtcbiAgICAgIHZhciBmdW5jID0gYXJyYXlSZWZbbWV0aG9kTmFtZV07XG4gICAgICBsb2Rhc2gucHJvdG90eXBlW21ldGhvZE5hbWVdID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBuZXcgbG9kYXNoV3JhcHBlcihmdW5jLmFwcGx5KHRoaXMuX193cmFwcGVkX18sIGFyZ3VtZW50cyksIHRoaXMuX19jaGFpbl9fKTtcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICByZXR1cm4gbG9kYXNoO1xuICB9XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLy8gZXhwb3NlIExvLURhc2hcbiAgdmFyIF8gPSBydW5JbkNvbnRleHQoKTtcblxuICAvLyBzb21lIEFNRCBidWlsZCBvcHRpbWl6ZXJzIGxpa2Ugci5qcyBjaGVjayBmb3IgY29uZGl0aW9uIHBhdHRlcm5zIGxpa2UgdGhlIGZvbGxvd2luZzpcbiAgaWYgKHR5cGVvZiBkZWZpbmUgPT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PSAnb2JqZWN0JyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgLy8gRXhwb3NlIExvLURhc2ggdG8gdGhlIGdsb2JhbCBvYmplY3QgZXZlbiB3aGVuIGFuIEFNRCBsb2FkZXIgaXMgcHJlc2VudCBpblxuICAgIC8vIGNhc2UgTG8tRGFzaCBpcyBsb2FkZWQgd2l0aCBhIFJlcXVpcmVKUyBzaGltIGNvbmZpZy5cbiAgICAvLyBTZWUgaHR0cDovL3JlcXVpcmVqcy5vcmcvZG9jcy9hcGkuaHRtbCNjb25maWctc2hpbVxuICAgIHJvb3QuXyA9IF87XG5cbiAgICAvLyBkZWZpbmUgYXMgYW4gYW5vbnltb3VzIG1vZHVsZSBzbywgdGhyb3VnaCBwYXRoIG1hcHBpbmcsIGl0IGNhbiBiZVxuICAgIC8vIHJlZmVyZW5jZWQgYXMgdGhlIFwidW5kZXJzY29yZVwiIG1vZHVsZVxuICAgIGRlZmluZShmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBfO1xuICAgIH0pO1xuICB9XG4gIC8vIGNoZWNrIGZvciBgZXhwb3J0c2AgYWZ0ZXIgYGRlZmluZWAgaW4gY2FzZSBhIGJ1aWxkIG9wdGltaXplciBhZGRzIGFuIGBleHBvcnRzYCBvYmplY3RcbiAgZWxzZSBpZiAoZnJlZUV4cG9ydHMgJiYgZnJlZU1vZHVsZSkge1xuICAgIC8vIGluIE5vZGUuanMgb3IgUmluZ29KU1xuICAgIGlmIChtb2R1bGVFeHBvcnRzKSB7XG4gICAgICAoZnJlZU1vZHVsZS5leHBvcnRzID0gXykuXyA9IF87XG4gICAgfVxuICAgIC8vIGluIE5hcndoYWwgb3IgUmhpbm8gLXJlcXVpcmVcbiAgICBlbHNlIHtcbiAgICAgIGZyZWVFeHBvcnRzLl8gPSBfO1xuICAgIH1cbiAgfVxuICBlbHNlIHtcbiAgICAvLyBpbiBhIGJyb3dzZXIgb3IgUmhpbm9cbiAgICByb290Ll8gPSBfO1xuICB9XG59LmNhbGwodGhpcykpO1xuIiwiLyoqXHJcbiAqIEBsaWNlbnNlXHJcbiAqIHBpeGkuanMgLSB2Mi4yLjNcclxuICogQ29weXJpZ2h0IChjKSAyMDEyLTIwMTQsIE1hdCBHcm92ZXNcclxuICogaHR0cDovL2dvb2Rib3lkaWdpdGFsLmNvbS9cclxuICpcclxuICogQ29tcGlsZWQ6IDIwMTUtMDEtMDZcclxuICpcclxuICogcGl4aS5qcyBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXHJcbiAqIGh0dHA6Ly93d3cub3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvbWl0LWxpY2Vuc2UucGhwXHJcbiAqL1xyXG4oZnVuY3Rpb24oKXt2YXIgYT10aGlzLGI9Ynx8e307Yi5XRUJHTF9SRU5ERVJFUj0wLGIuQ0FOVkFTX1JFTkRFUkVSPTEsYi5WRVJTSU9OPVwidjIuMi4zXCIsYi5ibGVuZE1vZGVzPXtOT1JNQUw6MCxBREQ6MSxNVUxUSVBMWToyLFNDUkVFTjozLE9WRVJMQVk6NCxEQVJLRU46NSxMSUdIVEVOOjYsQ09MT1JfRE9ER0U6NyxDT0xPUl9CVVJOOjgsSEFSRF9MSUdIVDo5LFNPRlRfTElHSFQ6MTAsRElGRkVSRU5DRToxMSxFWENMVVNJT046MTIsSFVFOjEzLFNBVFVSQVRJT046MTQsQ09MT1I6MTUsTFVNSU5PU0lUWToxNn0sYi5zY2FsZU1vZGVzPXtERUZBVUxUOjAsTElORUFSOjAsTkVBUkVTVDoxfSxiLl9VSUQ9MCxcInVuZGVmaW5lZFwiIT10eXBlb2YgRmxvYXQzMkFycmF5PyhiLkZsb2F0MzJBcnJheT1GbG9hdDMyQXJyYXksYi5VaW50MTZBcnJheT1VaW50MTZBcnJheSxiLlVpbnQzMkFycmF5PVVpbnQzMkFycmF5LGIuQXJyYXlCdWZmZXI9QXJyYXlCdWZmZXIpOihiLkZsb2F0MzJBcnJheT1BcnJheSxiLlVpbnQxNkFycmF5PUFycmF5KSxiLklOVEVSQUNUSU9OX0ZSRVFVRU5DWT0zMCxiLkFVVE9fUFJFVkVOVF9ERUZBVUxUPSEwLGIuUElfMj0yKk1hdGguUEksYi5SQURfVE9fREVHPTE4MC9NYXRoLlBJLGIuREVHX1RPX1JBRD1NYXRoLlBJLzE4MCxiLlJFVElOQV9QUkVGSVg9XCJAMnhcIixiLmRvbnRTYXlIZWxsbz0hMSxiLmRlZmF1bHRSZW5kZXJPcHRpb25zPXt2aWV3Om51bGwsdHJhbnNwYXJlbnQ6ITEsYW50aWFsaWFzOiExLHByZXNlcnZlRHJhd2luZ0J1ZmZlcjohMSxyZXNvbHV0aW9uOjEsY2xlYXJCZWZvcmVSZW5kZXI6ITAsYXV0b1Jlc2l6ZTohMX0sYi5zYXlIZWxsbz1mdW5jdGlvbihhKXtpZighYi5kb250U2F5SGVsbG8pe2lmKG5hdmlnYXRvci51c2VyQWdlbnQudG9Mb3dlckNhc2UoKS5pbmRleE9mKFwiY2hyb21lXCIpPi0xKXt2YXIgYz1bXCIlYyAlYyAlYyBQaXhpLmpzIFwiK2IuVkVSU0lPTitcIiAtIFwiK2ErXCIgICVjICAlYyAgaHR0cDovL3d3dy5waXhpanMuY29tLyAgJWMgJWMg4pmlJWPimaUlY+KZpSBcIixcImJhY2tncm91bmQ6ICNmZjY2YTVcIixcImJhY2tncm91bmQ6ICNmZjY2YTVcIixcImNvbG9yOiAjZmY2NmE1OyBiYWNrZ3JvdW5kOiAjMDMwMzA3O1wiLFwiYmFja2dyb3VuZDogI2ZmNjZhNVwiLFwiYmFja2dyb3VuZDogI2ZmYzNkY1wiLFwiYmFja2dyb3VuZDogI2ZmNjZhNVwiLFwiY29sb3I6ICNmZjI0MjQ7IGJhY2tncm91bmQ6ICNmZmZcIixcImNvbG9yOiAjZmYyNDI0OyBiYWNrZ3JvdW5kOiAjZmZmXCIsXCJjb2xvcjogI2ZmMjQyNDsgYmFja2dyb3VuZDogI2ZmZlwiXTtjb25zb2xlLmxvZy5hcHBseShjb25zb2xlLGMpfWVsc2Ugd2luZG93LmNvbnNvbGUmJmNvbnNvbGUubG9nKFwiUGl4aS5qcyBcIitiLlZFUlNJT04rXCIgLSBodHRwOi8vd3d3LnBpeGlqcy5jb20vXCIpO2IuZG9udFNheUhlbGxvPSEwfX0sYi5Qb2ludD1mdW5jdGlvbihhLGIpe3RoaXMueD1hfHwwLHRoaXMueT1ifHwwfSxiLlBvaW50LnByb3RvdHlwZS5jbG9uZT1mdW5jdGlvbigpe3JldHVybiBuZXcgYi5Qb2ludCh0aGlzLngsdGhpcy55KX0sYi5Qb2ludC5wcm90b3R5cGUuc2V0PWZ1bmN0aW9uKGEsYil7dGhpcy54PWF8fDAsdGhpcy55PWJ8fCgwIT09Yj90aGlzLng6MCl9LGIuUG9pbnQucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuUG9pbnQsYi5SZWN0YW5nbGU9ZnVuY3Rpb24oYSxiLGMsZCl7dGhpcy54PWF8fDAsdGhpcy55PWJ8fDAsdGhpcy53aWR0aD1jfHwwLHRoaXMuaGVpZ2h0PWR8fDB9LGIuUmVjdGFuZ2xlLnByb3RvdHlwZS5jbG9uZT1mdW5jdGlvbigpe3JldHVybiBuZXcgYi5SZWN0YW5nbGUodGhpcy54LHRoaXMueSx0aGlzLndpZHRoLHRoaXMuaGVpZ2h0KX0sYi5SZWN0YW5nbGUucHJvdG90eXBlLmNvbnRhaW5zPWZ1bmN0aW9uKGEsYil7aWYodGhpcy53aWR0aDw9MHx8dGhpcy5oZWlnaHQ8PTApcmV0dXJuITE7dmFyIGM9dGhpcy54O2lmKGE+PWMmJmE8PWMrdGhpcy53aWR0aCl7dmFyIGQ9dGhpcy55O2lmKGI+PWQmJmI8PWQrdGhpcy5oZWlnaHQpcmV0dXJuITB9cmV0dXJuITF9LGIuUmVjdGFuZ2xlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLlJlY3RhbmdsZSxiLkVtcHR5UmVjdGFuZ2xlPW5ldyBiLlJlY3RhbmdsZSgwLDAsMCwwKSxiLlBvbHlnb249ZnVuY3Rpb24oYSl7aWYoYSBpbnN0YW5jZW9mIEFycmF5fHwoYT1BcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSxhWzBdaW5zdGFuY2VvZiBiLlBvaW50KXtmb3IodmFyIGM9W10sZD0wLGU9YS5sZW5ndGg7ZT5kO2QrKyljLnB1c2goYVtkXS54LGFbZF0ueSk7YT1jfXRoaXMuY2xvc2VkPSEwLHRoaXMucG9pbnRzPWF9LGIuUG9seWdvbi5wcm90b3R5cGUuY2xvbmU9ZnVuY3Rpb24oKXt2YXIgYT10aGlzLnBvaW50cy5zbGljZSgpO3JldHVybiBuZXcgYi5Qb2x5Z29uKGEpfSxiLlBvbHlnb24ucHJvdG90eXBlLmNvbnRhaW5zPWZ1bmN0aW9uKGEsYil7Zm9yKHZhciBjPSExLGQ9dGhpcy5wb2ludHMubGVuZ3RoLzIsZT0wLGY9ZC0xO2Q+ZTtmPWUrKyl7dmFyIGc9dGhpcy5wb2ludHNbMiplXSxoPXRoaXMucG9pbnRzWzIqZSsxXSxpPXRoaXMucG9pbnRzWzIqZl0saj10aGlzLnBvaW50c1syKmYrMV0saz1oPmIhPWo+YiYmKGktZykqKGItaCkvKGotaCkrZz5hO2smJihjPSFjKX1yZXR1cm4gY30sYi5Qb2x5Z29uLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLlBvbHlnb24sYi5DaXJjbGU9ZnVuY3Rpb24oYSxiLGMpe3RoaXMueD1hfHwwLHRoaXMueT1ifHwwLHRoaXMucmFkaXVzPWN8fDB9LGIuQ2lyY2xlLnByb3RvdHlwZS5jbG9uZT1mdW5jdGlvbigpe3JldHVybiBuZXcgYi5DaXJjbGUodGhpcy54LHRoaXMueSx0aGlzLnJhZGl1cyl9LGIuQ2lyY2xlLnByb3RvdHlwZS5jb250YWlucz1mdW5jdGlvbihhLGIpe2lmKHRoaXMucmFkaXVzPD0wKXJldHVybiExO3ZhciBjPXRoaXMueC1hLGQ9dGhpcy55LWIsZT10aGlzLnJhZGl1cyp0aGlzLnJhZGl1cztyZXR1cm4gYyo9YyxkKj1kLGU+PWMrZH0sYi5DaXJjbGUucHJvdG90eXBlLmdldEJvdW5kcz1mdW5jdGlvbigpe3JldHVybiBuZXcgYi5SZWN0YW5nbGUodGhpcy54LXRoaXMucmFkaXVzLHRoaXMueS10aGlzLnJhZGl1cywyKnRoaXMucmFkaXVzLDIqdGhpcy5yYWRpdXMpfSxiLkNpcmNsZS5wcm90b3R5cGUuY29uc3RydWN0b3I9Yi5DaXJjbGUsYi5FbGxpcHNlPWZ1bmN0aW9uKGEsYixjLGQpe3RoaXMueD1hfHwwLHRoaXMueT1ifHwwLHRoaXMud2lkdGg9Y3x8MCx0aGlzLmhlaWdodD1kfHwwfSxiLkVsbGlwc2UucHJvdG90eXBlLmNsb25lPWZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBiLkVsbGlwc2UodGhpcy54LHRoaXMueSx0aGlzLndpZHRoLHRoaXMuaGVpZ2h0KX0sYi5FbGxpcHNlLnByb3RvdHlwZS5jb250YWlucz1mdW5jdGlvbihhLGIpe2lmKHRoaXMud2lkdGg8PTB8fHRoaXMuaGVpZ2h0PD0wKXJldHVybiExO3ZhciBjPShhLXRoaXMueCkvdGhpcy53aWR0aCxkPShiLXRoaXMueSkvdGhpcy5oZWlnaHQ7cmV0dXJuIGMqPWMsZCo9ZCwxPj1jK2R9LGIuRWxsaXBzZS5wcm90b3R5cGUuZ2V0Qm91bmRzPWZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBiLlJlY3RhbmdsZSh0aGlzLngtdGhpcy53aWR0aCx0aGlzLnktdGhpcy5oZWlnaHQsdGhpcy53aWR0aCx0aGlzLmhlaWdodCl9LGIuRWxsaXBzZS5wcm90b3R5cGUuY29uc3RydWN0b3I9Yi5FbGxpcHNlLGIuUm91bmRlZFJlY3RhbmdsZT1mdW5jdGlvbihhLGIsYyxkLGUpe3RoaXMueD1hfHwwLHRoaXMueT1ifHwwLHRoaXMud2lkdGg9Y3x8MCx0aGlzLmhlaWdodD1kfHwwLHRoaXMucmFkaXVzPWV8fDIwfSxiLlJvdW5kZWRSZWN0YW5nbGUucHJvdG90eXBlLmNsb25lPWZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBiLlJvdW5kZWRSZWN0YW5nbGUodGhpcy54LHRoaXMueSx0aGlzLndpZHRoLHRoaXMuaGVpZ2h0LHRoaXMucmFkaXVzKX0sYi5Sb3VuZGVkUmVjdGFuZ2xlLnByb3RvdHlwZS5jb250YWlucz1mdW5jdGlvbihhLGIpe2lmKHRoaXMud2lkdGg8PTB8fHRoaXMuaGVpZ2h0PD0wKXJldHVybiExO3ZhciBjPXRoaXMueDtpZihhPj1jJiZhPD1jK3RoaXMud2lkdGgpe3ZhciBkPXRoaXMueTtpZihiPj1kJiZiPD1kK3RoaXMuaGVpZ2h0KXJldHVybiEwfXJldHVybiExfSxiLlJvdW5kZWRSZWN0YW5nbGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuUm91bmRlZFJlY3RhbmdsZSxiLk1hdHJpeD1mdW5jdGlvbigpe3RoaXMuYT0xLHRoaXMuYj0wLHRoaXMuYz0wLHRoaXMuZD0xLHRoaXMudHg9MCx0aGlzLnR5PTB9LGIuTWF0cml4LnByb3RvdHlwZS5mcm9tQXJyYXk9ZnVuY3Rpb24oYSl7dGhpcy5hPWFbMF0sdGhpcy5iPWFbMV0sdGhpcy5jPWFbM10sdGhpcy5kPWFbNF0sdGhpcy50eD1hWzJdLHRoaXMudHk9YVs1XX0sYi5NYXRyaXgucHJvdG90eXBlLnRvQXJyYXk9ZnVuY3Rpb24oYSl7dGhpcy5hcnJheXx8KHRoaXMuYXJyYXk9bmV3IGIuRmxvYXQzMkFycmF5KDkpKTt2YXIgYz10aGlzLmFycmF5O3JldHVybiBhPyhjWzBdPXRoaXMuYSxjWzFdPXRoaXMuYixjWzJdPTAsY1szXT10aGlzLmMsY1s0XT10aGlzLmQsY1s1XT0wLGNbNl09dGhpcy50eCxjWzddPXRoaXMudHksY1s4XT0xKTooY1swXT10aGlzLmEsY1sxXT10aGlzLmMsY1syXT10aGlzLnR4LGNbM109dGhpcy5iLGNbNF09dGhpcy5kLGNbNV09dGhpcy50eSxjWzZdPTAsY1s3XT0wLGNbOF09MSksY30sYi5NYXRyaXgucHJvdG90eXBlLmFwcGx5PWZ1bmN0aW9uKGEsYyl7cmV0dXJuIGM9Y3x8bmV3IGIuUG9pbnQsYy54PXRoaXMuYSphLngrdGhpcy5jKmEueSt0aGlzLnR4LGMueT10aGlzLmIqYS54K3RoaXMuZCphLnkrdGhpcy50eSxjfSxiLk1hdHJpeC5wcm90b3R5cGUuYXBwbHlJbnZlcnNlPWZ1bmN0aW9uKGEsYyl7Yz1jfHxuZXcgYi5Qb2ludDt2YXIgZD0xLyh0aGlzLmEqdGhpcy5kK3RoaXMuYyotdGhpcy5iKTtyZXR1cm4gYy54PXRoaXMuZCpkKmEueCstdGhpcy5jKmQqYS55Kyh0aGlzLnR5KnRoaXMuYy10aGlzLnR4KnRoaXMuZCkqZCxjLnk9dGhpcy5hKmQqYS55Ky10aGlzLmIqZCphLngrKC10aGlzLnR5KnRoaXMuYSt0aGlzLnR4KnRoaXMuYikqZCxjfSxiLk1hdHJpeC5wcm90b3R5cGUudHJhbnNsYXRlPWZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMudHgrPWEsdGhpcy50eSs9Yix0aGlzfSxiLk1hdHJpeC5wcm90b3R5cGUuc2NhbGU9ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5hKj1hLHRoaXMuZCo9Yix0aGlzLmMqPWEsdGhpcy5iKj1iLHRoaXMudHgqPWEsdGhpcy50eSo9Yix0aGlzfSxiLk1hdHJpeC5wcm90b3R5cGUucm90YXRlPWZ1bmN0aW9uKGEpe3ZhciBiPU1hdGguY29zKGEpLGM9TWF0aC5zaW4oYSksZD10aGlzLmEsZT10aGlzLmMsZj10aGlzLnR4O3JldHVybiB0aGlzLmE9ZCpiLXRoaXMuYipjLHRoaXMuYj1kKmMrdGhpcy5iKmIsdGhpcy5jPWUqYi10aGlzLmQqYyx0aGlzLmQ9ZSpjK3RoaXMuZCpiLHRoaXMudHg9ZipiLXRoaXMudHkqYyx0aGlzLnR5PWYqYyt0aGlzLnR5KmIsdGhpc30sYi5NYXRyaXgucHJvdG90eXBlLmFwcGVuZD1mdW5jdGlvbihhKXt2YXIgYj10aGlzLmEsYz10aGlzLmIsZD10aGlzLmMsZT10aGlzLmQ7cmV0dXJuIHRoaXMuYT1hLmEqYithLmIqZCx0aGlzLmI9YS5hKmMrYS5iKmUsdGhpcy5jPWEuYypiK2EuZCpkLHRoaXMuZD1hLmMqYythLmQqZSx0aGlzLnR4PWEudHgqYithLnR5KmQrdGhpcy50eCx0aGlzLnR5PWEudHgqYythLnR5KmUrdGhpcy50eSx0aGlzfSxiLk1hdHJpeC5wcm90b3R5cGUuaWRlbnRpdHk9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5hPTEsdGhpcy5iPTAsdGhpcy5jPTAsdGhpcy5kPTEsdGhpcy50eD0wLHRoaXMudHk9MCx0aGlzfSxiLmlkZW50aXR5TWF0cml4PW5ldyBiLk1hdHJpeCxiLkRpc3BsYXlPYmplY3Q9ZnVuY3Rpb24oKXt0aGlzLnBvc2l0aW9uPW5ldyBiLlBvaW50LHRoaXMuc2NhbGU9bmV3IGIuUG9pbnQoMSwxKSx0aGlzLnBpdm90PW5ldyBiLlBvaW50KDAsMCksdGhpcy5yb3RhdGlvbj0wLHRoaXMuYWxwaGE9MSx0aGlzLnZpc2libGU9ITAsdGhpcy5oaXRBcmVhPW51bGwsdGhpcy5idXR0b25Nb2RlPSExLHRoaXMucmVuZGVyYWJsZT0hMSx0aGlzLnBhcmVudD1udWxsLHRoaXMuc3RhZ2U9bnVsbCx0aGlzLndvcmxkQWxwaGE9MSx0aGlzLl9pbnRlcmFjdGl2ZT0hMSx0aGlzLmRlZmF1bHRDdXJzb3I9XCJwb2ludGVyXCIsdGhpcy53b3JsZFRyYW5zZm9ybT1uZXcgYi5NYXRyaXgsdGhpcy5fc3I9MCx0aGlzLl9jcj0xLHRoaXMuZmlsdGVyQXJlYT1udWxsLHRoaXMuX2JvdW5kcz1uZXcgYi5SZWN0YW5nbGUoMCwwLDEsMSksdGhpcy5fY3VycmVudEJvdW5kcz1udWxsLHRoaXMuX21hc2s9bnVsbCx0aGlzLl9jYWNoZUFzQml0bWFwPSExLHRoaXMuX2NhY2hlSXNEaXJ0eT0hMX0sYi5EaXNwbGF5T2JqZWN0LnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLkRpc3BsYXlPYmplY3QsT2JqZWN0LmRlZmluZVByb3BlcnR5KGIuRGlzcGxheU9iamVjdC5wcm90b3R5cGUsXCJpbnRlcmFjdGl2ZVwiLHtnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5faW50ZXJhY3RpdmV9LHNldDpmdW5jdGlvbihhKXt0aGlzLl9pbnRlcmFjdGl2ZT1hLHRoaXMuc3RhZ2UmJih0aGlzLnN0YWdlLmRpcnR5PSEwKX19KSxPYmplY3QuZGVmaW5lUHJvcGVydHkoYi5EaXNwbGF5T2JqZWN0LnByb3RvdHlwZSxcIndvcmxkVmlzaWJsZVwiLHtnZXQ6ZnVuY3Rpb24oKXt2YXIgYT10aGlzO2Rve2lmKCFhLnZpc2libGUpcmV0dXJuITE7YT1hLnBhcmVudH13aGlsZShhKTtyZXR1cm4hMH19KSxPYmplY3QuZGVmaW5lUHJvcGVydHkoYi5EaXNwbGF5T2JqZWN0LnByb3RvdHlwZSxcIm1hc2tcIix7Z2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX21hc2t9LHNldDpmdW5jdGlvbihhKXt0aGlzLl9tYXNrJiYodGhpcy5fbWFzay5pc01hc2s9ITEpLHRoaXMuX21hc2s9YSx0aGlzLl9tYXNrJiYodGhpcy5fbWFzay5pc01hc2s9ITApfX0pLE9iamVjdC5kZWZpbmVQcm9wZXJ0eShiLkRpc3BsYXlPYmplY3QucHJvdG90eXBlLFwiZmlsdGVyc1wiLHtnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fZmlsdGVyc30sc2V0OmZ1bmN0aW9uKGEpe2lmKGEpe2Zvcih2YXIgYj1bXSxjPTA7YzxhLmxlbmd0aDtjKyspZm9yKHZhciBkPWFbY10ucGFzc2VzLGU9MDtlPGQubGVuZ3RoO2UrKyliLnB1c2goZFtlXSk7dGhpcy5fZmlsdGVyQmxvY2s9e3RhcmdldDp0aGlzLGZpbHRlclBhc3NlczpifX10aGlzLl9maWx0ZXJzPWF9fSksT2JqZWN0LmRlZmluZVByb3BlcnR5KGIuRGlzcGxheU9iamVjdC5wcm90b3R5cGUsXCJjYWNoZUFzQml0bWFwXCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLl9jYWNoZUFzQml0bWFwfSxzZXQ6ZnVuY3Rpb24oYSl7dGhpcy5fY2FjaGVBc0JpdG1hcCE9PWEmJihhP3RoaXMuX2dlbmVyYXRlQ2FjaGVkU3ByaXRlKCk6dGhpcy5fZGVzdHJveUNhY2hlZFNwcml0ZSgpLHRoaXMuX2NhY2hlQXNCaXRtYXA9YSl9fSksYi5EaXNwbGF5T2JqZWN0LnByb3RvdHlwZS51cGRhdGVUcmFuc2Zvcm09ZnVuY3Rpb24oKXt2YXIgYSxjLGQsZSxmLGcsaD10aGlzLnBhcmVudC53b3JsZFRyYW5zZm9ybSxpPXRoaXMud29ybGRUcmFuc2Zvcm07dGhpcy5yb3RhdGlvbiViLlBJXzI/KHRoaXMucm90YXRpb24hPT10aGlzLnJvdGF0aW9uQ2FjaGUmJih0aGlzLnJvdGF0aW9uQ2FjaGU9dGhpcy5yb3RhdGlvbix0aGlzLl9zcj1NYXRoLnNpbih0aGlzLnJvdGF0aW9uKSx0aGlzLl9jcj1NYXRoLmNvcyh0aGlzLnJvdGF0aW9uKSksYT10aGlzLl9jcip0aGlzLnNjYWxlLngsYz10aGlzLl9zcip0aGlzLnNjYWxlLngsZD0tdGhpcy5fc3IqdGhpcy5zY2FsZS55LGU9dGhpcy5fY3IqdGhpcy5zY2FsZS55LGY9dGhpcy5wb3NpdGlvbi54LGc9dGhpcy5wb3NpdGlvbi55LCh0aGlzLnBpdm90Lnh8fHRoaXMucGl2b3QueSkmJihmLT10aGlzLnBpdm90LngqYSt0aGlzLnBpdm90LnkqZCxnLT10aGlzLnBpdm90LngqYyt0aGlzLnBpdm90LnkqZSksaS5hPWEqaC5hK2MqaC5jLGkuYj1hKmguYitjKmguZCxpLmM9ZCpoLmErZSpoLmMsaS5kPWQqaC5iK2UqaC5kLGkudHg9ZipoLmErZypoLmMraC50eCxpLnR5PWYqaC5iK2cqaC5kK2gudHkpOihhPXRoaXMuc2NhbGUueCxlPXRoaXMuc2NhbGUueSxmPXRoaXMucG9zaXRpb24ueC10aGlzLnBpdm90LngqYSxnPXRoaXMucG9zaXRpb24ueS10aGlzLnBpdm90LnkqZSxpLmE9YSpoLmEsaS5iPWEqaC5iLGkuYz1lKmguYyxpLmQ9ZSpoLmQsaS50eD1mKmguYStnKmguYytoLnR4LGkudHk9ZipoLmIrZypoLmQraC50eSksdGhpcy53b3JsZEFscGhhPXRoaXMuYWxwaGEqdGhpcy5wYXJlbnQud29ybGRBbHBoYX0sYi5EaXNwbGF5T2JqZWN0LnByb3RvdHlwZS5kaXNwbGF5T2JqZWN0VXBkYXRlVHJhbnNmb3JtPWIuRGlzcGxheU9iamVjdC5wcm90b3R5cGUudXBkYXRlVHJhbnNmb3JtLGIuRGlzcGxheU9iamVjdC5wcm90b3R5cGUuZ2V0Qm91bmRzPWZ1bmN0aW9uKGEpe3JldHVybiBhPWEsYi5FbXB0eVJlY3RhbmdsZX0sYi5EaXNwbGF5T2JqZWN0LnByb3RvdHlwZS5nZXRMb2NhbEJvdW5kcz1mdW5jdGlvbigpe3JldHVybiB0aGlzLmdldEJvdW5kcyhiLmlkZW50aXR5TWF0cml4KX0sYi5EaXNwbGF5T2JqZWN0LnByb3RvdHlwZS5zZXRTdGFnZVJlZmVyZW5jZT1mdW5jdGlvbihhKXt0aGlzLnN0YWdlPWEsdGhpcy5faW50ZXJhY3RpdmUmJih0aGlzLnN0YWdlLmRpcnR5PSEwKX0sYi5EaXNwbGF5T2JqZWN0LnByb3RvdHlwZS5nZW5lcmF0ZVRleHR1cmU9ZnVuY3Rpb24oYSxjLGQpe3ZhciBlPXRoaXMuZ2V0TG9jYWxCb3VuZHMoKSxmPW5ldyBiLlJlbmRlclRleHR1cmUoMHxlLndpZHRoLDB8ZS5oZWlnaHQsZCxjLGEpO3JldHVybiBiLkRpc3BsYXlPYmplY3QuX3RlbXBNYXRyaXgudHg9LWUueCxiLkRpc3BsYXlPYmplY3QuX3RlbXBNYXRyaXgudHk9LWUueSxmLnJlbmRlcih0aGlzLGIuRGlzcGxheU9iamVjdC5fdGVtcE1hdHJpeCksZn0sYi5EaXNwbGF5T2JqZWN0LnByb3RvdHlwZS51cGRhdGVDYWNoZT1mdW5jdGlvbigpe3RoaXMuX2dlbmVyYXRlQ2FjaGVkU3ByaXRlKCl9LGIuRGlzcGxheU9iamVjdC5wcm90b3R5cGUudG9HbG9iYWw9ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZGlzcGxheU9iamVjdFVwZGF0ZVRyYW5zZm9ybSgpLHRoaXMud29ybGRUcmFuc2Zvcm0uYXBwbHkoYSl9LGIuRGlzcGxheU9iamVjdC5wcm90b3R5cGUudG9Mb2NhbD1mdW5jdGlvbihhLGIpe3JldHVybiBiJiYoYT1iLnRvR2xvYmFsKGEpKSx0aGlzLmRpc3BsYXlPYmplY3RVcGRhdGVUcmFuc2Zvcm0oKSx0aGlzLndvcmxkVHJhbnNmb3JtLmFwcGx5SW52ZXJzZShhKX0sYi5EaXNwbGF5T2JqZWN0LnByb3RvdHlwZS5fcmVuZGVyQ2FjaGVkU3ByaXRlPWZ1bmN0aW9uKGEpe3RoaXMuX2NhY2hlZFNwcml0ZS53b3JsZEFscGhhPXRoaXMud29ybGRBbHBoYSxhLmdsP2IuU3ByaXRlLnByb3RvdHlwZS5fcmVuZGVyV2ViR0wuY2FsbCh0aGlzLl9jYWNoZWRTcHJpdGUsYSk6Yi5TcHJpdGUucHJvdG90eXBlLl9yZW5kZXJDYW52YXMuY2FsbCh0aGlzLl9jYWNoZWRTcHJpdGUsYSl9LGIuRGlzcGxheU9iamVjdC5wcm90b3R5cGUuX2dlbmVyYXRlQ2FjaGVkU3ByaXRlPWZ1bmN0aW9uKCl7dGhpcy5fY2FjaGVBc0JpdG1hcD0hMTt2YXIgYT10aGlzLmdldExvY2FsQm91bmRzKCk7aWYodGhpcy5fY2FjaGVkU3ByaXRlKXRoaXMuX2NhY2hlZFNwcml0ZS50ZXh0dXJlLnJlc2l6ZSgwfGEud2lkdGgsMHxhLmhlaWdodCk7ZWxzZXt2YXIgYz1uZXcgYi5SZW5kZXJUZXh0dXJlKDB8YS53aWR0aCwwfGEuaGVpZ2h0KTt0aGlzLl9jYWNoZWRTcHJpdGU9bmV3IGIuU3ByaXRlKGMpLHRoaXMuX2NhY2hlZFNwcml0ZS53b3JsZFRyYW5zZm9ybT10aGlzLndvcmxkVHJhbnNmb3JtfXZhciBkPXRoaXMuX2ZpbHRlcnM7dGhpcy5fZmlsdGVycz1udWxsLHRoaXMuX2NhY2hlZFNwcml0ZS5maWx0ZXJzPWQsYi5EaXNwbGF5T2JqZWN0Ll90ZW1wTWF0cml4LnR4PS1hLngsYi5EaXNwbGF5T2JqZWN0Ll90ZW1wTWF0cml4LnR5PS1hLnksdGhpcy5fY2FjaGVkU3ByaXRlLnRleHR1cmUucmVuZGVyKHRoaXMsYi5EaXNwbGF5T2JqZWN0Ll90ZW1wTWF0cml4LCEwKSx0aGlzLl9jYWNoZWRTcHJpdGUuYW5jaG9yLng9LShhLngvYS53aWR0aCksdGhpcy5fY2FjaGVkU3ByaXRlLmFuY2hvci55PS0oYS55L2EuaGVpZ2h0KSx0aGlzLl9maWx0ZXJzPWQsdGhpcy5fY2FjaGVBc0JpdG1hcD0hMH0sYi5EaXNwbGF5T2JqZWN0LnByb3RvdHlwZS5fZGVzdHJveUNhY2hlZFNwcml0ZT1mdW5jdGlvbigpe3RoaXMuX2NhY2hlZFNwcml0ZSYmKHRoaXMuX2NhY2hlZFNwcml0ZS50ZXh0dXJlLmRlc3Ryb3koITApLHRoaXMuX2NhY2hlZFNwcml0ZT1udWxsKX0sYi5EaXNwbGF5T2JqZWN0LnByb3RvdHlwZS5fcmVuZGVyV2ViR0w9ZnVuY3Rpb24oYSl7YT1hfSxiLkRpc3BsYXlPYmplY3QucHJvdG90eXBlLl9yZW5kZXJDYW52YXM9ZnVuY3Rpb24oYSl7YT1hfSxiLkRpc3BsYXlPYmplY3QuX3RlbXBNYXRyaXg9bmV3IGIuTWF0cml4LE9iamVjdC5kZWZpbmVQcm9wZXJ0eShiLkRpc3BsYXlPYmplY3QucHJvdG90eXBlLFwieFwiLHtnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5wb3NpdGlvbi54fSxzZXQ6ZnVuY3Rpb24oYSl7dGhpcy5wb3NpdGlvbi54PWF9fSksT2JqZWN0LmRlZmluZVByb3BlcnR5KGIuRGlzcGxheU9iamVjdC5wcm90b3R5cGUsXCJ5XCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLnBvc2l0aW9uLnl9LHNldDpmdW5jdGlvbihhKXt0aGlzLnBvc2l0aW9uLnk9YX19KSxiLkRpc3BsYXlPYmplY3RDb250YWluZXI9ZnVuY3Rpb24oKXtiLkRpc3BsYXlPYmplY3QuY2FsbCh0aGlzKSx0aGlzLmNoaWxkcmVuPVtdfSxiLkRpc3BsYXlPYmplY3RDb250YWluZXIucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoYi5EaXNwbGF5T2JqZWN0LnByb3RvdHlwZSksYi5EaXNwbGF5T2JqZWN0Q29udGFpbmVyLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLkRpc3BsYXlPYmplY3RDb250YWluZXIsT2JqZWN0LmRlZmluZVByb3BlcnR5KGIuRGlzcGxheU9iamVjdENvbnRhaW5lci5wcm90b3R5cGUsXCJ3aWR0aFwiLHtnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5zY2FsZS54KnRoaXMuZ2V0TG9jYWxCb3VuZHMoKS53aWR0aH0sc2V0OmZ1bmN0aW9uKGEpe3ZhciBiPXRoaXMuZ2V0TG9jYWxCb3VuZHMoKS53aWR0aDt0aGlzLnNjYWxlLng9MCE9PWI/YS9iOjEsdGhpcy5fd2lkdGg9YX19KSxPYmplY3QuZGVmaW5lUHJvcGVydHkoYi5EaXNwbGF5T2JqZWN0Q29udGFpbmVyLnByb3RvdHlwZSxcImhlaWdodFwiLHtnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5zY2FsZS55KnRoaXMuZ2V0TG9jYWxCb3VuZHMoKS5oZWlnaHR9LHNldDpmdW5jdGlvbihhKXt2YXIgYj10aGlzLmdldExvY2FsQm91bmRzKCkuaGVpZ2h0O3RoaXMuc2NhbGUueT0wIT09Yj9hL2I6MSx0aGlzLl9oZWlnaHQ9YX19KSxiLkRpc3BsYXlPYmplY3RDb250YWluZXIucHJvdG90eXBlLmFkZENoaWxkPWZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmFkZENoaWxkQXQoYSx0aGlzLmNoaWxkcmVuLmxlbmd0aCl9LGIuRGlzcGxheU9iamVjdENvbnRhaW5lci5wcm90b3R5cGUuYWRkQ2hpbGRBdD1mdW5jdGlvbihhLGIpe2lmKGI+PTAmJmI8PXRoaXMuY2hpbGRyZW4ubGVuZ3RoKXJldHVybiBhLnBhcmVudCYmYS5wYXJlbnQucmVtb3ZlQ2hpbGQoYSksYS5wYXJlbnQ9dGhpcyx0aGlzLmNoaWxkcmVuLnNwbGljZShiLDAsYSksdGhpcy5zdGFnZSYmYS5zZXRTdGFnZVJlZmVyZW5jZSh0aGlzLnN0YWdlKSxhO3Rocm93IG5ldyBFcnJvcihhK1wiYWRkQ2hpbGRBdDogVGhlIGluZGV4IFwiK2IrXCIgc3VwcGxpZWQgaXMgb3V0IG9mIGJvdW5kcyBcIit0aGlzLmNoaWxkcmVuLmxlbmd0aCl9LGIuRGlzcGxheU9iamVjdENvbnRhaW5lci5wcm90b3R5cGUuc3dhcENoaWxkcmVuPWZ1bmN0aW9uKGEsYil7aWYoYSE9PWIpe3ZhciBjPXRoaXMuZ2V0Q2hpbGRJbmRleChhKSxkPXRoaXMuZ2V0Q2hpbGRJbmRleChiKTtpZigwPmN8fDA+ZCl0aHJvdyBuZXcgRXJyb3IoXCJzd2FwQ2hpbGRyZW46IEJvdGggdGhlIHN1cHBsaWVkIERpc3BsYXlPYmplY3RzIG11c3QgYmUgYSBjaGlsZCBvZiB0aGUgY2FsbGVyLlwiKTt0aGlzLmNoaWxkcmVuW2NdPWIsdGhpcy5jaGlsZHJlbltkXT1hfX0sYi5EaXNwbGF5T2JqZWN0Q29udGFpbmVyLnByb3RvdHlwZS5nZXRDaGlsZEluZGV4PWZ1bmN0aW9uKGEpe3ZhciBiPXRoaXMuY2hpbGRyZW4uaW5kZXhPZihhKTtpZigtMT09PWIpdGhyb3cgbmV3IEVycm9yKFwiVGhlIHN1cHBsaWVkIERpc3BsYXlPYmplY3QgbXVzdCBiZSBhIGNoaWxkIG9mIHRoZSBjYWxsZXJcIik7cmV0dXJuIGJ9LGIuRGlzcGxheU9iamVjdENvbnRhaW5lci5wcm90b3R5cGUuc2V0Q2hpbGRJbmRleD1mdW5jdGlvbihhLGIpe2lmKDA+Ynx8Yj49dGhpcy5jaGlsZHJlbi5sZW5ndGgpdGhyb3cgbmV3IEVycm9yKFwiVGhlIHN1cHBsaWVkIGluZGV4IGlzIG91dCBvZiBib3VuZHNcIik7dmFyIGM9dGhpcy5nZXRDaGlsZEluZGV4KGEpO3RoaXMuY2hpbGRyZW4uc3BsaWNlKGMsMSksdGhpcy5jaGlsZHJlbi5zcGxpY2UoYiwwLGEpfSxiLkRpc3BsYXlPYmplY3RDb250YWluZXIucHJvdG90eXBlLmdldENoaWxkQXQ9ZnVuY3Rpb24oYSl7aWYoMD5hfHxhPj10aGlzLmNoaWxkcmVuLmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoXCJnZXRDaGlsZEF0OiBTdXBwbGllZCBpbmRleCBcIithK1wiIGRvZXMgbm90IGV4aXN0IGluIHRoZSBjaGlsZCBsaXN0LCBvciB0aGUgc3VwcGxpZWQgRGlzcGxheU9iamVjdCBtdXN0IGJlIGEgY2hpbGQgb2YgdGhlIGNhbGxlclwiKTtyZXR1cm4gdGhpcy5jaGlsZHJlblthXX0sYi5EaXNwbGF5T2JqZWN0Q29udGFpbmVyLnByb3RvdHlwZS5yZW1vdmVDaGlsZD1mdW5jdGlvbihhKXt2YXIgYj10aGlzLmNoaWxkcmVuLmluZGV4T2YoYSk7aWYoLTEhPT1iKXJldHVybiB0aGlzLnJlbW92ZUNoaWxkQXQoYil9LGIuRGlzcGxheU9iamVjdENvbnRhaW5lci5wcm90b3R5cGUucmVtb3ZlQ2hpbGRBdD1mdW5jdGlvbihhKXt2YXIgYj10aGlzLmdldENoaWxkQXQoYSk7cmV0dXJuIHRoaXMuc3RhZ2UmJmIucmVtb3ZlU3RhZ2VSZWZlcmVuY2UoKSxiLnBhcmVudD12b2lkIDAsdGhpcy5jaGlsZHJlbi5zcGxpY2UoYSwxKSxifSxiLkRpc3BsYXlPYmplY3RDb250YWluZXIucHJvdG90eXBlLnJlbW92ZUNoaWxkcmVuPWZ1bmN0aW9uKGEsYil7dmFyIGM9YXx8MCxkPVwibnVtYmVyXCI9PXR5cGVvZiBiP2I6dGhpcy5jaGlsZHJlbi5sZW5ndGgsZT1kLWM7aWYoZT4wJiZkPj1lKXtmb3IodmFyIGY9dGhpcy5jaGlsZHJlbi5zcGxpY2UoYyxlKSxnPTA7ZzxmLmxlbmd0aDtnKyspe3ZhciBoPWZbZ107dGhpcy5zdGFnZSYmaC5yZW1vdmVTdGFnZVJlZmVyZW5jZSgpLGgucGFyZW50PXZvaWQgMH1yZXR1cm4gZn1pZigwPT09ZSYmMD09PXRoaXMuY2hpbGRyZW4ubGVuZ3RoKXJldHVybltdO3Rocm93IG5ldyBFcnJvcihcInJlbW92ZUNoaWxkcmVuOiBSYW5nZSBFcnJvciwgbnVtZXJpYyB2YWx1ZXMgYXJlIG91dHNpZGUgdGhlIGFjY2VwdGFibGUgcmFuZ2VcIil9LGIuRGlzcGxheU9iamVjdENvbnRhaW5lci5wcm90b3R5cGUudXBkYXRlVHJhbnNmb3JtPWZ1bmN0aW9uKCl7aWYodGhpcy52aXNpYmxlJiYodGhpcy5kaXNwbGF5T2JqZWN0VXBkYXRlVHJhbnNmb3JtKCksIXRoaXMuX2NhY2hlQXNCaXRtYXApKWZvcih2YXIgYT0wLGI9dGhpcy5jaGlsZHJlbi5sZW5ndGg7Yj5hO2ErKyl0aGlzLmNoaWxkcmVuW2FdLnVwZGF0ZVRyYW5zZm9ybSgpfSxiLkRpc3BsYXlPYmplY3RDb250YWluZXIucHJvdG90eXBlLmRpc3BsYXlPYmplY3RDb250YWluZXJVcGRhdGVUcmFuc2Zvcm09Yi5EaXNwbGF5T2JqZWN0Q29udGFpbmVyLnByb3RvdHlwZS51cGRhdGVUcmFuc2Zvcm0sYi5EaXNwbGF5T2JqZWN0Q29udGFpbmVyLnByb3RvdHlwZS5nZXRCb3VuZHM9ZnVuY3Rpb24oKXtpZigwPT09dGhpcy5jaGlsZHJlbi5sZW5ndGgpcmV0dXJuIGIuRW1wdHlSZWN0YW5nbGU7Zm9yKHZhciBhLGMsZCxlPTEvMCxmPTEvMCxnPS0xLzAsaD0tMS8wLGk9ITEsaj0wLGs9dGhpcy5jaGlsZHJlbi5sZW5ndGg7az5qO2orKyl7dmFyIGw9dGhpcy5jaGlsZHJlbltqXTtsLnZpc2libGUmJihpPSEwLGE9dGhpcy5jaGlsZHJlbltqXS5nZXRCb3VuZHMoKSxlPWU8YS54P2U6YS54LGY9ZjxhLnk/ZjphLnksYz1hLndpZHRoK2EueCxkPWEuaGVpZ2h0K2EueSxnPWc+Yz9nOmMsaD1oPmQ/aDpkKX1pZighaSlyZXR1cm4gYi5FbXB0eVJlY3RhbmdsZTt2YXIgbT10aGlzLl9ib3VuZHM7cmV0dXJuIG0ueD1lLG0ueT1mLG0ud2lkdGg9Zy1lLG0uaGVpZ2h0PWgtZixtfSxiLkRpc3BsYXlPYmplY3RDb250YWluZXIucHJvdG90eXBlLmdldExvY2FsQm91bmRzPWZ1bmN0aW9uKCl7dmFyIGE9dGhpcy53b3JsZFRyYW5zZm9ybTt0aGlzLndvcmxkVHJhbnNmb3JtPWIuaWRlbnRpdHlNYXRyaXg7Zm9yKHZhciBjPTAsZD10aGlzLmNoaWxkcmVuLmxlbmd0aDtkPmM7YysrKXRoaXMuY2hpbGRyZW5bY10udXBkYXRlVHJhbnNmb3JtKCk7dmFyIGU9dGhpcy5nZXRCb3VuZHMoKTtyZXR1cm4gdGhpcy53b3JsZFRyYW5zZm9ybT1hLGV9LGIuRGlzcGxheU9iamVjdENvbnRhaW5lci5wcm90b3R5cGUuc2V0U3RhZ2VSZWZlcmVuY2U9ZnVuY3Rpb24oYSl7dGhpcy5zdGFnZT1hLHRoaXMuX2ludGVyYWN0aXZlJiYodGhpcy5zdGFnZS5kaXJ0eT0hMCk7Zm9yKHZhciBiPTAsYz10aGlzLmNoaWxkcmVuLmxlbmd0aDtjPmI7YisrKXt2YXIgZD10aGlzLmNoaWxkcmVuW2JdO2Quc2V0U3RhZ2VSZWZlcmVuY2UoYSl9fSxiLkRpc3BsYXlPYmplY3RDb250YWluZXIucHJvdG90eXBlLnJlbW92ZVN0YWdlUmVmZXJlbmNlPWZ1bmN0aW9uKCl7Zm9yKHZhciBhPTAsYj10aGlzLmNoaWxkcmVuLmxlbmd0aDtiPmE7YSsrKXt2YXIgYz10aGlzLmNoaWxkcmVuW2FdO2MucmVtb3ZlU3RhZ2VSZWZlcmVuY2UoKX10aGlzLl9pbnRlcmFjdGl2ZSYmKHRoaXMuc3RhZ2UuZGlydHk9ITApLHRoaXMuc3RhZ2U9bnVsbH0sYi5EaXNwbGF5T2JqZWN0Q29udGFpbmVyLnByb3RvdHlwZS5fcmVuZGVyV2ViR0w9ZnVuY3Rpb24oYSl7aWYodGhpcy52aXNpYmxlJiYhKHRoaXMuYWxwaGE8PTApKXtpZih0aGlzLl9jYWNoZUFzQml0bWFwKXJldHVybiB2b2lkIHRoaXMuX3JlbmRlckNhY2hlZFNwcml0ZShhKTt2YXIgYixjO2lmKHRoaXMuX21hc2t8fHRoaXMuX2ZpbHRlcnMpe2Zvcih0aGlzLl9maWx0ZXJzJiYoYS5zcHJpdGVCYXRjaC5mbHVzaCgpLGEuZmlsdGVyTWFuYWdlci5wdXNoRmlsdGVyKHRoaXMuX2ZpbHRlckJsb2NrKSksdGhpcy5fbWFzayYmKGEuc3ByaXRlQmF0Y2guc3RvcCgpLGEubWFza01hbmFnZXIucHVzaE1hc2sodGhpcy5tYXNrLGEpLGEuc3ByaXRlQmF0Y2guc3RhcnQoKSksYj0wLGM9dGhpcy5jaGlsZHJlbi5sZW5ndGg7Yz5iO2IrKyl0aGlzLmNoaWxkcmVuW2JdLl9yZW5kZXJXZWJHTChhKTthLnNwcml0ZUJhdGNoLnN0b3AoKSx0aGlzLl9tYXNrJiZhLm1hc2tNYW5hZ2VyLnBvcE1hc2sodGhpcy5fbWFzayxhKSx0aGlzLl9maWx0ZXJzJiZhLmZpbHRlck1hbmFnZXIucG9wRmlsdGVyKCksYS5zcHJpdGVCYXRjaC5zdGFydCgpfWVsc2UgZm9yKGI9MCxjPXRoaXMuY2hpbGRyZW4ubGVuZ3RoO2M+YjtiKyspdGhpcy5jaGlsZHJlbltiXS5fcmVuZGVyV2ViR0woYSl9fSxiLkRpc3BsYXlPYmplY3RDb250YWluZXIucHJvdG90eXBlLl9yZW5kZXJDYW52YXM9ZnVuY3Rpb24oYSl7aWYodGhpcy52aXNpYmxlIT09ITEmJjAhPT10aGlzLmFscGhhKXtpZih0aGlzLl9jYWNoZUFzQml0bWFwKXJldHVybiB2b2lkIHRoaXMuX3JlbmRlckNhY2hlZFNwcml0ZShhKTt0aGlzLl9tYXNrJiZhLm1hc2tNYW5hZ2VyLnB1c2hNYXNrKHRoaXMuX21hc2ssYSk7Zm9yKHZhciBiPTAsYz10aGlzLmNoaWxkcmVuLmxlbmd0aDtjPmI7YisrKXt2YXIgZD10aGlzLmNoaWxkcmVuW2JdO2QuX3JlbmRlckNhbnZhcyhhKX10aGlzLl9tYXNrJiZhLm1hc2tNYW5hZ2VyLnBvcE1hc2soYSl9fSxiLlNwcml0ZT1mdW5jdGlvbihhKXtiLkRpc3BsYXlPYmplY3RDb250YWluZXIuY2FsbCh0aGlzKSx0aGlzLmFuY2hvcj1uZXcgYi5Qb2ludCx0aGlzLnRleHR1cmU9YXx8Yi5UZXh0dXJlLmVtcHR5VGV4dHVyZSx0aGlzLl93aWR0aD0wLHRoaXMuX2hlaWdodD0wLHRoaXMudGludD0xNjc3NzIxNSx0aGlzLmJsZW5kTW9kZT1iLmJsZW5kTW9kZXMuTk9STUFMLHRoaXMuc2hhZGVyPW51bGwsdGhpcy50ZXh0dXJlLmJhc2VUZXh0dXJlLmhhc0xvYWRlZD90aGlzLm9uVGV4dHVyZVVwZGF0ZSgpOnRoaXMudGV4dHVyZS5vbihcInVwZGF0ZVwiLHRoaXMub25UZXh0dXJlVXBkYXRlLmJpbmQodGhpcykpLHRoaXMucmVuZGVyYWJsZT0hMH0sYi5TcHJpdGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoYi5EaXNwbGF5T2JqZWN0Q29udGFpbmVyLnByb3RvdHlwZSksYi5TcHJpdGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuU3ByaXRlLE9iamVjdC5kZWZpbmVQcm9wZXJ0eShiLlNwcml0ZS5wcm90b3R5cGUsXCJ3aWR0aFwiLHtnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5zY2FsZS54KnRoaXMudGV4dHVyZS5mcmFtZS53aWR0aH0sc2V0OmZ1bmN0aW9uKGEpe3RoaXMuc2NhbGUueD1hL3RoaXMudGV4dHVyZS5mcmFtZS53aWR0aCx0aGlzLl93aWR0aD1hfX0pLE9iamVjdC5kZWZpbmVQcm9wZXJ0eShiLlNwcml0ZS5wcm90b3R5cGUsXCJoZWlnaHRcIix7Z2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuc2NhbGUueSp0aGlzLnRleHR1cmUuZnJhbWUuaGVpZ2h0fSxzZXQ6ZnVuY3Rpb24oYSl7dGhpcy5zY2FsZS55PWEvdGhpcy50ZXh0dXJlLmZyYW1lLmhlaWdodCx0aGlzLl9oZWlnaHQ9YX19KSxiLlNwcml0ZS5wcm90b3R5cGUuc2V0VGV4dHVyZT1mdW5jdGlvbihhKXt0aGlzLnRleHR1cmU9YSx0aGlzLmNhY2hlZFRpbnQ9MTY3NzcyMTV9LGIuU3ByaXRlLnByb3RvdHlwZS5vblRleHR1cmVVcGRhdGU9ZnVuY3Rpb24oKXt0aGlzLl93aWR0aCYmKHRoaXMuc2NhbGUueD10aGlzLl93aWR0aC90aGlzLnRleHR1cmUuZnJhbWUud2lkdGgpLHRoaXMuX2hlaWdodCYmKHRoaXMuc2NhbGUueT10aGlzLl9oZWlnaHQvdGhpcy50ZXh0dXJlLmZyYW1lLmhlaWdodCl9LGIuU3ByaXRlLnByb3RvdHlwZS5nZXRCb3VuZHM9ZnVuY3Rpb24oYSl7dmFyIGI9dGhpcy50ZXh0dXJlLmZyYW1lLndpZHRoLGM9dGhpcy50ZXh0dXJlLmZyYW1lLmhlaWdodCxkPWIqKDEtdGhpcy5hbmNob3IueCksZT1iKi10aGlzLmFuY2hvci54LGY9YyooMS10aGlzLmFuY2hvci55KSxnPWMqLXRoaXMuYW5jaG9yLnksaD1hfHx0aGlzLndvcmxkVHJhbnNmb3JtLGk9aC5hLGo9aC5iLGs9aC5jLGw9aC5kLG09aC50eCxuPWgudHksbz0tMS8wLHA9LTEvMCxxPTEvMCxyPTEvMDtpZigwPT09aiYmMD09PWspMD5pJiYoaSo9LTEpLDA+bCYmKGwqPS0xKSxxPWkqZSttLG89aSpkK20scj1sKmcrbixwPWwqZituO2Vsc2V7dmFyIHM9aSplK2sqZyttLHQ9bCpnK2oqZStuLHU9aSpkK2sqZyttLHY9bCpnK2oqZCtuLHc9aSpkK2sqZittLHg9bCpmK2oqZCtuLHk9aSplK2sqZittLHo9bCpmK2oqZStuO3E9cT5zP3M6cSxxPXE+dT91OnEscT1xPnc/dzpxLHE9cT55P3k6cSxyPXI+dD90OnIscj1yPnY/djpyLHI9cj54P3g6cixyPXI+ej96OnIsbz1zPm8/czpvLG89dT5vP3U6byxvPXc+bz93Om8sbz15Pm8/eTpvLHA9dD5wP3Q6cCxwPXY+cD92OnAscD14PnA/eDpwLHA9ej5wP3o6cH12YXIgQT10aGlzLl9ib3VuZHM7cmV0dXJuIEEueD1xLEEud2lkdGg9by1xLEEueT1yLEEuaGVpZ2h0PXAtcix0aGlzLl9jdXJyZW50Qm91bmRzPUEsQX0sYi5TcHJpdGUucHJvdG90eXBlLl9yZW5kZXJXZWJHTD1mdW5jdGlvbihhKXtpZih0aGlzLnZpc2libGUmJiEodGhpcy5hbHBoYTw9MCkpe3ZhciBiLGM7aWYodGhpcy5fbWFza3x8dGhpcy5fZmlsdGVycyl7dmFyIGQ9YS5zcHJpdGVCYXRjaDtmb3IodGhpcy5fZmlsdGVycyYmKGQuZmx1c2goKSxhLmZpbHRlck1hbmFnZXIucHVzaEZpbHRlcih0aGlzLl9maWx0ZXJCbG9jaykpLHRoaXMuX21hc2smJihkLnN0b3AoKSxhLm1hc2tNYW5hZ2VyLnB1c2hNYXNrKHRoaXMubWFzayxhKSxkLnN0YXJ0KCkpLGQucmVuZGVyKHRoaXMpLGI9MCxjPXRoaXMuY2hpbGRyZW4ubGVuZ3RoO2M+YjtiKyspdGhpcy5jaGlsZHJlbltiXS5fcmVuZGVyV2ViR0woYSk7ZC5zdG9wKCksdGhpcy5fbWFzayYmYS5tYXNrTWFuYWdlci5wb3BNYXNrKHRoaXMuX21hc2ssYSksdGhpcy5fZmlsdGVycyYmYS5maWx0ZXJNYW5hZ2VyLnBvcEZpbHRlcigpLGQuc3RhcnQoKX1lbHNlIGZvcihhLnNwcml0ZUJhdGNoLnJlbmRlcih0aGlzKSxiPTAsYz10aGlzLmNoaWxkcmVuLmxlbmd0aDtjPmI7YisrKXRoaXMuY2hpbGRyZW5bYl0uX3JlbmRlcldlYkdMKGEpfX0sYi5TcHJpdGUucHJvdG90eXBlLl9yZW5kZXJDYW52YXM9ZnVuY3Rpb24oYSl7aWYoISh0aGlzLnZpc2libGU9PT0hMXx8MD09PXRoaXMuYWxwaGF8fHRoaXMudGV4dHVyZS5jcm9wLndpZHRoPD0wfHx0aGlzLnRleHR1cmUuY3JvcC5oZWlnaHQ8PTApKXtpZih0aGlzLmJsZW5kTW9kZSE9PWEuY3VycmVudEJsZW5kTW9kZSYmKGEuY3VycmVudEJsZW5kTW9kZT10aGlzLmJsZW5kTW9kZSxhLmNvbnRleHQuZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uPWIuYmxlbmRNb2Rlc0NhbnZhc1thLmN1cnJlbnRCbGVuZE1vZGVdKSx0aGlzLl9tYXNrJiZhLm1hc2tNYW5hZ2VyLnB1c2hNYXNrKHRoaXMuX21hc2ssYSksdGhpcy50ZXh0dXJlLnZhbGlkKXt2YXIgYz10aGlzLnRleHR1cmUuYmFzZVRleHR1cmUucmVzb2x1dGlvbi9hLnJlc29sdXRpb247YS5jb250ZXh0Lmdsb2JhbEFscGhhPXRoaXMud29ybGRBbHBoYSxhLnNtb290aFByb3BlcnR5JiZhLnNjYWxlTW9kZSE9PXRoaXMudGV4dHVyZS5iYXNlVGV4dHVyZS5zY2FsZU1vZGUmJihhLnNjYWxlTW9kZT10aGlzLnRleHR1cmUuYmFzZVRleHR1cmUuc2NhbGVNb2RlLGEuY29udGV4dFthLnNtb290aFByb3BlcnR5XT1hLnNjYWxlTW9kZT09PWIuc2NhbGVNb2Rlcy5MSU5FQVIpO3ZhciBkPXRoaXMudGV4dHVyZS50cmltP3RoaXMudGV4dHVyZS50cmltLngtdGhpcy5hbmNob3IueCp0aGlzLnRleHR1cmUudHJpbS53aWR0aDp0aGlzLmFuY2hvci54Ki10aGlzLnRleHR1cmUuZnJhbWUud2lkdGgsZT10aGlzLnRleHR1cmUudHJpbT90aGlzLnRleHR1cmUudHJpbS55LXRoaXMuYW5jaG9yLnkqdGhpcy50ZXh0dXJlLnRyaW0uaGVpZ2h0OnRoaXMuYW5jaG9yLnkqLXRoaXMudGV4dHVyZS5mcmFtZS5oZWlnaHQ7YS5yb3VuZFBpeGVscz8oYS5jb250ZXh0LnNldFRyYW5zZm9ybSh0aGlzLndvcmxkVHJhbnNmb3JtLmEsdGhpcy53b3JsZFRyYW5zZm9ybS5iLHRoaXMud29ybGRUcmFuc2Zvcm0uYyx0aGlzLndvcmxkVHJhbnNmb3JtLmQsdGhpcy53b3JsZFRyYW5zZm9ybS50eCphLnJlc29sdXRpb258MCx0aGlzLndvcmxkVHJhbnNmb3JtLnR5KmEucmVzb2x1dGlvbnwwKSxkPTB8ZCxlPTB8ZSk6YS5jb250ZXh0LnNldFRyYW5zZm9ybSh0aGlzLndvcmxkVHJhbnNmb3JtLmEsdGhpcy53b3JsZFRyYW5zZm9ybS5iLHRoaXMud29ybGRUcmFuc2Zvcm0uYyx0aGlzLndvcmxkVHJhbnNmb3JtLmQsdGhpcy53b3JsZFRyYW5zZm9ybS50eCphLnJlc29sdXRpb24sdGhpcy53b3JsZFRyYW5zZm9ybS50eSphLnJlc29sdXRpb24pLDE2Nzc3MjE1IT09dGhpcy50aW50Pyh0aGlzLmNhY2hlZFRpbnQhPT10aGlzLnRpbnQmJih0aGlzLmNhY2hlZFRpbnQ9dGhpcy50aW50LHRoaXMudGludGVkVGV4dHVyZT1iLkNhbnZhc1RpbnRlci5nZXRUaW50ZWRUZXh0dXJlKHRoaXMsdGhpcy50aW50KSksYS5jb250ZXh0LmRyYXdJbWFnZSh0aGlzLnRpbnRlZFRleHR1cmUsMCwwLHRoaXMudGV4dHVyZS5jcm9wLndpZHRoLHRoaXMudGV4dHVyZS5jcm9wLmhlaWdodCxkL2MsZS9jLHRoaXMudGV4dHVyZS5jcm9wLndpZHRoL2MsdGhpcy50ZXh0dXJlLmNyb3AuaGVpZ2h0L2MpKTphLmNvbnRleHQuZHJhd0ltYWdlKHRoaXMudGV4dHVyZS5iYXNlVGV4dHVyZS5zb3VyY2UsdGhpcy50ZXh0dXJlLmNyb3AueCx0aGlzLnRleHR1cmUuY3JvcC55LHRoaXMudGV4dHVyZS5jcm9wLndpZHRoLHRoaXMudGV4dHVyZS5jcm9wLmhlaWdodCxkL2MsZS9jLHRoaXMudGV4dHVyZS5jcm9wLndpZHRoL2MsdGhpcy50ZXh0dXJlLmNyb3AuaGVpZ2h0L2MpfWZvcih2YXIgZj0wLGc9dGhpcy5jaGlsZHJlbi5sZW5ndGg7Zz5mO2YrKyl0aGlzLmNoaWxkcmVuW2ZdLl9yZW5kZXJDYW52YXMoYSk7dGhpcy5fbWFzayYmYS5tYXNrTWFuYWdlci5wb3BNYXNrKGEpfX0sYi5TcHJpdGUuZnJvbUZyYW1lPWZ1bmN0aW9uKGEpe3ZhciBjPWIuVGV4dHVyZUNhY2hlW2FdO2lmKCFjKXRocm93IG5ldyBFcnJvcignVGhlIGZyYW1lSWQgXCInK2ErJ1wiIGRvZXMgbm90IGV4aXN0IGluIHRoZSB0ZXh0dXJlIGNhY2hlJyt0aGlzKTtyZXR1cm4gbmV3IGIuU3ByaXRlKGMpfSxiLlNwcml0ZS5mcm9tSW1hZ2U9ZnVuY3Rpb24oYSxjLGQpe3ZhciBlPWIuVGV4dHVyZS5mcm9tSW1hZ2UoYSxjLGQpO3JldHVybiBuZXcgYi5TcHJpdGUoZSl9LGIuU3ByaXRlQmF0Y2g9ZnVuY3Rpb24oYSl7Yi5EaXNwbGF5T2JqZWN0Q29udGFpbmVyLmNhbGwodGhpcyksdGhpcy50ZXh0dXJlVGhpbmc9YSx0aGlzLnJlYWR5PSExfSxiLlNwcml0ZUJhdGNoLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGIuRGlzcGxheU9iamVjdENvbnRhaW5lci5wcm90b3R5cGUpLGIuU3ByaXRlQmF0Y2gucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuU3ByaXRlQmF0Y2gsYi5TcHJpdGVCYXRjaC5wcm90b3R5cGUuaW5pdFdlYkdMPWZ1bmN0aW9uKGEpe3RoaXMuZmFzdFNwcml0ZUJhdGNoPW5ldyBiLldlYkdMRmFzdFNwcml0ZUJhdGNoKGEpLHRoaXMucmVhZHk9ITB9LGIuU3ByaXRlQmF0Y2gucHJvdG90eXBlLnVwZGF0ZVRyYW5zZm9ybT1mdW5jdGlvbigpe3RoaXMuZGlzcGxheU9iamVjdFVwZGF0ZVRyYW5zZm9ybSgpfSxiLlNwcml0ZUJhdGNoLnByb3RvdHlwZS5fcmVuZGVyV2ViR0w9ZnVuY3Rpb24oYSl7IXRoaXMudmlzaWJsZXx8dGhpcy5hbHBoYTw9MHx8IXRoaXMuY2hpbGRyZW4ubGVuZ3RofHwodGhpcy5yZWFkeXx8dGhpcy5pbml0V2ViR0woYS5nbCksYS5zcHJpdGVCYXRjaC5zdG9wKCksYS5zaGFkZXJNYW5hZ2VyLnNldFNoYWRlcihhLnNoYWRlck1hbmFnZXIuZmFzdFNoYWRlciksdGhpcy5mYXN0U3ByaXRlQmF0Y2guYmVnaW4odGhpcyxhKSx0aGlzLmZhc3RTcHJpdGVCYXRjaC5yZW5kZXIodGhpcyksYS5zcHJpdGVCYXRjaC5zdGFydCgpKX0sYi5TcHJpdGVCYXRjaC5wcm90b3R5cGUuX3JlbmRlckNhbnZhcz1mdW5jdGlvbihhKXtpZih0aGlzLnZpc2libGUmJiEodGhpcy5hbHBoYTw9MCkmJnRoaXMuY2hpbGRyZW4ubGVuZ3RoKXt2YXIgYj1hLmNvbnRleHQ7Yi5nbG9iYWxBbHBoYT10aGlzLndvcmxkQWxwaGEsdGhpcy5kaXNwbGF5T2JqZWN0VXBkYXRlVHJhbnNmb3JtKCk7Zm9yKHZhciBjPXRoaXMud29ybGRUcmFuc2Zvcm0sZD0hMCxlPTA7ZTx0aGlzLmNoaWxkcmVuLmxlbmd0aDtlKyspe3ZhciBmPXRoaXMuY2hpbGRyZW5bZV07aWYoZi52aXNpYmxlKXt2YXIgZz1mLnRleHR1cmUsaD1nLmZyYW1lO2lmKGIuZ2xvYmFsQWxwaGE9dGhpcy53b3JsZEFscGhhKmYuYWxwaGEsZi5yb3RhdGlvbiUoMipNYXRoLlBJKT09PTApZCYmKGIuc2V0VHJhbnNmb3JtKGMuYSxjLmIsYy5jLGMuZCxjLnR4LGMudHkpLGQ9ITEpLGIuZHJhd0ltYWdlKGcuYmFzZVRleHR1cmUuc291cmNlLGgueCxoLnksaC53aWR0aCxoLmhlaWdodCxmLmFuY2hvci54Ki1oLndpZHRoKmYuc2NhbGUueCtmLnBvc2l0aW9uLngrLjV8MCxmLmFuY2hvci55Ki1oLmhlaWdodCpmLnNjYWxlLnkrZi5wb3NpdGlvbi55Ky41fDAsaC53aWR0aCpmLnNjYWxlLngsaC5oZWlnaHQqZi5zY2FsZS55KTtlbHNle2R8fChkPSEwKSxmLmRpc3BsYXlPYmplY3RVcGRhdGVUcmFuc2Zvcm0oKTt2YXIgaT1mLndvcmxkVHJhbnNmb3JtO2Eucm91bmRQaXhlbHM/Yi5zZXRUcmFuc2Zvcm0oaS5hLGkuYixpLmMsaS5kLDB8aS50eCwwfGkudHkpOmIuc2V0VHJhbnNmb3JtKGkuYSxpLmIsaS5jLGkuZCxpLnR4LGkudHkpLGIuZHJhd0ltYWdlKGcuYmFzZVRleHR1cmUuc291cmNlLGgueCxoLnksaC53aWR0aCxoLmhlaWdodCxmLmFuY2hvci54Ki1oLndpZHRoKy41fDAsZi5hbmNob3IueSotaC5oZWlnaHQrLjV8MCxoLndpZHRoLGguaGVpZ2h0KX19fX19LGIuTW92aWVDbGlwPWZ1bmN0aW9uKGEpe2IuU3ByaXRlLmNhbGwodGhpcyxhWzBdKSx0aGlzLnRleHR1cmVzPWEsdGhpcy5hbmltYXRpb25TcGVlZD0xLHRoaXMubG9vcD0hMCx0aGlzLm9uQ29tcGxldGU9bnVsbCx0aGlzLmN1cnJlbnRGcmFtZT0wLHRoaXMucGxheWluZz0hMX0sYi5Nb3ZpZUNsaXAucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoYi5TcHJpdGUucHJvdG90eXBlKSxiLk1vdmllQ2xpcC5wcm90b3R5cGUuY29uc3RydWN0b3I9Yi5Nb3ZpZUNsaXAsT2JqZWN0LmRlZmluZVByb3BlcnR5KGIuTW92aWVDbGlwLnByb3RvdHlwZSxcInRvdGFsRnJhbWVzXCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLnRleHR1cmVzLmxlbmd0aH19KSxiLk1vdmllQ2xpcC5wcm90b3R5cGUuc3RvcD1mdW5jdGlvbigpe3RoaXMucGxheWluZz0hMX0sYi5Nb3ZpZUNsaXAucHJvdG90eXBlLnBsYXk9ZnVuY3Rpb24oKXt0aGlzLnBsYXlpbmc9ITB9LGIuTW92aWVDbGlwLnByb3RvdHlwZS5nb3RvQW5kU3RvcD1mdW5jdGlvbihhKXt0aGlzLnBsYXlpbmc9ITEsdGhpcy5jdXJyZW50RnJhbWU9YTt2YXIgYj10aGlzLmN1cnJlbnRGcmFtZSsuNXwwO3RoaXMuc2V0VGV4dHVyZSh0aGlzLnRleHR1cmVzW2IldGhpcy50ZXh0dXJlcy5sZW5ndGhdKX0sYi5Nb3ZpZUNsaXAucHJvdG90eXBlLmdvdG9BbmRQbGF5PWZ1bmN0aW9uKGEpe3RoaXMuY3VycmVudEZyYW1lPWEsdGhpcy5wbGF5aW5nPSEwfSxiLk1vdmllQ2xpcC5wcm90b3R5cGUudXBkYXRlVHJhbnNmb3JtPWZ1bmN0aW9uKCl7aWYodGhpcy5kaXNwbGF5T2JqZWN0Q29udGFpbmVyVXBkYXRlVHJhbnNmb3JtKCksdGhpcy5wbGF5aW5nKXt0aGlzLmN1cnJlbnRGcmFtZSs9dGhpcy5hbmltYXRpb25TcGVlZDt2YXIgYT10aGlzLmN1cnJlbnRGcmFtZSsuNXwwO3RoaXMuY3VycmVudEZyYW1lPXRoaXMuY3VycmVudEZyYW1lJXRoaXMudGV4dHVyZXMubGVuZ3RoLHRoaXMubG9vcHx8YTx0aGlzLnRleHR1cmVzLmxlbmd0aD90aGlzLnNldFRleHR1cmUodGhpcy50ZXh0dXJlc1thJXRoaXMudGV4dHVyZXMubGVuZ3RoXSk6YT49dGhpcy50ZXh0dXJlcy5sZW5ndGgmJih0aGlzLmdvdG9BbmRTdG9wKHRoaXMudGV4dHVyZXMubGVuZ3RoLTEpLHRoaXMub25Db21wbGV0ZSYmdGhpcy5vbkNvbXBsZXRlKCkpfX0sYi5Nb3ZpZUNsaXAuZnJvbUZyYW1lcz1mdW5jdGlvbihhKXtmb3IodmFyIGM9W10sZD0wO2Q8YS5sZW5ndGg7ZCsrKWMucHVzaChuZXcgYi5UZXh0dXJlLmZyb21GcmFtZShhW2RdKSk7cmV0dXJuIG5ldyBiLk1vdmllQ2xpcChjKX0sYi5Nb3ZpZUNsaXAuZnJvbUltYWdlcz1mdW5jdGlvbihhKXtmb3IodmFyIGM9W10sZD0wO2Q8YS5sZW5ndGg7ZCsrKWMucHVzaChuZXcgYi5UZXh0dXJlLmZyb21JbWFnZShhW2RdKSk7cmV0dXJuIG5ldyBiLk1vdmllQ2xpcChjKX0sYi5GaWx0ZXJCbG9jaz1mdW5jdGlvbigpe3RoaXMudmlzaWJsZT0hMCx0aGlzLnJlbmRlcmFibGU9ITB9LGIuRmlsdGVyQmxvY2sucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuRmlsdGVyQmxvY2ssYi5UZXh0PWZ1bmN0aW9uKGEsYyl7dGhpcy5jYW52YXM9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImNhbnZhc1wiKSx0aGlzLmNvbnRleHQ9dGhpcy5jYW52YXMuZ2V0Q29udGV4dChcIjJkXCIpLHRoaXMucmVzb2x1dGlvbj0xLGIuU3ByaXRlLmNhbGwodGhpcyxiLlRleHR1cmUuZnJvbUNhbnZhcyh0aGlzLmNhbnZhcykpLHRoaXMuc2V0VGV4dChhKSx0aGlzLnNldFN0eWxlKGMpfSxiLlRleHQucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoYi5TcHJpdGUucHJvdG90eXBlKSxiLlRleHQucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuVGV4dCxPYmplY3QuZGVmaW5lUHJvcGVydHkoYi5UZXh0LnByb3RvdHlwZSxcIndpZHRoXCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmRpcnR5JiYodGhpcy51cGRhdGVUZXh0KCksdGhpcy5kaXJ0eT0hMSksdGhpcy5zY2FsZS54KnRoaXMudGV4dHVyZS5mcmFtZS53aWR0aH0sc2V0OmZ1bmN0aW9uKGEpe3RoaXMuc2NhbGUueD1hL3RoaXMudGV4dHVyZS5mcmFtZS53aWR0aCx0aGlzLl93aWR0aD1hfX0pLE9iamVjdC5kZWZpbmVQcm9wZXJ0eShiLlRleHQucHJvdG90eXBlLFwiaGVpZ2h0XCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmRpcnR5JiYodGhpcy51cGRhdGVUZXh0KCksdGhpcy5kaXJ0eT0hMSksdGhpcy5zY2FsZS55KnRoaXMudGV4dHVyZS5mcmFtZS5oZWlnaHR9LHNldDpmdW5jdGlvbihhKXt0aGlzLnNjYWxlLnk9YS90aGlzLnRleHR1cmUuZnJhbWUuaGVpZ2h0LHRoaXMuX2hlaWdodD1hfX0pLGIuVGV4dC5wcm90b3R5cGUuc2V0U3R5bGU9ZnVuY3Rpb24oYSl7YT1hfHx7fSxhLmZvbnQ9YS5mb250fHxcImJvbGQgMjBwdCBBcmlhbFwiLGEuZmlsbD1hLmZpbGx8fFwiYmxhY2tcIixhLmFsaWduPWEuYWxpZ258fFwibGVmdFwiLGEuc3Ryb2tlPWEuc3Ryb2tlfHxcImJsYWNrXCIsYS5zdHJva2VUaGlja25lc3M9YS5zdHJva2VUaGlja25lc3N8fDAsYS53b3JkV3JhcD1hLndvcmRXcmFwfHwhMSxhLndvcmRXcmFwV2lkdGg9YS53b3JkV3JhcFdpZHRofHwxMDAsYS5kcm9wU2hhZG93PWEuZHJvcFNoYWRvd3x8ITEsYS5kcm9wU2hhZG93QW5nbGU9YS5kcm9wU2hhZG93QW5nbGV8fE1hdGguUEkvNixhLmRyb3BTaGFkb3dEaXN0YW5jZT1hLmRyb3BTaGFkb3dEaXN0YW5jZXx8NCxhLmRyb3BTaGFkb3dDb2xvcj1hLmRyb3BTaGFkb3dDb2xvcnx8XCJibGFja1wiLHRoaXMuc3R5bGU9YSx0aGlzLmRpcnR5PSEwfSxiLlRleHQucHJvdG90eXBlLnNldFRleHQ9ZnVuY3Rpb24oYSl7dGhpcy50ZXh0PWEudG9TdHJpbmcoKXx8XCIgXCIsdGhpcy5kaXJ0eT0hMH0sYi5UZXh0LnByb3RvdHlwZS51cGRhdGVUZXh0PWZ1bmN0aW9uKCl7dGhpcy50ZXh0dXJlLmJhc2VUZXh0dXJlLnJlc29sdXRpb249dGhpcy5yZXNvbHV0aW9uLHRoaXMuY29udGV4dC5mb250PXRoaXMuc3R5bGUuZm9udDt2YXIgYT10aGlzLnRleHQ7dGhpcy5zdHlsZS53b3JkV3JhcCYmKGE9dGhpcy53b3JkV3JhcCh0aGlzLnRleHQpKTtmb3IodmFyIGI9YS5zcGxpdCgvKD86XFxyXFxufFxccnxcXG4pLyksYz1bXSxkPTAsZT10aGlzLmRldGVybWluZUZvbnRQcm9wZXJ0aWVzKHRoaXMuc3R5bGUuZm9udCksZj0wO2Y8Yi5sZW5ndGg7ZisrKXt2YXIgZz10aGlzLmNvbnRleHQubWVhc3VyZVRleHQoYltmXSkud2lkdGg7Y1tmXT1nLGQ9TWF0aC5tYXgoZCxnKX12YXIgaD1kK3RoaXMuc3R5bGUuc3Ryb2tlVGhpY2tuZXNzO3RoaXMuc3R5bGUuZHJvcFNoYWRvdyYmKGgrPXRoaXMuc3R5bGUuZHJvcFNoYWRvd0Rpc3RhbmNlKSx0aGlzLmNhbnZhcy53aWR0aD0oaCt0aGlzLmNvbnRleHQubGluZVdpZHRoKSp0aGlzLnJlc29sdXRpb247dmFyIGk9ZS5mb250U2l6ZSt0aGlzLnN0eWxlLnN0cm9rZVRoaWNrbmVzcyxqPWkqYi5sZW5ndGg7dGhpcy5zdHlsZS5kcm9wU2hhZG93JiYoais9dGhpcy5zdHlsZS5kcm9wU2hhZG93RGlzdGFuY2UpLHRoaXMuY2FudmFzLmhlaWdodD1qKnRoaXMucmVzb2x1dGlvbix0aGlzLmNvbnRleHQuc2NhbGUodGhpcy5yZXNvbHV0aW9uLHRoaXMucmVzb2x1dGlvbiksbmF2aWdhdG9yLmlzQ29jb29uSlMmJnRoaXMuY29udGV4dC5jbGVhclJlY3QoMCwwLHRoaXMuY2FudmFzLndpZHRoLHRoaXMuY2FudmFzLmhlaWdodCksdGhpcy5jb250ZXh0LmZvbnQ9dGhpcy5zdHlsZS5mb250LHRoaXMuY29udGV4dC5zdHJva2VTdHlsZT10aGlzLnN0eWxlLnN0cm9rZSx0aGlzLmNvbnRleHQubGluZVdpZHRoPXRoaXMuc3R5bGUuc3Ryb2tlVGhpY2tuZXNzLHRoaXMuY29udGV4dC50ZXh0QmFzZWxpbmU9XCJhbHBoYWJldGljXCI7dmFyIGssbDtpZih0aGlzLnN0eWxlLmRyb3BTaGFkb3cpe3RoaXMuY29udGV4dC5maWxsU3R5bGU9dGhpcy5zdHlsZS5kcm9wU2hhZG93Q29sb3I7dmFyIG09TWF0aC5zaW4odGhpcy5zdHlsZS5kcm9wU2hhZG93QW5nbGUpKnRoaXMuc3R5bGUuZHJvcFNoYWRvd0Rpc3RhbmNlLG49TWF0aC5jb3ModGhpcy5zdHlsZS5kcm9wU2hhZG93QW5nbGUpKnRoaXMuc3R5bGUuZHJvcFNoYWRvd0Rpc3RhbmNlO2ZvcihmPTA7ZjxiLmxlbmd0aDtmKyspaz10aGlzLnN0eWxlLnN0cm9rZVRoaWNrbmVzcy8yLGw9dGhpcy5zdHlsZS5zdHJva2VUaGlja25lc3MvMitmKmkrZS5hc2NlbnQsXCJyaWdodFwiPT09dGhpcy5zdHlsZS5hbGlnbj9rKz1kLWNbZl06XCJjZW50ZXJcIj09PXRoaXMuc3R5bGUuYWxpZ24mJihrKz0oZC1jW2ZdKS8yKSx0aGlzLnN0eWxlLmZpbGwmJnRoaXMuY29udGV4dC5maWxsVGV4dChiW2ZdLGsrbSxsK24pfWZvcih0aGlzLmNvbnRleHQuZmlsbFN0eWxlPXRoaXMuc3R5bGUuZmlsbCxmPTA7ZjxiLmxlbmd0aDtmKyspaz10aGlzLnN0eWxlLnN0cm9rZVRoaWNrbmVzcy8yLGw9dGhpcy5zdHlsZS5zdHJva2VUaGlja25lc3MvMitmKmkrZS5hc2NlbnQsXCJyaWdodFwiPT09dGhpcy5zdHlsZS5hbGlnbj9rKz1kLWNbZl06XCJjZW50ZXJcIj09PXRoaXMuc3R5bGUuYWxpZ24mJihrKz0oZC1jW2ZdKS8yKSx0aGlzLnN0eWxlLnN0cm9rZSYmdGhpcy5zdHlsZS5zdHJva2VUaGlja25lc3MmJnRoaXMuY29udGV4dC5zdHJva2VUZXh0KGJbZl0sayxsKSx0aGlzLnN0eWxlLmZpbGwmJnRoaXMuY29udGV4dC5maWxsVGV4dChiW2ZdLGssbCk7dGhpcy51cGRhdGVUZXh0dXJlKCl9LGIuVGV4dC5wcm90b3R5cGUudXBkYXRlVGV4dHVyZT1mdW5jdGlvbigpe3RoaXMudGV4dHVyZS5iYXNlVGV4dHVyZS53aWR0aD10aGlzLmNhbnZhcy53aWR0aCx0aGlzLnRleHR1cmUuYmFzZVRleHR1cmUuaGVpZ2h0PXRoaXMuY2FudmFzLmhlaWdodCx0aGlzLnRleHR1cmUuY3JvcC53aWR0aD10aGlzLnRleHR1cmUuZnJhbWUud2lkdGg9dGhpcy5jYW52YXMud2lkdGgsdGhpcy50ZXh0dXJlLmNyb3AuaGVpZ2h0PXRoaXMudGV4dHVyZS5mcmFtZS5oZWlnaHQ9dGhpcy5jYW52YXMuaGVpZ2h0LHRoaXMuX3dpZHRoPXRoaXMuY2FudmFzLndpZHRoLHRoaXMuX2hlaWdodD10aGlzLmNhbnZhcy5oZWlnaHQsdGhpcy50ZXh0dXJlLmJhc2VUZXh0dXJlLmRpcnR5KCl9LGIuVGV4dC5wcm90b3R5cGUuX3JlbmRlcldlYkdMPWZ1bmN0aW9uKGEpe3RoaXMuZGlydHkmJih0aGlzLnJlc29sdXRpb249YS5yZXNvbHV0aW9uLHRoaXMudXBkYXRlVGV4dCgpLHRoaXMuZGlydHk9ITEpLGIuU3ByaXRlLnByb3RvdHlwZS5fcmVuZGVyV2ViR0wuY2FsbCh0aGlzLGEpfSxiLlRleHQucHJvdG90eXBlLl9yZW5kZXJDYW52YXM9ZnVuY3Rpb24oYSl7dGhpcy5kaXJ0eSYmKHRoaXMucmVzb2x1dGlvbj1hLnJlc29sdXRpb24sdGhpcy51cGRhdGVUZXh0KCksdGhpcy5kaXJ0eT0hMSksYi5TcHJpdGUucHJvdG90eXBlLl9yZW5kZXJDYW52YXMuY2FsbCh0aGlzLGEpfSxiLlRleHQucHJvdG90eXBlLmRldGVybWluZUZvbnRQcm9wZXJ0aWVzPWZ1bmN0aW9uKGEpe3ZhciBjPWIuVGV4dC5mb250UHJvcGVydGllc0NhY2hlW2FdO2lmKCFjKXtjPXt9O3ZhciBkPWIuVGV4dC5mb250UHJvcGVydGllc0NhbnZhcyxlPWIuVGV4dC5mb250UHJvcGVydGllc0NvbnRleHQ7ZS5mb250PWE7dmFyIGY9TWF0aC5jZWlsKGUubWVhc3VyZVRleHQoXCJ8TXFcIikud2lkdGgpLGc9TWF0aC5jZWlsKGUubWVhc3VyZVRleHQoXCJNXCIpLndpZHRoKSxoPTIqZztnPTEuNCpnfDAsZC53aWR0aD1mLGQuaGVpZ2h0PWgsZS5maWxsU3R5bGU9XCIjZjAwXCIsZS5maWxsUmVjdCgwLDAsZixoKSxlLmZvbnQ9YSxlLnRleHRCYXNlbGluZT1cImFscGhhYmV0aWNcIixlLmZpbGxTdHlsZT1cIiMwMDBcIixlLmZpbGxUZXh0KFwifE3DiXFcIiwwLGcpO3ZhciBpLGosaz1lLmdldEltYWdlRGF0YSgwLDAsZixoKS5kYXRhLGw9ay5sZW5ndGgsbT00KmYsbj0wLG89ITE7Zm9yKGk9MDtnPmk7aSsrKXtmb3Ioaj0wO20+ajtqKz00KWlmKDI1NSE9PWtbbitqXSl7bz0hMDticmVha31pZihvKWJyZWFrO24rPW19Zm9yKGMuYXNjZW50PWctaSxuPWwtbSxvPSExLGk9aDtpPmc7aS0tKXtmb3Ioaj0wO20+ajtqKz00KWlmKDI1NSE9PWtbbitqXSl7bz0hMDticmVha31pZihvKWJyZWFrO24tPW19Yy5kZXNjZW50PWktZyxjLmRlc2NlbnQrPTYsYy5mb250U2l6ZT1jLmFzY2VudCtjLmRlc2NlbnQsYi5UZXh0LmZvbnRQcm9wZXJ0aWVzQ2FjaGVbYV09Y31yZXR1cm4gY30sYi5UZXh0LnByb3RvdHlwZS53b3JkV3JhcD1mdW5jdGlvbihhKXtmb3IodmFyIGI9XCJcIixjPWEuc3BsaXQoXCJcXG5cIiksZD0wO2Q8Yy5sZW5ndGg7ZCsrKXtmb3IodmFyIGU9dGhpcy5zdHlsZS53b3JkV3JhcFdpZHRoLGY9Y1tkXS5zcGxpdChcIiBcIiksZz0wO2c8Zi5sZW5ndGg7ZysrKXt2YXIgaD10aGlzLmNvbnRleHQubWVhc3VyZVRleHQoZltnXSkud2lkdGgsaT1oK3RoaXMuY29udGV4dC5tZWFzdXJlVGV4dChcIiBcIikud2lkdGg7MD09PWd8fGk+ZT8oZz4wJiYoYis9XCJcXG5cIiksYis9ZltnXSxlPXRoaXMuc3R5bGUud29yZFdyYXBXaWR0aC1oKTooZS09aSxiKz1cIiBcIitmW2ddKX1kPGMubGVuZ3RoLTEmJihiKz1cIlxcblwiKX1yZXR1cm4gYn0sYi5UZXh0LnByb3RvdHlwZS5nZXRCb3VuZHM9ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZGlydHkmJih0aGlzLnVwZGF0ZVRleHQoKSx0aGlzLmRpcnR5PSExKSxiLlNwcml0ZS5wcm90b3R5cGUuZ2V0Qm91bmRzLmNhbGwodGhpcyxhKX0sYi5UZXh0LnByb3RvdHlwZS5kZXN0cm95PWZ1bmN0aW9uKGEpe3RoaXMuY29udGV4dD1udWxsLHRoaXMuY2FudmFzPW51bGwsdGhpcy50ZXh0dXJlLmRlc3Ryb3kodm9pZCAwPT09YT8hMDphKX0sYi5UZXh0LmZvbnRQcm9wZXJ0aWVzQ2FjaGU9e30sYi5UZXh0LmZvbnRQcm9wZXJ0aWVzQ2FudmFzPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJjYW52YXNcIiksYi5UZXh0LmZvbnRQcm9wZXJ0aWVzQ29udGV4dD1iLlRleHQuZm9udFByb3BlcnRpZXNDYW52YXMuZ2V0Q29udGV4dChcIjJkXCIpLGIuQml0bWFwVGV4dD1mdW5jdGlvbihhLGMpe2IuRGlzcGxheU9iamVjdENvbnRhaW5lci5jYWxsKHRoaXMpLHRoaXMudGV4dFdpZHRoPTAsdGhpcy50ZXh0SGVpZ2h0PTAsdGhpcy5fcG9vbD1bXSx0aGlzLnNldFRleHQoYSksdGhpcy5zZXRTdHlsZShjKSx0aGlzLnVwZGF0ZVRleHQoKSx0aGlzLmRpcnR5PSExfSxiLkJpdG1hcFRleHQucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoYi5EaXNwbGF5T2JqZWN0Q29udGFpbmVyLnByb3RvdHlwZSksYi5CaXRtYXBUZXh0LnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLkJpdG1hcFRleHQsYi5CaXRtYXBUZXh0LnByb3RvdHlwZS5zZXRUZXh0PWZ1bmN0aW9uKGEpe3RoaXMudGV4dD1hfHxcIiBcIix0aGlzLmRpcnR5PSEwfSxiLkJpdG1hcFRleHQucHJvdG90eXBlLnNldFN0eWxlPWZ1bmN0aW9uKGEpe2E9YXx8e30sYS5hbGlnbj1hLmFsaWdufHxcImxlZnRcIix0aGlzLnN0eWxlPWE7dmFyIGM9YS5mb250LnNwbGl0KFwiIFwiKTt0aGlzLmZvbnROYW1lPWNbYy5sZW5ndGgtMV0sdGhpcy5mb250U2l6ZT1jLmxlbmd0aD49Mj9wYXJzZUludChjW2MubGVuZ3RoLTJdLDEwKTpiLkJpdG1hcFRleHQuZm9udHNbdGhpcy5mb250TmFtZV0uc2l6ZSx0aGlzLmRpcnR5PSEwLHRoaXMudGludD1hLnRpbnR9LGIuQml0bWFwVGV4dC5wcm90b3R5cGUudXBkYXRlVGV4dD1mdW5jdGlvbigpe2Zvcih2YXIgYT1iLkJpdG1hcFRleHQuZm9udHNbdGhpcy5mb250TmFtZV0sYz1uZXcgYi5Qb2ludCxkPW51bGwsZT1bXSxmPTAsZz1bXSxoPTAsaT10aGlzLmZvbnRTaXplL2Euc2l6ZSxqPTA7ajx0aGlzLnRleHQubGVuZ3RoO2orKyl7dmFyIGs9dGhpcy50ZXh0LmNoYXJDb2RlQXQoaik7aWYoLyg/OlxcclxcbnxcXHJ8XFxuKS8udGVzdCh0aGlzLnRleHQuY2hhckF0KGopKSlnLnB1c2goYy54KSxmPU1hdGgubWF4KGYsYy54KSxoKyssYy54PTAsYy55Kz1hLmxpbmVIZWlnaHQsZD1udWxsO2Vsc2V7dmFyIGw9YS5jaGFyc1trXTtsJiYoZCYmbC5rZXJuaW5nW2RdJiYoYy54Kz1sLmtlcm5pbmdbZF0pLGUucHVzaCh7dGV4dHVyZTpsLnRleHR1cmUsbGluZTpoLGNoYXJDb2RlOmsscG9zaXRpb246bmV3IGIuUG9pbnQoYy54K2wueE9mZnNldCxjLnkrbC55T2Zmc2V0KX0pLGMueCs9bC54QWR2YW5jZSxkPWspfX1nLnB1c2goYy54KSxmPU1hdGgubWF4KGYsYy54KTt2YXIgbT1bXTtmb3Ioaj0wO2g+PWo7aisrKXt2YXIgbj0wO1wicmlnaHRcIj09PXRoaXMuc3R5bGUuYWxpZ24/bj1mLWdbal06XCJjZW50ZXJcIj09PXRoaXMuc3R5bGUuYWxpZ24mJihuPShmLWdbal0pLzIpLG0ucHVzaChuKX12YXIgbz10aGlzLmNoaWxkcmVuLmxlbmd0aCxwPWUubGVuZ3RoLHE9dGhpcy50aW50fHwxNjc3NzIxNTtmb3Ioaj0wO3A+ajtqKyspe3ZhciByPW8+aj90aGlzLmNoaWxkcmVuW2pdOnRoaXMuX3Bvb2wucG9wKCk7cj9yLnNldFRleHR1cmUoZVtqXS50ZXh0dXJlKTpyPW5ldyBiLlNwcml0ZShlW2pdLnRleHR1cmUpLHIucG9zaXRpb24ueD0oZVtqXS5wb3NpdGlvbi54K21bZVtqXS5saW5lXSkqaSxyLnBvc2l0aW9uLnk9ZVtqXS5wb3NpdGlvbi55Kmksci5zY2FsZS54PXIuc2NhbGUueT1pLHIudGludD1xLHIucGFyZW50fHx0aGlzLmFkZENoaWxkKHIpfWZvcig7dGhpcy5jaGlsZHJlbi5sZW5ndGg+cDspe3ZhciBzPXRoaXMuZ2V0Q2hpbGRBdCh0aGlzLmNoaWxkcmVuLmxlbmd0aC0xKTt0aGlzLl9wb29sLnB1c2gocyksdGhpcy5yZW1vdmVDaGlsZChzKX10aGlzLnRleHRXaWR0aD1mKmksdGhpcy50ZXh0SGVpZ2h0PShjLnkrYS5saW5lSGVpZ2h0KSppfSxiLkJpdG1hcFRleHQucHJvdG90eXBlLnVwZGF0ZVRyYW5zZm9ybT1mdW5jdGlvbigpe3RoaXMuZGlydHkmJih0aGlzLnVwZGF0ZVRleHQoKSx0aGlzLmRpcnR5PSExKSxiLkRpc3BsYXlPYmplY3RDb250YWluZXIucHJvdG90eXBlLnVwZGF0ZVRyYW5zZm9ybS5jYWxsKHRoaXMpfSxiLkJpdG1hcFRleHQuZm9udHM9e30sYi5JbnRlcmFjdGlvbkRhdGE9ZnVuY3Rpb24oKXt0aGlzLmdsb2JhbD1uZXcgYi5Qb2ludCx0aGlzLnRhcmdldD1udWxsLHRoaXMub3JpZ2luYWxFdmVudD1udWxsfSxiLkludGVyYWN0aW9uRGF0YS5wcm90b3R5cGUuZ2V0TG9jYWxQb3NpdGlvbj1mdW5jdGlvbihhLGMpe3ZhciBkPWEud29ybGRUcmFuc2Zvcm0sZT10aGlzLmdsb2JhbCxmPWQuYSxnPWQuYyxoPWQudHgsaT1kLmIsaj1kLmQsaz1kLnR5LGw9MS8oZipqK2cqLWkpO3JldHVybiBjPWN8fG5ldyBiLlBvaW50LGMueD1qKmwqZS54Ky1nKmwqZS55KyhrKmctaCpqKSpsLGMueT1mKmwqZS55Ky1pKmwqZS54KygtaypmK2gqaSkqbCxjfSxiLkludGVyYWN0aW9uRGF0YS5wcm90b3R5cGUuY29uc3RydWN0b3I9Yi5JbnRlcmFjdGlvbkRhdGEsYi5JbnRlcmFjdGlvbk1hbmFnZXI9ZnVuY3Rpb24oYSl7dGhpcy5zdGFnZT1hLHRoaXMubW91c2U9bmV3IGIuSW50ZXJhY3Rpb25EYXRhLHRoaXMudG91Y2hlcz17fSx0aGlzLnRlbXBQb2ludD1uZXcgYi5Qb2ludCx0aGlzLm1vdXNlb3ZlckVuYWJsZWQ9ITAsdGhpcy5wb29sPVtdLHRoaXMuaW50ZXJhY3RpdmVJdGVtcz1bXSx0aGlzLmludGVyYWN0aW9uRE9NRWxlbWVudD1udWxsLHRoaXMub25Nb3VzZU1vdmU9dGhpcy5vbk1vdXNlTW92ZS5iaW5kKHRoaXMpLHRoaXMub25Nb3VzZURvd249dGhpcy5vbk1vdXNlRG93bi5iaW5kKHRoaXMpLHRoaXMub25Nb3VzZU91dD10aGlzLm9uTW91c2VPdXQuYmluZCh0aGlzKSx0aGlzLm9uTW91c2VVcD10aGlzLm9uTW91c2VVcC5iaW5kKHRoaXMpLHRoaXMub25Ub3VjaFN0YXJ0PXRoaXMub25Ub3VjaFN0YXJ0LmJpbmQodGhpcyksdGhpcy5vblRvdWNoRW5kPXRoaXMub25Ub3VjaEVuZC5iaW5kKHRoaXMpLHRoaXMub25Ub3VjaE1vdmU9dGhpcy5vblRvdWNoTW92ZS5iaW5kKHRoaXMpLHRoaXMubGFzdD0wLHRoaXMuY3VycmVudEN1cnNvclN0eWxlPVwiaW5oZXJpdFwiLHRoaXMubW91c2VPdXQ9ITEsdGhpcy5yZXNvbHV0aW9uPTEsdGhpcy5fdGVtcFBvaW50PW5ldyBiLlBvaW50fSxiLkludGVyYWN0aW9uTWFuYWdlci5wcm90b3R5cGUuY29uc3RydWN0b3I9Yi5JbnRlcmFjdGlvbk1hbmFnZXIsYi5JbnRlcmFjdGlvbk1hbmFnZXIucHJvdG90eXBlLmNvbGxlY3RJbnRlcmFjdGl2ZVNwcml0ZT1mdW5jdGlvbihhLGIpe2Zvcih2YXIgYz1hLmNoaWxkcmVuLGQ9Yy5sZW5ndGgsZT1kLTE7ZT49MDtlLS0pe3ZhciBmPWNbZV07XG5mLl9pbnRlcmFjdGl2ZT8oYi5pbnRlcmFjdGl2ZUNoaWxkcmVuPSEwLHRoaXMuaW50ZXJhY3RpdmVJdGVtcy5wdXNoKGYpLGYuY2hpbGRyZW4ubGVuZ3RoPjAmJnRoaXMuY29sbGVjdEludGVyYWN0aXZlU3ByaXRlKGYsZikpOihmLl9faVBhcmVudD1udWxsLGYuY2hpbGRyZW4ubGVuZ3RoPjAmJnRoaXMuY29sbGVjdEludGVyYWN0aXZlU3ByaXRlKGYsYikpfX0sYi5JbnRlcmFjdGlvbk1hbmFnZXIucHJvdG90eXBlLnNldFRhcmdldD1mdW5jdGlvbihhKXt0aGlzLnRhcmdldD1hLHRoaXMucmVzb2x1dGlvbj1hLnJlc29sdXRpb24sbnVsbD09PXRoaXMuaW50ZXJhY3Rpb25ET01FbGVtZW50JiZ0aGlzLnNldFRhcmdldERvbUVsZW1lbnQoYS52aWV3KX0sYi5JbnRlcmFjdGlvbk1hbmFnZXIucHJvdG90eXBlLnNldFRhcmdldERvbUVsZW1lbnQ9ZnVuY3Rpb24oYSl7dGhpcy5yZW1vdmVFdmVudHMoKSx3aW5kb3cubmF2aWdhdG9yLm1zUG9pbnRlckVuYWJsZWQmJihhLnN0eWxlW1wiLW1zLWNvbnRlbnQtem9vbWluZ1wiXT1cIm5vbmVcIixhLnN0eWxlW1wiLW1zLXRvdWNoLWFjdGlvblwiXT1cIm5vbmVcIiksdGhpcy5pbnRlcmFjdGlvbkRPTUVsZW1lbnQ9YSxhLmFkZEV2ZW50TGlzdGVuZXIoXCJtb3VzZW1vdmVcIix0aGlzLm9uTW91c2VNb3ZlLCEwKSxhLmFkZEV2ZW50TGlzdGVuZXIoXCJtb3VzZWRvd25cIix0aGlzLm9uTW91c2VEb3duLCEwKSxhLmFkZEV2ZW50TGlzdGVuZXIoXCJtb3VzZW91dFwiLHRoaXMub25Nb3VzZU91dCwhMCksYS5hZGRFdmVudExpc3RlbmVyKFwidG91Y2hzdGFydFwiLHRoaXMub25Ub3VjaFN0YXJ0LCEwKSxhLmFkZEV2ZW50TGlzdGVuZXIoXCJ0b3VjaGVuZFwiLHRoaXMub25Ub3VjaEVuZCwhMCksYS5hZGRFdmVudExpc3RlbmVyKFwidG91Y2htb3ZlXCIsdGhpcy5vblRvdWNoTW92ZSwhMCksd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJtb3VzZXVwXCIsdGhpcy5vbk1vdXNlVXAsITApfSxiLkludGVyYWN0aW9uTWFuYWdlci5wcm90b3R5cGUucmVtb3ZlRXZlbnRzPWZ1bmN0aW9uKCl7dGhpcy5pbnRlcmFjdGlvbkRPTUVsZW1lbnQmJih0aGlzLmludGVyYWN0aW9uRE9NRWxlbWVudC5zdHlsZVtcIi1tcy1jb250ZW50LXpvb21pbmdcIl09XCJcIix0aGlzLmludGVyYWN0aW9uRE9NRWxlbWVudC5zdHlsZVtcIi1tcy10b3VjaC1hY3Rpb25cIl09XCJcIix0aGlzLmludGVyYWN0aW9uRE9NRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFwibW91c2Vtb3ZlXCIsdGhpcy5vbk1vdXNlTW92ZSwhMCksdGhpcy5pbnRlcmFjdGlvbkRPTUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcIm1vdXNlZG93blwiLHRoaXMub25Nb3VzZURvd24sITApLHRoaXMuaW50ZXJhY3Rpb25ET01FbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJtb3VzZW91dFwiLHRoaXMub25Nb3VzZU91dCwhMCksdGhpcy5pbnRlcmFjdGlvbkRPTUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcInRvdWNoc3RhcnRcIix0aGlzLm9uVG91Y2hTdGFydCwhMCksdGhpcy5pbnRlcmFjdGlvbkRPTUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcInRvdWNoZW5kXCIsdGhpcy5vblRvdWNoRW5kLCEwKSx0aGlzLmludGVyYWN0aW9uRE9NRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFwidG91Y2htb3ZlXCIsdGhpcy5vblRvdWNoTW92ZSwhMCksdGhpcy5pbnRlcmFjdGlvbkRPTUVsZW1lbnQ9bnVsbCx3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihcIm1vdXNldXBcIix0aGlzLm9uTW91c2VVcCwhMCkpfSxiLkludGVyYWN0aW9uTWFuYWdlci5wcm90b3R5cGUudXBkYXRlPWZ1bmN0aW9uKCl7aWYodGhpcy50YXJnZXQpe3ZhciBhPURhdGUubm93KCksYz1hLXRoaXMubGFzdDtpZihjPWMqYi5JTlRFUkFDVElPTl9GUkVRVUVOQ1kvMWUzLCEoMT5jKSl7dGhpcy5sYXN0PWE7dmFyIGQ9MDt0aGlzLmRpcnR5JiZ0aGlzLnJlYnVpbGRJbnRlcmFjdGl2ZUdyYXBoKCk7dmFyIGU9dGhpcy5pbnRlcmFjdGl2ZUl0ZW1zLmxlbmd0aCxmPVwiaW5oZXJpdFwiLGc9ITE7Zm9yKGQ9MDtlPmQ7ZCsrKXt2YXIgaD10aGlzLmludGVyYWN0aXZlSXRlbXNbZF07aC5fX2hpdD10aGlzLmhpdFRlc3QoaCx0aGlzLm1vdXNlKSx0aGlzLm1vdXNlLnRhcmdldD1oLGguX19oaXQmJiFnPyhoLmJ1dHRvbk1vZGUmJihmPWguZGVmYXVsdEN1cnNvciksaC5pbnRlcmFjdGl2ZUNoaWxkcmVufHwoZz0hMCksaC5fX2lzT3Zlcnx8KGgubW91c2VvdmVyJiZoLm1vdXNlb3Zlcih0aGlzLm1vdXNlKSxoLl9faXNPdmVyPSEwKSk6aC5fX2lzT3ZlciYmKGgubW91c2VvdXQmJmgubW91c2VvdXQodGhpcy5tb3VzZSksaC5fX2lzT3Zlcj0hMSl9dGhpcy5jdXJyZW50Q3Vyc29yU3R5bGUhPT1mJiYodGhpcy5jdXJyZW50Q3Vyc29yU3R5bGU9Zix0aGlzLmludGVyYWN0aW9uRE9NRWxlbWVudC5zdHlsZS5jdXJzb3I9Zil9fX0sYi5JbnRlcmFjdGlvbk1hbmFnZXIucHJvdG90eXBlLnJlYnVpbGRJbnRlcmFjdGl2ZUdyYXBoPWZ1bmN0aW9uKCl7dGhpcy5kaXJ0eT0hMTtmb3IodmFyIGE9dGhpcy5pbnRlcmFjdGl2ZUl0ZW1zLmxlbmd0aCxiPTA7YT5iO2IrKyl0aGlzLmludGVyYWN0aXZlSXRlbXNbYl0uaW50ZXJhY3RpdmVDaGlsZHJlbj0hMTt0aGlzLmludGVyYWN0aXZlSXRlbXM9W10sdGhpcy5zdGFnZS5pbnRlcmFjdGl2ZSYmdGhpcy5pbnRlcmFjdGl2ZUl0ZW1zLnB1c2godGhpcy5zdGFnZSksdGhpcy5jb2xsZWN0SW50ZXJhY3RpdmVTcHJpdGUodGhpcy5zdGFnZSx0aGlzLnN0YWdlKX0sYi5JbnRlcmFjdGlvbk1hbmFnZXIucHJvdG90eXBlLm9uTW91c2VNb3ZlPWZ1bmN0aW9uKGEpe3RoaXMuZGlydHkmJnRoaXMucmVidWlsZEludGVyYWN0aXZlR3JhcGgoKSx0aGlzLm1vdXNlLm9yaWdpbmFsRXZlbnQ9YTt2YXIgYj10aGlzLmludGVyYWN0aW9uRE9NRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTt0aGlzLm1vdXNlLmdsb2JhbC54PShhLmNsaWVudFgtYi5sZWZ0KSoodGhpcy50YXJnZXQud2lkdGgvYi53aWR0aCkvdGhpcy5yZXNvbHV0aW9uLHRoaXMubW91c2UuZ2xvYmFsLnk9KGEuY2xpZW50WS1iLnRvcCkqKHRoaXMudGFyZ2V0LmhlaWdodC9iLmhlaWdodCkvdGhpcy5yZXNvbHV0aW9uO2Zvcih2YXIgYz10aGlzLmludGVyYWN0aXZlSXRlbXMubGVuZ3RoLGQ9MDtjPmQ7ZCsrKXt2YXIgZT10aGlzLmludGVyYWN0aXZlSXRlbXNbZF07ZS5tb3VzZW1vdmUmJmUubW91c2Vtb3ZlKHRoaXMubW91c2UpfX0sYi5JbnRlcmFjdGlvbk1hbmFnZXIucHJvdG90eXBlLm9uTW91c2VEb3duPWZ1bmN0aW9uKGEpe3RoaXMuZGlydHkmJnRoaXMucmVidWlsZEludGVyYWN0aXZlR3JhcGgoKSx0aGlzLm1vdXNlLm9yaWdpbmFsRXZlbnQ9YSxiLkFVVE9fUFJFVkVOVF9ERUZBVUxUJiZ0aGlzLm1vdXNlLm9yaWdpbmFsRXZlbnQucHJldmVudERlZmF1bHQoKTtmb3IodmFyIGM9dGhpcy5pbnRlcmFjdGl2ZUl0ZW1zLmxlbmd0aCxkPXRoaXMubW91c2Uub3JpZ2luYWxFdmVudCxlPTI9PT1kLmJ1dHRvbnx8Mz09PWQud2hpY2gsZj1lP1wicmlnaHRkb3duXCI6XCJtb3VzZWRvd25cIixnPWU/XCJyaWdodGNsaWNrXCI6XCJjbGlja1wiLGg9ZT9cIl9fcmlnaHRJc0Rvd25cIjpcIl9fbW91c2VJc0Rvd25cIixpPWU/XCJfX2lzUmlnaHREb3duXCI6XCJfX2lzRG93blwiLGo9MDtjPmo7aisrKXt2YXIgaz10aGlzLmludGVyYWN0aXZlSXRlbXNbal07aWYoKGtbZl18fGtbZ10pJiYoa1toXT0hMCxrLl9faGl0PXRoaXMuaGl0VGVzdChrLHRoaXMubW91c2UpLGsuX19oaXQmJihrW2ZdJiZrW2ZdKHRoaXMubW91c2UpLGtbaV09ITAsIWsuaW50ZXJhY3RpdmVDaGlsZHJlbikpKWJyZWFrfX0sYi5JbnRlcmFjdGlvbk1hbmFnZXIucHJvdG90eXBlLm9uTW91c2VPdXQ9ZnVuY3Rpb24oYSl7dGhpcy5kaXJ0eSYmdGhpcy5yZWJ1aWxkSW50ZXJhY3RpdmVHcmFwaCgpLHRoaXMubW91c2Uub3JpZ2luYWxFdmVudD1hO3ZhciBiPXRoaXMuaW50ZXJhY3RpdmVJdGVtcy5sZW5ndGg7dGhpcy5pbnRlcmFjdGlvbkRPTUVsZW1lbnQuc3R5bGUuY3Vyc29yPVwiaW5oZXJpdFwiO2Zvcih2YXIgYz0wO2I+YztjKyspe3ZhciBkPXRoaXMuaW50ZXJhY3RpdmVJdGVtc1tjXTtkLl9faXNPdmVyJiYodGhpcy5tb3VzZS50YXJnZXQ9ZCxkLm1vdXNlb3V0JiZkLm1vdXNlb3V0KHRoaXMubW91c2UpLGQuX19pc092ZXI9ITEpfXRoaXMubW91c2VPdXQ9ITAsdGhpcy5tb3VzZS5nbG9iYWwueD0tMWU0LHRoaXMubW91c2UuZ2xvYmFsLnk9LTFlNH0sYi5JbnRlcmFjdGlvbk1hbmFnZXIucHJvdG90eXBlLm9uTW91c2VVcD1mdW5jdGlvbihhKXt0aGlzLmRpcnR5JiZ0aGlzLnJlYnVpbGRJbnRlcmFjdGl2ZUdyYXBoKCksdGhpcy5tb3VzZS5vcmlnaW5hbEV2ZW50PWE7Zm9yKHZhciBiPXRoaXMuaW50ZXJhY3RpdmVJdGVtcy5sZW5ndGgsYz0hMSxkPXRoaXMubW91c2Uub3JpZ2luYWxFdmVudCxlPTI9PT1kLmJ1dHRvbnx8Mz09PWQud2hpY2gsZj1lP1wicmlnaHR1cFwiOlwibW91c2V1cFwiLGc9ZT9cInJpZ2h0Y2xpY2tcIjpcImNsaWNrXCIsaD1lP1wicmlnaHR1cG91dHNpZGVcIjpcIm1vdXNldXBvdXRzaWRlXCIsaT1lP1wiX19pc1JpZ2h0RG93blwiOlwiX19pc0Rvd25cIixqPTA7Yj5qO2orKyl7dmFyIGs9dGhpcy5pbnRlcmFjdGl2ZUl0ZW1zW2pdOyhrW2ddfHxrW2ZdfHxrW2hdKSYmKGsuX19oaXQ9dGhpcy5oaXRUZXN0KGssdGhpcy5tb3VzZSksay5fX2hpdCYmIWM/KGtbZl0mJmtbZl0odGhpcy5tb3VzZSksa1tpXSYma1tnXSYma1tnXSh0aGlzLm1vdXNlKSxrLmludGVyYWN0aXZlQ2hpbGRyZW58fChjPSEwKSk6a1tpXSYma1toXSYma1toXSh0aGlzLm1vdXNlKSxrW2ldPSExKX19LGIuSW50ZXJhY3Rpb25NYW5hZ2VyLnByb3RvdHlwZS5oaXRUZXN0PWZ1bmN0aW9uKGEsYyl7dmFyIGQ9Yy5nbG9iYWw7aWYoIWEud29ybGRWaXNpYmxlKXJldHVybiExO2Eud29ybGRUcmFuc2Zvcm0uYXBwbHlJbnZlcnNlKGQsdGhpcy5fdGVtcFBvaW50KTt2YXIgZSxmPXRoaXMuX3RlbXBQb2ludC54LGc9dGhpcy5fdGVtcFBvaW50Lnk7aWYoYy50YXJnZXQ9YSxhLmhpdEFyZWEmJmEuaGl0QXJlYS5jb250YWlucylyZXR1cm4gYS5oaXRBcmVhLmNvbnRhaW5zKGYsZyk7aWYoYSBpbnN0YW5jZW9mIGIuU3ByaXRlKXt2YXIgaCxpPWEudGV4dHVyZS5mcmFtZS53aWR0aCxqPWEudGV4dHVyZS5mcmFtZS5oZWlnaHQsaz0taSphLmFuY2hvci54O2lmKGY+ayYmaytpPmYmJihoPS1qKmEuYW5jaG9yLnksZz5oJiZoK2o+ZykpcmV0dXJuITB9ZWxzZSBpZihhIGluc3RhbmNlb2YgYi5HcmFwaGljcyl7dmFyIGw9YS5ncmFwaGljc0RhdGE7Zm9yKGU9MDtlPGwubGVuZ3RoO2UrKyl7dmFyIG09bFtlXTtpZihtLmZpbGwmJm0uc2hhcGUmJm0uc2hhcGUuY29udGFpbnMoZixnKSlyZXR1cm4hMH19dmFyIG49YS5jaGlsZHJlbi5sZW5ndGg7Zm9yKGU9MDtuPmU7ZSsrKXt2YXIgbz1hLmNoaWxkcmVuW2VdLHA9dGhpcy5oaXRUZXN0KG8sYyk7aWYocClyZXR1cm4gYy50YXJnZXQ9YSwhMH1yZXR1cm4hMX0sYi5JbnRlcmFjdGlvbk1hbmFnZXIucHJvdG90eXBlLm9uVG91Y2hNb3ZlPWZ1bmN0aW9uKGEpe3RoaXMuZGlydHkmJnRoaXMucmVidWlsZEludGVyYWN0aXZlR3JhcGgoKTt2YXIgYixjPXRoaXMuaW50ZXJhY3Rpb25ET01FbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLGQ9YS5jaGFuZ2VkVG91Y2hlcyxlPTA7Zm9yKGU9MDtlPGQubGVuZ3RoO2UrKyl7dmFyIGY9ZFtlXTtiPXRoaXMudG91Y2hlc1tmLmlkZW50aWZpZXJdLGIub3JpZ2luYWxFdmVudD1hLGIuZ2xvYmFsLng9KGYuY2xpZW50WC1jLmxlZnQpKih0aGlzLnRhcmdldC53aWR0aC9jLndpZHRoKS90aGlzLnJlc29sdXRpb24sYi5nbG9iYWwueT0oZi5jbGllbnRZLWMudG9wKSoodGhpcy50YXJnZXQuaGVpZ2h0L2MuaGVpZ2h0KS90aGlzLnJlc29sdXRpb24sIW5hdmlnYXRvci5pc0NvY29vbkpTfHxjLmxlZnR8fGMudG9wfHxhLnRhcmdldC5zdHlsZS53aWR0aHx8YS50YXJnZXQuc3R5bGUuaGVpZ2h0fHwoYi5nbG9iYWwueD1mLmNsaWVudFgsYi5nbG9iYWwueT1mLmNsaWVudFkpO2Zvcih2YXIgZz0wO2c8dGhpcy5pbnRlcmFjdGl2ZUl0ZW1zLmxlbmd0aDtnKyspe3ZhciBoPXRoaXMuaW50ZXJhY3RpdmVJdGVtc1tnXTtoLnRvdWNobW92ZSYmaC5fX3RvdWNoRGF0YSYmaC5fX3RvdWNoRGF0YVtmLmlkZW50aWZpZXJdJiZoLnRvdWNobW92ZShiKX19fSxiLkludGVyYWN0aW9uTWFuYWdlci5wcm90b3R5cGUub25Ub3VjaFN0YXJ0PWZ1bmN0aW9uKGEpe3RoaXMuZGlydHkmJnRoaXMucmVidWlsZEludGVyYWN0aXZlR3JhcGgoKTt2YXIgYz10aGlzLmludGVyYWN0aW9uRE9NRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtiLkFVVE9fUFJFVkVOVF9ERUZBVUxUJiZhLnByZXZlbnREZWZhdWx0KCk7Zm9yKHZhciBkPWEuY2hhbmdlZFRvdWNoZXMsZT0wO2U8ZC5sZW5ndGg7ZSsrKXt2YXIgZj1kW2VdLGc9dGhpcy5wb29sLnBvcCgpO2d8fChnPW5ldyBiLkludGVyYWN0aW9uRGF0YSksZy5vcmlnaW5hbEV2ZW50PWEsdGhpcy50b3VjaGVzW2YuaWRlbnRpZmllcl09ZyxnLmdsb2JhbC54PShmLmNsaWVudFgtYy5sZWZ0KSoodGhpcy50YXJnZXQud2lkdGgvYy53aWR0aCkvdGhpcy5yZXNvbHV0aW9uLGcuZ2xvYmFsLnk9KGYuY2xpZW50WS1jLnRvcCkqKHRoaXMudGFyZ2V0LmhlaWdodC9jLmhlaWdodCkvdGhpcy5yZXNvbHV0aW9uLCFuYXZpZ2F0b3IuaXNDb2Nvb25KU3x8Yy5sZWZ0fHxjLnRvcHx8YS50YXJnZXQuc3R5bGUud2lkdGh8fGEudGFyZ2V0LnN0eWxlLmhlaWdodHx8KGcuZ2xvYmFsLng9Zi5jbGllbnRYLGcuZ2xvYmFsLnk9Zi5jbGllbnRZKTtmb3IodmFyIGg9dGhpcy5pbnRlcmFjdGl2ZUl0ZW1zLmxlbmd0aCxpPTA7aD5pO2krKyl7dmFyIGo9dGhpcy5pbnRlcmFjdGl2ZUl0ZW1zW2ldO2lmKChqLnRvdWNoc3RhcnR8fGoudGFwKSYmKGouX19oaXQ9dGhpcy5oaXRUZXN0KGosZyksai5fX2hpdCYmKGoudG91Y2hzdGFydCYmai50b3VjaHN0YXJ0KGcpLGouX19pc0Rvd249ITAsai5fX3RvdWNoRGF0YT1qLl9fdG91Y2hEYXRhfHx7fSxqLl9fdG91Y2hEYXRhW2YuaWRlbnRpZmllcl09Zywhai5pbnRlcmFjdGl2ZUNoaWxkcmVuKSkpYnJlYWt9fX0sYi5JbnRlcmFjdGlvbk1hbmFnZXIucHJvdG90eXBlLm9uVG91Y2hFbmQ9ZnVuY3Rpb24oYSl7dGhpcy5kaXJ0eSYmdGhpcy5yZWJ1aWxkSW50ZXJhY3RpdmVHcmFwaCgpO2Zvcih2YXIgYj10aGlzLmludGVyYWN0aW9uRE9NRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSxjPWEuY2hhbmdlZFRvdWNoZXMsZD0wO2Q8Yy5sZW5ndGg7ZCsrKXt2YXIgZT1jW2RdLGY9dGhpcy50b3VjaGVzW2UuaWRlbnRpZmllcl0sZz0hMTtmLmdsb2JhbC54PShlLmNsaWVudFgtYi5sZWZ0KSoodGhpcy50YXJnZXQud2lkdGgvYi53aWR0aCkvdGhpcy5yZXNvbHV0aW9uLGYuZ2xvYmFsLnk9KGUuY2xpZW50WS1iLnRvcCkqKHRoaXMudGFyZ2V0LmhlaWdodC9iLmhlaWdodCkvdGhpcy5yZXNvbHV0aW9uLCFuYXZpZ2F0b3IuaXNDb2Nvb25KU3x8Yi5sZWZ0fHxiLnRvcHx8YS50YXJnZXQuc3R5bGUud2lkdGh8fGEudGFyZ2V0LnN0eWxlLmhlaWdodHx8KGYuZ2xvYmFsLng9ZS5jbGllbnRYLGYuZ2xvYmFsLnk9ZS5jbGllbnRZKTtmb3IodmFyIGg9dGhpcy5pbnRlcmFjdGl2ZUl0ZW1zLmxlbmd0aCxpPTA7aD5pO2krKyl7dmFyIGo9dGhpcy5pbnRlcmFjdGl2ZUl0ZW1zW2ldO2ouX190b3VjaERhdGEmJmouX190b3VjaERhdGFbZS5pZGVudGlmaWVyXSYmKGouX19oaXQ9dGhpcy5oaXRUZXN0KGosai5fX3RvdWNoRGF0YVtlLmlkZW50aWZpZXJdKSxmLm9yaWdpbmFsRXZlbnQ9YSwoai50b3VjaGVuZHx8ai50YXApJiYoai5fX2hpdCYmIWc/KGoudG91Y2hlbmQmJmoudG91Y2hlbmQoZiksai5fX2lzRG93biYmai50YXAmJmoudGFwKGYpLGouaW50ZXJhY3RpdmVDaGlsZHJlbnx8KGc9ITApKTpqLl9faXNEb3duJiZqLnRvdWNoZW5kb3V0c2lkZSYmai50b3VjaGVuZG91dHNpZGUoZiksai5fX2lzRG93bj0hMSksai5fX3RvdWNoRGF0YVtlLmlkZW50aWZpZXJdPW51bGwpfXRoaXMucG9vbC5wdXNoKGYpLHRoaXMudG91Y2hlc1tlLmlkZW50aWZpZXJdPW51bGx9fSxiLlN0YWdlPWZ1bmN0aW9uKGEpe2IuRGlzcGxheU9iamVjdENvbnRhaW5lci5jYWxsKHRoaXMpLHRoaXMud29ybGRUcmFuc2Zvcm09bmV3IGIuTWF0cml4LHRoaXMuaW50ZXJhY3RpdmU9ITAsdGhpcy5pbnRlcmFjdGlvbk1hbmFnZXI9bmV3IGIuSW50ZXJhY3Rpb25NYW5hZ2VyKHRoaXMpLHRoaXMuZGlydHk9ITAsdGhpcy5zdGFnZT10aGlzLHRoaXMuc3RhZ2UuaGl0QXJlYT1uZXcgYi5SZWN0YW5nbGUoMCwwLDFlNSwxZTUpLHRoaXMuc2V0QmFja2dyb3VuZENvbG9yKGEpfSxiLlN0YWdlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGIuRGlzcGxheU9iamVjdENvbnRhaW5lci5wcm90b3R5cGUpLGIuU3RhZ2UucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuU3RhZ2UsYi5TdGFnZS5wcm90b3R5cGUuc2V0SW50ZXJhY3Rpb25EZWxlZ2F0ZT1mdW5jdGlvbihhKXt0aGlzLmludGVyYWN0aW9uTWFuYWdlci5zZXRUYXJnZXREb21FbGVtZW50KGEpfSxiLlN0YWdlLnByb3RvdHlwZS51cGRhdGVUcmFuc2Zvcm09ZnVuY3Rpb24oKXt0aGlzLndvcmxkQWxwaGE9MTtmb3IodmFyIGE9MCxiPXRoaXMuY2hpbGRyZW4ubGVuZ3RoO2I+YTthKyspdGhpcy5jaGlsZHJlblthXS51cGRhdGVUcmFuc2Zvcm0oKTt0aGlzLmRpcnR5JiYodGhpcy5kaXJ0eT0hMSx0aGlzLmludGVyYWN0aW9uTWFuYWdlci5kaXJ0eT0hMCksdGhpcy5pbnRlcmFjdGl2ZSYmdGhpcy5pbnRlcmFjdGlvbk1hbmFnZXIudXBkYXRlKCl9LGIuU3RhZ2UucHJvdG90eXBlLnNldEJhY2tncm91bmRDb2xvcj1mdW5jdGlvbihhKXt0aGlzLmJhY2tncm91bmRDb2xvcj1hfHwwLHRoaXMuYmFja2dyb3VuZENvbG9yU3BsaXQ9Yi5oZXgycmdiKHRoaXMuYmFja2dyb3VuZENvbG9yKTt2YXIgYz10aGlzLmJhY2tncm91bmRDb2xvci50b1N0cmluZygxNik7Yz1cIjAwMDAwMFwiLnN1YnN0cigwLDYtYy5sZW5ndGgpK2MsdGhpcy5iYWNrZ3JvdW5kQ29sb3JTdHJpbmc9XCIjXCIrY30sYi5TdGFnZS5wcm90b3R5cGUuZ2V0TW91c2VQb3NpdGlvbj1mdW5jdGlvbigpe3JldHVybiB0aGlzLmludGVyYWN0aW9uTWFuYWdlci5tb3VzZS5nbG9iYWx9LGZ1bmN0aW9uKGEpe2Zvcih2YXIgYj0wLGM9W1wibXNcIixcIm1velwiLFwid2Via2l0XCIsXCJvXCJdLGQ9MDtkPGMubGVuZ3RoJiYhYS5yZXF1ZXN0QW5pbWF0aW9uRnJhbWU7KytkKWEucmVxdWVzdEFuaW1hdGlvbkZyYW1lPWFbY1tkXStcIlJlcXVlc3RBbmltYXRpb25GcmFtZVwiXSxhLmNhbmNlbEFuaW1hdGlvbkZyYW1lPWFbY1tkXStcIkNhbmNlbEFuaW1hdGlvbkZyYW1lXCJdfHxhW2NbZF0rXCJDYW5jZWxSZXF1ZXN0QW5pbWF0aW9uRnJhbWVcIl07YS5yZXF1ZXN0QW5pbWF0aW9uRnJhbWV8fChhLnJlcXVlc3RBbmltYXRpb25GcmFtZT1mdW5jdGlvbihjKXt2YXIgZD0obmV3IERhdGUpLmdldFRpbWUoKSxlPU1hdGgubWF4KDAsMTYtKGQtYikpLGY9YS5zZXRUaW1lb3V0KGZ1bmN0aW9uKCl7YyhkK2UpfSxlKTtyZXR1cm4gYj1kK2UsZn0pLGEuY2FuY2VsQW5pbWF0aW9uRnJhbWV8fChhLmNhbmNlbEFuaW1hdGlvbkZyYW1lPWZ1bmN0aW9uKGEpe2NsZWFyVGltZW91dChhKX0pLGEucmVxdWVzdEFuaW1GcmFtZT1hLnJlcXVlc3RBbmltYXRpb25GcmFtZX0odGhpcyksYi5oZXgycmdiPWZ1bmN0aW9uKGEpe3JldHVyblsoYT4+MTYmMjU1KS8yNTUsKGE+PjgmMjU1KS8yNTUsKDI1NSZhKS8yNTVdfSxiLnJnYjJoZXg9ZnVuY3Rpb24oYSl7cmV0dXJuKDI1NSphWzBdPDwxNikrKDI1NSphWzFdPDw4KSsyNTUqYVsyXX0sXCJmdW5jdGlvblwiIT10eXBlb2YgRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQmJihGdW5jdGlvbi5wcm90b3R5cGUuYmluZD1mdW5jdGlvbigpe3JldHVybiBmdW5jdGlvbihhKXtmdW5jdGlvbiBiKCl7Zm9yKHZhciBkPWFyZ3VtZW50cy5sZW5ndGgsZj1uZXcgQXJyYXkoZCk7ZC0tOylmW2RdPWFyZ3VtZW50c1tkXTtyZXR1cm4gZj1lLmNvbmNhdChmKSxjLmFwcGx5KHRoaXMgaW5zdGFuY2VvZiBiP3RoaXM6YSxmKX12YXIgYz10aGlzLGQ9YXJndW1lbnRzLmxlbmd0aC0xLGU9W107aWYoZD4wKWZvcihlLmxlbmd0aD1kO2QtLTspZVtkXT1hcmd1bWVudHNbZCsxXTtpZihcImZ1bmN0aW9uXCIhPXR5cGVvZiBjKXRocm93IG5ldyBUeXBlRXJyb3I7cmV0dXJuIGIucHJvdG90eXBlPWZ1bmN0aW9uIGYoYSl7cmV0dXJuIGEmJihmLnByb3RvdHlwZT1hKSx0aGlzIGluc3RhbmNlb2YgZj92b2lkIDA6bmV3IGZ9KGMucHJvdG90eXBlKSxifX0oKSksYi5BamF4UmVxdWVzdD1mdW5jdGlvbigpe3ZhciBhPVtcIk1zeG1sMi5YTUxIVFRQLjYuMFwiLFwiTXN4bWwyLlhNTEhUVFAuMy4wXCIsXCJNaWNyb3NvZnQuWE1MSFRUUFwiXTtpZighd2luZG93LkFjdGl2ZVhPYmplY3QpcmV0dXJuIHdpbmRvdy5YTUxIdHRwUmVxdWVzdD9uZXcgd2luZG93LlhNTEh0dHBSZXF1ZXN0OiExO2Zvcih2YXIgYj0wO2I8YS5sZW5ndGg7YisrKXRyeXtyZXR1cm4gbmV3IHdpbmRvdy5BY3RpdmVYT2JqZWN0KGFbYl0pfWNhdGNoKGMpe319LGIuY2FuVXNlTmV3Q2FudmFzQmxlbmRNb2Rlcz1mdW5jdGlvbigpe2lmKFwidW5kZWZpbmVkXCI9PXR5cGVvZiBkb2N1bWVudClyZXR1cm4hMTt2YXIgYT1kb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiY2FudmFzXCIpO2Eud2lkdGg9MSxhLmhlaWdodD0xO3ZhciBiPWEuZ2V0Q29udGV4dChcIjJkXCIpO3JldHVybiBiLmZpbGxTdHlsZT1cIiMwMDBcIixiLmZpbGxSZWN0KDAsMCwxLDEpLGIuZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uPVwibXVsdGlwbHlcIixiLmZpbGxTdHlsZT1cIiNmZmZcIixiLmZpbGxSZWN0KDAsMCwxLDEpLDA9PT1iLmdldEltYWdlRGF0YSgwLDAsMSwxKS5kYXRhWzBdfSxiLmdldE5leHRQb3dlck9mVHdvPWZ1bmN0aW9uKGEpe2lmKGE+MCYmMD09PShhJmEtMSkpcmV0dXJuIGE7Zm9yKHZhciBiPTE7YT5iOyliPDw9MTtyZXR1cm4gYn0sYi5pc1Bvd2VyT2ZUd289ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYT4wJiYwPT09KGEmYS0xKSYmYj4wJiYwPT09KGImYi0xKX0sYi5FdmVudFRhcmdldD17Y2FsbDpmdW5jdGlvbihhKXthJiYoYT1hLnByb3RvdHlwZXx8YSxiLkV2ZW50VGFyZ2V0Lm1peGluKGEpKX0sbWl4aW46ZnVuY3Rpb24oYSl7YS5saXN0ZW5lcnM9ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuX2xpc3RlbmVycz10aGlzLl9saXN0ZW5lcnN8fHt9LHRoaXMuX2xpc3RlbmVyc1thXT90aGlzLl9saXN0ZW5lcnNbYV0uc2xpY2UoKTpbXX0sYS5lbWl0PWEuZGlzcGF0Y2hFdmVudD1mdW5jdGlvbihhLGMpe2lmKHRoaXMuX2xpc3RlbmVycz10aGlzLl9saXN0ZW5lcnN8fHt9LFwib2JqZWN0XCI9PXR5cGVvZiBhJiYoYz1hLGE9YS50eXBlKSxjJiZjLl9faXNFdmVudE9iamVjdD09PSEwfHwoYz1uZXcgYi5FdmVudCh0aGlzLGEsYykpLHRoaXMuX2xpc3RlbmVycyYmdGhpcy5fbGlzdGVuZXJzW2FdKXt2YXIgZCxlPXRoaXMuX2xpc3RlbmVyc1thXS5zbGljZSgwKSxmPWUubGVuZ3RoLGc9ZVswXTtmb3IoZD0wO2Y+ZDtnPWVbKytkXSlpZihnLmNhbGwodGhpcyxjKSxjLnN0b3BwZWRJbW1lZGlhdGUpcmV0dXJuIHRoaXM7aWYoYy5zdG9wcGVkKXJldHVybiB0aGlzfXJldHVybiB0aGlzLnBhcmVudCYmdGhpcy5wYXJlbnQuZW1pdCYmdGhpcy5wYXJlbnQuZW1pdC5jYWxsKHRoaXMucGFyZW50LGEsYyksdGhpc30sYS5vbj1hLmFkZEV2ZW50TGlzdGVuZXI9ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5fbGlzdGVuZXJzPXRoaXMuX2xpc3RlbmVyc3x8e30sKHRoaXMuX2xpc3RlbmVyc1thXT10aGlzLl9saXN0ZW5lcnNbYV18fFtdKS5wdXNoKGIpLHRoaXN9LGEub25jZT1mdW5jdGlvbihhLGIpe2Z1bmN0aW9uIGMoKXtiLmFwcGx5KGQub2ZmKGEsYyksYXJndW1lbnRzKX10aGlzLl9saXN0ZW5lcnM9dGhpcy5fbGlzdGVuZXJzfHx7fTt2YXIgZD10aGlzO3JldHVybiBjLl9vcmlnaW5hbEhhbmRsZXI9Yix0aGlzLm9uKGEsYyl9LGEub2ZmPWEucmVtb3ZlRXZlbnRMaXN0ZW5lcj1mdW5jdGlvbihhLGIpe2lmKHRoaXMuX2xpc3RlbmVycz10aGlzLl9saXN0ZW5lcnN8fHt9LCF0aGlzLl9saXN0ZW5lcnNbYV0pcmV0dXJuIHRoaXM7Zm9yKHZhciBjPXRoaXMuX2xpc3RlbmVyc1thXSxkPWI/Yy5sZW5ndGg6MDtkLS0+MDspKGNbZF09PT1ifHxjW2RdLl9vcmlnaW5hbEhhbmRsZXI9PT1iKSYmYy5zcGxpY2UoZCwxKTtyZXR1cm4gMD09PWMubGVuZ3RoJiZkZWxldGUgdGhpcy5fbGlzdGVuZXJzW2FdLHRoaXN9LGEucmVtb3ZlQWxsTGlzdGVuZXJzPWZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLl9saXN0ZW5lcnM9dGhpcy5fbGlzdGVuZXJzfHx7fSx0aGlzLl9saXN0ZW5lcnNbYV0/KGRlbGV0ZSB0aGlzLl9saXN0ZW5lcnNbYV0sdGhpcyk6dGhpc319fSxiLkV2ZW50PWZ1bmN0aW9uKGEsYixjKXt0aGlzLl9faXNFdmVudE9iamVjdD0hMCx0aGlzLnN0b3BwZWQ9ITEsdGhpcy5zdG9wcGVkSW1tZWRpYXRlPSExLHRoaXMudGFyZ2V0PWEsdGhpcy50eXBlPWIsdGhpcy5kYXRhPWMsdGhpcy5jb250ZW50PWMsdGhpcy50aW1lU3RhbXA9RGF0ZS5ub3coKX0sYi5FdmVudC5wcm90b3R5cGUuc3RvcFByb3BhZ2F0aW9uPWZ1bmN0aW9uKCl7dGhpcy5zdG9wcGVkPSEwfSxiLkV2ZW50LnByb3RvdHlwZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb249ZnVuY3Rpb24oKXt0aGlzLnN0b3BwZWRJbW1lZGlhdGU9ITB9LGIuYXV0b0RldGVjdFJlbmRlcmVyPWZ1bmN0aW9uKGEsYyxkKXthfHwoYT04MDApLGN8fChjPTYwMCk7dmFyIGU9ZnVuY3Rpb24oKXt0cnl7dmFyIGE9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImNhbnZhc1wiKTtyZXR1cm4hIXdpbmRvdy5XZWJHTFJlbmRlcmluZ0NvbnRleHQmJihhLmdldENvbnRleHQoXCJ3ZWJnbFwiKXx8YS5nZXRDb250ZXh0KFwiZXhwZXJpbWVudGFsLXdlYmdsXCIpKX1jYXRjaChiKXtyZXR1cm4hMX19KCk7cmV0dXJuIGU/bmV3IGIuV2ViR0xSZW5kZXJlcihhLGMsZCk6bmV3IGIuQ2FudmFzUmVuZGVyZXIoYSxjLGQpfSxiLmF1dG9EZXRlY3RSZWNvbW1lbmRlZFJlbmRlcmVyPWZ1bmN0aW9uKGEsYyxkKXthfHwoYT04MDApLGN8fChjPTYwMCk7dmFyIGU9ZnVuY3Rpb24oKXt0cnl7dmFyIGE9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImNhbnZhc1wiKTtyZXR1cm4hIXdpbmRvdy5XZWJHTFJlbmRlcmluZ0NvbnRleHQmJihhLmdldENvbnRleHQoXCJ3ZWJnbFwiKXx8YS5nZXRDb250ZXh0KFwiZXhwZXJpbWVudGFsLXdlYmdsXCIpKX1jYXRjaChiKXtyZXR1cm4hMX19KCksZj0vQW5kcm9pZC9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7cmV0dXJuIGUmJiFmP25ldyBiLldlYkdMUmVuZGVyZXIoYSxjLGQpOm5ldyBiLkNhbnZhc1JlbmRlcmVyKGEsYyxkKX0sYi5Qb2x5Sz17fSxiLlBvbHlLLlRyaWFuZ3VsYXRlPWZ1bmN0aW9uKGEpe3ZhciBjPSEwLGQ9YS5sZW5ndGg+PjE7aWYoMz5kKXJldHVybltdO2Zvcih2YXIgZT1bXSxmPVtdLGc9MDtkPmc7ZysrKWYucHVzaChnKTtnPTA7Zm9yKHZhciBoPWQ7aD4zOyl7dmFyIGk9ZlsoZyswKSVoXSxqPWZbKGcrMSklaF0saz1mWyhnKzIpJWhdLGw9YVsyKmldLG09YVsyKmkrMV0sbj1hWzIqal0sbz1hWzIqaisxXSxwPWFbMiprXSxxPWFbMiprKzFdLHI9ITE7aWYoYi5Qb2x5Sy5fY29udmV4KGwsbSxuLG8scCxxLGMpKXtyPSEwO2Zvcih2YXIgcz0wO2g+cztzKyspe3ZhciB0PWZbc107aWYodCE9PWkmJnQhPT1qJiZ0IT09ayYmYi5Qb2x5Sy5fUG9pbnRJblRyaWFuZ2xlKGFbMip0XSxhWzIqdCsxXSxsLG0sbixvLHAscSkpe3I9ITE7YnJlYWt9fX1pZihyKWUucHVzaChpLGosayksZi5zcGxpY2UoKGcrMSklaCwxKSxoLS0sZz0wO2Vsc2UgaWYoZysrPjMqaCl7aWYoIWMpcmV0dXJuIG51bGw7Zm9yKGU9W10sZj1bXSxnPTA7ZD5nO2crKylmLnB1c2goZyk7Zz0wLGg9ZCxjPSExfX1yZXR1cm4gZS5wdXNoKGZbMF0sZlsxXSxmWzJdKSxlfSxiLlBvbHlLLl9Qb2ludEluVHJpYW5nbGU9ZnVuY3Rpb24oYSxiLGMsZCxlLGYsZyxoKXt2YXIgaT1nLWMsaj1oLWQsaz1lLWMsbD1mLWQsbT1hLWMsbj1iLWQsbz1pKmkraipqLHA9aSprK2oqbCxxPWkqbStqKm4scj1rKmsrbCpsLHM9ayptK2wqbix0PTEvKG8qci1wKnApLHU9KHIqcS1wKnMpKnQsdj0obypzLXAqcSkqdDtyZXR1cm4gdT49MCYmdj49MCYmMT51K3Z9LGIuUG9seUsuX2NvbnZleD1mdW5jdGlvbihhLGIsYyxkLGUsZixnKXtyZXR1cm4oYi1kKSooZS1jKSsoYy1hKSooZi1kKT49MD09PWd9LGIuaW5pdERlZmF1bHRTaGFkZXJzPWZ1bmN0aW9uKCl7fSxiLkNvbXBpbGVWZXJ0ZXhTaGFkZXI9ZnVuY3Rpb24oYSxjKXtyZXR1cm4gYi5fQ29tcGlsZVNoYWRlcihhLGMsYS5WRVJURVhfU0hBREVSKX0sYi5Db21waWxlRnJhZ21lbnRTaGFkZXI9ZnVuY3Rpb24oYSxjKXtyZXR1cm4gYi5fQ29tcGlsZVNoYWRlcihhLGMsYS5GUkFHTUVOVF9TSEFERVIpfSxiLl9Db21waWxlU2hhZGVyPWZ1bmN0aW9uKGEsYixjKXt2YXIgZD1iLmpvaW4oXCJcXG5cIiksZT1hLmNyZWF0ZVNoYWRlcihjKTtyZXR1cm4gYS5zaGFkZXJTb3VyY2UoZSxkKSxhLmNvbXBpbGVTaGFkZXIoZSksYS5nZXRTaGFkZXJQYXJhbWV0ZXIoZSxhLkNPTVBJTEVfU1RBVFVTKT9lOih3aW5kb3cuY29uc29sZS5sb2coYS5nZXRTaGFkZXJJbmZvTG9nKGUpKSxudWxsKX0sYi5jb21waWxlUHJvZ3JhbT1mdW5jdGlvbihhLGMsZCl7dmFyIGU9Yi5Db21waWxlRnJhZ21lbnRTaGFkZXIoYSxkKSxmPWIuQ29tcGlsZVZlcnRleFNoYWRlcihhLGMpLGc9YS5jcmVhdGVQcm9ncmFtKCk7cmV0dXJuIGEuYXR0YWNoU2hhZGVyKGcsZiksYS5hdHRhY2hTaGFkZXIoZyxlKSxhLmxpbmtQcm9ncmFtKGcpLGEuZ2V0UHJvZ3JhbVBhcmFtZXRlcihnLGEuTElOS19TVEFUVVMpfHx3aW5kb3cuY29uc29sZS5sb2coXCJDb3VsZCBub3QgaW5pdGlhbGlzZSBzaGFkZXJzXCIpLGd9LGIuUGl4aVNoYWRlcj1mdW5jdGlvbihhKXt0aGlzLl9VSUQ9Yi5fVUlEKyssdGhpcy5nbD1hLHRoaXMucHJvZ3JhbT1udWxsLHRoaXMuZnJhZ21lbnRTcmM9W1wicHJlY2lzaW9uIGxvd3AgZmxvYXQ7XCIsXCJ2YXJ5aW5nIHZlYzIgdlRleHR1cmVDb29yZDtcIixcInZhcnlpbmcgdmVjNCB2Q29sb3I7XCIsXCJ1bmlmb3JtIHNhbXBsZXIyRCB1U2FtcGxlcjtcIixcInZvaWQgbWFpbih2b2lkKSB7XCIsXCIgICBnbF9GcmFnQ29sb3IgPSB0ZXh0dXJlMkQodVNhbXBsZXIsIHZUZXh0dXJlQ29vcmQpICogdkNvbG9yIDtcIixcIn1cIl0sdGhpcy50ZXh0dXJlQ291bnQ9MCx0aGlzLmZpcnN0UnVuPSEwLHRoaXMuZGlydHk9ITAsdGhpcy5hdHRyaWJ1dGVzPVtdLHRoaXMuaW5pdCgpfSxiLlBpeGlTaGFkZXIucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuUGl4aVNoYWRlcixiLlBpeGlTaGFkZXIucHJvdG90eXBlLmluaXQ9ZnVuY3Rpb24oKXt2YXIgYT10aGlzLmdsLGM9Yi5jb21waWxlUHJvZ3JhbShhLHRoaXMudmVydGV4U3JjfHxiLlBpeGlTaGFkZXIuZGVmYXVsdFZlcnRleFNyYyx0aGlzLmZyYWdtZW50U3JjKTthLnVzZVByb2dyYW0oYyksdGhpcy51U2FtcGxlcj1hLmdldFVuaWZvcm1Mb2NhdGlvbihjLFwidVNhbXBsZXJcIiksdGhpcy5wcm9qZWN0aW9uVmVjdG9yPWEuZ2V0VW5pZm9ybUxvY2F0aW9uKGMsXCJwcm9qZWN0aW9uVmVjdG9yXCIpLHRoaXMub2Zmc2V0VmVjdG9yPWEuZ2V0VW5pZm9ybUxvY2F0aW9uKGMsXCJvZmZzZXRWZWN0b3JcIiksdGhpcy5kaW1lbnNpb25zPWEuZ2V0VW5pZm9ybUxvY2F0aW9uKGMsXCJkaW1lbnNpb25zXCIpLHRoaXMuYVZlcnRleFBvc2l0aW9uPWEuZ2V0QXR0cmliTG9jYXRpb24oYyxcImFWZXJ0ZXhQb3NpdGlvblwiKSx0aGlzLmFUZXh0dXJlQ29vcmQ9YS5nZXRBdHRyaWJMb2NhdGlvbihjLFwiYVRleHR1cmVDb29yZFwiKSx0aGlzLmNvbG9yQXR0cmlidXRlPWEuZ2V0QXR0cmliTG9jYXRpb24oYyxcImFDb2xvclwiKSwtMT09PXRoaXMuY29sb3JBdHRyaWJ1dGUmJih0aGlzLmNvbG9yQXR0cmlidXRlPTIpLHRoaXMuYXR0cmlidXRlcz1bdGhpcy5hVmVydGV4UG9zaXRpb24sdGhpcy5hVGV4dHVyZUNvb3JkLHRoaXMuY29sb3JBdHRyaWJ1dGVdO2Zvcih2YXIgZCBpbiB0aGlzLnVuaWZvcm1zKXRoaXMudW5pZm9ybXNbZF0udW5pZm9ybUxvY2F0aW9uPWEuZ2V0VW5pZm9ybUxvY2F0aW9uKGMsZCk7dGhpcy5pbml0VW5pZm9ybXMoKSx0aGlzLnByb2dyYW09Y30sYi5QaXhpU2hhZGVyLnByb3RvdHlwZS5pbml0VW5pZm9ybXM9ZnVuY3Rpb24oKXt0aGlzLnRleHR1cmVDb3VudD0xO3ZhciBhLGI9dGhpcy5nbDtmb3IodmFyIGMgaW4gdGhpcy51bmlmb3Jtcyl7YT10aGlzLnVuaWZvcm1zW2NdO3ZhciBkPWEudHlwZTtcInNhbXBsZXIyRFwiPT09ZD8oYS5faW5pdD0hMSxudWxsIT09YS52YWx1ZSYmdGhpcy5pbml0U2FtcGxlcjJEKGEpKTpcIm1hdDJcIj09PWR8fFwibWF0M1wiPT09ZHx8XCJtYXQ0XCI9PT1kPyhhLmdsTWF0cml4PSEwLGEuZ2xWYWx1ZUxlbmd0aD0xLFwibWF0MlwiPT09ZD9hLmdsRnVuYz1iLnVuaWZvcm1NYXRyaXgyZnY6XCJtYXQzXCI9PT1kP2EuZ2xGdW5jPWIudW5pZm9ybU1hdHJpeDNmdjpcIm1hdDRcIj09PWQmJihhLmdsRnVuYz1iLnVuaWZvcm1NYXRyaXg0ZnYpKTooYS5nbEZ1bmM9YltcInVuaWZvcm1cIitkXSxhLmdsVmFsdWVMZW5ndGg9XCIyZlwiPT09ZHx8XCIyaVwiPT09ZD8yOlwiM2ZcIj09PWR8fFwiM2lcIj09PWQ/MzpcIjRmXCI9PT1kfHxcIjRpXCI9PT1kPzQ6MSl9fSxiLlBpeGlTaGFkZXIucHJvdG90eXBlLmluaXRTYW1wbGVyMkQ9ZnVuY3Rpb24oYSl7aWYoYS52YWx1ZSYmYS52YWx1ZS5iYXNlVGV4dHVyZSYmYS52YWx1ZS5iYXNlVGV4dHVyZS5oYXNMb2FkZWQpe3ZhciBiPXRoaXMuZ2w7aWYoYi5hY3RpdmVUZXh0dXJlKGJbXCJURVhUVVJFXCIrdGhpcy50ZXh0dXJlQ291bnRdKSxiLmJpbmRUZXh0dXJlKGIuVEVYVFVSRV8yRCxhLnZhbHVlLmJhc2VUZXh0dXJlLl9nbFRleHR1cmVzW2IuaWRdKSxhLnRleHR1cmVEYXRhKXt2YXIgYz1hLnRleHR1cmVEYXRhLGQ9Yy5tYWdGaWx0ZXI/Yy5tYWdGaWx0ZXI6Yi5MSU5FQVIsZT1jLm1pbkZpbHRlcj9jLm1pbkZpbHRlcjpiLkxJTkVBUixmPWMud3JhcFM/Yy53cmFwUzpiLkNMQU1QX1RPX0VER0UsZz1jLndyYXBUP2Mud3JhcFQ6Yi5DTEFNUF9UT19FREdFLGg9Yy5sdW1pbmFuY2U/Yi5MVU1JTkFOQ0U6Yi5SR0JBO2lmKGMucmVwZWF0JiYoZj1iLlJFUEVBVCxnPWIuUkVQRUFUKSxiLnBpeGVsU3RvcmVpKGIuVU5QQUNLX0ZMSVBfWV9XRUJHTCwhIWMuZmxpcFkpLGMud2lkdGgpe3ZhciBpPWMud2lkdGg/Yy53aWR0aDo1MTIsaj1jLmhlaWdodD9jLmhlaWdodDoyLGs9Yy5ib3JkZXI/Yy5ib3JkZXI6MDtiLnRleEltYWdlMkQoYi5URVhUVVJFXzJELDAsaCxpLGosayxoLGIuVU5TSUdORURfQllURSxudWxsKX1lbHNlIGIudGV4SW1hZ2UyRChiLlRFWFRVUkVfMkQsMCxoLGIuUkdCQSxiLlVOU0lHTkVEX0JZVEUsYS52YWx1ZS5iYXNlVGV4dHVyZS5zb3VyY2UpO2IudGV4UGFyYW1ldGVyaShiLlRFWFRVUkVfMkQsYi5URVhUVVJFX01BR19GSUxURVIsZCksYi50ZXhQYXJhbWV0ZXJpKGIuVEVYVFVSRV8yRCxiLlRFWFRVUkVfTUlOX0ZJTFRFUixlKSxiLnRleFBhcmFtZXRlcmkoYi5URVhUVVJFXzJELGIuVEVYVFVSRV9XUkFQX1MsZiksYi50ZXhQYXJhbWV0ZXJpKGIuVEVYVFVSRV8yRCxiLlRFWFRVUkVfV1JBUF9ULGcpfWIudW5pZm9ybTFpKGEudW5pZm9ybUxvY2F0aW9uLHRoaXMudGV4dHVyZUNvdW50KSxhLl9pbml0PSEwLHRoaXMudGV4dHVyZUNvdW50Kyt9fSxiLlBpeGlTaGFkZXIucHJvdG90eXBlLnN5bmNVbmlmb3Jtcz1mdW5jdGlvbigpe3RoaXMudGV4dHVyZUNvdW50PTE7dmFyIGEsYz10aGlzLmdsO2Zvcih2YXIgZCBpbiB0aGlzLnVuaWZvcm1zKWE9dGhpcy51bmlmb3Jtc1tkXSwxPT09YS5nbFZhbHVlTGVuZ3RoP2EuZ2xNYXRyaXg9PT0hMD9hLmdsRnVuYy5jYWxsKGMsYS51bmlmb3JtTG9jYXRpb24sYS50cmFuc3Bvc2UsYS52YWx1ZSk6YS5nbEZ1bmMuY2FsbChjLGEudW5pZm9ybUxvY2F0aW9uLGEudmFsdWUpOjI9PT1hLmdsVmFsdWVMZW5ndGg/YS5nbEZ1bmMuY2FsbChjLGEudW5pZm9ybUxvY2F0aW9uLGEudmFsdWUueCxhLnZhbHVlLnkpOjM9PT1hLmdsVmFsdWVMZW5ndGg/YS5nbEZ1bmMuY2FsbChjLGEudW5pZm9ybUxvY2F0aW9uLGEudmFsdWUueCxhLnZhbHVlLnksYS52YWx1ZS56KTo0PT09YS5nbFZhbHVlTGVuZ3RoP2EuZ2xGdW5jLmNhbGwoYyxhLnVuaWZvcm1Mb2NhdGlvbixhLnZhbHVlLngsYS52YWx1ZS55LGEudmFsdWUueixhLnZhbHVlLncpOlwic2FtcGxlcjJEXCI9PT1hLnR5cGUmJihhLl9pbml0PyhjLmFjdGl2ZVRleHR1cmUoY1tcIlRFWFRVUkVcIit0aGlzLnRleHR1cmVDb3VudF0pLGEudmFsdWUuYmFzZVRleHR1cmUuX2RpcnR5W2MuaWRdP2IuaW5zdGFuY2VzW2MuaWRdLnVwZGF0ZVRleHR1cmUoYS52YWx1ZS5iYXNlVGV4dHVyZSk6Yy5iaW5kVGV4dHVyZShjLlRFWFRVUkVfMkQsYS52YWx1ZS5iYXNlVGV4dHVyZS5fZ2xUZXh0dXJlc1tjLmlkXSksYy51bmlmb3JtMWkoYS51bmlmb3JtTG9jYXRpb24sdGhpcy50ZXh0dXJlQ291bnQpLHRoaXMudGV4dHVyZUNvdW50KyspOnRoaXMuaW5pdFNhbXBsZXIyRChhKSl9LGIuUGl4aVNoYWRlci5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe3RoaXMuZ2wuZGVsZXRlUHJvZ3JhbSh0aGlzLnByb2dyYW0pLHRoaXMudW5pZm9ybXM9bnVsbCx0aGlzLmdsPW51bGwsdGhpcy5hdHRyaWJ1dGVzPW51bGx9LGIuUGl4aVNoYWRlci5kZWZhdWx0VmVydGV4U3JjPVtcImF0dHJpYnV0ZSB2ZWMyIGFWZXJ0ZXhQb3NpdGlvbjtcIixcImF0dHJpYnV0ZSB2ZWMyIGFUZXh0dXJlQ29vcmQ7XCIsXCJhdHRyaWJ1dGUgdmVjNCBhQ29sb3I7XCIsXCJ1bmlmb3JtIHZlYzIgcHJvamVjdGlvblZlY3RvcjtcIixcInVuaWZvcm0gdmVjMiBvZmZzZXRWZWN0b3I7XCIsXCJ2YXJ5aW5nIHZlYzIgdlRleHR1cmVDb29yZDtcIixcInZhcnlpbmcgdmVjNCB2Q29sb3I7XCIsXCJjb25zdCB2ZWMyIGNlbnRlciA9IHZlYzIoLTEuMCwgMS4wKTtcIixcInZvaWQgbWFpbih2b2lkKSB7XCIsXCIgICBnbF9Qb3NpdGlvbiA9IHZlYzQoICgoYVZlcnRleFBvc2l0aW9uICsgb2Zmc2V0VmVjdG9yKSAvIHByb2plY3Rpb25WZWN0b3IpICsgY2VudGVyICwgMC4wLCAxLjApO1wiLFwiICAgdlRleHR1cmVDb29yZCA9IGFUZXh0dXJlQ29vcmQ7XCIsXCIgICB2Q29sb3IgPSB2ZWM0KGFDb2xvci5yZ2IgKiBhQ29sb3IuYSwgYUNvbG9yLmEpO1wiLFwifVwiXSxiLlBpeGlGYXN0U2hhZGVyPWZ1bmN0aW9uKGEpe3RoaXMuX1VJRD1iLl9VSUQrKyx0aGlzLmdsPWEsdGhpcy5wcm9ncmFtPW51bGwsdGhpcy5mcmFnbWVudFNyYz1bXCJwcmVjaXNpb24gbG93cCBmbG9hdDtcIixcInZhcnlpbmcgdmVjMiB2VGV4dHVyZUNvb3JkO1wiLFwidmFyeWluZyBmbG9hdCB2Q29sb3I7XCIsXCJ1bmlmb3JtIHNhbXBsZXIyRCB1U2FtcGxlcjtcIixcInZvaWQgbWFpbih2b2lkKSB7XCIsXCIgICBnbF9GcmFnQ29sb3IgPSB0ZXh0dXJlMkQodVNhbXBsZXIsIHZUZXh0dXJlQ29vcmQpICogdkNvbG9yIDtcIixcIn1cIl0sdGhpcy52ZXJ0ZXhTcmM9W1wiYXR0cmlidXRlIHZlYzIgYVZlcnRleFBvc2l0aW9uO1wiLFwiYXR0cmlidXRlIHZlYzIgYVBvc2l0aW9uQ29vcmQ7XCIsXCJhdHRyaWJ1dGUgdmVjMiBhU2NhbGU7XCIsXCJhdHRyaWJ1dGUgZmxvYXQgYVJvdGF0aW9uO1wiLFwiYXR0cmlidXRlIHZlYzIgYVRleHR1cmVDb29yZDtcIixcImF0dHJpYnV0ZSBmbG9hdCBhQ29sb3I7XCIsXCJ1bmlmb3JtIHZlYzIgcHJvamVjdGlvblZlY3RvcjtcIixcInVuaWZvcm0gdmVjMiBvZmZzZXRWZWN0b3I7XCIsXCJ1bmlmb3JtIG1hdDMgdU1hdHJpeDtcIixcInZhcnlpbmcgdmVjMiB2VGV4dHVyZUNvb3JkO1wiLFwidmFyeWluZyBmbG9hdCB2Q29sb3I7XCIsXCJjb25zdCB2ZWMyIGNlbnRlciA9IHZlYzIoLTEuMCwgMS4wKTtcIixcInZvaWQgbWFpbih2b2lkKSB7XCIsXCIgICB2ZWMyIHY7XCIsXCIgICB2ZWMyIHN2ID0gYVZlcnRleFBvc2l0aW9uICogYVNjYWxlO1wiLFwiICAgdi54ID0gKHN2LngpICogY29zKGFSb3RhdGlvbikgLSAoc3YueSkgKiBzaW4oYVJvdGF0aW9uKTtcIixcIiAgIHYueSA9IChzdi54KSAqIHNpbihhUm90YXRpb24pICsgKHN2LnkpICogY29zKGFSb3RhdGlvbik7XCIsXCIgICB2ID0gKCB1TWF0cml4ICogdmVjMyh2ICsgYVBvc2l0aW9uQ29vcmQgLCAxLjApICkueHkgO1wiLFwiICAgZ2xfUG9zaXRpb24gPSB2ZWM0KCAoIHYgLyBwcm9qZWN0aW9uVmVjdG9yKSArIGNlbnRlciAsIDAuMCwgMS4wKTtcIixcIiAgIHZUZXh0dXJlQ29vcmQgPSBhVGV4dHVyZUNvb3JkO1wiLFwiICAgdkNvbG9yID0gYUNvbG9yO1wiLFwifVwiXSx0aGlzLnRleHR1cmVDb3VudD0wLHRoaXMuaW5pdCgpfSxiLlBpeGlGYXN0U2hhZGVyLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLlBpeGlGYXN0U2hhZGVyLGIuUGl4aUZhc3RTaGFkZXIucHJvdG90eXBlLmluaXQ9ZnVuY3Rpb24oKXt2YXIgYT10aGlzLmdsLGM9Yi5jb21waWxlUHJvZ3JhbShhLHRoaXMudmVydGV4U3JjLHRoaXMuZnJhZ21lbnRTcmMpO2EudXNlUHJvZ3JhbShjKSx0aGlzLnVTYW1wbGVyPWEuZ2V0VW5pZm9ybUxvY2F0aW9uKGMsXCJ1U2FtcGxlclwiKSx0aGlzLnByb2plY3Rpb25WZWN0b3I9YS5nZXRVbmlmb3JtTG9jYXRpb24oYyxcInByb2plY3Rpb25WZWN0b3JcIiksdGhpcy5vZmZzZXRWZWN0b3I9YS5nZXRVbmlmb3JtTG9jYXRpb24oYyxcIm9mZnNldFZlY3RvclwiKSx0aGlzLmRpbWVuc2lvbnM9YS5nZXRVbmlmb3JtTG9jYXRpb24oYyxcImRpbWVuc2lvbnNcIiksdGhpcy51TWF0cml4PWEuZ2V0VW5pZm9ybUxvY2F0aW9uKGMsXCJ1TWF0cml4XCIpLHRoaXMuYVZlcnRleFBvc2l0aW9uPWEuZ2V0QXR0cmliTG9jYXRpb24oYyxcImFWZXJ0ZXhQb3NpdGlvblwiKSx0aGlzLmFQb3NpdGlvbkNvb3JkPWEuZ2V0QXR0cmliTG9jYXRpb24oYyxcImFQb3NpdGlvbkNvb3JkXCIpLHRoaXMuYVNjYWxlPWEuZ2V0QXR0cmliTG9jYXRpb24oYyxcImFTY2FsZVwiKSx0aGlzLmFSb3RhdGlvbj1hLmdldEF0dHJpYkxvY2F0aW9uKGMsXCJhUm90YXRpb25cIiksdGhpcy5hVGV4dHVyZUNvb3JkPWEuZ2V0QXR0cmliTG9jYXRpb24oYyxcImFUZXh0dXJlQ29vcmRcIiksdGhpcy5jb2xvckF0dHJpYnV0ZT1hLmdldEF0dHJpYkxvY2F0aW9uKGMsXCJhQ29sb3JcIiksLTE9PT10aGlzLmNvbG9yQXR0cmlidXRlJiYodGhpcy5jb2xvckF0dHJpYnV0ZT0yKSx0aGlzLmF0dHJpYnV0ZXM9W3RoaXMuYVZlcnRleFBvc2l0aW9uLHRoaXMuYVBvc2l0aW9uQ29vcmQsdGhpcy5hU2NhbGUsdGhpcy5hUm90YXRpb24sdGhpcy5hVGV4dHVyZUNvb3JkLHRoaXMuY29sb3JBdHRyaWJ1dGVdLHRoaXMucHJvZ3JhbT1jfSxiLlBpeGlGYXN0U2hhZGVyLnByb3RvdHlwZS5kZXN0cm95PWZ1bmN0aW9uKCl7dGhpcy5nbC5kZWxldGVQcm9ncmFtKHRoaXMucHJvZ3JhbSksdGhpcy51bmlmb3Jtcz1udWxsLHRoaXMuZ2w9bnVsbCx0aGlzLmF0dHJpYnV0ZXM9bnVsbH0sYi5TdHJpcFNoYWRlcj1mdW5jdGlvbihhKXt0aGlzLl9VSUQ9Yi5fVUlEKyssdGhpcy5nbD1hLHRoaXMucHJvZ3JhbT1udWxsLHRoaXMuZnJhZ21lbnRTcmM9W1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XCIsXCJ2YXJ5aW5nIHZlYzIgdlRleHR1cmVDb29yZDtcIixcInVuaWZvcm0gZmxvYXQgYWxwaGE7XCIsXCJ1bmlmb3JtIHNhbXBsZXIyRCB1U2FtcGxlcjtcIixcInZvaWQgbWFpbih2b2lkKSB7XCIsXCIgICBnbF9GcmFnQ29sb3IgPSB0ZXh0dXJlMkQodVNhbXBsZXIsIHZlYzIodlRleHR1cmVDb29yZC54LCB2VGV4dHVyZUNvb3JkLnkpKSAqIGFscGhhO1wiLFwifVwiXSx0aGlzLnZlcnRleFNyYz1bXCJhdHRyaWJ1dGUgdmVjMiBhVmVydGV4UG9zaXRpb247XCIsXCJhdHRyaWJ1dGUgdmVjMiBhVGV4dHVyZUNvb3JkO1wiLFwidW5pZm9ybSBtYXQzIHRyYW5zbGF0aW9uTWF0cml4O1wiLFwidW5pZm9ybSB2ZWMyIHByb2plY3Rpb25WZWN0b3I7XCIsXCJ1bmlmb3JtIHZlYzIgb2Zmc2V0VmVjdG9yO1wiLFwidmFyeWluZyB2ZWMyIHZUZXh0dXJlQ29vcmQ7XCIsXCJ2b2lkIG1haW4odm9pZCkge1wiLFwiICAgdmVjMyB2ID0gdHJhbnNsYXRpb25NYXRyaXggKiB2ZWMzKGFWZXJ0ZXhQb3NpdGlvbiAsIDEuMCk7XCIsXCIgICB2IC09IG9mZnNldFZlY3Rvci54eXg7XCIsXCIgICBnbF9Qb3NpdGlvbiA9IHZlYzQoIHYueCAvIHByb2plY3Rpb25WZWN0b3IueCAtMS4wLCB2LnkgLyAtcHJvamVjdGlvblZlY3Rvci55ICsgMS4wICwgMC4wLCAxLjApO1wiLFwiICAgdlRleHR1cmVDb29yZCA9IGFUZXh0dXJlQ29vcmQ7XCIsXCJ9XCJdLHRoaXMuaW5pdCgpfSxiLlN0cmlwU2hhZGVyLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLlN0cmlwU2hhZGVyLGIuU3RyaXBTaGFkZXIucHJvdG90eXBlLmluaXQ9ZnVuY3Rpb24oKXt2YXIgYT10aGlzLmdsLGM9Yi5jb21waWxlUHJvZ3JhbShhLHRoaXMudmVydGV4U3JjLHRoaXMuZnJhZ21lbnRTcmMpO2EudXNlUHJvZ3JhbShjKSx0aGlzLnVTYW1wbGVyPWEuZ2V0VW5pZm9ybUxvY2F0aW9uKGMsXCJ1U2FtcGxlclwiKSx0aGlzLnByb2plY3Rpb25WZWN0b3I9YS5nZXRVbmlmb3JtTG9jYXRpb24oYyxcInByb2plY3Rpb25WZWN0b3JcIiksdGhpcy5vZmZzZXRWZWN0b3I9YS5nZXRVbmlmb3JtTG9jYXRpb24oYyxcIm9mZnNldFZlY3RvclwiKSx0aGlzLmNvbG9yQXR0cmlidXRlPWEuZ2V0QXR0cmliTG9jYXRpb24oYyxcImFDb2xvclwiKSx0aGlzLmFWZXJ0ZXhQb3NpdGlvbj1hLmdldEF0dHJpYkxvY2F0aW9uKGMsXCJhVmVydGV4UG9zaXRpb25cIiksdGhpcy5hVGV4dHVyZUNvb3JkPWEuZ2V0QXR0cmliTG9jYXRpb24oYyxcImFUZXh0dXJlQ29vcmRcIiksdGhpcy5hdHRyaWJ1dGVzPVt0aGlzLmFWZXJ0ZXhQb3NpdGlvbix0aGlzLmFUZXh0dXJlQ29vcmRdLHRoaXMudHJhbnNsYXRpb25NYXRyaXg9YS5nZXRVbmlmb3JtTG9jYXRpb24oYyxcInRyYW5zbGF0aW9uTWF0cml4XCIpLHRoaXMuYWxwaGE9YS5nZXRVbmlmb3JtTG9jYXRpb24oYyxcImFscGhhXCIpLHRoaXMucHJvZ3JhbT1jfSxiLlN0cmlwU2hhZGVyLnByb3RvdHlwZS5kZXN0cm95PWZ1bmN0aW9uKCl7dGhpcy5nbC5kZWxldGVQcm9ncmFtKHRoaXMucHJvZ3JhbSksdGhpcy51bmlmb3Jtcz1udWxsLHRoaXMuZ2w9bnVsbCx0aGlzLmF0dHJpYnV0ZT1udWxsfSxiLlByaW1pdGl2ZVNoYWRlcj1mdW5jdGlvbihhKXt0aGlzLl9VSUQ9Yi5fVUlEKyssdGhpcy5nbD1hLHRoaXMucHJvZ3JhbT1udWxsLHRoaXMuZnJhZ21lbnRTcmM9W1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XCIsXCJ2YXJ5aW5nIHZlYzQgdkNvbG9yO1wiLFwidm9pZCBtYWluKHZvaWQpIHtcIixcIiAgIGdsX0ZyYWdDb2xvciA9IHZDb2xvcjtcIixcIn1cIl0sdGhpcy52ZXJ0ZXhTcmM9W1wiYXR0cmlidXRlIHZlYzIgYVZlcnRleFBvc2l0aW9uO1wiLFwiYXR0cmlidXRlIHZlYzQgYUNvbG9yO1wiLFwidW5pZm9ybSBtYXQzIHRyYW5zbGF0aW9uTWF0cml4O1wiLFwidW5pZm9ybSB2ZWMyIHByb2plY3Rpb25WZWN0b3I7XCIsXCJ1bmlmb3JtIHZlYzIgb2Zmc2V0VmVjdG9yO1wiLFwidW5pZm9ybSBmbG9hdCBhbHBoYTtcIixcInVuaWZvcm0gZmxvYXQgZmxpcFk7XCIsXCJ1bmlmb3JtIHZlYzMgdGludDtcIixcInZhcnlpbmcgdmVjNCB2Q29sb3I7XCIsXCJ2b2lkIG1haW4odm9pZCkge1wiLFwiICAgdmVjMyB2ID0gdHJhbnNsYXRpb25NYXRyaXggKiB2ZWMzKGFWZXJ0ZXhQb3NpdGlvbiAsIDEuMCk7XCIsXCIgICB2IC09IG9mZnNldFZlY3Rvci54eXg7XCIsXCIgICBnbF9Qb3NpdGlvbiA9IHZlYzQoIHYueCAvIHByb2plY3Rpb25WZWN0b3IueCAtMS4wLCAodi55IC8gcHJvamVjdGlvblZlY3Rvci55ICogLWZsaXBZKSArIGZsaXBZICwgMC4wLCAxLjApO1wiLFwiICAgdkNvbG9yID0gYUNvbG9yICogdmVjNCh0aW50ICogYWxwaGEsIGFscGhhKTtcIixcIn1cIl0sdGhpcy5pbml0KCl9LGIuUHJpbWl0aXZlU2hhZGVyLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLlByaW1pdGl2ZVNoYWRlcixiLlByaW1pdGl2ZVNoYWRlci5wcm90b3R5cGUuaW5pdD1mdW5jdGlvbigpe3ZhciBhPXRoaXMuZ2wsYz1iLmNvbXBpbGVQcm9ncmFtKGEsdGhpcy52ZXJ0ZXhTcmMsdGhpcy5mcmFnbWVudFNyYyk7YS51c2VQcm9ncmFtKGMpLHRoaXMucHJvamVjdGlvblZlY3Rvcj1hLmdldFVuaWZvcm1Mb2NhdGlvbihjLFwicHJvamVjdGlvblZlY3RvclwiKSx0aGlzLm9mZnNldFZlY3Rvcj1hLmdldFVuaWZvcm1Mb2NhdGlvbihjLFwib2Zmc2V0VmVjdG9yXCIpLHRoaXMudGludENvbG9yPWEuZ2V0VW5pZm9ybUxvY2F0aW9uKGMsXCJ0aW50XCIpLHRoaXMuZmxpcFk9YS5nZXRVbmlmb3JtTG9jYXRpb24oYyxcImZsaXBZXCIpLHRoaXMuYVZlcnRleFBvc2l0aW9uPWEuZ2V0QXR0cmliTG9jYXRpb24oYyxcImFWZXJ0ZXhQb3NpdGlvblwiKSx0aGlzLmNvbG9yQXR0cmlidXRlPWEuZ2V0QXR0cmliTG9jYXRpb24oYyxcImFDb2xvclwiKSx0aGlzLmF0dHJpYnV0ZXM9W3RoaXMuYVZlcnRleFBvc2l0aW9uLHRoaXMuY29sb3JBdHRyaWJ1dGVdLHRoaXMudHJhbnNsYXRpb25NYXRyaXg9YS5nZXRVbmlmb3JtTG9jYXRpb24oYyxcInRyYW5zbGF0aW9uTWF0cml4XCIpLHRoaXMuYWxwaGE9YS5nZXRVbmlmb3JtTG9jYXRpb24oYyxcImFscGhhXCIpLHRoaXMucHJvZ3JhbT1jfSxiLlByaW1pdGl2ZVNoYWRlci5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe3RoaXMuZ2wuZGVsZXRlUHJvZ3JhbSh0aGlzLnByb2dyYW0pLHRoaXMudW5pZm9ybXM9bnVsbCx0aGlzLmdsPW51bGwsdGhpcy5hdHRyaWJ1dGVzPW51bGx9LGIuQ29tcGxleFByaW1pdGl2ZVNoYWRlcj1mdW5jdGlvbihhKXt0aGlzLl9VSUQ9Yi5fVUlEKyssdGhpcy5nbD1hLHRoaXMucHJvZ3JhbT1udWxsLHRoaXMuZnJhZ21lbnRTcmM9W1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XCIsXCJ2YXJ5aW5nIHZlYzQgdkNvbG9yO1wiLFwidm9pZCBtYWluKHZvaWQpIHtcIixcIiAgIGdsX0ZyYWdDb2xvciA9IHZDb2xvcjtcIixcIn1cIl0sdGhpcy52ZXJ0ZXhTcmM9W1wiYXR0cmlidXRlIHZlYzIgYVZlcnRleFBvc2l0aW9uO1wiLFwidW5pZm9ybSBtYXQzIHRyYW5zbGF0aW9uTWF0cml4O1wiLFwidW5pZm9ybSB2ZWMyIHByb2plY3Rpb25WZWN0b3I7XCIsXCJ1bmlmb3JtIHZlYzIgb2Zmc2V0VmVjdG9yO1wiLFwidW5pZm9ybSB2ZWMzIHRpbnQ7XCIsXCJ1bmlmb3JtIGZsb2F0IGFscGhhO1wiLFwidW5pZm9ybSB2ZWMzIGNvbG9yO1wiLFwidW5pZm9ybSBmbG9hdCBmbGlwWTtcIixcInZhcnlpbmcgdmVjNCB2Q29sb3I7XCIsXCJ2b2lkIG1haW4odm9pZCkge1wiLFwiICAgdmVjMyB2ID0gdHJhbnNsYXRpb25NYXRyaXggKiB2ZWMzKGFWZXJ0ZXhQb3NpdGlvbiAsIDEuMCk7XCIsXCIgICB2IC09IG9mZnNldFZlY3Rvci54eXg7XCIsXCIgICBnbF9Qb3NpdGlvbiA9IHZlYzQoIHYueCAvIHByb2plY3Rpb25WZWN0b3IueCAtMS4wLCAodi55IC8gcHJvamVjdGlvblZlY3Rvci55ICogLWZsaXBZKSArIGZsaXBZICwgMC4wLCAxLjApO1wiLFwiICAgdkNvbG9yID0gdmVjNChjb2xvciAqIGFscGhhICogdGludCwgYWxwaGEpO1wiLFwifVwiXSx0aGlzLmluaXQoKX0sYi5Db21wbGV4UHJpbWl0aXZlU2hhZGVyLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLkNvbXBsZXhQcmltaXRpdmVTaGFkZXIsYi5Db21wbGV4UHJpbWl0aXZlU2hhZGVyLnByb3RvdHlwZS5pbml0PWZ1bmN0aW9uKCl7dmFyIGE9dGhpcy5nbCxjPWIuY29tcGlsZVByb2dyYW0oYSx0aGlzLnZlcnRleFNyYyx0aGlzLmZyYWdtZW50U3JjKTthLnVzZVByb2dyYW0oYyksdGhpcy5wcm9qZWN0aW9uVmVjdG9yPWEuZ2V0VW5pZm9ybUxvY2F0aW9uKGMsXCJwcm9qZWN0aW9uVmVjdG9yXCIpLHRoaXMub2Zmc2V0VmVjdG9yPWEuZ2V0VW5pZm9ybUxvY2F0aW9uKGMsXCJvZmZzZXRWZWN0b3JcIiksdGhpcy50aW50Q29sb3I9YS5nZXRVbmlmb3JtTG9jYXRpb24oYyxcInRpbnRcIiksdGhpcy5jb2xvcj1hLmdldFVuaWZvcm1Mb2NhdGlvbihjLFwiY29sb3JcIiksdGhpcy5mbGlwWT1hLmdldFVuaWZvcm1Mb2NhdGlvbihjLFwiZmxpcFlcIiksdGhpcy5hVmVydGV4UG9zaXRpb249YS5nZXRBdHRyaWJMb2NhdGlvbihjLFwiYVZlcnRleFBvc2l0aW9uXCIpLHRoaXMuYXR0cmlidXRlcz1bdGhpcy5hVmVydGV4UG9zaXRpb24sdGhpcy5jb2xvckF0dHJpYnV0ZV0sdGhpcy50cmFuc2xhdGlvbk1hdHJpeD1hLmdldFVuaWZvcm1Mb2NhdGlvbihjLFwidHJhbnNsYXRpb25NYXRyaXhcIiksdGhpcy5hbHBoYT1hLmdldFVuaWZvcm1Mb2NhdGlvbihjLFwiYWxwaGFcIiksdGhpcy5wcm9ncmFtPWN9LGIuQ29tcGxleFByaW1pdGl2ZVNoYWRlci5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe3RoaXMuZ2wuZGVsZXRlUHJvZ3JhbSh0aGlzLnByb2dyYW0pLHRoaXMudW5pZm9ybXM9bnVsbCx0aGlzLmdsPW51bGwsdGhpcy5hdHRyaWJ1dGU9bnVsbH0sYi5XZWJHTEdyYXBoaWNzPWZ1bmN0aW9uKCl7fSxiLldlYkdMR3JhcGhpY3MucmVuZGVyR3JhcGhpY3M9ZnVuY3Rpb24oYSxjKXt2YXIgZCxlPWMuZ2wsZj1jLnByb2plY3Rpb24sZz1jLm9mZnNldCxoPWMuc2hhZGVyTWFuYWdlci5wcmltaXRpdmVTaGFkZXI7YS5kaXJ0eSYmYi5XZWJHTEdyYXBoaWNzLnVwZGF0ZUdyYXBoaWNzKGEsZSk7Zm9yKHZhciBpPWEuX3dlYkdMW2UuaWRdLGo9MDtqPGkuZGF0YS5sZW5ndGg7aisrKTE9PT1pLmRhdGFbal0ubW9kZT8oZD1pLmRhdGFbal0sYy5zdGVuY2lsTWFuYWdlci5wdXNoU3RlbmNpbChhLGQsYyksZS5kcmF3RWxlbWVudHMoZS5UUklBTkdMRV9GQU4sNCxlLlVOU0lHTkVEX1NIT1JULDIqKGQuaW5kaWNlcy5sZW5ndGgtNCkpLGMuc3RlbmNpbE1hbmFnZXIucG9wU3RlbmNpbChhLGQsYykpOihkPWkuZGF0YVtqXSxjLnNoYWRlck1hbmFnZXIuc2V0U2hhZGVyKGgpLGg9Yy5zaGFkZXJNYW5hZ2VyLnByaW1pdGl2ZVNoYWRlcixlLnVuaWZvcm1NYXRyaXgzZnYoaC50cmFuc2xhdGlvbk1hdHJpeCwhMSxhLndvcmxkVHJhbnNmb3JtLnRvQXJyYXkoITApKSxlLnVuaWZvcm0xZihoLmZsaXBZLDEpLGUudW5pZm9ybTJmKGgucHJvamVjdGlvblZlY3RvcixmLngsLWYueSksZS51bmlmb3JtMmYoaC5vZmZzZXRWZWN0b3IsLWcueCwtZy55KSxlLnVuaWZvcm0zZnYoaC50aW50Q29sb3IsYi5oZXgycmdiKGEudGludCkpLGUudW5pZm9ybTFmKGguYWxwaGEsYS53b3JsZEFscGhhKSxlLmJpbmRCdWZmZXIoZS5BUlJBWV9CVUZGRVIsZC5idWZmZXIpLGUudmVydGV4QXR0cmliUG9pbnRlcihoLmFWZXJ0ZXhQb3NpdGlvbiwyLGUuRkxPQVQsITEsMjQsMCksZS52ZXJ0ZXhBdHRyaWJQb2ludGVyKGguY29sb3JBdHRyaWJ1dGUsNCxlLkZMT0FULCExLDI0LDgpLGUuYmluZEJ1ZmZlcihlLkVMRU1FTlRfQVJSQVlfQlVGRkVSLGQuaW5kZXhCdWZmZXIpLGUuZHJhd0VsZW1lbnRzKGUuVFJJQU5HTEVfU1RSSVAsZC5pbmRpY2VzLmxlbmd0aCxlLlVOU0lHTkVEX1NIT1JULDApKX0sYi5XZWJHTEdyYXBoaWNzLnVwZGF0ZUdyYXBoaWNzPWZ1bmN0aW9uKGEsYyl7dmFyIGQ9YS5fd2ViR0xbYy5pZF07ZHx8KGQ9YS5fd2ViR0xbYy5pZF09e2xhc3RJbmRleDowLGRhdGE6W10sZ2w6Y30pLGEuZGlydHk9ITE7dmFyIGU7aWYoYS5jbGVhckRpcnR5KXtmb3IoYS5jbGVhckRpcnR5PSExLGU9MDtlPGQuZGF0YS5sZW5ndGg7ZSsrKXt2YXIgZj1kLmRhdGFbZV07Zi5yZXNldCgpLGIuV2ViR0xHcmFwaGljcy5ncmFwaGljc0RhdGFQb29sLnB1c2goZil9ZC5kYXRhPVtdLGQubGFzdEluZGV4PTB9dmFyIGc7Zm9yKGU9ZC5sYXN0SW5kZXg7ZTxhLmdyYXBoaWNzRGF0YS5sZW5ndGg7ZSsrKXt2YXIgaD1hLmdyYXBoaWNzRGF0YVtlXTtpZihoLnR5cGU9PT1iLkdyYXBoaWNzLlBPTFkpe2lmKGgucG9pbnRzPWguc2hhcGUucG9pbnRzLnNsaWNlKCksaC5zaGFwZS5jbG9zZWQmJihoLnBvaW50c1swXSE9PWgucG9pbnRzW2gucG9pbnRzLmxlbmd0aC0yXXx8aC5wb2ludHNbMV0hPT1oLnBvaW50c1toLnBvaW50cy5sZW5ndGgtMV0pJiZoLnBvaW50cy5wdXNoKGgucG9pbnRzWzBdLGgucG9pbnRzWzFdKSxoLmZpbGwmJmgucG9pbnRzLmxlbmd0aD49NilpZihoLnBvaW50cy5sZW5ndGg8MTIpe2c9Yi5XZWJHTEdyYXBoaWNzLnN3aXRjaE1vZGUoZCwwKTt2YXIgaT1iLldlYkdMR3JhcGhpY3MuYnVpbGRQb2x5KGgsZyk7aXx8KGc9Yi5XZWJHTEdyYXBoaWNzLnN3aXRjaE1vZGUoZCwxKSxiLldlYkdMR3JhcGhpY3MuYnVpbGRDb21wbGV4UG9seShoLGcpKX1lbHNlIGc9Yi5XZWJHTEdyYXBoaWNzLnN3aXRjaE1vZGUoZCwxKSxiLldlYkdMR3JhcGhpY3MuYnVpbGRDb21wbGV4UG9seShoLGcpO2gubGluZVdpZHRoPjAmJihnPWIuV2ViR0xHcmFwaGljcy5zd2l0Y2hNb2RlKGQsMCksYi5XZWJHTEdyYXBoaWNzLmJ1aWxkTGluZShoLGcpKX1lbHNlIGc9Yi5XZWJHTEdyYXBoaWNzLnN3aXRjaE1vZGUoZCwwKSxoLnR5cGU9PT1iLkdyYXBoaWNzLlJFQ1Q/Yi5XZWJHTEdyYXBoaWNzLmJ1aWxkUmVjdGFuZ2xlKGgsZyk6aC50eXBlPT09Yi5HcmFwaGljcy5DSVJDfHxoLnR5cGU9PT1iLkdyYXBoaWNzLkVMSVA/Yi5XZWJHTEdyYXBoaWNzLmJ1aWxkQ2lyY2xlKGgsZyk6aC50eXBlPT09Yi5HcmFwaGljcy5SUkVDJiZiLldlYkdMR3JhcGhpY3MuYnVpbGRSb3VuZGVkUmVjdGFuZ2xlKGgsZyk7ZC5sYXN0SW5kZXgrK31mb3IoZT0wO2U8ZC5kYXRhLmxlbmd0aDtlKyspZz1kLmRhdGFbZV0sZy5kaXJ0eSYmZy51cGxvYWQoKX0sYi5XZWJHTEdyYXBoaWNzLnN3aXRjaE1vZGU9ZnVuY3Rpb24oYSxjKXt2YXIgZDtyZXR1cm4gYS5kYXRhLmxlbmd0aD8oZD1hLmRhdGFbYS5kYXRhLmxlbmd0aC0xXSwoZC5tb2RlIT09Y3x8MT09PWMpJiYoZD1iLldlYkdMR3JhcGhpY3MuZ3JhcGhpY3NEYXRhUG9vbC5wb3AoKXx8bmV3IGIuV2ViR0xHcmFwaGljc0RhdGEoYS5nbCksZC5tb2RlPWMsYS5kYXRhLnB1c2goZCkpKTooZD1iLldlYkdMR3JhcGhpY3MuZ3JhcGhpY3NEYXRhUG9vbC5wb3AoKXx8bmV3IGIuV2ViR0xHcmFwaGljc0RhdGEoYS5nbCksZC5tb2RlPWMsYS5kYXRhLnB1c2goZCkpLGQuZGlydHk9ITAsZH0sYi5XZWJHTEdyYXBoaWNzLmJ1aWxkUmVjdGFuZ2xlPWZ1bmN0aW9uKGEsYyl7dmFyIGQ9YS5zaGFwZSxlPWQueCxmPWQueSxnPWQud2lkdGgsaD1kLmhlaWdodDtpZihhLmZpbGwpe3ZhciBpPWIuaGV4MnJnYihhLmZpbGxDb2xvciksaj1hLmZpbGxBbHBoYSxrPWlbMF0qaixsPWlbMV0qaixtPWlbMl0qaixuPWMucG9pbnRzLG89Yy5pbmRpY2VzLHA9bi5sZW5ndGgvNjtuLnB1c2goZSxmKSxuLnB1c2goayxsLG0saiksbi5wdXNoKGUrZyxmKSxuLnB1c2goayxsLG0saiksbi5wdXNoKGUsZitoKSxuLnB1c2goayxsLG0saiksbi5wdXNoKGUrZyxmK2gpLG4ucHVzaChrLGwsbSxqKSxvLnB1c2gocCxwLHArMSxwKzIscCszLHArMyl9aWYoYS5saW5lV2lkdGgpe3ZhciBxPWEucG9pbnRzO2EucG9pbnRzPVtlLGYsZStnLGYsZStnLGYraCxlLGYraCxlLGZdLGIuV2ViR0xHcmFwaGljcy5idWlsZExpbmUoYSxjKSxhLnBvaW50cz1xfX0sYi5XZWJHTEdyYXBoaWNzLmJ1aWxkUm91bmRlZFJlY3RhbmdsZT1mdW5jdGlvbihhLGMpe3ZhciBkPWEuc2hhcGUsZT1kLngsZj1kLnksZz1kLndpZHRoLGg9ZC5oZWlnaHQsaT1kLnJhZGl1cyxqPVtdO2lmKGoucHVzaChlLGYraSksaj1qLmNvbmNhdChiLldlYkdMR3JhcGhpY3MucXVhZHJhdGljQmV6aWVyQ3VydmUoZSxmK2gtaSxlLGYraCxlK2ksZitoKSksaj1qLmNvbmNhdChiLldlYkdMR3JhcGhpY3MucXVhZHJhdGljQmV6aWVyQ3VydmUoZStnLWksZitoLGUrZyxmK2gsZStnLGYraC1pKSksaj1qLmNvbmNhdChiLldlYkdMR3JhcGhpY3MucXVhZHJhdGljQmV6aWVyQ3VydmUoZStnLGYraSxlK2csZixlK2ctaSxmKSksaj1qLmNvbmNhdChiLldlYkdMR3JhcGhpY3MucXVhZHJhdGljQmV6aWVyQ3VydmUoZStpLGYsZSxmLGUsZitpKSksYS5maWxsKXt2YXIgaz1iLmhleDJyZ2IoYS5maWxsQ29sb3IpLGw9YS5maWxsQWxwaGEsbT1rWzBdKmwsbj1rWzFdKmwsbz1rWzJdKmwscD1jLnBvaW50cyxxPWMuaW5kaWNlcyxyPXAubGVuZ3RoLzYscz1iLlBvbHlLLlRyaWFuZ3VsYXRlKGopLHQ9MDtmb3IodD0wO3Q8cy5sZW5ndGg7dCs9MylxLnB1c2goc1t0XStyKSxxLnB1c2goc1t0XStyKSxxLnB1c2goc1t0KzFdK3IpLHEucHVzaChzW3QrMl0rcikscS5wdXNoKHNbdCsyXStyKTtmb3IodD0wO3Q8ai5sZW5ndGg7dCsrKXAucHVzaChqW3RdLGpbKyt0XSxtLG4sbyxsKX1pZihhLmxpbmVXaWR0aCl7dmFyIHU9YS5wb2ludHM7YS5wb2ludHM9aixiLldlYkdMR3JhcGhpY3MuYnVpbGRMaW5lKGEsYyksYS5wb2ludHM9dX19LGIuV2ViR0xHcmFwaGljcy5xdWFkcmF0aWNCZXppZXJDdXJ2ZT1mdW5jdGlvbihhLGIsYyxkLGUsZil7ZnVuY3Rpb24gZyhhLGIsYyl7dmFyIGQ9Yi1hO3JldHVybiBhK2QqY31mb3IodmFyIGgsaSxqLGssbCxtLG49MjAsbz1bXSxwPTAscT0wO24+PXE7cSsrKXA9cS9uLGg9ZyhhLGMscCksaT1nKGIsZCxwKSxqPWcoYyxlLHApLGs9ZyhkLGYscCksbD1nKGgsaixwKSxtPWcoaSxrLHApLG8ucHVzaChsLG0pO3JldHVybiBvfSxiLldlYkdMR3JhcGhpY3MuYnVpbGRDaXJjbGU9ZnVuY3Rpb24oYSxjKXt2YXIgZCxlLGY9YS5zaGFwZSxnPWYueCxoPWYueTthLnR5cGU9PT1iLkdyYXBoaWNzLkNJUkM/KGQ9Zi5yYWRpdXMsZT1mLnJhZGl1cyk6KGQ9Zi53aWR0aCxlPWYuaGVpZ2h0KTt2YXIgaT00MCxqPTIqTWF0aC5QSS9pLGs9MDtpZihhLmZpbGwpe3ZhciBsPWIuaGV4MnJnYihhLmZpbGxDb2xvciksbT1hLmZpbGxBbHBoYSxuPWxbMF0qbSxvPWxbMV0qbSxwPWxbMl0qbSxxPWMucG9pbnRzLHI9Yy5pbmRpY2VzLHM9cS5sZW5ndGgvNjtmb3Ioci5wdXNoKHMpLGs9MDtpKzE+aztrKyspcS5wdXNoKGcsaCxuLG8scCxtKSxxLnB1c2goZytNYXRoLnNpbihqKmspKmQsaCtNYXRoLmNvcyhqKmspKmUsbixvLHAsbSksci5wdXNoKHMrKyxzKyspO3IucHVzaChzLTEpfWlmKGEubGluZVdpZHRoKXt2YXIgdD1hLnBvaW50cztmb3IoYS5wb2ludHM9W10saz0wO2krMT5rO2srKylhLnBvaW50cy5wdXNoKGcrTWF0aC5zaW4oaiprKSpkLGgrTWF0aC5jb3MoaiprKSplKTtiLldlYkdMR3JhcGhpY3MuYnVpbGRMaW5lKGEsYyksYS5wb2ludHM9dH19LGIuV2ViR0xHcmFwaGljcy5idWlsZExpbmU9ZnVuY3Rpb24oYSxjKXt2YXIgZD0wLGU9YS5wb2ludHM7aWYoMCE9PWUubGVuZ3RoKXtpZihhLmxpbmVXaWR0aCUyKWZvcihkPTA7ZDxlLmxlbmd0aDtkKyspZVtkXSs9LjU7dmFyIGY9bmV3IGIuUG9pbnQoZVswXSxlWzFdKSxnPW5ldyBiLlBvaW50KGVbZS5sZW5ndGgtMl0sZVtlLmxlbmd0aC0xXSk7aWYoZi54PT09Zy54JiZmLnk9PT1nLnkpe2U9ZS5zbGljZSgpLGUucG9wKCksZS5wb3AoKSxnPW5ldyBiLlBvaW50KGVbZS5sZW5ndGgtMl0sZVtlLmxlbmd0aC0xXSk7dmFyIGg9Zy54Ky41KihmLngtZy54KSxpPWcueSsuNSooZi55LWcueSk7ZS51bnNoaWZ0KGgsaSksZS5wdXNoKGgsaSl9dmFyIGosayxsLG0sbixvLHAscSxyLHMsdCx1LHYsdyx4LHkseixBLEIsQyxELEUsRixHPWMucG9pbnRzLEg9Yy5pbmRpY2VzLEk9ZS5sZW5ndGgvMixKPWUubGVuZ3RoLEs9Ry5sZW5ndGgvNixMPWEubGluZVdpZHRoLzIsTT1iLmhleDJyZ2IoYS5saW5lQ29sb3IpLE49YS5saW5lQWxwaGEsTz1NWzBdKk4sUD1NWzFdKk4sUT1NWzJdKk47Zm9yKGw9ZVswXSxtPWVbMV0sbj1lWzJdLG89ZVszXSxyPS0obS1vKSxzPWwtbixGPU1hdGguc3FydChyKnIrcypzKSxyLz1GLHMvPUYscio9TCxzKj1MLEcucHVzaChsLXIsbS1zLE8sUCxRLE4pLEcucHVzaChsK3IsbStzLE8sUCxRLE4pLGQ9MTtJLTE+ZDtkKyspbD1lWzIqKGQtMSldLG09ZVsyKihkLTEpKzFdLG49ZVsyKmRdLG89ZVsyKmQrMV0scD1lWzIqKGQrMSldLHE9ZVsyKihkKzEpKzFdLHI9LShtLW8pLHM9bC1uLEY9TWF0aC5zcXJ0KHIqcitzKnMpLHIvPUYscy89RixyKj1MLHMqPUwsdD0tKG8tcSksdT1uLXAsRj1NYXRoLnNxcnQodCp0K3UqdSksdC89Rix1Lz1GLHQqPUwsdSo9TCx4PS1zK20tKC1zK28pLHk9LXIrbi0oLXIrbCksej0oLXIrbCkqKC1zK28pLSgtcituKSooLXMrbSksQT0tdStxLSgtdStvKSxCPS10K24tKC10K3ApLEM9KC10K3ApKigtdStvKS0oLXQrbikqKC11K3EpLEQ9eCpCLUEqeSxNYXRoLmFicyhEKTwuMT8oRCs9MTAuMSxHLnB1c2gobi1yLG8tcyxPLFAsUSxOKSxHLnB1c2gobityLG8rcyxPLFAsUSxOKSk6KGo9KHkqQy1CKnopL0Qsaz0oQSp6LXgqQykvRCxFPShqLW4pKihqLW4pKyhrLW8pKyhrLW8pLEU+MTk2MDA/KHY9ci10LHc9cy11LEY9TWF0aC5zcXJ0KHYqdit3KncpLHYvPUYsdy89Rix2Kj1MLHcqPUwsRy5wdXNoKG4tdixvLXcpLEcucHVzaChPLFAsUSxOKSxHLnB1c2gobit2LG8rdyksRy5wdXNoKE8sUCxRLE4pLEcucHVzaChuLXYsby13KSxHLnB1c2goTyxQLFEsTiksSisrKTooRy5wdXNoKGosayksRy5wdXNoKE8sUCxRLE4pLEcucHVzaChuLShqLW4pLG8tKGstbykpLEcucHVzaChPLFAsUSxOKSkpO1xuZm9yKGw9ZVsyKihJLTIpXSxtPWVbMiooSS0yKSsxXSxuPWVbMiooSS0xKV0sbz1lWzIqKEktMSkrMV0scj0tKG0tbykscz1sLW4sRj1NYXRoLnNxcnQocipyK3Mqcyksci89RixzLz1GLHIqPUwscyo9TCxHLnB1c2gobi1yLG8tcyksRy5wdXNoKE8sUCxRLE4pLEcucHVzaChuK3IsbytzKSxHLnB1c2goTyxQLFEsTiksSC5wdXNoKEspLGQ9MDtKPmQ7ZCsrKUgucHVzaChLKyspO0gucHVzaChLLTEpfX0sYi5XZWJHTEdyYXBoaWNzLmJ1aWxkQ29tcGxleFBvbHk9ZnVuY3Rpb24oYSxjKXt2YXIgZD1hLnBvaW50cy5zbGljZSgpO2lmKCEoZC5sZW5ndGg8Nikpe3ZhciBlPWMuaW5kaWNlcztjLnBvaW50cz1kLGMuYWxwaGE9YS5maWxsQWxwaGEsYy5jb2xvcj1iLmhleDJyZ2IoYS5maWxsQ29sb3IpO2Zvcih2YXIgZixnLGg9MS8wLGk9LTEvMCxqPTEvMCxrPS0xLzAsbD0wO2w8ZC5sZW5ndGg7bCs9MilmPWRbbF0sZz1kW2wrMV0saD1oPmY/ZjpoLGk9Zj5pP2Y6aSxqPWo+Zz9nOmosaz1nPms/ZzprO2QucHVzaChoLGosaSxqLGksayxoLGspO3ZhciBtPWQubGVuZ3RoLzI7Zm9yKGw9MDttPmw7bCsrKWUucHVzaChsKX19LGIuV2ViR0xHcmFwaGljcy5idWlsZFBvbHk9ZnVuY3Rpb24oYSxjKXt2YXIgZD1hLnBvaW50cztpZighKGQubGVuZ3RoPDYpKXt2YXIgZT1jLnBvaW50cyxmPWMuaW5kaWNlcyxnPWQubGVuZ3RoLzIsaD1iLmhleDJyZ2IoYS5maWxsQ29sb3IpLGk9YS5maWxsQWxwaGEsaj1oWzBdKmksaz1oWzFdKmksbD1oWzJdKmksbT1iLlBvbHlLLlRyaWFuZ3VsYXRlKGQpO2lmKCFtKXJldHVybiExO3ZhciBuPWUubGVuZ3RoLzYsbz0wO2ZvcihvPTA7bzxtLmxlbmd0aDtvKz0zKWYucHVzaChtW29dK24pLGYucHVzaChtW29dK24pLGYucHVzaChtW28rMV0rbiksZi5wdXNoKG1bbysyXStuKSxmLnB1c2gobVtvKzJdK24pO2ZvcihvPTA7Zz5vO28rKyllLnB1c2goZFsyKm9dLGRbMipvKzFdLGosayxsLGkpO3JldHVybiEwfX0sYi5XZWJHTEdyYXBoaWNzLmdyYXBoaWNzRGF0YVBvb2w9W10sYi5XZWJHTEdyYXBoaWNzRGF0YT1mdW5jdGlvbihhKXt0aGlzLmdsPWEsdGhpcy5jb2xvcj1bMCwwLDBdLHRoaXMucG9pbnRzPVtdLHRoaXMuaW5kaWNlcz1bXSx0aGlzLmJ1ZmZlcj1hLmNyZWF0ZUJ1ZmZlcigpLHRoaXMuaW5kZXhCdWZmZXI9YS5jcmVhdGVCdWZmZXIoKSx0aGlzLm1vZGU9MSx0aGlzLmFscGhhPTEsdGhpcy5kaXJ0eT0hMH0sYi5XZWJHTEdyYXBoaWNzRGF0YS5wcm90b3R5cGUucmVzZXQ9ZnVuY3Rpb24oKXt0aGlzLnBvaW50cz1bXSx0aGlzLmluZGljZXM9W119LGIuV2ViR0xHcmFwaGljc0RhdGEucHJvdG90eXBlLnVwbG9hZD1mdW5jdGlvbigpe3ZhciBhPXRoaXMuZ2w7dGhpcy5nbFBvaW50cz1uZXcgYi5GbG9hdDMyQXJyYXkodGhpcy5wb2ludHMpLGEuYmluZEJ1ZmZlcihhLkFSUkFZX0JVRkZFUix0aGlzLmJ1ZmZlciksYS5idWZmZXJEYXRhKGEuQVJSQVlfQlVGRkVSLHRoaXMuZ2xQb2ludHMsYS5TVEFUSUNfRFJBVyksdGhpcy5nbEluZGljaWVzPW5ldyBiLlVpbnQxNkFycmF5KHRoaXMuaW5kaWNlcyksYS5iaW5kQnVmZmVyKGEuRUxFTUVOVF9BUlJBWV9CVUZGRVIsdGhpcy5pbmRleEJ1ZmZlciksYS5idWZmZXJEYXRhKGEuRUxFTUVOVF9BUlJBWV9CVUZGRVIsdGhpcy5nbEluZGljaWVzLGEuU1RBVElDX0RSQVcpLHRoaXMuZGlydHk9ITF9LGIuZ2xDb250ZXh0cz1bXSxiLmluc3RhbmNlcz1bXSxiLldlYkdMUmVuZGVyZXI9ZnVuY3Rpb24oYSxjLGQpe2lmKGQpZm9yKHZhciBlIGluIGIuZGVmYXVsdFJlbmRlck9wdGlvbnMpXCJ1bmRlZmluZWRcIj09dHlwZW9mIGRbZV0mJihkW2VdPWIuZGVmYXVsdFJlbmRlck9wdGlvbnNbZV0pO2Vsc2UgZD1iLmRlZmF1bHRSZW5kZXJPcHRpb25zO2IuZGVmYXVsdFJlbmRlcmVyfHwoYi5zYXlIZWxsbyhcIndlYkdMXCIpLGIuZGVmYXVsdFJlbmRlcmVyPXRoaXMpLHRoaXMudHlwZT1iLldFQkdMX1JFTkRFUkVSLHRoaXMucmVzb2x1dGlvbj1kLnJlc29sdXRpb24sdGhpcy50cmFuc3BhcmVudD1kLnRyYW5zcGFyZW50LHRoaXMuYXV0b1Jlc2l6ZT1kLmF1dG9SZXNpemV8fCExLHRoaXMucHJlc2VydmVEcmF3aW5nQnVmZmVyPWQucHJlc2VydmVEcmF3aW5nQnVmZmVyLHRoaXMuY2xlYXJCZWZvcmVSZW5kZXI9ZC5jbGVhckJlZm9yZVJlbmRlcix0aGlzLndpZHRoPWF8fDgwMCx0aGlzLmhlaWdodD1jfHw2MDAsdGhpcy52aWV3PWQudmlld3x8ZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImNhbnZhc1wiKSx0aGlzLmNvbnRleHRMb3N0Qm91bmQ9dGhpcy5oYW5kbGVDb250ZXh0TG9zdC5iaW5kKHRoaXMpLHRoaXMuY29udGV4dFJlc3RvcmVkQm91bmQ9dGhpcy5oYW5kbGVDb250ZXh0UmVzdG9yZWQuYmluZCh0aGlzKSx0aGlzLnZpZXcuYWRkRXZlbnRMaXN0ZW5lcihcIndlYmdsY29udGV4dGxvc3RcIix0aGlzLmNvbnRleHRMb3N0Qm91bmQsITEpLHRoaXMudmlldy5hZGRFdmVudExpc3RlbmVyKFwid2ViZ2xjb250ZXh0cmVzdG9yZWRcIix0aGlzLmNvbnRleHRSZXN0b3JlZEJvdW5kLCExKSx0aGlzLl9jb250ZXh0T3B0aW9ucz17YWxwaGE6dGhpcy50cmFuc3BhcmVudCxhbnRpYWxpYXM6ZC5hbnRpYWxpYXMscHJlbXVsdGlwbGllZEFscGhhOnRoaXMudHJhbnNwYXJlbnQmJlwibm90TXVsdGlwbGllZFwiIT09dGhpcy50cmFuc3BhcmVudCxzdGVuY2lsOiEwLHByZXNlcnZlRHJhd2luZ0J1ZmZlcjpkLnByZXNlcnZlRHJhd2luZ0J1ZmZlcn0sdGhpcy5wcm9qZWN0aW9uPW5ldyBiLlBvaW50LHRoaXMub2Zmc2V0PW5ldyBiLlBvaW50KDAsMCksdGhpcy5zaGFkZXJNYW5hZ2VyPW5ldyBiLldlYkdMU2hhZGVyTWFuYWdlcix0aGlzLnNwcml0ZUJhdGNoPW5ldyBiLldlYkdMU3ByaXRlQmF0Y2gsdGhpcy5tYXNrTWFuYWdlcj1uZXcgYi5XZWJHTE1hc2tNYW5hZ2VyLHRoaXMuZmlsdGVyTWFuYWdlcj1uZXcgYi5XZWJHTEZpbHRlck1hbmFnZXIsdGhpcy5zdGVuY2lsTWFuYWdlcj1uZXcgYi5XZWJHTFN0ZW5jaWxNYW5hZ2VyLHRoaXMuYmxlbmRNb2RlTWFuYWdlcj1uZXcgYi5XZWJHTEJsZW5kTW9kZU1hbmFnZXIsdGhpcy5yZW5kZXJTZXNzaW9uPXt9LHRoaXMucmVuZGVyU2Vzc2lvbi5nbD10aGlzLmdsLHRoaXMucmVuZGVyU2Vzc2lvbi5kcmF3Q291bnQ9MCx0aGlzLnJlbmRlclNlc3Npb24uc2hhZGVyTWFuYWdlcj10aGlzLnNoYWRlck1hbmFnZXIsdGhpcy5yZW5kZXJTZXNzaW9uLm1hc2tNYW5hZ2VyPXRoaXMubWFza01hbmFnZXIsdGhpcy5yZW5kZXJTZXNzaW9uLmZpbHRlck1hbmFnZXI9dGhpcy5maWx0ZXJNYW5hZ2VyLHRoaXMucmVuZGVyU2Vzc2lvbi5ibGVuZE1vZGVNYW5hZ2VyPXRoaXMuYmxlbmRNb2RlTWFuYWdlcix0aGlzLnJlbmRlclNlc3Npb24uc3ByaXRlQmF0Y2g9dGhpcy5zcHJpdGVCYXRjaCx0aGlzLnJlbmRlclNlc3Npb24uc3RlbmNpbE1hbmFnZXI9dGhpcy5zdGVuY2lsTWFuYWdlcix0aGlzLnJlbmRlclNlc3Npb24ucmVuZGVyZXI9dGhpcyx0aGlzLnJlbmRlclNlc3Npb24ucmVzb2x1dGlvbj10aGlzLnJlc29sdXRpb24sdGhpcy5pbml0Q29udGV4dCgpLHRoaXMubWFwQmxlbmRNb2RlcygpfSxiLldlYkdMUmVuZGVyZXIucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuV2ViR0xSZW5kZXJlcixiLldlYkdMUmVuZGVyZXIucHJvdG90eXBlLmluaXRDb250ZXh0PWZ1bmN0aW9uKCl7dmFyIGE9dGhpcy52aWV3LmdldENvbnRleHQoXCJ3ZWJnbFwiLHRoaXMuX2NvbnRleHRPcHRpb25zKXx8dGhpcy52aWV3LmdldENvbnRleHQoXCJleHBlcmltZW50YWwtd2ViZ2xcIix0aGlzLl9jb250ZXh0T3B0aW9ucyk7aWYodGhpcy5nbD1hLCFhKXRocm93IG5ldyBFcnJvcihcIlRoaXMgYnJvd3NlciBkb2VzIG5vdCBzdXBwb3J0IHdlYkdMLiBUcnkgdXNpbmcgdGhlIGNhbnZhcyByZW5kZXJlclwiKTt0aGlzLmdsQ29udGV4dElkPWEuaWQ9Yi5XZWJHTFJlbmRlcmVyLmdsQ29udGV4dElkKyssYi5nbENvbnRleHRzW3RoaXMuZ2xDb250ZXh0SWRdPWEsYi5pbnN0YW5jZXNbdGhpcy5nbENvbnRleHRJZF09dGhpcyxhLmRpc2FibGUoYS5ERVBUSF9URVNUKSxhLmRpc2FibGUoYS5DVUxMX0ZBQ0UpLGEuZW5hYmxlKGEuQkxFTkQpLHRoaXMuc2hhZGVyTWFuYWdlci5zZXRDb250ZXh0KGEpLHRoaXMuc3ByaXRlQmF0Y2guc2V0Q29udGV4dChhKSx0aGlzLm1hc2tNYW5hZ2VyLnNldENvbnRleHQoYSksdGhpcy5maWx0ZXJNYW5hZ2VyLnNldENvbnRleHQoYSksdGhpcy5ibGVuZE1vZGVNYW5hZ2VyLnNldENvbnRleHQoYSksdGhpcy5zdGVuY2lsTWFuYWdlci5zZXRDb250ZXh0KGEpLHRoaXMucmVuZGVyU2Vzc2lvbi5nbD10aGlzLmdsLHRoaXMucmVzaXplKHRoaXMud2lkdGgsdGhpcy5oZWlnaHQpfSxiLldlYkdMUmVuZGVyZXIucHJvdG90eXBlLnJlbmRlcj1mdW5jdGlvbihhKXtpZighdGhpcy5jb250ZXh0TG9zdCl7dGhpcy5fX3N0YWdlIT09YSYmKGEuaW50ZXJhY3RpdmUmJmEuaW50ZXJhY3Rpb25NYW5hZ2VyLnJlbW92ZUV2ZW50cygpLHRoaXMuX19zdGFnZT1hKSxhLnVwZGF0ZVRyYW5zZm9ybSgpO3ZhciBiPXRoaXMuZ2w7YS5faW50ZXJhY3RpdmU/YS5faW50ZXJhY3RpdmVFdmVudHNBZGRlZHx8KGEuX2ludGVyYWN0aXZlRXZlbnRzQWRkZWQ9ITAsYS5pbnRlcmFjdGlvbk1hbmFnZXIuc2V0VGFyZ2V0KHRoaXMpKTphLl9pbnRlcmFjdGl2ZUV2ZW50c0FkZGVkJiYoYS5faW50ZXJhY3RpdmVFdmVudHNBZGRlZD0hMSxhLmludGVyYWN0aW9uTWFuYWdlci5zZXRUYXJnZXQodGhpcykpLGIudmlld3BvcnQoMCwwLHRoaXMud2lkdGgsdGhpcy5oZWlnaHQpLGIuYmluZEZyYW1lYnVmZmVyKGIuRlJBTUVCVUZGRVIsbnVsbCksdGhpcy5jbGVhckJlZm9yZVJlbmRlciYmKHRoaXMudHJhbnNwYXJlbnQ/Yi5jbGVhckNvbG9yKDAsMCwwLDApOmIuY2xlYXJDb2xvcihhLmJhY2tncm91bmRDb2xvclNwbGl0WzBdLGEuYmFja2dyb3VuZENvbG9yU3BsaXRbMV0sYS5iYWNrZ3JvdW5kQ29sb3JTcGxpdFsyXSwxKSxiLmNsZWFyKGIuQ09MT1JfQlVGRkVSX0JJVCkpLHRoaXMucmVuZGVyRGlzcGxheU9iamVjdChhLHRoaXMucHJvamVjdGlvbil9fSxiLldlYkdMUmVuZGVyZXIucHJvdG90eXBlLnJlbmRlckRpc3BsYXlPYmplY3Q9ZnVuY3Rpb24oYSxjLGQpe3RoaXMucmVuZGVyU2Vzc2lvbi5ibGVuZE1vZGVNYW5hZ2VyLnNldEJsZW5kTW9kZShiLmJsZW5kTW9kZXMuTk9STUFMKSx0aGlzLnJlbmRlclNlc3Npb24uZHJhd0NvdW50PTAsdGhpcy5yZW5kZXJTZXNzaW9uLmZsaXBZPWQ/LTE6MSx0aGlzLnJlbmRlclNlc3Npb24ucHJvamVjdGlvbj1jLHRoaXMucmVuZGVyU2Vzc2lvbi5vZmZzZXQ9dGhpcy5vZmZzZXQsdGhpcy5zcHJpdGVCYXRjaC5iZWdpbih0aGlzLnJlbmRlclNlc3Npb24pLHRoaXMuZmlsdGVyTWFuYWdlci5iZWdpbih0aGlzLnJlbmRlclNlc3Npb24sZCksYS5fcmVuZGVyV2ViR0wodGhpcy5yZW5kZXJTZXNzaW9uKSx0aGlzLnNwcml0ZUJhdGNoLmVuZCgpfSxiLldlYkdMUmVuZGVyZXIucHJvdG90eXBlLnJlc2l6ZT1mdW5jdGlvbihhLGIpe3RoaXMud2lkdGg9YSp0aGlzLnJlc29sdXRpb24sdGhpcy5oZWlnaHQ9Yip0aGlzLnJlc29sdXRpb24sdGhpcy52aWV3LndpZHRoPXRoaXMud2lkdGgsdGhpcy52aWV3LmhlaWdodD10aGlzLmhlaWdodCx0aGlzLmF1dG9SZXNpemUmJih0aGlzLnZpZXcuc3R5bGUud2lkdGg9dGhpcy53aWR0aC90aGlzLnJlc29sdXRpb24rXCJweFwiLHRoaXMudmlldy5zdHlsZS5oZWlnaHQ9dGhpcy5oZWlnaHQvdGhpcy5yZXNvbHV0aW9uK1wicHhcIiksdGhpcy5nbC52aWV3cG9ydCgwLDAsdGhpcy53aWR0aCx0aGlzLmhlaWdodCksdGhpcy5wcm9qZWN0aW9uLng9dGhpcy53aWR0aC8yL3RoaXMucmVzb2x1dGlvbix0aGlzLnByb2plY3Rpb24ueT0tdGhpcy5oZWlnaHQvMi90aGlzLnJlc29sdXRpb259LGIuV2ViR0xSZW5kZXJlci5wcm90b3R5cGUudXBkYXRlVGV4dHVyZT1mdW5jdGlvbihhKXtpZihhLmhhc0xvYWRlZCl7dmFyIGM9dGhpcy5nbDtyZXR1cm4gYS5fZ2xUZXh0dXJlc1tjLmlkXXx8KGEuX2dsVGV4dHVyZXNbYy5pZF09Yy5jcmVhdGVUZXh0dXJlKCkpLGMuYmluZFRleHR1cmUoYy5URVhUVVJFXzJELGEuX2dsVGV4dHVyZXNbYy5pZF0pLGMucGl4ZWxTdG9yZWkoYy5VTlBBQ0tfUFJFTVVMVElQTFlfQUxQSEFfV0VCR0wsYS5wcmVtdWx0aXBsaWVkQWxwaGEpLGMudGV4SW1hZ2UyRChjLlRFWFRVUkVfMkQsMCxjLlJHQkEsYy5SR0JBLGMuVU5TSUdORURfQllURSxhLnNvdXJjZSksYy50ZXhQYXJhbWV0ZXJpKGMuVEVYVFVSRV8yRCxjLlRFWFRVUkVfTUFHX0ZJTFRFUixhLnNjYWxlTW9kZT09PWIuc2NhbGVNb2Rlcy5MSU5FQVI/Yy5MSU5FQVI6Yy5ORUFSRVNUKSxhLm1pcG1hcCYmYi5pc1Bvd2VyT2ZUd28oYS53aWR0aCxhLmhlaWdodCk/KGMudGV4UGFyYW1ldGVyaShjLlRFWFRVUkVfMkQsYy5URVhUVVJFX01JTl9GSUxURVIsYS5zY2FsZU1vZGU9PT1iLnNjYWxlTW9kZXMuTElORUFSP2MuTElORUFSX01JUE1BUF9MSU5FQVI6Yy5ORUFSRVNUX01JUE1BUF9ORUFSRVNUKSxjLmdlbmVyYXRlTWlwbWFwKGMuVEVYVFVSRV8yRCkpOmMudGV4UGFyYW1ldGVyaShjLlRFWFRVUkVfMkQsYy5URVhUVVJFX01JTl9GSUxURVIsYS5zY2FsZU1vZGU9PT1iLnNjYWxlTW9kZXMuTElORUFSP2MuTElORUFSOmMuTkVBUkVTVCksYS5fcG93ZXJPZjI/KGMudGV4UGFyYW1ldGVyaShjLlRFWFRVUkVfMkQsYy5URVhUVVJFX1dSQVBfUyxjLlJFUEVBVCksYy50ZXhQYXJhbWV0ZXJpKGMuVEVYVFVSRV8yRCxjLlRFWFRVUkVfV1JBUF9ULGMuUkVQRUFUKSk6KGMudGV4UGFyYW1ldGVyaShjLlRFWFRVUkVfMkQsYy5URVhUVVJFX1dSQVBfUyxjLkNMQU1QX1RPX0VER0UpLGMudGV4UGFyYW1ldGVyaShjLlRFWFRVUkVfMkQsYy5URVhUVVJFX1dSQVBfVCxjLkNMQU1QX1RPX0VER0UpKSxhLl9kaXJ0eVtjLmlkXT0hMSxhLl9nbFRleHR1cmVzW2MuaWRdfX0sYi5XZWJHTFJlbmRlcmVyLnByb3RvdHlwZS5oYW5kbGVDb250ZXh0TG9zdD1mdW5jdGlvbihhKXthLnByZXZlbnREZWZhdWx0KCksdGhpcy5jb250ZXh0TG9zdD0hMH0sYi5XZWJHTFJlbmRlcmVyLnByb3RvdHlwZS5oYW5kbGVDb250ZXh0UmVzdG9yZWQ9ZnVuY3Rpb24oKXt0aGlzLmluaXRDb250ZXh0KCk7Zm9yKHZhciBhIGluIGIuVGV4dHVyZUNhY2hlKXt2YXIgYz1iLlRleHR1cmVDYWNoZVthXS5iYXNlVGV4dHVyZTtjLl9nbFRleHR1cmVzPVtdfXRoaXMuY29udGV4dExvc3Q9ITF9LGIuV2ViR0xSZW5kZXJlci5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe3RoaXMudmlldy5yZW1vdmVFdmVudExpc3RlbmVyKFwid2ViZ2xjb250ZXh0bG9zdFwiLHRoaXMuY29udGV4dExvc3RCb3VuZCksdGhpcy52aWV3LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJ3ZWJnbGNvbnRleHRyZXN0b3JlZFwiLHRoaXMuY29udGV4dFJlc3RvcmVkQm91bmQpLGIuZ2xDb250ZXh0c1t0aGlzLmdsQ29udGV4dElkXT1udWxsLHRoaXMucHJvamVjdGlvbj1udWxsLHRoaXMub2Zmc2V0PW51bGwsdGhpcy5zaGFkZXJNYW5hZ2VyLmRlc3Ryb3koKSx0aGlzLnNwcml0ZUJhdGNoLmRlc3Ryb3koKSx0aGlzLm1hc2tNYW5hZ2VyLmRlc3Ryb3koKSx0aGlzLmZpbHRlck1hbmFnZXIuZGVzdHJveSgpLHRoaXMuc2hhZGVyTWFuYWdlcj1udWxsLHRoaXMuc3ByaXRlQmF0Y2g9bnVsbCx0aGlzLm1hc2tNYW5hZ2VyPW51bGwsdGhpcy5maWx0ZXJNYW5hZ2VyPW51bGwsdGhpcy5nbD1udWxsLHRoaXMucmVuZGVyU2Vzc2lvbj1udWxsfSxiLldlYkdMUmVuZGVyZXIucHJvdG90eXBlLm1hcEJsZW5kTW9kZXM9ZnVuY3Rpb24oKXt2YXIgYT10aGlzLmdsO2IuYmxlbmRNb2Rlc1dlYkdMfHwoYi5ibGVuZE1vZGVzV2ViR0w9W10sYi5ibGVuZE1vZGVzV2ViR0xbYi5ibGVuZE1vZGVzLk5PUk1BTF09W2EuT05FLGEuT05FX01JTlVTX1NSQ19BTFBIQV0sYi5ibGVuZE1vZGVzV2ViR0xbYi5ibGVuZE1vZGVzLkFERF09W2EuU1JDX0FMUEhBLGEuRFNUX0FMUEhBXSxiLmJsZW5kTW9kZXNXZWJHTFtiLmJsZW5kTW9kZXMuTVVMVElQTFldPVthLkRTVF9DT0xPUixhLk9ORV9NSU5VU19TUkNfQUxQSEFdLGIuYmxlbmRNb2Rlc1dlYkdMW2IuYmxlbmRNb2Rlcy5TQ1JFRU5dPVthLlNSQ19BTFBIQSxhLk9ORV0sYi5ibGVuZE1vZGVzV2ViR0xbYi5ibGVuZE1vZGVzLk9WRVJMQVldPVthLk9ORSxhLk9ORV9NSU5VU19TUkNfQUxQSEFdLGIuYmxlbmRNb2Rlc1dlYkdMW2IuYmxlbmRNb2Rlcy5EQVJLRU5dPVthLk9ORSxhLk9ORV9NSU5VU19TUkNfQUxQSEFdLGIuYmxlbmRNb2Rlc1dlYkdMW2IuYmxlbmRNb2Rlcy5MSUdIVEVOXT1bYS5PTkUsYS5PTkVfTUlOVVNfU1JDX0FMUEhBXSxiLmJsZW5kTW9kZXNXZWJHTFtiLmJsZW5kTW9kZXMuQ09MT1JfRE9ER0VdPVthLk9ORSxhLk9ORV9NSU5VU19TUkNfQUxQSEFdLGIuYmxlbmRNb2Rlc1dlYkdMW2IuYmxlbmRNb2Rlcy5DT0xPUl9CVVJOXT1bYS5PTkUsYS5PTkVfTUlOVVNfU1JDX0FMUEhBXSxiLmJsZW5kTW9kZXNXZWJHTFtiLmJsZW5kTW9kZXMuSEFSRF9MSUdIVF09W2EuT05FLGEuT05FX01JTlVTX1NSQ19BTFBIQV0sYi5ibGVuZE1vZGVzV2ViR0xbYi5ibGVuZE1vZGVzLlNPRlRfTElHSFRdPVthLk9ORSxhLk9ORV9NSU5VU19TUkNfQUxQSEFdLGIuYmxlbmRNb2Rlc1dlYkdMW2IuYmxlbmRNb2Rlcy5ESUZGRVJFTkNFXT1bYS5PTkUsYS5PTkVfTUlOVVNfU1JDX0FMUEhBXSxiLmJsZW5kTW9kZXNXZWJHTFtiLmJsZW5kTW9kZXMuRVhDTFVTSU9OXT1bYS5PTkUsYS5PTkVfTUlOVVNfU1JDX0FMUEhBXSxiLmJsZW5kTW9kZXNXZWJHTFtiLmJsZW5kTW9kZXMuSFVFXT1bYS5PTkUsYS5PTkVfTUlOVVNfU1JDX0FMUEhBXSxiLmJsZW5kTW9kZXNXZWJHTFtiLmJsZW5kTW9kZXMuU0FUVVJBVElPTl09W2EuT05FLGEuT05FX01JTlVTX1NSQ19BTFBIQV0sYi5ibGVuZE1vZGVzV2ViR0xbYi5ibGVuZE1vZGVzLkNPTE9SXT1bYS5PTkUsYS5PTkVfTUlOVVNfU1JDX0FMUEhBXSxiLmJsZW5kTW9kZXNXZWJHTFtiLmJsZW5kTW9kZXMuTFVNSU5PU0lUWV09W2EuT05FLGEuT05FX01JTlVTX1NSQ19BTFBIQV0pfSxiLldlYkdMUmVuZGVyZXIuZ2xDb250ZXh0SWQ9MCxiLldlYkdMQmxlbmRNb2RlTWFuYWdlcj1mdW5jdGlvbigpe3RoaXMuY3VycmVudEJsZW5kTW9kZT05OTk5OX0sYi5XZWJHTEJsZW5kTW9kZU1hbmFnZXIucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuV2ViR0xCbGVuZE1vZGVNYW5hZ2VyLGIuV2ViR0xCbGVuZE1vZGVNYW5hZ2VyLnByb3RvdHlwZS5zZXRDb250ZXh0PWZ1bmN0aW9uKGEpe3RoaXMuZ2w9YX0sYi5XZWJHTEJsZW5kTW9kZU1hbmFnZXIucHJvdG90eXBlLnNldEJsZW5kTW9kZT1mdW5jdGlvbihhKXtpZih0aGlzLmN1cnJlbnRCbGVuZE1vZGU9PT1hKXJldHVybiExO3RoaXMuY3VycmVudEJsZW5kTW9kZT1hO3ZhciBjPWIuYmxlbmRNb2Rlc1dlYkdMW3RoaXMuY3VycmVudEJsZW5kTW9kZV07cmV0dXJuIHRoaXMuZ2wuYmxlbmRGdW5jKGNbMF0sY1sxXSksITB9LGIuV2ViR0xCbGVuZE1vZGVNYW5hZ2VyLnByb3RvdHlwZS5kZXN0cm95PWZ1bmN0aW9uKCl7dGhpcy5nbD1udWxsfSxiLldlYkdMTWFza01hbmFnZXI9ZnVuY3Rpb24oKXt9LGIuV2ViR0xNYXNrTWFuYWdlci5wcm90b3R5cGUuY29uc3RydWN0b3I9Yi5XZWJHTE1hc2tNYW5hZ2VyLGIuV2ViR0xNYXNrTWFuYWdlci5wcm90b3R5cGUuc2V0Q29udGV4dD1mdW5jdGlvbihhKXt0aGlzLmdsPWF9LGIuV2ViR0xNYXNrTWFuYWdlci5wcm90b3R5cGUucHVzaE1hc2s9ZnVuY3Rpb24oYSxjKXt2YXIgZD1jLmdsO2EuZGlydHkmJmIuV2ViR0xHcmFwaGljcy51cGRhdGVHcmFwaGljcyhhLGQpLGEuX3dlYkdMW2QuaWRdLmRhdGEubGVuZ3RoJiZjLnN0ZW5jaWxNYW5hZ2VyLnB1c2hTdGVuY2lsKGEsYS5fd2ViR0xbZC5pZF0uZGF0YVswXSxjKX0sYi5XZWJHTE1hc2tNYW5hZ2VyLnByb3RvdHlwZS5wb3BNYXNrPWZ1bmN0aW9uKGEsYil7dmFyIGM9dGhpcy5nbDtiLnN0ZW5jaWxNYW5hZ2VyLnBvcFN0ZW5jaWwoYSxhLl93ZWJHTFtjLmlkXS5kYXRhWzBdLGIpfSxiLldlYkdMTWFza01hbmFnZXIucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oKXt0aGlzLmdsPW51bGx9LGIuV2ViR0xTdGVuY2lsTWFuYWdlcj1mdW5jdGlvbigpe3RoaXMuc3RlbmNpbFN0YWNrPVtdLHRoaXMucmV2ZXJzZT0hMCx0aGlzLmNvdW50PTB9LGIuV2ViR0xTdGVuY2lsTWFuYWdlci5wcm90b3R5cGUuc2V0Q29udGV4dD1mdW5jdGlvbihhKXt0aGlzLmdsPWF9LGIuV2ViR0xTdGVuY2lsTWFuYWdlci5wcm90b3R5cGUucHVzaFN0ZW5jaWw9ZnVuY3Rpb24oYSxiLGMpe3ZhciBkPXRoaXMuZ2w7dGhpcy5iaW5kR3JhcGhpY3MoYSxiLGMpLDA9PT10aGlzLnN0ZW5jaWxTdGFjay5sZW5ndGgmJihkLmVuYWJsZShkLlNURU5DSUxfVEVTVCksZC5jbGVhcihkLlNURU5DSUxfQlVGRkVSX0JJVCksdGhpcy5yZXZlcnNlPSEwLHRoaXMuY291bnQ9MCksdGhpcy5zdGVuY2lsU3RhY2sucHVzaChiKTt2YXIgZT10aGlzLmNvdW50O2QuY29sb3JNYXNrKCExLCExLCExLCExKSxkLnN0ZW5jaWxGdW5jKGQuQUxXQVlTLDAsMjU1KSxkLnN0ZW5jaWxPcChkLktFRVAsZC5LRUVQLGQuSU5WRVJUKSwxPT09Yi5tb2RlPyhkLmRyYXdFbGVtZW50cyhkLlRSSUFOR0xFX0ZBTixiLmluZGljZXMubGVuZ3RoLTQsZC5VTlNJR05FRF9TSE9SVCwwKSx0aGlzLnJldmVyc2U/KGQuc3RlbmNpbEZ1bmMoZC5FUVVBTCwyNTUtZSwyNTUpLGQuc3RlbmNpbE9wKGQuS0VFUCxkLktFRVAsZC5ERUNSKSk6KGQuc3RlbmNpbEZ1bmMoZC5FUVVBTCxlLDI1NSksZC5zdGVuY2lsT3AoZC5LRUVQLGQuS0VFUCxkLklOQ1IpKSxkLmRyYXdFbGVtZW50cyhkLlRSSUFOR0xFX0ZBTiw0LGQuVU5TSUdORURfU0hPUlQsMiooYi5pbmRpY2VzLmxlbmd0aC00KSksdGhpcy5yZXZlcnNlP2Quc3RlbmNpbEZ1bmMoZC5FUVVBTCwyNTUtKGUrMSksMjU1KTpkLnN0ZW5jaWxGdW5jKGQuRVFVQUwsZSsxLDI1NSksdGhpcy5yZXZlcnNlPSF0aGlzLnJldmVyc2UpOih0aGlzLnJldmVyc2U/KGQuc3RlbmNpbEZ1bmMoZC5FUVVBTCxlLDI1NSksZC5zdGVuY2lsT3AoZC5LRUVQLGQuS0VFUCxkLklOQ1IpKTooZC5zdGVuY2lsRnVuYyhkLkVRVUFMLDI1NS1lLDI1NSksZC5zdGVuY2lsT3AoZC5LRUVQLGQuS0VFUCxkLkRFQ1IpKSxkLmRyYXdFbGVtZW50cyhkLlRSSUFOR0xFX1NUUklQLGIuaW5kaWNlcy5sZW5ndGgsZC5VTlNJR05FRF9TSE9SVCwwKSx0aGlzLnJldmVyc2U/ZC5zdGVuY2lsRnVuYyhkLkVRVUFMLGUrMSwyNTUpOmQuc3RlbmNpbEZ1bmMoZC5FUVVBTCwyNTUtKGUrMSksMjU1KSksZC5jb2xvck1hc2soITAsITAsITAsITApLGQuc3RlbmNpbE9wKGQuS0VFUCxkLktFRVAsZC5LRUVQKSx0aGlzLmNvdW50Kyt9LGIuV2ViR0xTdGVuY2lsTWFuYWdlci5wcm90b3R5cGUuYmluZEdyYXBoaWNzPWZ1bmN0aW9uKGEsYyxkKXt0aGlzLl9jdXJyZW50R3JhcGhpY3M9YTt2YXIgZSxmPXRoaXMuZ2wsZz1kLnByb2plY3Rpb24saD1kLm9mZnNldDsxPT09Yy5tb2RlPyhlPWQuc2hhZGVyTWFuYWdlci5jb21wbGV4UHJpbWl0aXZlU2hhZGVyLGQuc2hhZGVyTWFuYWdlci5zZXRTaGFkZXIoZSksZi51bmlmb3JtMWYoZS5mbGlwWSxkLmZsaXBZKSxmLnVuaWZvcm1NYXRyaXgzZnYoZS50cmFuc2xhdGlvbk1hdHJpeCwhMSxhLndvcmxkVHJhbnNmb3JtLnRvQXJyYXkoITApKSxmLnVuaWZvcm0yZihlLnByb2plY3Rpb25WZWN0b3IsZy54LC1nLnkpLGYudW5pZm9ybTJmKGUub2Zmc2V0VmVjdG9yLC1oLngsLWgueSksZi51bmlmb3JtM2Z2KGUudGludENvbG9yLGIuaGV4MnJnYihhLnRpbnQpKSxmLnVuaWZvcm0zZnYoZS5jb2xvcixjLmNvbG9yKSxmLnVuaWZvcm0xZihlLmFscGhhLGEud29ybGRBbHBoYSpjLmFscGhhKSxmLmJpbmRCdWZmZXIoZi5BUlJBWV9CVUZGRVIsYy5idWZmZXIpLGYudmVydGV4QXR0cmliUG9pbnRlcihlLmFWZXJ0ZXhQb3NpdGlvbiwyLGYuRkxPQVQsITEsOCwwKSxmLmJpbmRCdWZmZXIoZi5FTEVNRU5UX0FSUkFZX0JVRkZFUixjLmluZGV4QnVmZmVyKSk6KGU9ZC5zaGFkZXJNYW5hZ2VyLnByaW1pdGl2ZVNoYWRlcixkLnNoYWRlck1hbmFnZXIuc2V0U2hhZGVyKGUpLGYudW5pZm9ybU1hdHJpeDNmdihlLnRyYW5zbGF0aW9uTWF0cml4LCExLGEud29ybGRUcmFuc2Zvcm0udG9BcnJheSghMCkpLGYudW5pZm9ybTFmKGUuZmxpcFksZC5mbGlwWSksZi51bmlmb3JtMmYoZS5wcm9qZWN0aW9uVmVjdG9yLGcueCwtZy55KSxmLnVuaWZvcm0yZihlLm9mZnNldFZlY3RvciwtaC54LC1oLnkpLGYudW5pZm9ybTNmdihlLnRpbnRDb2xvcixiLmhleDJyZ2IoYS50aW50KSksZi51bmlmb3JtMWYoZS5hbHBoYSxhLndvcmxkQWxwaGEpLGYuYmluZEJ1ZmZlcihmLkFSUkFZX0JVRkZFUixjLmJ1ZmZlciksZi52ZXJ0ZXhBdHRyaWJQb2ludGVyKGUuYVZlcnRleFBvc2l0aW9uLDIsZi5GTE9BVCwhMSwyNCwwKSxmLnZlcnRleEF0dHJpYlBvaW50ZXIoZS5jb2xvckF0dHJpYnV0ZSw0LGYuRkxPQVQsITEsMjQsOCksZi5iaW5kQnVmZmVyKGYuRUxFTUVOVF9BUlJBWV9CVUZGRVIsYy5pbmRleEJ1ZmZlcikpfSxiLldlYkdMU3RlbmNpbE1hbmFnZXIucHJvdG90eXBlLnBvcFN0ZW5jaWw9ZnVuY3Rpb24oYSxiLGMpe3ZhciBkPXRoaXMuZ2w7aWYodGhpcy5zdGVuY2lsU3RhY2sucG9wKCksdGhpcy5jb3VudC0tLDA9PT10aGlzLnN0ZW5jaWxTdGFjay5sZW5ndGgpZC5kaXNhYmxlKGQuU1RFTkNJTF9URVNUKTtlbHNle3ZhciBlPXRoaXMuY291bnQ7dGhpcy5iaW5kR3JhcGhpY3MoYSxiLGMpLGQuY29sb3JNYXNrKCExLCExLCExLCExKSwxPT09Yi5tb2RlPyh0aGlzLnJldmVyc2U9IXRoaXMucmV2ZXJzZSx0aGlzLnJldmVyc2U/KGQuc3RlbmNpbEZ1bmMoZC5FUVVBTCwyNTUtKGUrMSksMjU1KSxkLnN0ZW5jaWxPcChkLktFRVAsZC5LRUVQLGQuSU5DUikpOihkLnN0ZW5jaWxGdW5jKGQuRVFVQUwsZSsxLDI1NSksZC5zdGVuY2lsT3AoZC5LRUVQLGQuS0VFUCxkLkRFQ1IpKSxkLmRyYXdFbGVtZW50cyhkLlRSSUFOR0xFX0ZBTiw0LGQuVU5TSUdORURfU0hPUlQsMiooYi5pbmRpY2VzLmxlbmd0aC00KSksZC5zdGVuY2lsRnVuYyhkLkFMV0FZUywwLDI1NSksZC5zdGVuY2lsT3AoZC5LRUVQLGQuS0VFUCxkLklOVkVSVCksZC5kcmF3RWxlbWVudHMoZC5UUklBTkdMRV9GQU4sYi5pbmRpY2VzLmxlbmd0aC00LGQuVU5TSUdORURfU0hPUlQsMCksdGhpcy5yZXZlcnNlP2Quc3RlbmNpbEZ1bmMoZC5FUVVBTCxlLDI1NSk6ZC5zdGVuY2lsRnVuYyhkLkVRVUFMLDI1NS1lLDI1NSkpOih0aGlzLnJldmVyc2U/KGQuc3RlbmNpbEZ1bmMoZC5FUVVBTCxlKzEsMjU1KSxkLnN0ZW5jaWxPcChkLktFRVAsZC5LRUVQLGQuREVDUikpOihkLnN0ZW5jaWxGdW5jKGQuRVFVQUwsMjU1LShlKzEpLDI1NSksZC5zdGVuY2lsT3AoZC5LRUVQLGQuS0VFUCxkLklOQ1IpKSxkLmRyYXdFbGVtZW50cyhkLlRSSUFOR0xFX1NUUklQLGIuaW5kaWNlcy5sZW5ndGgsZC5VTlNJR05FRF9TSE9SVCwwKSx0aGlzLnJldmVyc2U/ZC5zdGVuY2lsRnVuYyhkLkVRVUFMLGUsMjU1KTpkLnN0ZW5jaWxGdW5jKGQuRVFVQUwsMjU1LWUsMjU1KSksZC5jb2xvck1hc2soITAsITAsITAsITApLGQuc3RlbmNpbE9wKGQuS0VFUCxkLktFRVAsZC5LRUVQKX19LGIuV2ViR0xTdGVuY2lsTWFuYWdlci5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe3RoaXMuc3RlbmNpbFN0YWNrPW51bGwsdGhpcy5nbD1udWxsfSxiLldlYkdMU2hhZGVyTWFuYWdlcj1mdW5jdGlvbigpe3RoaXMubWF4QXR0aWJzPTEwLHRoaXMuYXR0cmliU3RhdGU9W10sdGhpcy50ZW1wQXR0cmliU3RhdGU9W107Zm9yKHZhciBhPTA7YTx0aGlzLm1heEF0dGliczthKyspdGhpcy5hdHRyaWJTdGF0ZVthXT0hMTt0aGlzLnN0YWNrPVtdfSxiLldlYkdMU2hhZGVyTWFuYWdlci5wcm90b3R5cGUuY29uc3RydWN0b3I9Yi5XZWJHTFNoYWRlck1hbmFnZXIsYi5XZWJHTFNoYWRlck1hbmFnZXIucHJvdG90eXBlLnNldENvbnRleHQ9ZnVuY3Rpb24oYSl7dGhpcy5nbD1hLHRoaXMucHJpbWl0aXZlU2hhZGVyPW5ldyBiLlByaW1pdGl2ZVNoYWRlcihhKSx0aGlzLmNvbXBsZXhQcmltaXRpdmVTaGFkZXI9bmV3IGIuQ29tcGxleFByaW1pdGl2ZVNoYWRlcihhKSx0aGlzLmRlZmF1bHRTaGFkZXI9bmV3IGIuUGl4aVNoYWRlcihhKSx0aGlzLmZhc3RTaGFkZXI9bmV3IGIuUGl4aUZhc3RTaGFkZXIoYSksdGhpcy5zdHJpcFNoYWRlcj1uZXcgYi5TdHJpcFNoYWRlcihhKSx0aGlzLnNldFNoYWRlcih0aGlzLmRlZmF1bHRTaGFkZXIpfSxiLldlYkdMU2hhZGVyTWFuYWdlci5wcm90b3R5cGUuc2V0QXR0cmlicz1mdW5jdGlvbihhKXt2YXIgYjtmb3IoYj0wO2I8dGhpcy50ZW1wQXR0cmliU3RhdGUubGVuZ3RoO2IrKyl0aGlzLnRlbXBBdHRyaWJTdGF0ZVtiXT0hMTtmb3IoYj0wO2I8YS5sZW5ndGg7YisrKXt2YXIgYz1hW2JdO3RoaXMudGVtcEF0dHJpYlN0YXRlW2NdPSEwfXZhciBkPXRoaXMuZ2w7Zm9yKGI9MDtiPHRoaXMuYXR0cmliU3RhdGUubGVuZ3RoO2IrKyl0aGlzLmF0dHJpYlN0YXRlW2JdIT09dGhpcy50ZW1wQXR0cmliU3RhdGVbYl0mJih0aGlzLmF0dHJpYlN0YXRlW2JdPXRoaXMudGVtcEF0dHJpYlN0YXRlW2JdLHRoaXMudGVtcEF0dHJpYlN0YXRlW2JdP2QuZW5hYmxlVmVydGV4QXR0cmliQXJyYXkoYik6ZC5kaXNhYmxlVmVydGV4QXR0cmliQXJyYXkoYikpfSxiLldlYkdMU2hhZGVyTWFuYWdlci5wcm90b3R5cGUuc2V0U2hhZGVyPWZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLl9jdXJyZW50SWQ9PT1hLl9VSUQ/ITE6KHRoaXMuX2N1cnJlbnRJZD1hLl9VSUQsdGhpcy5jdXJyZW50U2hhZGVyPWEsdGhpcy5nbC51c2VQcm9ncmFtKGEucHJvZ3JhbSksdGhpcy5zZXRBdHRyaWJzKGEuYXR0cmlidXRlcyksITApfSxiLldlYkdMU2hhZGVyTWFuYWdlci5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe3RoaXMuYXR0cmliU3RhdGU9bnVsbCx0aGlzLnRlbXBBdHRyaWJTdGF0ZT1udWxsLHRoaXMucHJpbWl0aXZlU2hhZGVyLmRlc3Ryb3koKSx0aGlzLmNvbXBsZXhQcmltaXRpdmVTaGFkZXIuZGVzdHJveSgpLHRoaXMuZGVmYXVsdFNoYWRlci5kZXN0cm95KCksdGhpcy5mYXN0U2hhZGVyLmRlc3Ryb3koKSx0aGlzLnN0cmlwU2hhZGVyLmRlc3Ryb3koKSx0aGlzLmdsPW51bGx9LGIuV2ViR0xTcHJpdGVCYXRjaD1mdW5jdGlvbigpe3RoaXMudmVydFNpemU9NSx0aGlzLnNpemU9MmUzO3ZhciBhPTQqdGhpcy5zaXplKjQqdGhpcy52ZXJ0U2l6ZSxjPTYqdGhpcy5zaXplO3RoaXMudmVydGljZXM9bmV3IGIuQXJyYXlCdWZmZXIoYSksdGhpcy5wb3NpdGlvbnM9bmV3IGIuRmxvYXQzMkFycmF5KHRoaXMudmVydGljZXMpLHRoaXMuY29sb3JzPW5ldyBiLlVpbnQzMkFycmF5KHRoaXMudmVydGljZXMpLHRoaXMuaW5kaWNlcz1uZXcgYi5VaW50MTZBcnJheShjKSx0aGlzLmxhc3RJbmRleENvdW50PTA7Zm9yKHZhciBkPTAsZT0wO2M+ZDtkKz02LGUrPTQpdGhpcy5pbmRpY2VzW2QrMF09ZSswLHRoaXMuaW5kaWNlc1tkKzFdPWUrMSx0aGlzLmluZGljZXNbZCsyXT1lKzIsdGhpcy5pbmRpY2VzW2QrM109ZSswLHRoaXMuaW5kaWNlc1tkKzRdPWUrMix0aGlzLmluZGljZXNbZCs1XT1lKzM7dGhpcy5kcmF3aW5nPSExLHRoaXMuY3VycmVudEJhdGNoU2l6ZT0wLHRoaXMuY3VycmVudEJhc2VUZXh0dXJlPW51bGwsdGhpcy5kaXJ0eT0hMCx0aGlzLnRleHR1cmVzPVtdLHRoaXMuYmxlbmRNb2Rlcz1bXSx0aGlzLnNoYWRlcnM9W10sdGhpcy5zcHJpdGVzPVtdLHRoaXMuZGVmYXVsdFNoYWRlcj1uZXcgYi5BYnN0cmFjdEZpbHRlcihbXCJwcmVjaXNpb24gbG93cCBmbG9hdDtcIixcInZhcnlpbmcgdmVjMiB2VGV4dHVyZUNvb3JkO1wiLFwidmFyeWluZyB2ZWM0IHZDb2xvcjtcIixcInVuaWZvcm0gc2FtcGxlcjJEIHVTYW1wbGVyO1wiLFwidm9pZCBtYWluKHZvaWQpIHtcIixcIiAgIGdsX0ZyYWdDb2xvciA9IHRleHR1cmUyRCh1U2FtcGxlciwgdlRleHR1cmVDb29yZCkgKiB2Q29sb3IgO1wiLFwifVwiXSl9LGIuV2ViR0xTcHJpdGVCYXRjaC5wcm90b3R5cGUuc2V0Q29udGV4dD1mdW5jdGlvbihhKXt0aGlzLmdsPWEsdGhpcy52ZXJ0ZXhCdWZmZXI9YS5jcmVhdGVCdWZmZXIoKSx0aGlzLmluZGV4QnVmZmVyPWEuY3JlYXRlQnVmZmVyKCksYS5iaW5kQnVmZmVyKGEuRUxFTUVOVF9BUlJBWV9CVUZGRVIsdGhpcy5pbmRleEJ1ZmZlciksYS5idWZmZXJEYXRhKGEuRUxFTUVOVF9BUlJBWV9CVUZGRVIsdGhpcy5pbmRpY2VzLGEuU1RBVElDX0RSQVcpLGEuYmluZEJ1ZmZlcihhLkFSUkFZX0JVRkZFUix0aGlzLnZlcnRleEJ1ZmZlciksYS5idWZmZXJEYXRhKGEuQVJSQVlfQlVGRkVSLHRoaXMudmVydGljZXMsYS5EWU5BTUlDX0RSQVcpLHRoaXMuY3VycmVudEJsZW5kTW9kZT05OTk5OTt2YXIgYz1uZXcgYi5QaXhpU2hhZGVyKGEpO2MuZnJhZ21lbnRTcmM9dGhpcy5kZWZhdWx0U2hhZGVyLmZyYWdtZW50U3JjLGMudW5pZm9ybXM9e30sYy5pbml0KCksdGhpcy5kZWZhdWx0U2hhZGVyLnNoYWRlcnNbYS5pZF09Y30sYi5XZWJHTFNwcml0ZUJhdGNoLnByb3RvdHlwZS5iZWdpbj1mdW5jdGlvbihhKXt0aGlzLnJlbmRlclNlc3Npb249YSx0aGlzLnNoYWRlcj10aGlzLnJlbmRlclNlc3Npb24uc2hhZGVyTWFuYWdlci5kZWZhdWx0U2hhZGVyLHRoaXMuc3RhcnQoKX0sYi5XZWJHTFNwcml0ZUJhdGNoLnByb3RvdHlwZS5lbmQ9ZnVuY3Rpb24oKXt0aGlzLmZsdXNoKCl9LGIuV2ViR0xTcHJpdGVCYXRjaC5wcm90b3R5cGUucmVuZGVyPWZ1bmN0aW9uKGEpe3ZhciBiPWEudGV4dHVyZTt0aGlzLmN1cnJlbnRCYXRjaFNpemU+PXRoaXMuc2l6ZSYmKHRoaXMuZmx1c2goKSx0aGlzLmN1cnJlbnRCYXNlVGV4dHVyZT1iLmJhc2VUZXh0dXJlKTt2YXIgYz1iLl91dnM7aWYoYyl7dmFyIGQsZSxmLGcsaD1hLmFuY2hvci54LGk9YS5hbmNob3IueTtpZihiLnRyaW0pe3ZhciBqPWIudHJpbTtlPWoueC1oKmoud2lkdGgsZD1lK2IuY3JvcC53aWR0aCxnPWoueS1pKmouaGVpZ2h0LGY9ZytiLmNyb3AuaGVpZ2h0fWVsc2UgZD1iLmZyYW1lLndpZHRoKigxLWgpLGU9Yi5mcmFtZS53aWR0aCotaCxmPWIuZnJhbWUuaGVpZ2h0KigxLWkpLGc9Yi5mcmFtZS5oZWlnaHQqLWk7dmFyIGs9NCp0aGlzLmN1cnJlbnRCYXRjaFNpemUqdGhpcy52ZXJ0U2l6ZSxsPWIuYmFzZVRleHR1cmUucmVzb2x1dGlvbixtPWEud29ybGRUcmFuc2Zvcm0sbj1tLmEvbCxvPW0uYi9sLHA9bS5jL2wscT1tLmQvbCxyPW0udHgscz1tLnR5LHQ9dGhpcy5jb2xvcnMsdT10aGlzLnBvc2l0aW9uczt0aGlzLnJlbmRlclNlc3Npb24ucm91bmRQaXhlbHM/KHVba109biplK3AqZytyfDAsdVtrKzFdPXEqZytvKmUrc3wwLHVbays1XT1uKmQrcCpnK3J8MCx1W2srNl09cSpnK28qZCtzfDAsdVtrKzEwXT1uKmQrcCpmK3J8MCx1W2srMTFdPXEqZitvKmQrc3wwLHVbaysxNV09biplK3AqZityfDAsdVtrKzE2XT1xKmYrbyplK3N8MCk6KHVba109biplK3AqZytyLHVbaysxXT1xKmcrbyplK3MsdVtrKzVdPW4qZCtwKmcrcix1W2srNl09cSpnK28qZCtzLHVbaysxMF09bipkK3AqZityLHVbaysxMV09cSpmK28qZCtzLHVbaysxNV09biplK3AqZityLHVbaysxNl09cSpmK28qZStzKSx1W2srMl09Yy54MCx1W2srM109Yy55MCx1W2srN109Yy54MSx1W2srOF09Yy55MSx1W2srMTJdPWMueDIsdVtrKzEzXT1jLnkyLHVbaysxN109Yy54Myx1W2srMThdPWMueTM7dmFyIHY9YS50aW50O3Rbays0XT10W2srOV09dFtrKzE0XT10W2srMTldPSh2Pj4xNikrKDY1MjgwJnYpKygoMjU1JnYpPDwxNikrKDI1NSphLndvcmxkQWxwaGE8PDI0KSx0aGlzLnNwcml0ZXNbdGhpcy5jdXJyZW50QmF0Y2hTaXplKytdPWF9fSxiLldlYkdMU3ByaXRlQmF0Y2gucHJvdG90eXBlLnJlbmRlclRpbGluZ1Nwcml0ZT1mdW5jdGlvbihhKXt2YXIgYz1hLnRpbGluZ1RleHR1cmU7dGhpcy5jdXJyZW50QmF0Y2hTaXplPj10aGlzLnNpemUmJih0aGlzLmZsdXNoKCksdGhpcy5jdXJyZW50QmFzZVRleHR1cmU9Yy5iYXNlVGV4dHVyZSksYS5fdXZzfHwoYS5fdXZzPW5ldyBiLlRleHR1cmVVdnMpO3ZhciBkPWEuX3V2czthLnRpbGVQb3NpdGlvbi54JT1jLmJhc2VUZXh0dXJlLndpZHRoKmEudGlsZVNjYWxlT2Zmc2V0LngsYS50aWxlUG9zaXRpb24ueSU9Yy5iYXNlVGV4dHVyZS5oZWlnaHQqYS50aWxlU2NhbGVPZmZzZXQueTt2YXIgZT1hLnRpbGVQb3NpdGlvbi54LyhjLmJhc2VUZXh0dXJlLndpZHRoKmEudGlsZVNjYWxlT2Zmc2V0LngpLGY9YS50aWxlUG9zaXRpb24ueS8oYy5iYXNlVGV4dHVyZS5oZWlnaHQqYS50aWxlU2NhbGVPZmZzZXQueSksZz1hLndpZHRoL2MuYmFzZVRleHR1cmUud2lkdGgvKGEudGlsZVNjYWxlLngqYS50aWxlU2NhbGVPZmZzZXQueCksaD1hLmhlaWdodC9jLmJhc2VUZXh0dXJlLmhlaWdodC8oYS50aWxlU2NhbGUueSphLnRpbGVTY2FsZU9mZnNldC55KTtkLngwPTAtZSxkLnkwPTAtZixkLngxPTEqZy1lLGQueTE9MC1mLGQueDI9MSpnLWUsZC55Mj0xKmgtZixkLngzPTAtZSxkLnkzPTEqaC1mO3ZhciBpPWEudGludCxqPShpPj4xNikrKDY1MjgwJmkpKygoMjU1JmkpPDwxNikrKDI1NSphLmFscGhhPDwyNCksaz10aGlzLnBvc2l0aW9ucyxsPXRoaXMuY29sb3JzLG09YS53aWR0aCxuPWEuaGVpZ2h0LG89YS5hbmNob3IueCxwPWEuYW5jaG9yLnkscT1tKigxLW8pLHI9bSotbyxzPW4qKDEtcCksdD1uKi1wLHU9NCp0aGlzLmN1cnJlbnRCYXRjaFNpemUqdGhpcy52ZXJ0U2l6ZSx2PWMuYmFzZVRleHR1cmUucmVzb2x1dGlvbix3PWEud29ybGRUcmFuc2Zvcm0seD13LmEvdix5PXcuYi92LHo9dy5jL3YsQT13LmQvdixCPXcudHgsQz13LnR5O2tbdSsrXT14KnIreip0K0Isa1t1KytdPUEqdCt5KnIrQyxrW3UrK109ZC54MCxrW3UrK109ZC55MCxsW3UrK109aixrW3UrK109eCpxK3oqdCtCLGtbdSsrXT1BKnQreSpxK0Msa1t1KytdPWQueDEsa1t1KytdPWQueTEsbFt1KytdPWosa1t1KytdPXgqcSt6KnMrQixrW3UrK109QSpzK3kqcStDLGtbdSsrXT1kLngyLGtbdSsrXT1kLnkyLGxbdSsrXT1qLGtbdSsrXT14KnIreipzK0Isa1t1KytdPUEqcyt5KnIrQyxrW3UrK109ZC54MyxrW3UrK109ZC55MyxsW3UrK109aix0aGlzLnNwcml0ZXNbdGhpcy5jdXJyZW50QmF0Y2hTaXplKytdPWF9LGIuV2ViR0xTcHJpdGVCYXRjaC5wcm90b3R5cGUuZmx1c2g9ZnVuY3Rpb24oKXtpZigwIT09dGhpcy5jdXJyZW50QmF0Y2hTaXplKXt2YXIgYSxjPXRoaXMuZ2w7aWYodGhpcy5kaXJ0eSl7dGhpcy5kaXJ0eT0hMSxjLmFjdGl2ZVRleHR1cmUoYy5URVhUVVJFMCksYy5iaW5kQnVmZmVyKGMuQVJSQVlfQlVGRkVSLHRoaXMudmVydGV4QnVmZmVyKSxjLmJpbmRCdWZmZXIoYy5FTEVNRU5UX0FSUkFZX0JVRkZFUix0aGlzLmluZGV4QnVmZmVyKSxhPXRoaXMuZGVmYXVsdFNoYWRlci5zaGFkZXJzW2MuaWRdO3ZhciBkPTQqdGhpcy52ZXJ0U2l6ZTtjLnZlcnRleEF0dHJpYlBvaW50ZXIoYS5hVmVydGV4UG9zaXRpb24sMixjLkZMT0FULCExLGQsMCksYy52ZXJ0ZXhBdHRyaWJQb2ludGVyKGEuYVRleHR1cmVDb29yZCwyLGMuRkxPQVQsITEsZCw4KSxjLnZlcnRleEF0dHJpYlBvaW50ZXIoYS5jb2xvckF0dHJpYnV0ZSw0LGMuVU5TSUdORURfQllURSwhMCxkLDE2KX1pZih0aGlzLmN1cnJlbnRCYXRjaFNpemU+LjUqdGhpcy5zaXplKWMuYnVmZmVyU3ViRGF0YShjLkFSUkFZX0JVRkZFUiwwLHRoaXMudmVydGljZXMpO2Vsc2V7dmFyIGU9dGhpcy5wb3NpdGlvbnMuc3ViYXJyYXkoMCw0KnRoaXMuY3VycmVudEJhdGNoU2l6ZSp0aGlzLnZlcnRTaXplKTtjLmJ1ZmZlclN1YkRhdGEoYy5BUlJBWV9CVUZGRVIsMCxlKX1mb3IodmFyIGYsZyxoLGksaj0wLGs9MCxsPW51bGwsbT10aGlzLnJlbmRlclNlc3Npb24uYmxlbmRNb2RlTWFuYWdlci5jdXJyZW50QmxlbmRNb2RlLG49bnVsbCxvPSExLHA9ITEscT0wLHI9dGhpcy5jdXJyZW50QmF0Y2hTaXplO3I+cTtxKyspe2lmKGk9dGhpcy5zcHJpdGVzW3FdLGY9aS50ZXh0dXJlLmJhc2VUZXh0dXJlLGc9aS5ibGVuZE1vZGUsaD1pLnNoYWRlcnx8dGhpcy5kZWZhdWx0U2hhZGVyLG89bSE9PWcscD1uIT09aCwobCE9PWZ8fG98fHApJiYodGhpcy5yZW5kZXJCYXRjaChsLGosayksaz1xLGo9MCxsPWYsbyYmKG09Zyx0aGlzLnJlbmRlclNlc3Npb24uYmxlbmRNb2RlTWFuYWdlci5zZXRCbGVuZE1vZGUobSkpLHApKXtuPWgsYT1uLnNoYWRlcnNbYy5pZF0sYXx8KGE9bmV3IGIuUGl4aVNoYWRlcihjKSxhLmZyYWdtZW50U3JjPW4uZnJhZ21lbnRTcmMsYS51bmlmb3Jtcz1uLnVuaWZvcm1zLGEuaW5pdCgpLG4uc2hhZGVyc1tjLmlkXT1hKSx0aGlzLnJlbmRlclNlc3Npb24uc2hhZGVyTWFuYWdlci5zZXRTaGFkZXIoYSksYS5kaXJ0eSYmYS5zeW5jVW5pZm9ybXMoKTt2YXIgcz10aGlzLnJlbmRlclNlc3Npb24ucHJvamVjdGlvbjtjLnVuaWZvcm0yZihhLnByb2plY3Rpb25WZWN0b3Iscy54LHMueSk7dmFyIHQ9dGhpcy5yZW5kZXJTZXNzaW9uLm9mZnNldDtjLnVuaWZvcm0yZihhLm9mZnNldFZlY3Rvcix0LngsdC55KX1qKyt9dGhpcy5yZW5kZXJCYXRjaChsLGosayksdGhpcy5jdXJyZW50QmF0Y2hTaXplPTB9fSxiLldlYkdMU3ByaXRlQmF0Y2gucHJvdG90eXBlLnJlbmRlckJhdGNoPWZ1bmN0aW9uKGEsYixjKXtpZigwIT09Yil7dmFyIGQ9dGhpcy5nbDthLl9kaXJ0eVtkLmlkXT90aGlzLnJlbmRlclNlc3Npb24ucmVuZGVyZXIudXBkYXRlVGV4dHVyZShhKTpkLmJpbmRUZXh0dXJlKGQuVEVYVFVSRV8yRCxhLl9nbFRleHR1cmVzW2QuaWRdKSxkLmRyYXdFbGVtZW50cyhkLlRSSUFOR0xFUyw2KmIsZC5VTlNJR05FRF9TSE9SVCw2KmMqMiksdGhpcy5yZW5kZXJTZXNzaW9uLmRyYXdDb3VudCsrfX0sYi5XZWJHTFNwcml0ZUJhdGNoLnByb3RvdHlwZS5zdG9wPWZ1bmN0aW9uKCl7dGhpcy5mbHVzaCgpLHRoaXMuZGlydHk9ITB9LGIuV2ViR0xTcHJpdGVCYXRjaC5wcm90b3R5cGUuc3RhcnQ9ZnVuY3Rpb24oKXt0aGlzLmRpcnR5PSEwfSxiLldlYkdMU3ByaXRlQmF0Y2gucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oKXt0aGlzLnZlcnRpY2VzPW51bGwsdGhpcy5pbmRpY2VzPW51bGwsdGhpcy5nbC5kZWxldGVCdWZmZXIodGhpcy52ZXJ0ZXhCdWZmZXIpLHRoaXMuZ2wuZGVsZXRlQnVmZmVyKHRoaXMuaW5kZXhCdWZmZXIpLHRoaXMuY3VycmVudEJhc2VUZXh0dXJlPW51bGwsdGhpcy5nbD1udWxsfSxiLldlYkdMRmFzdFNwcml0ZUJhdGNoPWZ1bmN0aW9uKGEpe3RoaXMudmVydFNpemU9MTAsdGhpcy5tYXhTaXplPTZlMyx0aGlzLnNpemU9dGhpcy5tYXhTaXplO3ZhciBjPTQqdGhpcy5zaXplKnRoaXMudmVydFNpemUsZD02KnRoaXMubWF4U2l6ZTt0aGlzLnZlcnRpY2VzPW5ldyBiLkZsb2F0MzJBcnJheShjKSx0aGlzLmluZGljZXM9bmV3IGIuVWludDE2QXJyYXkoZCksdGhpcy52ZXJ0ZXhCdWZmZXI9bnVsbCx0aGlzLmluZGV4QnVmZmVyPW51bGwsdGhpcy5sYXN0SW5kZXhDb3VudD0wO2Zvcih2YXIgZT0wLGY9MDtkPmU7ZSs9NixmKz00KXRoaXMuaW5kaWNlc1tlKzBdPWYrMCx0aGlzLmluZGljZXNbZSsxXT1mKzEsdGhpcy5pbmRpY2VzW2UrMl09ZisyLHRoaXMuaW5kaWNlc1tlKzNdPWYrMCx0aGlzLmluZGljZXNbZSs0XT1mKzIsdGhpcy5pbmRpY2VzW2UrNV09ZiszO3RoaXMuZHJhd2luZz0hMSx0aGlzLmN1cnJlbnRCYXRjaFNpemU9MCx0aGlzLmN1cnJlbnRCYXNlVGV4dHVyZT1udWxsLHRoaXMuY3VycmVudEJsZW5kTW9kZT0wLHRoaXMucmVuZGVyU2Vzc2lvbj1udWxsLHRoaXMuc2hhZGVyPW51bGwsdGhpcy5tYXRyaXg9bnVsbCx0aGlzLnNldENvbnRleHQoYSl9LGIuV2ViR0xGYXN0U3ByaXRlQmF0Y2gucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuV2ViR0xGYXN0U3ByaXRlQmF0Y2gsYi5XZWJHTEZhc3RTcHJpdGVCYXRjaC5wcm90b3R5cGUuc2V0Q29udGV4dD1mdW5jdGlvbihhKXt0aGlzLmdsPWEsdGhpcy52ZXJ0ZXhCdWZmZXI9YS5jcmVhdGVCdWZmZXIoKSx0aGlzLmluZGV4QnVmZmVyPWEuY3JlYXRlQnVmZmVyKCksYS5iaW5kQnVmZmVyKGEuRUxFTUVOVF9BUlJBWV9CVUZGRVIsdGhpcy5pbmRleEJ1ZmZlciksYS5idWZmZXJEYXRhKGEuRUxFTUVOVF9BUlJBWV9CVUZGRVIsdGhpcy5pbmRpY2VzLGEuU1RBVElDX0RSQVcpLGEuYmluZEJ1ZmZlcihhLkFSUkFZX0JVRkZFUix0aGlzLnZlcnRleEJ1ZmZlciksYS5idWZmZXJEYXRhKGEuQVJSQVlfQlVGRkVSLHRoaXMudmVydGljZXMsYS5EWU5BTUlDX0RSQVcpfSxiLldlYkdMRmFzdFNwcml0ZUJhdGNoLnByb3RvdHlwZS5iZWdpbj1mdW5jdGlvbihhLGIpe3RoaXMucmVuZGVyU2Vzc2lvbj1iLHRoaXMuc2hhZGVyPXRoaXMucmVuZGVyU2Vzc2lvbi5zaGFkZXJNYW5hZ2VyLmZhc3RTaGFkZXIsdGhpcy5tYXRyaXg9YS53b3JsZFRyYW5zZm9ybS50b0FycmF5KCEwKSx0aGlzLnN0YXJ0KCl9LGIuV2ViR0xGYXN0U3ByaXRlQmF0Y2gucHJvdG90eXBlLmVuZD1mdW5jdGlvbigpe3RoaXMuZmx1c2goKX0sYi5XZWJHTEZhc3RTcHJpdGVCYXRjaC5wcm90b3R5cGUucmVuZGVyPWZ1bmN0aW9uKGEpe3ZhciBiPWEuY2hpbGRyZW4sYz1iWzBdO2lmKGMudGV4dHVyZS5fdXZzKXt0aGlzLmN1cnJlbnRCYXNlVGV4dHVyZT1jLnRleHR1cmUuYmFzZVRleHR1cmUsYy5ibGVuZE1vZGUhPT10aGlzLnJlbmRlclNlc3Npb24uYmxlbmRNb2RlTWFuYWdlci5jdXJyZW50QmxlbmRNb2RlJiYodGhpcy5mbHVzaCgpLHRoaXMucmVuZGVyU2Vzc2lvbi5ibGVuZE1vZGVNYW5hZ2VyLnNldEJsZW5kTW9kZShjLmJsZW5kTW9kZSkpO2Zvcih2YXIgZD0wLGU9Yi5sZW5ndGg7ZT5kO2QrKyl0aGlzLnJlbmRlclNwcml0ZShiW2RdKTt0aGlzLmZsdXNoKCl9fSxiLldlYkdMRmFzdFNwcml0ZUJhdGNoLnByb3RvdHlwZS5yZW5kZXJTcHJpdGU9ZnVuY3Rpb24oYSl7aWYoYS52aXNpYmxlJiYoYS50ZXh0dXJlLmJhc2VUZXh0dXJlPT09dGhpcy5jdXJyZW50QmFzZVRleHR1cmV8fCh0aGlzLmZsdXNoKCksdGhpcy5jdXJyZW50QmFzZVRleHR1cmU9YS50ZXh0dXJlLmJhc2VUZXh0dXJlLGEudGV4dHVyZS5fdXZzKSkpe3ZhciBiLGMsZCxlLGYsZyxoLGksaj10aGlzLnZlcnRpY2VzO2lmKGI9YS50ZXh0dXJlLl91dnMsYz1hLnRleHR1cmUuZnJhbWUud2lkdGgsZD1hLnRleHR1cmUuZnJhbWUuaGVpZ2h0LGEudGV4dHVyZS50cmltKXt2YXIgaz1hLnRleHR1cmUudHJpbTtmPWsueC1hLmFuY2hvci54Kmsud2lkdGgsZT1mK2EudGV4dHVyZS5jcm9wLndpZHRoLGg9ay55LWEuYW5jaG9yLnkqay5oZWlnaHQsZz1oK2EudGV4dHVyZS5jcm9wLmhlaWdodH1lbHNlIGU9YS50ZXh0dXJlLmZyYW1lLndpZHRoKigxLWEuYW5jaG9yLngpLGY9YS50ZXh0dXJlLmZyYW1lLndpZHRoKi1hLmFuY2hvci54LGc9YS50ZXh0dXJlLmZyYW1lLmhlaWdodCooMS1hLmFuY2hvci55KSxoPWEudGV4dHVyZS5mcmFtZS5oZWlnaHQqLWEuYW5jaG9yLnk7aT00KnRoaXMuY3VycmVudEJhdGNoU2l6ZSp0aGlzLnZlcnRTaXplLGpbaSsrXT1mLGpbaSsrXT1oLGpbaSsrXT1hLnBvc2l0aW9uLngsaltpKytdPWEucG9zaXRpb24ueSxqW2krK109YS5zY2FsZS54LGpbaSsrXT1hLnNjYWxlLnksaltpKytdPWEucm90YXRpb24saltpKytdPWIueDAsaltpKytdPWIueTEsaltpKytdPWEuYWxwaGEsaltpKytdPWUsaltpKytdPWgsaltpKytdPWEucG9zaXRpb24ueCxqW2krK109YS5wb3NpdGlvbi55LGpbaSsrXT1hLnNjYWxlLngsaltpKytdPWEuc2NhbGUueSxqW2krK109YS5yb3RhdGlvbixqW2krK109Yi54MSxqW2krK109Yi55MSxqW2krK109YS5hbHBoYSxqW2krK109ZSxqW2krK109ZyxqW2krK109YS5wb3NpdGlvbi54LGpbaSsrXT1hLnBvc2l0aW9uLnksaltpKytdPWEuc2NhbGUueCxqW2krK109YS5zY2FsZS55LGpbaSsrXT1hLnJvdGF0aW9uLGpbaSsrXT1iLngyLGpbaSsrXT1iLnkyLGpbaSsrXT1hLmFscGhhLGpbaSsrXT1mLGpbaSsrXT1nLGpbaSsrXT1hLnBvc2l0aW9uLngsaltpKytdPWEucG9zaXRpb24ueSxqW2krK109YS5zY2FsZS54LGpbaSsrXT1hLnNjYWxlLnksaltpKytdPWEucm90YXRpb24saltpKytdPWIueDMsaltpKytdPWIueTMsaltpKytdPWEuYWxwaGEsdGhpcy5jdXJyZW50QmF0Y2hTaXplKyssdGhpcy5jdXJyZW50QmF0Y2hTaXplPj10aGlzLnNpemUmJnRoaXMuZmx1c2goKX19LGIuV2ViR0xGYXN0U3ByaXRlQmF0Y2gucHJvdG90eXBlLmZsdXNoPWZ1bmN0aW9uKCl7aWYoMCE9PXRoaXMuY3VycmVudEJhdGNoU2l6ZSl7dmFyIGE9dGhpcy5nbDtpZih0aGlzLmN1cnJlbnRCYXNlVGV4dHVyZS5fZ2xUZXh0dXJlc1thLmlkXXx8dGhpcy5yZW5kZXJTZXNzaW9uLnJlbmRlcmVyLnVwZGF0ZVRleHR1cmUodGhpcy5jdXJyZW50QmFzZVRleHR1cmUsYSksYS5iaW5kVGV4dHVyZShhLlRFWFRVUkVfMkQsdGhpcy5jdXJyZW50QmFzZVRleHR1cmUuX2dsVGV4dHVyZXNbYS5pZF0pLHRoaXMuY3VycmVudEJhdGNoU2l6ZT4uNSp0aGlzLnNpemUpYS5idWZmZXJTdWJEYXRhKGEuQVJSQVlfQlVGRkVSLDAsdGhpcy52ZXJ0aWNlcyk7ZWxzZXt2YXIgYj10aGlzLnZlcnRpY2VzLnN1YmFycmF5KDAsNCp0aGlzLmN1cnJlbnRCYXRjaFNpemUqdGhpcy52ZXJ0U2l6ZSk7YS5idWZmZXJTdWJEYXRhKGEuQVJSQVlfQlVGRkVSLDAsYil9YS5kcmF3RWxlbWVudHMoYS5UUklBTkdMRVMsNip0aGlzLmN1cnJlbnRCYXRjaFNpemUsYS5VTlNJR05FRF9TSE9SVCwwKSx0aGlzLmN1cnJlbnRCYXRjaFNpemU9MCx0aGlzLnJlbmRlclNlc3Npb24uZHJhd0NvdW50Kyt9fSxiLldlYkdMRmFzdFNwcml0ZUJhdGNoLnByb3RvdHlwZS5zdG9wPWZ1bmN0aW9uKCl7dGhpcy5mbHVzaCgpfSxiLldlYkdMRmFzdFNwcml0ZUJhdGNoLnByb3RvdHlwZS5zdGFydD1mdW5jdGlvbigpe3ZhciBhPXRoaXMuZ2w7YS5hY3RpdmVUZXh0dXJlKGEuVEVYVFVSRTApLGEuYmluZEJ1ZmZlcihhLkFSUkFZX0JVRkZFUix0aGlzLnZlcnRleEJ1ZmZlciksYS5iaW5kQnVmZmVyKGEuRUxFTUVOVF9BUlJBWV9CVUZGRVIsdGhpcy5pbmRleEJ1ZmZlcik7dmFyIGI9dGhpcy5yZW5kZXJTZXNzaW9uLnByb2plY3Rpb247YS51bmlmb3JtMmYodGhpcy5zaGFkZXIucHJvamVjdGlvblZlY3RvcixiLngsYi55KSxhLnVuaWZvcm1NYXRyaXgzZnYodGhpcy5zaGFkZXIudU1hdHJpeCwhMSx0aGlzLm1hdHJpeCk7dmFyIGM9NCp0aGlzLnZlcnRTaXplO2EudmVydGV4QXR0cmliUG9pbnRlcih0aGlzLnNoYWRlci5hVmVydGV4UG9zaXRpb24sMixhLkZMT0FULCExLGMsMCksYS52ZXJ0ZXhBdHRyaWJQb2ludGVyKHRoaXMuc2hhZGVyLmFQb3NpdGlvbkNvb3JkLDIsYS5GTE9BVCwhMSxjLDgpLGEudmVydGV4QXR0cmliUG9pbnRlcih0aGlzLnNoYWRlci5hU2NhbGUsMixhLkZMT0FULCExLGMsMTYpLGEudmVydGV4QXR0cmliUG9pbnRlcih0aGlzLnNoYWRlci5hUm90YXRpb24sMSxhLkZMT0FULCExLGMsMjQpLGEudmVydGV4QXR0cmliUG9pbnRlcih0aGlzLnNoYWRlci5hVGV4dHVyZUNvb3JkLDIsYS5GTE9BVCwhMSxjLDI4KSxhLnZlcnRleEF0dHJpYlBvaW50ZXIodGhpcy5zaGFkZXIuY29sb3JBdHRyaWJ1dGUsMSxhLkZMT0FULCExLGMsMzYpfSxiLldlYkdMRmlsdGVyTWFuYWdlcj1mdW5jdGlvbigpe3RoaXMuZmlsdGVyU3RhY2s9W10sdGhpcy5vZmZzZXRYPTAsdGhpcy5vZmZzZXRZPTB9LGIuV2ViR0xGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLldlYkdMRmlsdGVyTWFuYWdlcixiLldlYkdMRmlsdGVyTWFuYWdlci5wcm90b3R5cGUuc2V0Q29udGV4dD1mdW5jdGlvbihhKXt0aGlzLmdsPWEsdGhpcy50ZXh0dXJlUG9vbD1bXSx0aGlzLmluaXRTaGFkZXJCdWZmZXJzKCl9LGIuV2ViR0xGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZS5iZWdpbj1mdW5jdGlvbihhLGIpe3RoaXMucmVuZGVyU2Vzc2lvbj1hLHRoaXMuZGVmYXVsdFNoYWRlcj1hLnNoYWRlck1hbmFnZXIuZGVmYXVsdFNoYWRlcjt2YXIgYz10aGlzLnJlbmRlclNlc3Npb24ucHJvamVjdGlvbjt0aGlzLndpZHRoPTIqYy54LHRoaXMuaGVpZ2h0PTIqLWMueSx0aGlzLmJ1ZmZlcj1ifSxiLldlYkdMRmlsdGVyTWFuYWdlci5wcm90b3R5cGUucHVzaEZpbHRlcj1mdW5jdGlvbihhKXt2YXIgYz10aGlzLmdsLGQ9dGhpcy5yZW5kZXJTZXNzaW9uLnByb2plY3Rpb24sZT10aGlzLnJlbmRlclNlc3Npb24ub2Zmc2V0O2EuX2ZpbHRlckFyZWE9YS50YXJnZXQuZmlsdGVyQXJlYXx8YS50YXJnZXQuZ2V0Qm91bmRzKCksdGhpcy5maWx0ZXJTdGFjay5wdXNoKGEpO3ZhciBmPWEuZmlsdGVyUGFzc2VzWzBdO3RoaXMub2Zmc2V0WCs9YS5fZmlsdGVyQXJlYS54LHRoaXMub2Zmc2V0WSs9YS5fZmlsdGVyQXJlYS55O3ZhciBnPXRoaXMudGV4dHVyZVBvb2wucG9wKCk7Zz9nLnJlc2l6ZSh0aGlzLndpZHRoLHRoaXMuaGVpZ2h0KTpnPW5ldyBiLkZpbHRlclRleHR1cmUodGhpcy5nbCx0aGlzLndpZHRoLHRoaXMuaGVpZ2h0KSxjLmJpbmRUZXh0dXJlKGMuVEVYVFVSRV8yRCxnLnRleHR1cmUpO3ZhciBoPWEuX2ZpbHRlckFyZWEsaT1mLnBhZGRpbmc7aC54LT1pLGgueS09aSxoLndpZHRoKz0yKmksaC5oZWlnaHQrPTIqaSxoLng8MCYmKGgueD0wKSxoLndpZHRoPnRoaXMud2lkdGgmJihoLndpZHRoPXRoaXMud2lkdGgpLGgueTwwJiYoaC55PTApLGguaGVpZ2h0PnRoaXMuaGVpZ2h0JiYoaC5oZWlnaHQ9dGhpcy5oZWlnaHQpLGMuYmluZEZyYW1lYnVmZmVyKGMuRlJBTUVCVUZGRVIsZy5mcmFtZUJ1ZmZlciksYy52aWV3cG9ydCgwLDAsaC53aWR0aCxoLmhlaWdodCksZC54PWgud2lkdGgvMixkLnk9LWguaGVpZ2h0LzIsZS54PS1oLngsZS55PS1oLnksYy5jb2xvck1hc2soITAsITAsITAsITApLGMuY2xlYXJDb2xvcigwLDAsMCwwKSxjLmNsZWFyKGMuQ09MT1JfQlVGRkVSX0JJVCksYS5fZ2xGaWx0ZXJUZXh0dXJlPWd9LGIuV2ViR0xGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZS5wb3BGaWx0ZXI9ZnVuY3Rpb24oKXt2YXIgYT10aGlzLmdsLGM9dGhpcy5maWx0ZXJTdGFjay5wb3AoKSxkPWMuX2ZpbHRlckFyZWEsZT1jLl9nbEZpbHRlclRleHR1cmUsZj10aGlzLnJlbmRlclNlc3Npb24ucHJvamVjdGlvbixnPXRoaXMucmVuZGVyU2Vzc2lvbi5vZmZzZXQ7aWYoYy5maWx0ZXJQYXNzZXMubGVuZ3RoPjEpe2Eudmlld3BvcnQoMCwwLGQud2lkdGgsZC5oZWlnaHQpLGEuYmluZEJ1ZmZlcihhLkFSUkFZX0JVRkZFUix0aGlzLnZlcnRleEJ1ZmZlciksdGhpcy52ZXJ0ZXhBcnJheVswXT0wLHRoaXMudmVydGV4QXJyYXlbMV09ZC5oZWlnaHQsdGhpcy52ZXJ0ZXhBcnJheVsyXT1kLndpZHRoLHRoaXMudmVydGV4QXJyYXlbM109ZC5oZWlnaHQsdGhpcy52ZXJ0ZXhBcnJheVs0XT0wLHRoaXMudmVydGV4QXJyYXlbNV09MCx0aGlzLnZlcnRleEFycmF5WzZdPWQud2lkdGgsdGhpcy52ZXJ0ZXhBcnJheVs3XT0wLGEuYnVmZmVyU3ViRGF0YShhLkFSUkFZX0JVRkZFUiwwLHRoaXMudmVydGV4QXJyYXkpLGEuYmluZEJ1ZmZlcihhLkFSUkFZX0JVRkZFUix0aGlzLnV2QnVmZmVyKSx0aGlzLnV2QXJyYXlbMl09ZC53aWR0aC90aGlzLndpZHRoLHRoaXMudXZBcnJheVs1XT1kLmhlaWdodC90aGlzLmhlaWdodCx0aGlzLnV2QXJyYXlbNl09ZC53aWR0aC90aGlzLndpZHRoLHRoaXMudXZBcnJheVs3XT1kLmhlaWdodC90aGlzLmhlaWdodCxhLmJ1ZmZlclN1YkRhdGEoYS5BUlJBWV9CVUZGRVIsMCx0aGlzLnV2QXJyYXkpO3ZhciBoPWUsaT10aGlzLnRleHR1cmVQb29sLnBvcCgpO2l8fChpPW5ldyBiLkZpbHRlclRleHR1cmUodGhpcy5nbCx0aGlzLndpZHRoLHRoaXMuaGVpZ2h0KSksaS5yZXNpemUodGhpcy53aWR0aCx0aGlzLmhlaWdodCksYS5iaW5kRnJhbWVidWZmZXIoYS5GUkFNRUJVRkZFUixpLmZyYW1lQnVmZmVyKSxhLmNsZWFyKGEuQ09MT1JfQlVGRkVSX0JJVCksYS5kaXNhYmxlKGEuQkxFTkQpO2Zvcih2YXIgaj0wO2o8Yy5maWx0ZXJQYXNzZXMubGVuZ3RoLTE7aisrKXt2YXIgaz1jLmZpbHRlclBhc3Nlc1tqXTthLmJpbmRGcmFtZWJ1ZmZlcihhLkZSQU1FQlVGRkVSLGkuZnJhbWVCdWZmZXIpLGEuYWN0aXZlVGV4dHVyZShhLlRFWFRVUkUwKSxhLmJpbmRUZXh0dXJlKGEuVEVYVFVSRV8yRCxoLnRleHR1cmUpLHRoaXMuYXBwbHlGaWx0ZXJQYXNzKGssZCxkLndpZHRoLGQuaGVpZ2h0KTt2YXIgbD1oO2g9aSxpPWx9YS5lbmFibGUoYS5CTEVORCksZT1oLHRoaXMudGV4dHVyZVBvb2wucHVzaChpKX12YXIgbT1jLmZpbHRlclBhc3Nlc1tjLmZpbHRlclBhc3Nlcy5sZW5ndGgtMV07dGhpcy5vZmZzZXRYLT1kLngsdGhpcy5vZmZzZXRZLT1kLnk7dmFyIG49dGhpcy53aWR0aCxvPXRoaXMuaGVpZ2h0LHA9MCxxPTAscj10aGlzLmJ1ZmZlcjtpZigwPT09dGhpcy5maWx0ZXJTdGFjay5sZW5ndGgpYS5jb2xvck1hc2soITAsITAsITAsITApO2Vsc2V7dmFyIHM9dGhpcy5maWx0ZXJTdGFja1t0aGlzLmZpbHRlclN0YWNrLmxlbmd0aC0xXTtkPXMuX2ZpbHRlckFyZWEsbj1kLndpZHRoLG89ZC5oZWlnaHQscD1kLngscT1kLnkscj1zLl9nbEZpbHRlclRleHR1cmUuZnJhbWVCdWZmZXJ9Zi54PW4vMixmLnk9LW8vMixnLng9cCxnLnk9cSxkPWMuX2ZpbHRlckFyZWE7dmFyIHQ9ZC54LXAsdT1kLnktcTthLmJpbmRCdWZmZXIoYS5BUlJBWV9CVUZGRVIsdGhpcy52ZXJ0ZXhCdWZmZXIpLHRoaXMudmVydGV4QXJyYXlbMF09dCx0aGlzLnZlcnRleEFycmF5WzFdPXUrZC5oZWlnaHQsdGhpcy52ZXJ0ZXhBcnJheVsyXT10K2Qud2lkdGgsdGhpcy52ZXJ0ZXhBcnJheVszXT11K2QuaGVpZ2h0LHRoaXMudmVydGV4QXJyYXlbNF09dCx0aGlzLnZlcnRleEFycmF5WzVdPXUsdGhpcy52ZXJ0ZXhBcnJheVs2XT10K2Qud2lkdGgsdGhpcy52ZXJ0ZXhBcnJheVs3XT11LGEuYnVmZmVyU3ViRGF0YShhLkFSUkFZX0JVRkZFUiwwLHRoaXMudmVydGV4QXJyYXkpLGEuYmluZEJ1ZmZlcihhLkFSUkFZX0JVRkZFUix0aGlzLnV2QnVmZmVyKSx0aGlzLnV2QXJyYXlbMl09ZC53aWR0aC90aGlzLndpZHRoLHRoaXMudXZBcnJheVs1XT1kLmhlaWdodC90aGlzLmhlaWdodCx0aGlzLnV2QXJyYXlbNl09ZC53aWR0aC90aGlzLndpZHRoLHRoaXMudXZBcnJheVs3XT1kLmhlaWdodC90aGlzLmhlaWdodCxhLmJ1ZmZlclN1YkRhdGEoYS5BUlJBWV9CVUZGRVIsMCx0aGlzLnV2QXJyYXkpLGEudmlld3BvcnQoMCwwLG4sbyksYS5iaW5kRnJhbWVidWZmZXIoYS5GUkFNRUJVRkZFUixyKSxhLmFjdGl2ZVRleHR1cmUoYS5URVhUVVJFMCksYS5iaW5kVGV4dHVyZShhLlRFWFRVUkVfMkQsZS50ZXh0dXJlKSx0aGlzLmFwcGx5RmlsdGVyUGFzcyhtLGQsbixvKSx0aGlzLnRleHR1cmVQb29sLnB1c2goZSksYy5fZ2xGaWx0ZXJUZXh0dXJlPW51bGx9LGIuV2ViR0xGaWx0ZXJNYW5hZ2VyLnByb3RvdHlwZS5hcHBseUZpbHRlclBhc3M9ZnVuY3Rpb24oYSxjLGQsZSl7dmFyIGY9dGhpcy5nbCxnPWEuc2hhZGVyc1tmLmlkXTtnfHwoZz1uZXcgYi5QaXhpU2hhZGVyKGYpLGcuZnJhZ21lbnRTcmM9YS5mcmFnbWVudFNyYyxnLnVuaWZvcm1zPWEudW5pZm9ybXMsZy5pbml0KCksYS5zaGFkZXJzW2YuaWRdPWcpLHRoaXMucmVuZGVyU2Vzc2lvbi5zaGFkZXJNYW5hZ2VyLnNldFNoYWRlcihnKSxmLnVuaWZvcm0yZihnLnByb2plY3Rpb25WZWN0b3IsZC8yLC1lLzIpLGYudW5pZm9ybTJmKGcub2Zmc2V0VmVjdG9yLDAsMCksYS51bmlmb3Jtcy5kaW1lbnNpb25zJiYoYS51bmlmb3Jtcy5kaW1lbnNpb25zLnZhbHVlWzBdPXRoaXMud2lkdGgsYS51bmlmb3Jtcy5kaW1lbnNpb25zLnZhbHVlWzFdPXRoaXMuaGVpZ2h0LGEudW5pZm9ybXMuZGltZW5zaW9ucy52YWx1ZVsyXT10aGlzLnZlcnRleEFycmF5WzBdLGEudW5pZm9ybXMuZGltZW5zaW9ucy52YWx1ZVszXT10aGlzLnZlcnRleEFycmF5WzVdKSxnLnN5bmNVbmlmb3JtcygpLGYuYmluZEJ1ZmZlcihmLkFSUkFZX0JVRkZFUix0aGlzLnZlcnRleEJ1ZmZlciksZi52ZXJ0ZXhBdHRyaWJQb2ludGVyKGcuYVZlcnRleFBvc2l0aW9uLDIsZi5GTE9BVCwhMSwwLDApLGYuYmluZEJ1ZmZlcihmLkFSUkFZX0JVRkZFUix0aGlzLnV2QnVmZmVyKSxmLnZlcnRleEF0dHJpYlBvaW50ZXIoZy5hVGV4dHVyZUNvb3JkLDIsZi5GTE9BVCwhMSwwLDApLGYuYmluZEJ1ZmZlcihmLkFSUkFZX0JVRkZFUix0aGlzLmNvbG9yQnVmZmVyKSxmLnZlcnRleEF0dHJpYlBvaW50ZXIoZy5jb2xvckF0dHJpYnV0ZSwyLGYuRkxPQVQsITEsMCwwKSxmLmJpbmRCdWZmZXIoZi5FTEVNRU5UX0FSUkFZX0JVRkZFUix0aGlzLmluZGV4QnVmZmVyKSxmLmRyYXdFbGVtZW50cyhmLlRSSUFOR0xFUyw2LGYuVU5TSUdORURfU0hPUlQsMCksdGhpcy5yZW5kZXJTZXNzaW9uLmRyYXdDb3VudCsrfSxiLldlYkdMRmlsdGVyTWFuYWdlci5wcm90b3R5cGUuaW5pdFNoYWRlckJ1ZmZlcnM9ZnVuY3Rpb24oKXt2YXIgYT10aGlzLmdsO3RoaXMudmVydGV4QnVmZmVyPWEuY3JlYXRlQnVmZmVyKCksdGhpcy51dkJ1ZmZlcj1hLmNyZWF0ZUJ1ZmZlcigpLHRoaXMuY29sb3JCdWZmZXI9YS5jcmVhdGVCdWZmZXIoKSx0aGlzLmluZGV4QnVmZmVyPWEuY3JlYXRlQnVmZmVyKCksdGhpcy52ZXJ0ZXhBcnJheT1uZXcgYi5GbG9hdDMyQXJyYXkoWzAsMCwxLDAsMCwxLDEsMV0pLGEuYmluZEJ1ZmZlcihhLkFSUkFZX0JVRkZFUix0aGlzLnZlcnRleEJ1ZmZlciksYS5idWZmZXJEYXRhKGEuQVJSQVlfQlVGRkVSLHRoaXMudmVydGV4QXJyYXksYS5TVEFUSUNfRFJBVyksdGhpcy51dkFycmF5PW5ldyBiLkZsb2F0MzJBcnJheShbMCwwLDEsMCwwLDEsMSwxXSksYS5iaW5kQnVmZmVyKGEuQVJSQVlfQlVGRkVSLHRoaXMudXZCdWZmZXIpLGEuYnVmZmVyRGF0YShhLkFSUkFZX0JVRkZFUix0aGlzLnV2QXJyYXksYS5TVEFUSUNfRFJBVyksdGhpcy5jb2xvckFycmF5PW5ldyBiLkZsb2F0MzJBcnJheShbMSwxNjc3NzIxNSwxLDE2Nzc3MjE1LDEsMTY3NzcyMTUsMSwxNjc3NzIxNV0pLGEuYmluZEJ1ZmZlcihhLkFSUkFZX0JVRkZFUix0aGlzLmNvbG9yQnVmZmVyKSxhLmJ1ZmZlckRhdGEoYS5BUlJBWV9CVUZGRVIsdGhpcy5jb2xvckFycmF5LGEuU1RBVElDX0RSQVcpLGEuYmluZEJ1ZmZlcihhLkVMRU1FTlRfQVJSQVlfQlVGRkVSLHRoaXMuaW5kZXhCdWZmZXIpLGEuYnVmZmVyRGF0YShhLkVMRU1FTlRfQVJSQVlfQlVGRkVSLG5ldyBVaW50MTZBcnJheShbMCwxLDIsMSwzLDJdKSxhLlNUQVRJQ19EUkFXKX0sYi5XZWJHTEZpbHRlck1hbmFnZXIucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oKXt2YXIgYT10aGlzLmdsO3RoaXMuZmlsdGVyU3RhY2s9bnVsbCx0aGlzLm9mZnNldFg9MCx0aGlzLm9mZnNldFk9MDtmb3IodmFyIGI9MDtiPHRoaXMudGV4dHVyZVBvb2wubGVuZ3RoO2IrKyl0aGlzLnRleHR1cmVQb29sW2JdLmRlc3Ryb3koKTt0aGlzLnRleHR1cmVQb29sPW51bGwsYS5kZWxldGVCdWZmZXIodGhpcy52ZXJ0ZXhCdWZmZXIpLGEuZGVsZXRlQnVmZmVyKHRoaXMudXZCdWZmZXIpLGEuZGVsZXRlQnVmZmVyKHRoaXMuY29sb3JCdWZmZXIpLGEuZGVsZXRlQnVmZmVyKHRoaXMuaW5kZXhCdWZmZXIpfSxiLkZpbHRlclRleHR1cmU9ZnVuY3Rpb24oYSxjLGQsZSl7dGhpcy5nbD1hLHRoaXMuZnJhbWVCdWZmZXI9YS5jcmVhdGVGcmFtZWJ1ZmZlcigpLHRoaXMudGV4dHVyZT1hLmNyZWF0ZVRleHR1cmUoKSxlPWV8fGIuc2NhbGVNb2Rlcy5ERUZBVUxULGEuYmluZFRleHR1cmUoYS5URVhUVVJFXzJELHRoaXMudGV4dHVyZSksYS50ZXhQYXJhbWV0ZXJpKGEuVEVYVFVSRV8yRCxhLlRFWFRVUkVfTUFHX0ZJTFRFUixlPT09Yi5zY2FsZU1vZGVzLkxJTkVBUj9hLkxJTkVBUjphLk5FQVJFU1QpLGEudGV4UGFyYW1ldGVyaShhLlRFWFRVUkVfMkQsYS5URVhUVVJFX01JTl9GSUxURVIsZT09PWIuc2NhbGVNb2Rlcy5MSU5FQVI/YS5MSU5FQVI6YS5ORUFSRVNUKSxhLnRleFBhcmFtZXRlcmkoYS5URVhUVVJFXzJELGEuVEVYVFVSRV9XUkFQX1MsYS5DTEFNUF9UT19FREdFKSxhLnRleFBhcmFtZXRlcmkoYS5URVhUVVJFXzJELGEuVEVYVFVSRV9XUkFQX1QsYS5DTEFNUF9UT19FREdFKSxhLmJpbmRGcmFtZWJ1ZmZlcihhLkZSQU1FQlVGRkVSLHRoaXMuZnJhbWVCdWZmZXIpLGEuYmluZEZyYW1lYnVmZmVyKGEuRlJBTUVCVUZGRVIsdGhpcy5mcmFtZUJ1ZmZlciksYS5mcmFtZWJ1ZmZlclRleHR1cmUyRChhLkZSQU1FQlVGRkVSLGEuQ09MT1JfQVRUQUNITUVOVDAsYS5URVhUVVJFXzJELHRoaXMudGV4dHVyZSwwKSx0aGlzLnJlbmRlckJ1ZmZlcj1hLmNyZWF0ZVJlbmRlcmJ1ZmZlcigpLGEuYmluZFJlbmRlcmJ1ZmZlcihhLlJFTkRFUkJVRkZFUix0aGlzLnJlbmRlckJ1ZmZlciksYS5mcmFtZWJ1ZmZlclJlbmRlcmJ1ZmZlcihhLkZSQU1FQlVGRkVSLGEuREVQVEhfU1RFTkNJTF9BVFRBQ0hNRU5ULGEuUkVOREVSQlVGRkVSLHRoaXMucmVuZGVyQnVmZmVyKSx0aGlzLnJlc2l6ZShjLGQpXG59LGIuRmlsdGVyVGV4dHVyZS5wcm90b3R5cGUuY29uc3RydWN0b3I9Yi5GaWx0ZXJUZXh0dXJlLGIuRmlsdGVyVGV4dHVyZS5wcm90b3R5cGUuY2xlYXI9ZnVuY3Rpb24oKXt2YXIgYT10aGlzLmdsO2EuY2xlYXJDb2xvcigwLDAsMCwwKSxhLmNsZWFyKGEuQ09MT1JfQlVGRkVSX0JJVCl9LGIuRmlsdGVyVGV4dHVyZS5wcm90b3R5cGUucmVzaXplPWZ1bmN0aW9uKGEsYil7aWYodGhpcy53aWR0aCE9PWF8fHRoaXMuaGVpZ2h0IT09Yil7dGhpcy53aWR0aD1hLHRoaXMuaGVpZ2h0PWI7dmFyIGM9dGhpcy5nbDtjLmJpbmRUZXh0dXJlKGMuVEVYVFVSRV8yRCx0aGlzLnRleHR1cmUpLGMudGV4SW1hZ2UyRChjLlRFWFRVUkVfMkQsMCxjLlJHQkEsYSxiLDAsYy5SR0JBLGMuVU5TSUdORURfQllURSxudWxsKSxjLmJpbmRSZW5kZXJidWZmZXIoYy5SRU5ERVJCVUZGRVIsdGhpcy5yZW5kZXJCdWZmZXIpLGMucmVuZGVyYnVmZmVyU3RvcmFnZShjLlJFTkRFUkJVRkZFUixjLkRFUFRIX1NURU5DSUwsYSxiKX19LGIuRmlsdGVyVGV4dHVyZS5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbigpe3ZhciBhPXRoaXMuZ2w7YS5kZWxldGVGcmFtZWJ1ZmZlcih0aGlzLmZyYW1lQnVmZmVyKSxhLmRlbGV0ZVRleHR1cmUodGhpcy50ZXh0dXJlKSx0aGlzLmZyYW1lQnVmZmVyPW51bGwsdGhpcy50ZXh0dXJlPW51bGx9LGIuQ2FudmFzQnVmZmVyPWZ1bmN0aW9uKGEsYil7dGhpcy53aWR0aD1hLHRoaXMuaGVpZ2h0PWIsdGhpcy5jYW52YXM9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImNhbnZhc1wiKSx0aGlzLmNvbnRleHQ9dGhpcy5jYW52YXMuZ2V0Q29udGV4dChcIjJkXCIpLHRoaXMuY2FudmFzLndpZHRoPWEsdGhpcy5jYW52YXMuaGVpZ2h0PWJ9LGIuQ2FudmFzQnVmZmVyLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLkNhbnZhc0J1ZmZlcixiLkNhbnZhc0J1ZmZlci5wcm90b3R5cGUuY2xlYXI9ZnVuY3Rpb24oKXt0aGlzLmNvbnRleHQuc2V0VHJhbnNmb3JtKDEsMCwwLDEsMCwwKSx0aGlzLmNvbnRleHQuY2xlYXJSZWN0KDAsMCx0aGlzLndpZHRoLHRoaXMuaGVpZ2h0KX0sYi5DYW52YXNCdWZmZXIucHJvdG90eXBlLnJlc2l6ZT1mdW5jdGlvbihhLGIpe3RoaXMud2lkdGg9dGhpcy5jYW52YXMud2lkdGg9YSx0aGlzLmhlaWdodD10aGlzLmNhbnZhcy5oZWlnaHQ9Yn0sYi5DYW52YXNNYXNrTWFuYWdlcj1mdW5jdGlvbigpe30sYi5DYW52YXNNYXNrTWFuYWdlci5wcm90b3R5cGUuY29uc3RydWN0b3I9Yi5DYW52YXNNYXNrTWFuYWdlcixiLkNhbnZhc01hc2tNYW5hZ2VyLnByb3RvdHlwZS5wdXNoTWFzaz1mdW5jdGlvbihhLGMpe3ZhciBkPWMuY29udGV4dDtkLnNhdmUoKTt2YXIgZT1hLmFscGhhLGY9YS53b3JsZFRyYW5zZm9ybSxnPWMucmVzb2x1dGlvbjtkLnNldFRyYW5zZm9ybShmLmEqZyxmLmIqZyxmLmMqZyxmLmQqZyxmLnR4KmcsZi50eSpnKSxiLkNhbnZhc0dyYXBoaWNzLnJlbmRlckdyYXBoaWNzTWFzayhhLGQpLGQuY2xpcCgpLGEud29ybGRBbHBoYT1lfSxiLkNhbnZhc01hc2tNYW5hZ2VyLnByb3RvdHlwZS5wb3BNYXNrPWZ1bmN0aW9uKGEpe2EuY29udGV4dC5yZXN0b3JlKCl9LGIuQ2FudmFzVGludGVyPWZ1bmN0aW9uKCl7fSxiLkNhbnZhc1RpbnRlci5nZXRUaW50ZWRUZXh0dXJlPWZ1bmN0aW9uKGEsYyl7dmFyIGQ9YS50ZXh0dXJlO2M9Yi5DYW52YXNUaW50ZXIucm91bmRDb2xvcihjKTt2YXIgZT1cIiNcIisoXCIwMDAwMFwiKygwfGMpLnRvU3RyaW5nKDE2KSkuc3Vic3RyKC02KTtpZihkLnRpbnRDYWNoZT1kLnRpbnRDYWNoZXx8e30sZC50aW50Q2FjaGVbZV0pcmV0dXJuIGQudGludENhY2hlW2VdO3ZhciBmPWIuQ2FudmFzVGludGVyLmNhbnZhc3x8ZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImNhbnZhc1wiKTtpZihiLkNhbnZhc1RpbnRlci50aW50TWV0aG9kKGQsYyxmKSxiLkNhbnZhc1RpbnRlci5jb252ZXJ0VGludFRvSW1hZ2Upe3ZhciBnPW5ldyBJbWFnZTtnLnNyYz1mLnRvRGF0YVVSTCgpLGQudGludENhY2hlW2VdPWd9ZWxzZSBkLnRpbnRDYWNoZVtlXT1mLGIuQ2FudmFzVGludGVyLmNhbnZhcz1udWxsO3JldHVybiBmfSxiLkNhbnZhc1RpbnRlci50aW50V2l0aE11bHRpcGx5PWZ1bmN0aW9uKGEsYixjKXt2YXIgZD1jLmdldENvbnRleHQoXCIyZFwiKSxlPWEuY3JvcDtjLndpZHRoPWUud2lkdGgsYy5oZWlnaHQ9ZS5oZWlnaHQsZC5maWxsU3R5bGU9XCIjXCIrKFwiMDAwMDBcIisoMHxiKS50b1N0cmluZygxNikpLnN1YnN0cigtNiksZC5maWxsUmVjdCgwLDAsZS53aWR0aCxlLmhlaWdodCksZC5nbG9iYWxDb21wb3NpdGVPcGVyYXRpb249XCJtdWx0aXBseVwiLGQuZHJhd0ltYWdlKGEuYmFzZVRleHR1cmUuc291cmNlLGUueCxlLnksZS53aWR0aCxlLmhlaWdodCwwLDAsZS53aWR0aCxlLmhlaWdodCksZC5nbG9iYWxDb21wb3NpdGVPcGVyYXRpb249XCJkZXN0aW5hdGlvbi1hdG9wXCIsZC5kcmF3SW1hZ2UoYS5iYXNlVGV4dHVyZS5zb3VyY2UsZS54LGUueSxlLndpZHRoLGUuaGVpZ2h0LDAsMCxlLndpZHRoLGUuaGVpZ2h0KX0sYi5DYW52YXNUaW50ZXIudGludFdpdGhPdmVybGF5PWZ1bmN0aW9uKGEsYixjKXt2YXIgZD1jLmdldENvbnRleHQoXCIyZFwiKSxlPWEuY3JvcDtjLndpZHRoPWUud2lkdGgsYy5oZWlnaHQ9ZS5oZWlnaHQsZC5nbG9iYWxDb21wb3NpdGVPcGVyYXRpb249XCJjb3B5XCIsZC5maWxsU3R5bGU9XCIjXCIrKFwiMDAwMDBcIisoMHxiKS50b1N0cmluZygxNikpLnN1YnN0cigtNiksZC5maWxsUmVjdCgwLDAsZS53aWR0aCxlLmhlaWdodCksZC5nbG9iYWxDb21wb3NpdGVPcGVyYXRpb249XCJkZXN0aW5hdGlvbi1hdG9wXCIsZC5kcmF3SW1hZ2UoYS5iYXNlVGV4dHVyZS5zb3VyY2UsZS54LGUueSxlLndpZHRoLGUuaGVpZ2h0LDAsMCxlLndpZHRoLGUuaGVpZ2h0KX0sYi5DYW52YXNUaW50ZXIudGludFdpdGhQZXJQaXhlbD1mdW5jdGlvbihhLGMsZCl7dmFyIGU9ZC5nZXRDb250ZXh0KFwiMmRcIiksZj1hLmNyb3A7ZC53aWR0aD1mLndpZHRoLGQuaGVpZ2h0PWYuaGVpZ2h0LGUuZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uPVwiY29weVwiLGUuZHJhd0ltYWdlKGEuYmFzZVRleHR1cmUuc291cmNlLGYueCxmLnksZi53aWR0aCxmLmhlaWdodCwwLDAsZi53aWR0aCxmLmhlaWdodCk7Zm9yKHZhciBnPWIuaGV4MnJnYihjKSxoPWdbMF0saT1nWzFdLGo9Z1syXSxrPWUuZ2V0SW1hZ2VEYXRhKDAsMCxmLndpZHRoLGYuaGVpZ2h0KSxsPWsuZGF0YSxtPTA7bTxsLmxlbmd0aDttKz00KWxbbSswXSo9aCxsW20rMV0qPWksbFttKzJdKj1qO2UucHV0SW1hZ2VEYXRhKGssMCwwKX0sYi5DYW52YXNUaW50ZXIucm91bmRDb2xvcj1mdW5jdGlvbihhKXt2YXIgYz1iLkNhbnZhc1RpbnRlci5jYWNoZVN0ZXBzUGVyQ29sb3JDaGFubmVsLGQ9Yi5oZXgycmdiKGEpO3JldHVybiBkWzBdPU1hdGgubWluKDI1NSxkWzBdL2MqYyksZFsxXT1NYXRoLm1pbigyNTUsZFsxXS9jKmMpLGRbMl09TWF0aC5taW4oMjU1LGRbMl0vYypjKSxiLnJnYjJoZXgoZCl9LGIuQ2FudmFzVGludGVyLmNhY2hlU3RlcHNQZXJDb2xvckNoYW5uZWw9OCxiLkNhbnZhc1RpbnRlci5jb252ZXJ0VGludFRvSW1hZ2U9ITEsYi5DYW52YXNUaW50ZXIuY2FuVXNlTXVsdGlwbHk9Yi5jYW5Vc2VOZXdDYW52YXNCbGVuZE1vZGVzKCksYi5DYW52YXNUaW50ZXIudGludE1ldGhvZD1iLkNhbnZhc1RpbnRlci5jYW5Vc2VNdWx0aXBseT9iLkNhbnZhc1RpbnRlci50aW50V2l0aE11bHRpcGx5OmIuQ2FudmFzVGludGVyLnRpbnRXaXRoUGVyUGl4ZWwsYi5DYW52YXNSZW5kZXJlcj1mdW5jdGlvbihhLGMsZCl7aWYoZClmb3IodmFyIGUgaW4gYi5kZWZhdWx0UmVuZGVyT3B0aW9ucylcInVuZGVmaW5lZFwiPT10eXBlb2YgZFtlXSYmKGRbZV09Yi5kZWZhdWx0UmVuZGVyT3B0aW9uc1tlXSk7ZWxzZSBkPWIuZGVmYXVsdFJlbmRlck9wdGlvbnM7Yi5kZWZhdWx0UmVuZGVyZXJ8fChiLnNheUhlbGxvKFwiQ2FudmFzXCIpLGIuZGVmYXVsdFJlbmRlcmVyPXRoaXMpLHRoaXMudHlwZT1iLkNBTlZBU19SRU5ERVJFUix0aGlzLnJlc29sdXRpb249ZC5yZXNvbHV0aW9uLHRoaXMuY2xlYXJCZWZvcmVSZW5kZXI9ZC5jbGVhckJlZm9yZVJlbmRlcix0aGlzLnRyYW5zcGFyZW50PWQudHJhbnNwYXJlbnQsdGhpcy5hdXRvUmVzaXplPWQuYXV0b1Jlc2l6ZXx8ITEsdGhpcy53aWR0aD1hfHw4MDAsdGhpcy5oZWlnaHQ9Y3x8NjAwLHRoaXMud2lkdGgqPXRoaXMucmVzb2x1dGlvbix0aGlzLmhlaWdodCo9dGhpcy5yZXNvbHV0aW9uLHRoaXMudmlldz1kLnZpZXd8fGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJjYW52YXNcIiksdGhpcy5jb250ZXh0PXRoaXMudmlldy5nZXRDb250ZXh0KFwiMmRcIix7YWxwaGE6dGhpcy50cmFuc3BhcmVudH0pLHRoaXMucmVmcmVzaD0hMCx0aGlzLnZpZXcud2lkdGg9dGhpcy53aWR0aCp0aGlzLnJlc29sdXRpb24sdGhpcy52aWV3LmhlaWdodD10aGlzLmhlaWdodCp0aGlzLnJlc29sdXRpb24sdGhpcy5jb3VudD0wLHRoaXMubWFza01hbmFnZXI9bmV3IGIuQ2FudmFzTWFza01hbmFnZXIsdGhpcy5yZW5kZXJTZXNzaW9uPXtjb250ZXh0OnRoaXMuY29udGV4dCxtYXNrTWFuYWdlcjp0aGlzLm1hc2tNYW5hZ2VyLHNjYWxlTW9kZTpudWxsLHNtb290aFByb3BlcnR5Om51bGwscm91bmRQaXhlbHM6ITF9LHRoaXMubWFwQmxlbmRNb2RlcygpLHRoaXMucmVzaXplKGEsYyksXCJpbWFnZVNtb290aGluZ0VuYWJsZWRcImluIHRoaXMuY29udGV4dD90aGlzLnJlbmRlclNlc3Npb24uc21vb3RoUHJvcGVydHk9XCJpbWFnZVNtb290aGluZ0VuYWJsZWRcIjpcIndlYmtpdEltYWdlU21vb3RoaW5nRW5hYmxlZFwiaW4gdGhpcy5jb250ZXh0P3RoaXMucmVuZGVyU2Vzc2lvbi5zbW9vdGhQcm9wZXJ0eT1cIndlYmtpdEltYWdlU21vb3RoaW5nRW5hYmxlZFwiOlwibW96SW1hZ2VTbW9vdGhpbmdFbmFibGVkXCJpbiB0aGlzLmNvbnRleHQ/dGhpcy5yZW5kZXJTZXNzaW9uLnNtb290aFByb3BlcnR5PVwibW96SW1hZ2VTbW9vdGhpbmdFbmFibGVkXCI6XCJvSW1hZ2VTbW9vdGhpbmdFbmFibGVkXCJpbiB0aGlzLmNvbnRleHQ/dGhpcy5yZW5kZXJTZXNzaW9uLnNtb290aFByb3BlcnR5PVwib0ltYWdlU21vb3RoaW5nRW5hYmxlZFwiOlwibXNJbWFnZVNtb290aGluZ0VuYWJsZWRcImluIHRoaXMuY29udGV4dCYmKHRoaXMucmVuZGVyU2Vzc2lvbi5zbW9vdGhQcm9wZXJ0eT1cIm1zSW1hZ2VTbW9vdGhpbmdFbmFibGVkXCIpfSxiLkNhbnZhc1JlbmRlcmVyLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLkNhbnZhc1JlbmRlcmVyLGIuQ2FudmFzUmVuZGVyZXIucHJvdG90eXBlLnJlbmRlcj1mdW5jdGlvbihhKXthLnVwZGF0ZVRyYW5zZm9ybSgpLHRoaXMuY29udGV4dC5zZXRUcmFuc2Zvcm0oMSwwLDAsMSwwLDApLHRoaXMuY29udGV4dC5nbG9iYWxBbHBoYT0xLHRoaXMucmVuZGVyU2Vzc2lvbi5jdXJyZW50QmxlbmRNb2RlPWIuYmxlbmRNb2Rlcy5OT1JNQUwsdGhpcy5jb250ZXh0Lmdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbj1iLmJsZW5kTW9kZXNDYW52YXNbYi5ibGVuZE1vZGVzLk5PUk1BTF0sbmF2aWdhdG9yLmlzQ29jb29uSlMmJnRoaXMudmlldy5zY3JlZW5jYW52YXMmJih0aGlzLmNvbnRleHQuZmlsbFN0eWxlPVwiYmxhY2tcIix0aGlzLmNvbnRleHQuY2xlYXIoKSksdGhpcy5jbGVhckJlZm9yZVJlbmRlciYmKHRoaXMudHJhbnNwYXJlbnQ/dGhpcy5jb250ZXh0LmNsZWFyUmVjdCgwLDAsdGhpcy53aWR0aCx0aGlzLmhlaWdodCk6KHRoaXMuY29udGV4dC5maWxsU3R5bGU9YS5iYWNrZ3JvdW5kQ29sb3JTdHJpbmcsdGhpcy5jb250ZXh0LmZpbGxSZWN0KDAsMCx0aGlzLndpZHRoLHRoaXMuaGVpZ2h0KSkpLHRoaXMucmVuZGVyRGlzcGxheU9iamVjdChhKSxhLmludGVyYWN0aXZlJiYoYS5faW50ZXJhY3RpdmVFdmVudHNBZGRlZHx8KGEuX2ludGVyYWN0aXZlRXZlbnRzQWRkZWQ9ITAsYS5pbnRlcmFjdGlvbk1hbmFnZXIuc2V0VGFyZ2V0KHRoaXMpKSl9LGIuQ2FudmFzUmVuZGVyZXIucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oYSl7XCJ1bmRlZmluZWRcIj09dHlwZW9mIGEmJihhPSEwKSxhJiZ0aGlzLnZpZXcucGFyZW50JiZ0aGlzLnZpZXcucGFyZW50LnJlbW92ZUNoaWxkKHRoaXMudmlldyksdGhpcy52aWV3PW51bGwsdGhpcy5jb250ZXh0PW51bGwsdGhpcy5tYXNrTWFuYWdlcj1udWxsLHRoaXMucmVuZGVyU2Vzc2lvbj1udWxsfSxiLkNhbnZhc1JlbmRlcmVyLnByb3RvdHlwZS5yZXNpemU9ZnVuY3Rpb24oYSxiKXt0aGlzLndpZHRoPWEqdGhpcy5yZXNvbHV0aW9uLHRoaXMuaGVpZ2h0PWIqdGhpcy5yZXNvbHV0aW9uLHRoaXMudmlldy53aWR0aD10aGlzLndpZHRoLHRoaXMudmlldy5oZWlnaHQ9dGhpcy5oZWlnaHQsdGhpcy5hdXRvUmVzaXplJiYodGhpcy52aWV3LnN0eWxlLndpZHRoPXRoaXMud2lkdGgvdGhpcy5yZXNvbHV0aW9uK1wicHhcIix0aGlzLnZpZXcuc3R5bGUuaGVpZ2h0PXRoaXMuaGVpZ2h0L3RoaXMucmVzb2x1dGlvbitcInB4XCIpfSxiLkNhbnZhc1JlbmRlcmVyLnByb3RvdHlwZS5yZW5kZXJEaXNwbGF5T2JqZWN0PWZ1bmN0aW9uKGEsYil7dGhpcy5yZW5kZXJTZXNzaW9uLmNvbnRleHQ9Ynx8dGhpcy5jb250ZXh0LHRoaXMucmVuZGVyU2Vzc2lvbi5yZXNvbHV0aW9uPXRoaXMucmVzb2x1dGlvbixhLl9yZW5kZXJDYW52YXModGhpcy5yZW5kZXJTZXNzaW9uKX0sYi5DYW52YXNSZW5kZXJlci5wcm90b3R5cGUubWFwQmxlbmRNb2Rlcz1mdW5jdGlvbigpe2IuYmxlbmRNb2Rlc0NhbnZhc3x8KGIuYmxlbmRNb2Rlc0NhbnZhcz1bXSxiLmNhblVzZU5ld0NhbnZhc0JsZW5kTW9kZXMoKT8oYi5ibGVuZE1vZGVzQ2FudmFzW2IuYmxlbmRNb2Rlcy5OT1JNQUxdPVwic291cmNlLW92ZXJcIixiLmJsZW5kTW9kZXNDYW52YXNbYi5ibGVuZE1vZGVzLkFERF09XCJsaWdodGVyXCIsYi5ibGVuZE1vZGVzQ2FudmFzW2IuYmxlbmRNb2Rlcy5NVUxUSVBMWV09XCJtdWx0aXBseVwiLGIuYmxlbmRNb2Rlc0NhbnZhc1tiLmJsZW5kTW9kZXMuU0NSRUVOXT1cInNjcmVlblwiLGIuYmxlbmRNb2Rlc0NhbnZhc1tiLmJsZW5kTW9kZXMuT1ZFUkxBWV09XCJvdmVybGF5XCIsYi5ibGVuZE1vZGVzQ2FudmFzW2IuYmxlbmRNb2Rlcy5EQVJLRU5dPVwiZGFya2VuXCIsYi5ibGVuZE1vZGVzQ2FudmFzW2IuYmxlbmRNb2Rlcy5MSUdIVEVOXT1cImxpZ2h0ZW5cIixiLmJsZW5kTW9kZXNDYW52YXNbYi5ibGVuZE1vZGVzLkNPTE9SX0RPREdFXT1cImNvbG9yLWRvZGdlXCIsYi5ibGVuZE1vZGVzQ2FudmFzW2IuYmxlbmRNb2Rlcy5DT0xPUl9CVVJOXT1cImNvbG9yLWJ1cm5cIixiLmJsZW5kTW9kZXNDYW52YXNbYi5ibGVuZE1vZGVzLkhBUkRfTElHSFRdPVwiaGFyZC1saWdodFwiLGIuYmxlbmRNb2Rlc0NhbnZhc1tiLmJsZW5kTW9kZXMuU09GVF9MSUdIVF09XCJzb2Z0LWxpZ2h0XCIsYi5ibGVuZE1vZGVzQ2FudmFzW2IuYmxlbmRNb2Rlcy5ESUZGRVJFTkNFXT1cImRpZmZlcmVuY2VcIixiLmJsZW5kTW9kZXNDYW52YXNbYi5ibGVuZE1vZGVzLkVYQ0xVU0lPTl09XCJleGNsdXNpb25cIixiLmJsZW5kTW9kZXNDYW52YXNbYi5ibGVuZE1vZGVzLkhVRV09XCJodWVcIixiLmJsZW5kTW9kZXNDYW52YXNbYi5ibGVuZE1vZGVzLlNBVFVSQVRJT05dPVwic2F0dXJhdGlvblwiLGIuYmxlbmRNb2Rlc0NhbnZhc1tiLmJsZW5kTW9kZXMuQ09MT1JdPVwiY29sb3JcIixiLmJsZW5kTW9kZXNDYW52YXNbYi5ibGVuZE1vZGVzLkxVTUlOT1NJVFldPVwibHVtaW5vc2l0eVwiKTooYi5ibGVuZE1vZGVzQ2FudmFzW2IuYmxlbmRNb2Rlcy5OT1JNQUxdPVwic291cmNlLW92ZXJcIixiLmJsZW5kTW9kZXNDYW52YXNbYi5ibGVuZE1vZGVzLkFERF09XCJsaWdodGVyXCIsYi5ibGVuZE1vZGVzQ2FudmFzW2IuYmxlbmRNb2Rlcy5NVUxUSVBMWV09XCJzb3VyY2Utb3ZlclwiLGIuYmxlbmRNb2Rlc0NhbnZhc1tiLmJsZW5kTW9kZXMuU0NSRUVOXT1cInNvdXJjZS1vdmVyXCIsYi5ibGVuZE1vZGVzQ2FudmFzW2IuYmxlbmRNb2Rlcy5PVkVSTEFZXT1cInNvdXJjZS1vdmVyXCIsYi5ibGVuZE1vZGVzQ2FudmFzW2IuYmxlbmRNb2Rlcy5EQVJLRU5dPVwic291cmNlLW92ZXJcIixiLmJsZW5kTW9kZXNDYW52YXNbYi5ibGVuZE1vZGVzLkxJR0hURU5dPVwic291cmNlLW92ZXJcIixiLmJsZW5kTW9kZXNDYW52YXNbYi5ibGVuZE1vZGVzLkNPTE9SX0RPREdFXT1cInNvdXJjZS1vdmVyXCIsYi5ibGVuZE1vZGVzQ2FudmFzW2IuYmxlbmRNb2Rlcy5DT0xPUl9CVVJOXT1cInNvdXJjZS1vdmVyXCIsYi5ibGVuZE1vZGVzQ2FudmFzW2IuYmxlbmRNb2Rlcy5IQVJEX0xJR0hUXT1cInNvdXJjZS1vdmVyXCIsYi5ibGVuZE1vZGVzQ2FudmFzW2IuYmxlbmRNb2Rlcy5TT0ZUX0xJR0hUXT1cInNvdXJjZS1vdmVyXCIsYi5ibGVuZE1vZGVzQ2FudmFzW2IuYmxlbmRNb2Rlcy5ESUZGRVJFTkNFXT1cInNvdXJjZS1vdmVyXCIsYi5ibGVuZE1vZGVzQ2FudmFzW2IuYmxlbmRNb2Rlcy5FWENMVVNJT05dPVwic291cmNlLW92ZXJcIixiLmJsZW5kTW9kZXNDYW52YXNbYi5ibGVuZE1vZGVzLkhVRV09XCJzb3VyY2Utb3ZlclwiLGIuYmxlbmRNb2Rlc0NhbnZhc1tiLmJsZW5kTW9kZXMuU0FUVVJBVElPTl09XCJzb3VyY2Utb3ZlclwiLGIuYmxlbmRNb2Rlc0NhbnZhc1tiLmJsZW5kTW9kZXMuQ09MT1JdPVwic291cmNlLW92ZXJcIixiLmJsZW5kTW9kZXNDYW52YXNbYi5ibGVuZE1vZGVzLkxVTUlOT1NJVFldPVwic291cmNlLW92ZXJcIikpfSxiLkNhbnZhc0dyYXBoaWNzPWZ1bmN0aW9uKCl7fSxiLkNhbnZhc0dyYXBoaWNzLnJlbmRlckdyYXBoaWNzPWZ1bmN0aW9uKGEsYyl7dmFyIGQ9YS53b3JsZEFscGhhO2EuZGlydHkmJih0aGlzLnVwZGF0ZUdyYXBoaWNzVGludChhKSxhLmRpcnR5PSExKTtmb3IodmFyIGU9MDtlPGEuZ3JhcGhpY3NEYXRhLmxlbmd0aDtlKyspe3ZhciBmPWEuZ3JhcGhpY3NEYXRhW2VdLGc9Zi5zaGFwZSxoPWYuX2ZpbGxUaW50LGk9Zi5fbGluZVRpbnQ7aWYoYy5saW5lV2lkdGg9Zi5saW5lV2lkdGgsZi50eXBlPT09Yi5HcmFwaGljcy5QT0xZKXtjLmJlZ2luUGF0aCgpO3ZhciBqPWcucG9pbnRzO2MubW92ZVRvKGpbMF0salsxXSk7Zm9yKHZhciBrPTE7azxqLmxlbmd0aC8yO2srKyljLmxpbmVUbyhqWzIqa10salsyKmsrMV0pO2cuY2xvc2VkJiZjLmxpbmVUbyhqWzBdLGpbMV0pLGpbMF09PT1qW2oubGVuZ3RoLTJdJiZqWzFdPT09altqLmxlbmd0aC0xXSYmYy5jbG9zZVBhdGgoKSxmLmZpbGwmJihjLmdsb2JhbEFscGhhPWYuZmlsbEFscGhhKmQsYy5maWxsU3R5bGU9XCIjXCIrKFwiMDAwMDBcIisoMHxoKS50b1N0cmluZygxNikpLnN1YnN0cigtNiksYy5maWxsKCkpLGYubGluZVdpZHRoJiYoYy5nbG9iYWxBbHBoYT1mLmxpbmVBbHBoYSpkLGMuc3Ryb2tlU3R5bGU9XCIjXCIrKFwiMDAwMDBcIisoMHxpKS50b1N0cmluZygxNikpLnN1YnN0cigtNiksYy5zdHJva2UoKSl9ZWxzZSBpZihmLnR5cGU9PT1iLkdyYXBoaWNzLlJFQ1QpKGYuZmlsbENvbG9yfHwwPT09Zi5maWxsQ29sb3IpJiYoYy5nbG9iYWxBbHBoYT1mLmZpbGxBbHBoYSpkLGMuZmlsbFN0eWxlPVwiI1wiKyhcIjAwMDAwXCIrKDB8aCkudG9TdHJpbmcoMTYpKS5zdWJzdHIoLTYpLGMuZmlsbFJlY3QoZy54LGcueSxnLndpZHRoLGcuaGVpZ2h0KSksZi5saW5lV2lkdGgmJihjLmdsb2JhbEFscGhhPWYubGluZUFscGhhKmQsYy5zdHJva2VTdHlsZT1cIiNcIisoXCIwMDAwMFwiKygwfGkpLnRvU3RyaW5nKDE2KSkuc3Vic3RyKC02KSxjLnN0cm9rZVJlY3QoZy54LGcueSxnLndpZHRoLGcuaGVpZ2h0KSk7ZWxzZSBpZihmLnR5cGU9PT1iLkdyYXBoaWNzLkNJUkMpYy5iZWdpblBhdGgoKSxjLmFyYyhnLngsZy55LGcucmFkaXVzLDAsMipNYXRoLlBJKSxjLmNsb3NlUGF0aCgpLGYuZmlsbCYmKGMuZ2xvYmFsQWxwaGE9Zi5maWxsQWxwaGEqZCxjLmZpbGxTdHlsZT1cIiNcIisoXCIwMDAwMFwiKygwfGgpLnRvU3RyaW5nKDE2KSkuc3Vic3RyKC02KSxjLmZpbGwoKSksZi5saW5lV2lkdGgmJihjLmdsb2JhbEFscGhhPWYubGluZUFscGhhKmQsYy5zdHJva2VTdHlsZT1cIiNcIisoXCIwMDAwMFwiKygwfGkpLnRvU3RyaW5nKDE2KSkuc3Vic3RyKC02KSxjLnN0cm9rZSgpKTtlbHNlIGlmKGYudHlwZT09PWIuR3JhcGhpY3MuRUxJUCl7dmFyIGw9MipnLndpZHRoLG09MipnLmhlaWdodCxuPWcueC1sLzIsbz1nLnktbS8yO2MuYmVnaW5QYXRoKCk7dmFyIHA9LjU1MjI4NDgscT1sLzIqcCxyPW0vMipwLHM9bitsLHQ9byttLHU9bitsLzIsdj1vK20vMjtjLm1vdmVUbyhuLHYpLGMuYmV6aWVyQ3VydmVUbyhuLHYtcix1LXEsbyx1LG8pLGMuYmV6aWVyQ3VydmVUbyh1K3EsbyxzLHYtcixzLHYpLGMuYmV6aWVyQ3VydmVUbyhzLHYrcix1K3EsdCx1LHQpLGMuYmV6aWVyQ3VydmVUbyh1LXEsdCxuLHYrcixuLHYpLGMuY2xvc2VQYXRoKCksZi5maWxsJiYoYy5nbG9iYWxBbHBoYT1mLmZpbGxBbHBoYSpkLGMuZmlsbFN0eWxlPVwiI1wiKyhcIjAwMDAwXCIrKDB8aCkudG9TdHJpbmcoMTYpKS5zdWJzdHIoLTYpLGMuZmlsbCgpKSxmLmxpbmVXaWR0aCYmKGMuZ2xvYmFsQWxwaGE9Zi5saW5lQWxwaGEqZCxjLnN0cm9rZVN0eWxlPVwiI1wiKyhcIjAwMDAwXCIrKDB8aSkudG9TdHJpbmcoMTYpKS5zdWJzdHIoLTYpLGMuc3Ryb2tlKCkpfWVsc2UgaWYoZi50eXBlPT09Yi5HcmFwaGljcy5SUkVDKXt2YXIgdz1nLngseD1nLnkseT1nLndpZHRoLHo9Zy5oZWlnaHQsQT1nLnJhZGl1cyxCPU1hdGgubWluKHkseikvMnwwO0E9QT5CP0I6QSxjLmJlZ2luUGF0aCgpLGMubW92ZVRvKHcseCtBKSxjLmxpbmVUbyh3LHgrei1BKSxjLnF1YWRyYXRpY0N1cnZlVG8odyx4K3osdytBLHgreiksYy5saW5lVG8odyt5LUEseCt6KSxjLnF1YWRyYXRpY0N1cnZlVG8odyt5LHgreix3K3kseCt6LUEpLGMubGluZVRvKHcreSx4K0EpLGMucXVhZHJhdGljQ3VydmVUbyh3K3kseCx3K3ktQSx4KSxjLmxpbmVUbyh3K0EseCksYy5xdWFkcmF0aWNDdXJ2ZVRvKHcseCx3LHgrQSksYy5jbG9zZVBhdGgoKSwoZi5maWxsQ29sb3J8fDA9PT1mLmZpbGxDb2xvcikmJihjLmdsb2JhbEFscGhhPWYuZmlsbEFscGhhKmQsYy5maWxsU3R5bGU9XCIjXCIrKFwiMDAwMDBcIisoMHxoKS50b1N0cmluZygxNikpLnN1YnN0cigtNiksYy5maWxsKCkpLGYubGluZVdpZHRoJiYoYy5nbG9iYWxBbHBoYT1mLmxpbmVBbHBoYSpkLGMuc3Ryb2tlU3R5bGU9XCIjXCIrKFwiMDAwMDBcIisoMHxpKS50b1N0cmluZygxNikpLnN1YnN0cigtNiksYy5zdHJva2UoKSl9fX0sYi5DYW52YXNHcmFwaGljcy5yZW5kZXJHcmFwaGljc01hc2s9ZnVuY3Rpb24oYSxjKXt2YXIgZD1hLmdyYXBoaWNzRGF0YS5sZW5ndGg7aWYoMCE9PWQpe2Q+MSYmKGQ9MSx3aW5kb3cuY29uc29sZS5sb2coXCJQaXhpLmpzIHdhcm5pbmc6IG1hc2tzIGluIGNhbnZhcyBjYW4gb25seSBtYXNrIHVzaW5nIHRoZSBmaXJzdCBwYXRoIGluIHRoZSBncmFwaGljcyBvYmplY3RcIikpO2Zvcih2YXIgZT0wOzE+ZTtlKyspe3ZhciBmPWEuZ3JhcGhpY3NEYXRhW2VdLGc9Zi5zaGFwZTtpZihmLnR5cGU9PT1iLkdyYXBoaWNzLlBPTFkpe2MuYmVnaW5QYXRoKCk7dmFyIGg9Zy5wb2ludHM7Yy5tb3ZlVG8oaFswXSxoWzFdKTtmb3IodmFyIGk9MTtpPGgubGVuZ3RoLzI7aSsrKWMubGluZVRvKGhbMippXSxoWzIqaSsxXSk7aFswXT09PWhbaC5sZW5ndGgtMl0mJmhbMV09PT1oW2gubGVuZ3RoLTFdJiZjLmNsb3NlUGF0aCgpfWVsc2UgaWYoZi50eXBlPT09Yi5HcmFwaGljcy5SRUNUKWMuYmVnaW5QYXRoKCksYy5yZWN0KGcueCxnLnksZy53aWR0aCxnLmhlaWdodCksYy5jbG9zZVBhdGgoKTtlbHNlIGlmKGYudHlwZT09PWIuR3JhcGhpY3MuQ0lSQyljLmJlZ2luUGF0aCgpLGMuYXJjKGcueCxnLnksZy5yYWRpdXMsMCwyKk1hdGguUEkpLGMuY2xvc2VQYXRoKCk7ZWxzZSBpZihmLnR5cGU9PT1iLkdyYXBoaWNzLkVMSVApe3ZhciBqPTIqZy53aWR0aCxrPTIqZy5oZWlnaHQsbD1nLngtai8yLG09Zy55LWsvMjtjLmJlZ2luUGF0aCgpO3ZhciBuPS41NTIyODQ4LG89ai8yKm4scD1rLzIqbixxPWwraixyPW0rayxzPWwrai8yLHQ9bStrLzI7Yy5tb3ZlVG8obCx0KSxjLmJlemllckN1cnZlVG8obCx0LXAscy1vLG0scyxtKSxjLmJlemllckN1cnZlVG8ocytvLG0scSx0LXAscSx0KSxjLmJlemllckN1cnZlVG8ocSx0K3AscytvLHIscyxyKSxjLmJlemllckN1cnZlVG8ocy1vLHIsbCx0K3AsbCx0KSxjLmNsb3NlUGF0aCgpfWVsc2UgaWYoZi50eXBlPT09Yi5HcmFwaGljcy5SUkVDKXt2YXIgdT1nLnBvaW50cyx2PXVbMF0sdz11WzFdLHg9dVsyXSx5PXVbM10sej11WzRdLEE9TWF0aC5taW4oeCx5KS8yfDA7ej16PkE/QTp6LGMuYmVnaW5QYXRoKCksYy5tb3ZlVG8odix3K3opLGMubGluZVRvKHYsdyt5LXopLGMucXVhZHJhdGljQ3VydmVUbyh2LHcreSx2K3osdyt5KSxjLmxpbmVUbyh2K3gteix3K3kpLGMucXVhZHJhdGljQ3VydmVUbyh2K3gsdyt5LHYreCx3K3kteiksYy5saW5lVG8odit4LHcreiksYy5xdWFkcmF0aWNDdXJ2ZVRvKHYreCx3LHYreC16LHcpLGMubGluZVRvKHYreix3KSxjLnF1YWRyYXRpY0N1cnZlVG8odix3LHYsdyt6KSxjLmNsb3NlUGF0aCgpfX19fSxiLkNhbnZhc0dyYXBoaWNzLnVwZGF0ZUdyYXBoaWNzVGludD1mdW5jdGlvbihhKXtpZigxNjc3NzIxNSE9PWEudGludClmb3IodmFyIGI9KGEudGludD4+MTYmMjU1KS8yNTUsYz0oYS50aW50Pj44JjI1NSkvMjU1LGQ9KDI1NSZhLnRpbnQpLzI1NSxlPTA7ZTxhLmdyYXBoaWNzRGF0YS5sZW5ndGg7ZSsrKXt2YXIgZj1hLmdyYXBoaWNzRGF0YVtlXSxnPTB8Zi5maWxsQ29sb3IsaD0wfGYubGluZUNvbG9yO2YuX2ZpbGxUaW50PSgoZz4+MTYmMjU1KS8yNTUqYioyNTU8PDE2KSsoKGc+PjgmMjU1KS8yNTUqYyoyNTU8PDgpKygyNTUmZykvMjU1KmQqMjU1LGYuX2xpbmVUaW50PSgoaD4+MTYmMjU1KS8yNTUqYioyNTU8PDE2KSsoKGg+PjgmMjU1KS8yNTUqYyoyNTU8PDgpKygyNTUmaCkvMjU1KmQqMjU1fX0sYi5HcmFwaGljcz1mdW5jdGlvbigpe2IuRGlzcGxheU9iamVjdENvbnRhaW5lci5jYWxsKHRoaXMpLHRoaXMucmVuZGVyYWJsZT0hMCx0aGlzLmZpbGxBbHBoYT0xLHRoaXMubGluZVdpZHRoPTAsdGhpcy5saW5lQ29sb3I9MCx0aGlzLmdyYXBoaWNzRGF0YT1bXSx0aGlzLnRpbnQ9MTY3NzcyMTUsdGhpcy5ibGVuZE1vZGU9Yi5ibGVuZE1vZGVzLk5PUk1BTCx0aGlzLmN1cnJlbnRQYXRoPW51bGwsdGhpcy5fd2ViR0w9W10sdGhpcy5pc01hc2s9ITEsdGhpcy5ib3VuZHNQYWRkaW5nPTAsdGhpcy5fbG9jYWxCb3VuZHM9bmV3IGIuUmVjdGFuZ2xlKDAsMCwxLDEpLHRoaXMuZGlydHk9ITAsdGhpcy53ZWJHTERpcnR5PSExLHRoaXMuY2FjaGVkU3ByaXRlRGlydHk9ITF9LGIuR3JhcGhpY3MucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoYi5EaXNwbGF5T2JqZWN0Q29udGFpbmVyLnByb3RvdHlwZSksYi5HcmFwaGljcy5wcm90b3R5cGUuY29uc3RydWN0b3I9Yi5HcmFwaGljcyxPYmplY3QuZGVmaW5lUHJvcGVydHkoYi5HcmFwaGljcy5wcm90b3R5cGUsXCJjYWNoZUFzQml0bWFwXCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLl9jYWNoZUFzQml0bWFwfSxzZXQ6ZnVuY3Rpb24oYSl7dGhpcy5fY2FjaGVBc0JpdG1hcD1hLHRoaXMuX2NhY2hlQXNCaXRtYXA/dGhpcy5fZ2VuZXJhdGVDYWNoZWRTcHJpdGUoKToodGhpcy5kZXN0cm95Q2FjaGVkU3ByaXRlKCksdGhpcy5kaXJ0eT0hMCl9fSksYi5HcmFwaGljcy5wcm90b3R5cGUubGluZVN0eWxlPWZ1bmN0aW9uKGEsYyxkKXtpZih0aGlzLmxpbmVXaWR0aD1hfHwwLHRoaXMubGluZUNvbG9yPWN8fDAsdGhpcy5saW5lQWxwaGE9YXJndW1lbnRzLmxlbmd0aDwzPzE6ZCx0aGlzLmN1cnJlbnRQYXRoKXtpZih0aGlzLmN1cnJlbnRQYXRoLnNoYXBlLnBvaW50cy5sZW5ndGgpcmV0dXJuIHRoaXMuZHJhd1NoYXBlKG5ldyBiLlBvbHlnb24odGhpcy5jdXJyZW50UGF0aC5zaGFwZS5wb2ludHMuc2xpY2UoLTIpKSksdGhpczt0aGlzLmN1cnJlbnRQYXRoLmxpbmVXaWR0aD10aGlzLmxpbmVXaWR0aCx0aGlzLmN1cnJlbnRQYXRoLmxpbmVDb2xvcj10aGlzLmxpbmVDb2xvcix0aGlzLmN1cnJlbnRQYXRoLmxpbmVBbHBoYT10aGlzLmxpbmVBbHBoYX1yZXR1cm4gdGhpc30sYi5HcmFwaGljcy5wcm90b3R5cGUubW92ZVRvPWZ1bmN0aW9uKGEsYyl7cmV0dXJuIHRoaXMuZHJhd1NoYXBlKG5ldyBiLlBvbHlnb24oW2EsY10pKSx0aGlzfSxiLkdyYXBoaWNzLnByb3RvdHlwZS5saW5lVG89ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5jdXJyZW50UGF0aC5zaGFwZS5wb2ludHMucHVzaChhLGIpLHRoaXMuZGlydHk9ITAsdGhpc30sYi5HcmFwaGljcy5wcm90b3R5cGUucXVhZHJhdGljQ3VydmVUbz1mdW5jdGlvbihhLGIsYyxkKXt0aGlzLmN1cnJlbnRQYXRoPzA9PT10aGlzLmN1cnJlbnRQYXRoLnNoYXBlLnBvaW50cy5sZW5ndGgmJih0aGlzLmN1cnJlbnRQYXRoLnNoYXBlLnBvaW50cz1bMCwwXSk6dGhpcy5tb3ZlVG8oMCwwKTt2YXIgZSxmLGc9MjAsaD10aGlzLmN1cnJlbnRQYXRoLnNoYXBlLnBvaW50czswPT09aC5sZW5ndGgmJnRoaXMubW92ZVRvKDAsMCk7Zm9yKHZhciBpPWhbaC5sZW5ndGgtMl0saj1oW2gubGVuZ3RoLTFdLGs9MCxsPTE7Zz49bDtsKyspaz1sL2csZT1pKyhhLWkpKmssZj1qKyhiLWopKmssaC5wdXNoKGUrKGErKGMtYSkqay1lKSprLGYrKGIrKGQtYikqay1mKSprKTtyZXR1cm4gdGhpcy5kaXJ0eT0hMCx0aGlzfSxiLkdyYXBoaWNzLnByb3RvdHlwZS5iZXppZXJDdXJ2ZVRvPWZ1bmN0aW9uKGEsYixjLGQsZSxmKXt0aGlzLmN1cnJlbnRQYXRoPzA9PT10aGlzLmN1cnJlbnRQYXRoLnNoYXBlLnBvaW50cy5sZW5ndGgmJih0aGlzLmN1cnJlbnRQYXRoLnNoYXBlLnBvaW50cz1bMCwwXSk6dGhpcy5tb3ZlVG8oMCwwKTtmb3IodmFyIGcsaCxpLGosayxsPTIwLG09dGhpcy5jdXJyZW50UGF0aC5zaGFwZS5wb2ludHMsbj1tW20ubGVuZ3RoLTJdLG89bVttLmxlbmd0aC0xXSxwPTAscT0xO2w+PXE7cSsrKXA9cS9sLGc9MS1wLGg9ZypnLGk9aCpnLGo9cCpwLGs9aipwLG0ucHVzaChpKm4rMypoKnAqYSszKmcqaipjK2sqZSxpKm8rMypoKnAqYiszKmcqaipkK2sqZik7cmV0dXJuIHRoaXMuZGlydHk9ITAsdGhpc30sYi5HcmFwaGljcy5wcm90b3R5cGUuYXJjVG89ZnVuY3Rpb24oYSxiLGMsZCxlKXt0aGlzLmN1cnJlbnRQYXRoPzA9PT10aGlzLmN1cnJlbnRQYXRoLnNoYXBlLnBvaW50cy5sZW5ndGgmJnRoaXMuY3VycmVudFBhdGguc2hhcGUucG9pbnRzLnB1c2goYSxiKTp0aGlzLm1vdmVUbyhhLGIpO3ZhciBmPXRoaXMuY3VycmVudFBhdGguc2hhcGUucG9pbnRzLGc9ZltmLmxlbmd0aC0yXSxoPWZbZi5sZW5ndGgtMV0saT1oLWIsaj1nLWEsaz1kLWIsbD1jLWEsbT1NYXRoLmFicyhpKmwtaiprKTtpZigxZS04Pm18fDA9PT1lKShmW2YubGVuZ3RoLTJdIT09YXx8ZltmLmxlbmd0aC0xXSE9PWIpJiZmLnB1c2goYSxiKTtlbHNle3ZhciBuPWkqaStqKmosbz1rKmsrbCpsLHA9aSprK2oqbCxxPWUqTWF0aC5zcXJ0KG4pL20scj1lKk1hdGguc3FydChvKS9tLHM9cSpwL24sdD1yKnAvbyx1PXEqbCtyKmosdj1xKmsrcippLHc9aioocitzKSx4PWkqKHIrcykseT1sKihxK3QpLHo9ayoocSt0KSxBPU1hdGguYXRhbjIoeC12LHctdSksQj1NYXRoLmF0YW4yKHotdix5LXUpO3RoaXMuYXJjKHUrYSx2K2IsZSxBLEIsaiprPmwqaSl9cmV0dXJuIHRoaXMuZGlydHk9ITAsdGhpc30sYi5HcmFwaGljcy5wcm90b3R5cGUuYXJjPWZ1bmN0aW9uKGEsYixjLGQsZSxmKXt2YXIgZyxoPWErTWF0aC5jb3MoZCkqYyxpPWIrTWF0aC5zaW4oZCkqYztpZih0aGlzLmN1cnJlbnRQYXRoPyhnPXRoaXMuY3VycmVudFBhdGguc2hhcGUucG9pbnRzLDA9PT1nLmxlbmd0aD9nLnB1c2goaCxpKTooZ1tnLmxlbmd0aC0yXSE9PWh8fGdbZy5sZW5ndGgtMV0hPT1pKSYmZy5wdXNoKGgsaSkpOih0aGlzLm1vdmVUbyhoLGkpLGc9dGhpcy5jdXJyZW50UGF0aC5zaGFwZS5wb2ludHMpLGQ9PT1lKXJldHVybiB0aGlzOyFmJiZkPj1lP2UrPTIqTWF0aC5QSTpmJiZlPj1kJiYoZCs9MipNYXRoLlBJKTt2YXIgaj1mPy0xKihkLWUpOmUtZCxrPU1hdGguYWJzKGopLygyKk1hdGguUEkpKjQwO2lmKDA9PT1qKXJldHVybiB0aGlzO2Zvcih2YXIgbD1qLygyKmspLG09MipsLG49TWF0aC5jb3MobCksbz1NYXRoLnNpbihsKSxwPWstMSxxPXAlMS9wLHI9MDtwPj1yO3IrKyl7dmFyIHM9citxKnIsdD1sK2QrbSpzLHU9TWF0aC5jb3ModCksdj0tTWF0aC5zaW4odCk7Zy5wdXNoKChuKnUrbyp2KSpjK2EsKG4qLXYrbyp1KSpjK2IpfXJldHVybiB0aGlzLmRpcnR5PSEwLHRoaXN9LGIuR3JhcGhpY3MucHJvdG90eXBlLmJlZ2luRmlsbD1mdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLmZpbGxpbmc9ITAsdGhpcy5maWxsQ29sb3I9YXx8MCx0aGlzLmZpbGxBbHBoYT12b2lkIDA9PT1iPzE6Yix0aGlzLmN1cnJlbnRQYXRoJiZ0aGlzLmN1cnJlbnRQYXRoLnNoYXBlLnBvaW50cy5sZW5ndGg8PTImJih0aGlzLmN1cnJlbnRQYXRoLmZpbGw9dGhpcy5maWxsaW5nLHRoaXMuY3VycmVudFBhdGguZmlsbENvbG9yPXRoaXMuZmlsbENvbG9yLHRoaXMuY3VycmVudFBhdGguZmlsbEFscGhhPXRoaXMuZmlsbEFscGhhKSx0aGlzfSxiLkdyYXBoaWNzLnByb3RvdHlwZS5lbmRGaWxsPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZmlsbGluZz0hMSx0aGlzLmZpbGxDb2xvcj1udWxsLHRoaXMuZmlsbEFscGhhPTEsdGhpc30sYi5HcmFwaGljcy5wcm90b3R5cGUuZHJhd1JlY3Q9ZnVuY3Rpb24oYSxjLGQsZSl7cmV0dXJuIHRoaXMuZHJhd1NoYXBlKG5ldyBiLlJlY3RhbmdsZShhLGMsZCxlKSksdGhpc30sYi5HcmFwaGljcy5wcm90b3R5cGUuZHJhd1JvdW5kZWRSZWN0PWZ1bmN0aW9uKGEsYyxkLGUsZil7cmV0dXJuIHRoaXMuZHJhd1NoYXBlKG5ldyBiLlJvdW5kZWRSZWN0YW5nbGUoYSxjLGQsZSxmKSksdGhpc30sYi5HcmFwaGljcy5wcm90b3R5cGUuZHJhd0NpcmNsZT1mdW5jdGlvbihhLGMsZCl7cmV0dXJuIHRoaXMuZHJhd1NoYXBlKG5ldyBiLkNpcmNsZShhLGMsZCkpLHRoaXN9LGIuR3JhcGhpY3MucHJvdG90eXBlLmRyYXdFbGxpcHNlPWZ1bmN0aW9uKGEsYyxkLGUpe3JldHVybiB0aGlzLmRyYXdTaGFwZShuZXcgYi5FbGxpcHNlKGEsYyxkLGUpKSx0aGlzfSxiLkdyYXBoaWNzLnByb3RvdHlwZS5kcmF3UG9seWdvbj1mdW5jdGlvbihhKXtyZXR1cm4gYSBpbnN0YW5jZW9mIEFycmF5fHwoYT1BcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpKSx0aGlzLmRyYXdTaGFwZShuZXcgYi5Qb2x5Z29uKGEpKSx0aGlzfSxiLkdyYXBoaWNzLnByb3RvdHlwZS5jbGVhcj1mdW5jdGlvbigpe3JldHVybiB0aGlzLmxpbmVXaWR0aD0wLHRoaXMuZmlsbGluZz0hMSx0aGlzLmRpcnR5PSEwLHRoaXMuY2xlYXJEaXJ0eT0hMCx0aGlzLmdyYXBoaWNzRGF0YT1bXSx0aGlzfSxiLkdyYXBoaWNzLnByb3RvdHlwZS5nZW5lcmF0ZVRleHR1cmU9ZnVuY3Rpb24oYSxjKXthPWF8fDE7dmFyIGQ9dGhpcy5nZXRCb3VuZHMoKSxlPW5ldyBiLkNhbnZhc0J1ZmZlcihkLndpZHRoKmEsZC5oZWlnaHQqYSksZj1iLlRleHR1cmUuZnJvbUNhbnZhcyhlLmNhbnZhcyxjKTtyZXR1cm4gZi5iYXNlVGV4dHVyZS5yZXNvbHV0aW9uPWEsZS5jb250ZXh0LnNjYWxlKGEsYSksZS5jb250ZXh0LnRyYW5zbGF0ZSgtZC54LC1kLnkpLGIuQ2FudmFzR3JhcGhpY3MucmVuZGVyR3JhcGhpY3ModGhpcyxlLmNvbnRleHQpLGZ9LGIuR3JhcGhpY3MucHJvdG90eXBlLl9yZW5kZXJXZWJHTD1mdW5jdGlvbihhKXtpZih0aGlzLnZpc2libGUhPT0hMSYmMCE9PXRoaXMuYWxwaGEmJnRoaXMuaXNNYXNrIT09ITApe2lmKHRoaXMuX2NhY2hlQXNCaXRtYXApcmV0dXJuKHRoaXMuZGlydHl8fHRoaXMuY2FjaGVkU3ByaXRlRGlydHkpJiYodGhpcy5fZ2VuZXJhdGVDYWNoZWRTcHJpdGUoKSx0aGlzLnVwZGF0ZUNhY2hlZFNwcml0ZVRleHR1cmUoKSx0aGlzLmNhY2hlZFNwcml0ZURpcnR5PSExLHRoaXMuZGlydHk9ITEpLHRoaXMuX2NhY2hlZFNwcml0ZS53b3JsZEFscGhhPXRoaXMud29ybGRBbHBoYSx2b2lkIGIuU3ByaXRlLnByb3RvdHlwZS5fcmVuZGVyV2ViR0wuY2FsbCh0aGlzLl9jYWNoZWRTcHJpdGUsYSk7aWYoYS5zcHJpdGVCYXRjaC5zdG9wKCksYS5ibGVuZE1vZGVNYW5hZ2VyLnNldEJsZW5kTW9kZSh0aGlzLmJsZW5kTW9kZSksdGhpcy5fbWFzayYmYS5tYXNrTWFuYWdlci5wdXNoTWFzayh0aGlzLl9tYXNrLGEpLHRoaXMuX2ZpbHRlcnMmJmEuZmlsdGVyTWFuYWdlci5wdXNoRmlsdGVyKHRoaXMuX2ZpbHRlckJsb2NrKSx0aGlzLmJsZW5kTW9kZSE9PWEuc3ByaXRlQmF0Y2guY3VycmVudEJsZW5kTW9kZSl7YS5zcHJpdGVCYXRjaC5jdXJyZW50QmxlbmRNb2RlPXRoaXMuYmxlbmRNb2RlO3ZhciBjPWIuYmxlbmRNb2Rlc1dlYkdMW2Euc3ByaXRlQmF0Y2guY3VycmVudEJsZW5kTW9kZV07YS5zcHJpdGVCYXRjaC5nbC5ibGVuZEZ1bmMoY1swXSxjWzFdKX1pZih0aGlzLndlYkdMRGlydHkmJih0aGlzLmRpcnR5PSEwLHRoaXMud2ViR0xEaXJ0eT0hMSksYi5XZWJHTEdyYXBoaWNzLnJlbmRlckdyYXBoaWNzKHRoaXMsYSksdGhpcy5jaGlsZHJlbi5sZW5ndGgpe2Euc3ByaXRlQmF0Y2guc3RhcnQoKTtmb3IodmFyIGQ9MCxlPXRoaXMuY2hpbGRyZW4ubGVuZ3RoO2U+ZDtkKyspdGhpcy5jaGlsZHJlbltkXS5fcmVuZGVyV2ViR0woYSk7YS5zcHJpdGVCYXRjaC5zdG9wKCl9dGhpcy5fZmlsdGVycyYmYS5maWx0ZXJNYW5hZ2VyLnBvcEZpbHRlcigpLHRoaXMuX21hc2smJmEubWFza01hbmFnZXIucG9wTWFzayh0aGlzLm1hc2ssYSksYS5kcmF3Q291bnQrKyxhLnNwcml0ZUJhdGNoLnN0YXJ0KCl9fSxiLkdyYXBoaWNzLnByb3RvdHlwZS5fcmVuZGVyQ2FudmFzPWZ1bmN0aW9uKGEpe2lmKHRoaXMudmlzaWJsZSE9PSExJiYwIT09dGhpcy5hbHBoYSYmdGhpcy5pc01hc2shPT0hMCl7aWYodGhpcy5fY2FjaGVBc0JpdG1hcClyZXR1cm4odGhpcy5kaXJ0eXx8dGhpcy5jYWNoZWRTcHJpdGVEaXJ0eSkmJih0aGlzLl9nZW5lcmF0ZUNhY2hlZFNwcml0ZSgpLHRoaXMudXBkYXRlQ2FjaGVkU3ByaXRlVGV4dHVyZSgpLHRoaXMuY2FjaGVkU3ByaXRlRGlydHk9ITEsdGhpcy5kaXJ0eT0hMSksdGhpcy5fY2FjaGVkU3ByaXRlLmFscGhhPXRoaXMuYWxwaGEsdm9pZCBiLlNwcml0ZS5wcm90b3R5cGUuX3JlbmRlckNhbnZhcy5jYWxsKHRoaXMuX2NhY2hlZFNwcml0ZSxhKTt2YXIgYz1hLmNvbnRleHQsZD10aGlzLndvcmxkVHJhbnNmb3JtO3RoaXMuYmxlbmRNb2RlIT09YS5jdXJyZW50QmxlbmRNb2RlJiYoYS5jdXJyZW50QmxlbmRNb2RlPXRoaXMuYmxlbmRNb2RlLGMuZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uPWIuYmxlbmRNb2Rlc0NhbnZhc1thLmN1cnJlbnRCbGVuZE1vZGVdKSx0aGlzLl9tYXNrJiZhLm1hc2tNYW5hZ2VyLnB1c2hNYXNrKHRoaXMuX21hc2ssYSk7dmFyIGU9YS5yZXNvbHV0aW9uO2Muc2V0VHJhbnNmb3JtKGQuYSplLGQuYiplLGQuYyplLGQuZCplLGQudHgqZSxkLnR5KmUpLGIuQ2FudmFzR3JhcGhpY3MucmVuZGVyR3JhcGhpY3ModGhpcyxjKTtmb3IodmFyIGY9MCxnPXRoaXMuY2hpbGRyZW4ubGVuZ3RoO2c+ZjtmKyspdGhpcy5jaGlsZHJlbltmXS5fcmVuZGVyQ2FudmFzKGEpO3RoaXMuX21hc2smJmEubWFza01hbmFnZXIucG9wTWFzayhhKX19LGIuR3JhcGhpY3MucHJvdG90eXBlLmdldEJvdW5kcz1mdW5jdGlvbihhKXtpZih0aGlzLmlzTWFzaylyZXR1cm4gYi5FbXB0eVJlY3RhbmdsZTt0aGlzLmRpcnR5JiYodGhpcy51cGRhdGVMb2NhbEJvdW5kcygpLHRoaXMud2ViR0xEaXJ0eT0hMCx0aGlzLmNhY2hlZFNwcml0ZURpcnR5PSEwLHRoaXMuZGlydHk9ITEpO3ZhciBjPXRoaXMuX2xvY2FsQm91bmRzLGQ9Yy54LGU9Yy53aWR0aCtjLngsZj1jLnksZz1jLmhlaWdodCtjLnksaD1hfHx0aGlzLndvcmxkVHJhbnNmb3JtLGk9aC5hLGo9aC5iLGs9aC5jLGw9aC5kLG09aC50eCxuPWgudHksbz1pKmUraypnK20scD1sKmcraiplK24scT1pKmQraypnK20scj1sKmcraipkK24scz1pKmQraypmK20sdD1sKmYraipkK24sdT1pKmUraypmK20sdj1sKmYraiplK24sdz1vLHg9cCx5PW8sej1wO3JldHVybiB5PXk+cT9xOnkseT15PnM/czp5LHk9eT51P3U6eSx6PXo+cj9yOnosej16PnQ/dDp6LHo9ej52P3Y6eix3PXE+dz9xOncsdz1zPnc/czp3LHc9dT53P3U6dyx4PXI+eD9yOngseD10Png/dDp4LHg9dj54P3Y6eCx0aGlzLl9ib3VuZHMueD15LHRoaXMuX2JvdW5kcy53aWR0aD13LXksdGhpcy5fYm91bmRzLnk9eix0aGlzLl9ib3VuZHMuaGVpZ2h0PXgteix0aGlzLl9ib3VuZHN9LGIuR3JhcGhpY3MucHJvdG90eXBlLnVwZGF0ZUxvY2FsQm91bmRzPWZ1bmN0aW9uKCl7dmFyIGE9MS8wLGM9LTEvMCxkPTEvMCxlPS0xLzA7aWYodGhpcy5ncmFwaGljc0RhdGEubGVuZ3RoKWZvcih2YXIgZixnLGgsaSxqLGssbD0wO2w8dGhpcy5ncmFwaGljc0RhdGEubGVuZ3RoO2wrKyl7dmFyIG09dGhpcy5ncmFwaGljc0RhdGFbbF0sbj1tLnR5cGUsbz1tLmxpbmVXaWR0aDtpZihmPW0uc2hhcGUsbj09PWIuR3JhcGhpY3MuUkVDVHx8bj09PWIuR3JhcGhpY3MuUlJFQyloPWYueC1vLzIsaT1mLnktby8yLGo9Zi53aWR0aCtvLGs9Zi5oZWlnaHQrbyxhPWE+aD9oOmEsYz1oK2o+Yz9oK2o6YyxkPWQ+aT9pOmQsZT1pK2s+ZT9pK2s6ZTtlbHNlIGlmKG49PT1iLkdyYXBoaWNzLkNJUkMpaD1mLngsaT1mLnksaj1mLnJhZGl1cytvLzIsaz1mLnJhZGl1cytvLzIsYT1hPmgtaj9oLWo6YSxjPWgraj5jP2grajpjLGQ9ZD5pLWs/aS1rOmQsZT1pK2s+ZT9pK2s6ZTtlbHNlIGlmKG49PT1iLkdyYXBoaWNzLkVMSVApaD1mLngsaT1mLnksaj1mLndpZHRoK28vMixrPWYuaGVpZ2h0K28vMixhPWE+aC1qP2gtajphLGM9aCtqPmM/aCtqOmMsZD1kPmktaz9pLWs6ZCxlPWkraz5lP2krazplO2Vsc2V7Zz1mLnBvaW50cztmb3IodmFyIHA9MDtwPGcubGVuZ3RoO3ArPTIpaD1nW3BdLGk9Z1twKzFdLGE9YT5oLW8/aC1vOmEsYz1oK28+Yz9oK286YyxkPWQ+aS1vP2ktbzpkLGU9aStvPmU/aStvOmV9fWVsc2UgYT0wLGM9MCxkPTAsZT0wO3ZhciBxPXRoaXMuYm91bmRzUGFkZGluZzt0aGlzLl9sb2NhbEJvdW5kcy54PWEtcSx0aGlzLl9sb2NhbEJvdW5kcy53aWR0aD1jLWErMipxLHRoaXMuX2xvY2FsQm91bmRzLnk9ZC1xLHRoaXMuX2xvY2FsQm91bmRzLmhlaWdodD1lLWQrMipxfSxiLkdyYXBoaWNzLnByb3RvdHlwZS5fZ2VuZXJhdGVDYWNoZWRTcHJpdGU9ZnVuY3Rpb24oKXt2YXIgYT10aGlzLmdldExvY2FsQm91bmRzKCk7aWYodGhpcy5fY2FjaGVkU3ByaXRlKXRoaXMuX2NhY2hlZFNwcml0ZS5idWZmZXIucmVzaXplKGEud2lkdGgsYS5oZWlnaHQpO2Vsc2V7dmFyIGM9bmV3IGIuQ2FudmFzQnVmZmVyKGEud2lkdGgsYS5oZWlnaHQpLGQ9Yi5UZXh0dXJlLmZyb21DYW52YXMoYy5jYW52YXMpO3RoaXMuX2NhY2hlZFNwcml0ZT1uZXcgYi5TcHJpdGUoZCksdGhpcy5fY2FjaGVkU3ByaXRlLmJ1ZmZlcj1jLHRoaXMuX2NhY2hlZFNwcml0ZS53b3JsZFRyYW5zZm9ybT10aGlzLndvcmxkVHJhbnNmb3JtfXRoaXMuX2NhY2hlZFNwcml0ZS5hbmNob3IueD0tKGEueC9hLndpZHRoKSx0aGlzLl9jYWNoZWRTcHJpdGUuYW5jaG9yLnk9LShhLnkvYS5oZWlnaHQpLHRoaXMuX2NhY2hlZFNwcml0ZS5idWZmZXIuY29udGV4dC50cmFuc2xhdGUoLWEueCwtYS55KSx0aGlzLndvcmxkQWxwaGE9MSxiLkNhbnZhc0dyYXBoaWNzLnJlbmRlckdyYXBoaWNzKHRoaXMsdGhpcy5fY2FjaGVkU3ByaXRlLmJ1ZmZlci5jb250ZXh0KSx0aGlzLl9jYWNoZWRTcHJpdGUuYWxwaGE9dGhpcy5hbHBoYX0sYi5HcmFwaGljcy5wcm90b3R5cGUudXBkYXRlQ2FjaGVkU3ByaXRlVGV4dHVyZT1mdW5jdGlvbigpe3ZhciBhPXRoaXMuX2NhY2hlZFNwcml0ZSxiPWEudGV4dHVyZSxjPWEuYnVmZmVyLmNhbnZhcztiLmJhc2VUZXh0dXJlLndpZHRoPWMud2lkdGgsYi5iYXNlVGV4dHVyZS5oZWlnaHQ9Yy5oZWlnaHQsYi5jcm9wLndpZHRoPWIuZnJhbWUud2lkdGg9Yy53aWR0aCxiLmNyb3AuaGVpZ2h0PWIuZnJhbWUuaGVpZ2h0PWMuaGVpZ2h0LGEuX3dpZHRoPWMud2lkdGgsYS5faGVpZ2h0PWMuaGVpZ2h0LGIuYmFzZVRleHR1cmUuZGlydHkoKX0sYi5HcmFwaGljcy5wcm90b3R5cGUuZGVzdHJveUNhY2hlZFNwcml0ZT1mdW5jdGlvbigpe3RoaXMuX2NhY2hlZFNwcml0ZS50ZXh0dXJlLmRlc3Ryb3koITApLHRoaXMuX2NhY2hlZFNwcml0ZT1udWxsfSxiLkdyYXBoaWNzLnByb3RvdHlwZS5kcmF3U2hhcGU9ZnVuY3Rpb24oYSl7dGhpcy5jdXJyZW50UGF0aCYmdGhpcy5jdXJyZW50UGF0aC5zaGFwZS5wb2ludHMubGVuZ3RoPD0yJiZ0aGlzLmdyYXBoaWNzRGF0YS5wb3AoKSx0aGlzLmN1cnJlbnRQYXRoPW51bGw7dmFyIGM9bmV3IGIuR3JhcGhpY3NEYXRhKHRoaXMubGluZVdpZHRoLHRoaXMubGluZUNvbG9yLHRoaXMubGluZUFscGhhLHRoaXMuZmlsbENvbG9yLHRoaXMuZmlsbEFscGhhLHRoaXMuZmlsbGluZyxhKTtyZXR1cm4gdGhpcy5ncmFwaGljc0RhdGEucHVzaChjKSxjLnR5cGU9PT1iLkdyYXBoaWNzLlBPTFkmJihjLnNoYXBlLmNsb3NlZD10aGlzLmZpbGxpbmcsdGhpcy5jdXJyZW50UGF0aD1jKSx0aGlzLmRpcnR5PSEwLGN9LGIuR3JhcGhpY3NEYXRhPWZ1bmN0aW9uKGEsYixjLGQsZSxmLGcpe3RoaXMubGluZVdpZHRoPWEsdGhpcy5saW5lQ29sb3I9Yix0aGlzLmxpbmVBbHBoYT1jLHRoaXMuX2xpbmVUaW50PWIsdGhpcy5maWxsQ29sb3I9ZCx0aGlzLmZpbGxBbHBoYT1lLHRoaXMuX2ZpbGxUaW50PWQsdGhpcy5maWxsPWYsdGhpcy5zaGFwZT1nLHRoaXMudHlwZT1nLnR5cGV9LGIuR3JhcGhpY3MuUE9MWT0wLGIuR3JhcGhpY3MuUkVDVD0xLGIuR3JhcGhpY3MuQ0lSQz0yLGIuR3JhcGhpY3MuRUxJUD0zLGIuR3JhcGhpY3MuUlJFQz00LGIuUG9seWdvbi5wcm90b3R5cGUudHlwZT1iLkdyYXBoaWNzLlBPTFksYi5SZWN0YW5nbGUucHJvdG90eXBlLnR5cGU9Yi5HcmFwaGljcy5SRUNULGIuQ2lyY2xlLnByb3RvdHlwZS50eXBlPWIuR3JhcGhpY3MuQ0lSQyxiLkVsbGlwc2UucHJvdG90eXBlLnR5cGU9Yi5HcmFwaGljcy5FTElQLGIuUm91bmRlZFJlY3RhbmdsZS5wcm90b3R5cGUudHlwZT1iLkdyYXBoaWNzLlJSRUMsYi5TdHJpcD1mdW5jdGlvbihhKXtiLkRpc3BsYXlPYmplY3RDb250YWluZXIuY2FsbCh0aGlzKSx0aGlzLnRleHR1cmU9YSx0aGlzLnV2cz1uZXcgYi5GbG9hdDMyQXJyYXkoWzAsMSwxLDEsMSwwLDAsMV0pLHRoaXMudmVydGljZXM9bmV3IGIuRmxvYXQzMkFycmF5KFswLDAsMTAwLDAsMTAwLDEwMCwwLDEwMF0pLHRoaXMuY29sb3JzPW5ldyBiLkZsb2F0MzJBcnJheShbMSwxLDEsMV0pLHRoaXMuaW5kaWNlcz1uZXcgYi5VaW50MTZBcnJheShbMCwxLDIsM10pLHRoaXMuZGlydHk9ITAsdGhpcy5ibGVuZE1vZGU9Yi5ibGVuZE1vZGVzLk5PUk1BTCx0aGlzLmNhbnZhc1BhZGRpbmc9MCx0aGlzLmRyYXdNb2RlPWIuU3RyaXAuRHJhd01vZGVzLlRSSUFOR0xFX1NUUklQfSxiLlN0cmlwLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGIuRGlzcGxheU9iamVjdENvbnRhaW5lci5wcm90b3R5cGUpLGIuU3RyaXAucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuU3RyaXAsYi5TdHJpcC5wcm90b3R5cGUuX3JlbmRlcldlYkdMPWZ1bmN0aW9uKGEpeyF0aGlzLnZpc2libGV8fHRoaXMuYWxwaGE8PTB8fChhLnNwcml0ZUJhdGNoLnN0b3AoKSx0aGlzLl92ZXJ0ZXhCdWZmZXJ8fHRoaXMuX2luaXRXZWJHTChhKSxhLnNoYWRlck1hbmFnZXIuc2V0U2hhZGVyKGEuc2hhZGVyTWFuYWdlci5zdHJpcFNoYWRlciksdGhpcy5fcmVuZGVyU3RyaXAoYSksYS5zcHJpdGVCYXRjaC5zdGFydCgpKX0sYi5TdHJpcC5wcm90b3R5cGUuX2luaXRXZWJHTD1mdW5jdGlvbihhKXt2YXIgYj1hLmdsO3RoaXMuX3ZlcnRleEJ1ZmZlcj1iLmNyZWF0ZUJ1ZmZlcigpLHRoaXMuX2luZGV4QnVmZmVyPWIuY3JlYXRlQnVmZmVyKCksdGhpcy5fdXZCdWZmZXI9Yi5jcmVhdGVCdWZmZXIoKSx0aGlzLl9jb2xvckJ1ZmZlcj1iLmNyZWF0ZUJ1ZmZlcigpLGIuYmluZEJ1ZmZlcihiLkFSUkFZX0JVRkZFUix0aGlzLl92ZXJ0ZXhCdWZmZXIpLGIuYnVmZmVyRGF0YShiLkFSUkFZX0JVRkZFUix0aGlzLnZlcnRpY2VzLGIuRFlOQU1JQ19EUkFXKSxiLmJpbmRCdWZmZXIoYi5BUlJBWV9CVUZGRVIsdGhpcy5fdXZCdWZmZXIpLGIuYnVmZmVyRGF0YShiLkFSUkFZX0JVRkZFUix0aGlzLnV2cyxiLlNUQVRJQ19EUkFXKSxiLmJpbmRCdWZmZXIoYi5BUlJBWV9CVUZGRVIsdGhpcy5fY29sb3JCdWZmZXIpLGIuYnVmZmVyRGF0YShiLkFSUkFZX0JVRkZFUix0aGlzLmNvbG9ycyxiLlNUQVRJQ19EUkFXKSxiLmJpbmRCdWZmZXIoYi5FTEVNRU5UX0FSUkFZX0JVRkZFUix0aGlzLl9pbmRleEJ1ZmZlciksYi5idWZmZXJEYXRhKGIuRUxFTUVOVF9BUlJBWV9CVUZGRVIsdGhpcy5pbmRpY2VzLGIuU1RBVElDX0RSQVcpfSxiLlN0cmlwLnByb3RvdHlwZS5fcmVuZGVyU3RyaXA9ZnVuY3Rpb24oYSl7dmFyIGM9YS5nbCxkPWEucHJvamVjdGlvbixlPWEub2Zmc2V0LGY9YS5zaGFkZXJNYW5hZ2VyLnN0cmlwU2hhZGVyLGc9dGhpcy5kcmF3TW9kZT09PWIuU3RyaXAuRHJhd01vZGVzLlRSSUFOR0xFX1NUUklQP2MuVFJJQU5HTEVfU1RSSVA6Yy5UUklBTkdMRVM7YS5ibGVuZE1vZGVNYW5hZ2VyLnNldEJsZW5kTW9kZSh0aGlzLmJsZW5kTW9kZSksYy51bmlmb3JtTWF0cml4M2Z2KGYudHJhbnNsYXRpb25NYXRyaXgsITEsdGhpcy53b3JsZFRyYW5zZm9ybS50b0FycmF5KCEwKSksYy51bmlmb3JtMmYoZi5wcm9qZWN0aW9uVmVjdG9yLGQueCwtZC55KSxjLnVuaWZvcm0yZihmLm9mZnNldFZlY3RvciwtZS54LC1lLnkpLGMudW5pZm9ybTFmKGYuYWxwaGEsdGhpcy53b3JsZEFscGhhKSx0aGlzLmRpcnR5Pyh0aGlzLmRpcnR5PSExLGMuYmluZEJ1ZmZlcihjLkFSUkFZX0JVRkZFUix0aGlzLl92ZXJ0ZXhCdWZmZXIpLGMuYnVmZmVyRGF0YShjLkFSUkFZX0JVRkZFUix0aGlzLnZlcnRpY2VzLGMuU1RBVElDX0RSQVcpLGMudmVydGV4QXR0cmliUG9pbnRlcihmLmFWZXJ0ZXhQb3NpdGlvbiwyLGMuRkxPQVQsITEsMCwwKSxjLmJpbmRCdWZmZXIoYy5BUlJBWV9CVUZGRVIsdGhpcy5fdXZCdWZmZXIpLGMuYnVmZmVyRGF0YShjLkFSUkFZX0JVRkZFUix0aGlzLnV2cyxjLlNUQVRJQ19EUkFXKSxjLnZlcnRleEF0dHJpYlBvaW50ZXIoZi5hVGV4dHVyZUNvb3JkLDIsYy5GTE9BVCwhMSwwLDApLGMuYWN0aXZlVGV4dHVyZShjLlRFWFRVUkUwKSx0aGlzLnRleHR1cmUuYmFzZVRleHR1cmUuX2RpcnR5W2MuaWRdP2EucmVuZGVyZXIudXBkYXRlVGV4dHVyZSh0aGlzLnRleHR1cmUuYmFzZVRleHR1cmUpOmMuYmluZFRleHR1cmUoYy5URVhUVVJFXzJELHRoaXMudGV4dHVyZS5iYXNlVGV4dHVyZS5fZ2xUZXh0dXJlc1tjLmlkXSksYy5iaW5kQnVmZmVyKGMuRUxFTUVOVF9BUlJBWV9CVUZGRVIsdGhpcy5faW5kZXhCdWZmZXIpLGMuYnVmZmVyRGF0YShjLkVMRU1FTlRfQVJSQVlfQlVGRkVSLHRoaXMuaW5kaWNlcyxjLlNUQVRJQ19EUkFXKSk6KGMuYmluZEJ1ZmZlcihjLkFSUkFZX0JVRkZFUix0aGlzLl92ZXJ0ZXhCdWZmZXIpLGMuYnVmZmVyU3ViRGF0YShjLkFSUkFZX0JVRkZFUiwwLHRoaXMudmVydGljZXMpLGMudmVydGV4QXR0cmliUG9pbnRlcihmLmFWZXJ0ZXhQb3NpdGlvbiwyLGMuRkxPQVQsITEsMCwwKSxjLmJpbmRCdWZmZXIoYy5BUlJBWV9CVUZGRVIsdGhpcy5fdXZCdWZmZXIpLGMudmVydGV4QXR0cmliUG9pbnRlcihmLmFUZXh0dXJlQ29vcmQsMixjLkZMT0FULCExLDAsMCksYy5hY3RpdmVUZXh0dXJlKGMuVEVYVFVSRTApLHRoaXMudGV4dHVyZS5iYXNlVGV4dHVyZS5fZGlydHlbYy5pZF0/YS5yZW5kZXJlci51cGRhdGVUZXh0dXJlKHRoaXMudGV4dHVyZS5iYXNlVGV4dHVyZSk6Yy5iaW5kVGV4dHVyZShjLlRFWFRVUkVfMkQsdGhpcy50ZXh0dXJlLmJhc2VUZXh0dXJlLl9nbFRleHR1cmVzW2MuaWRdKSxjLmJpbmRCdWZmZXIoYy5FTEVNRU5UX0FSUkFZX0JVRkZFUix0aGlzLl9pbmRleEJ1ZmZlcikpLGMuZHJhd0VsZW1lbnRzKGcsdGhpcy5pbmRpY2VzLmxlbmd0aCxjLlVOU0lHTkVEX1NIT1JULDApfSxiLlN0cmlwLnByb3RvdHlwZS5fcmVuZGVyQ2FudmFzPWZ1bmN0aW9uKGEpe3ZhciBjPWEuY29udGV4dCxkPXRoaXMud29ybGRUcmFuc2Zvcm07YS5yb3VuZFBpeGVscz9jLnNldFRyYW5zZm9ybShkLmEsZC5iLGQuYyxkLmQsMHxkLnR4LDB8ZC50eSk6Yy5zZXRUcmFuc2Zvcm0oZC5hLGQuYixkLmMsZC5kLGQudHgsZC50eSksdGhpcy5kcmF3TW9kZT09PWIuU3RyaXAuRHJhd01vZGVzLlRSSUFOR0xFX1NUUklQP3RoaXMuX3JlbmRlckNhbnZhc1RyaWFuZ2xlU3RyaXAoYyk6dGhpcy5fcmVuZGVyQ2FudmFzVHJpYW5nbGVzKGMpfSxiLlN0cmlwLnByb3RvdHlwZS5fcmVuZGVyQ2FudmFzVHJpYW5nbGVTdHJpcD1mdW5jdGlvbihhKXt2YXIgYj10aGlzLnZlcnRpY2VzLGM9dGhpcy51dnMsZD1iLmxlbmd0aC8yO3RoaXMuY291bnQrKztmb3IodmFyIGU9MDtkLTI+ZTtlKyspe3ZhciBmPTIqZTt0aGlzLl9yZW5kZXJDYW52YXNEcmF3VHJpYW5nbGUoYSxiLGMsZixmKzIsZis0KX19LGIuU3RyaXAucHJvdG90eXBlLl9yZW5kZXJDYW52YXNUcmlhbmdsZXM9ZnVuY3Rpb24oYSl7dmFyIGI9dGhpcy52ZXJ0aWNlcyxjPXRoaXMudXZzLGQ9dGhpcy5pbmRpY2VzLGU9ZC5sZW5ndGg7dGhpcy5jb3VudCsrO2Zvcih2YXIgZj0wO2U+ZjtmKz0zKXt2YXIgZz0yKmRbZl0saD0yKmRbZisxXSxpPTIqZFtmKzJdO3RoaXMuX3JlbmRlckNhbnZhc0RyYXdUcmlhbmdsZShhLGIsYyxnLGgsaSl9fSxiLlN0cmlwLnByb3RvdHlwZS5fcmVuZGVyQ2FudmFzRHJhd1RyaWFuZ2xlPWZ1bmN0aW9uKGEsYixjLGQsZSxmKXt2YXIgZz10aGlzLnRleHR1cmUuYmFzZVRleHR1cmUuc291cmNlLGg9dGhpcy50ZXh0dXJlLndpZHRoLGk9dGhpcy50ZXh0dXJlLmhlaWdodCxqPWJbZF0saz1iW2VdLGw9YltmXSxtPWJbZCsxXSxuPWJbZSsxXSxvPWJbZisxXSxwPWNbZF0qaCxxPWNbZV0qaCxyPWNbZl0qaCxzPWNbZCsxXSppLHQ9Y1tlKzFdKmksdT1jW2YrMV0qaTtpZih0aGlzLmNhbnZhc1BhZGRpbmc+MCl7dmFyIHY9dGhpcy5jYW52YXNQYWRkaW5nL3RoaXMud29ybGRUcmFuc2Zvcm0uYSx3PXRoaXMuY2FudmFzUGFkZGluZy90aGlzLndvcmxkVHJhbnNmb3JtLmQseD0oaitrK2wpLzMseT0obStuK28pLzMsej1qLXgsQT1tLXksQj1NYXRoLnNxcnQoeip6K0EqQSk7aj14K3ovQiooQit2KSxtPXkrQS9CKihCK3cpLHo9ay14LEE9bi15LEI9TWF0aC5zcXJ0KHoqeitBKkEpLGs9eCt6L0IqKEIrdiksbj15K0EvQiooQit3KSx6PWwteCxBPW8teSxCPU1hdGguc3FydCh6KnorQSpBKSxsPXgrei9CKihCK3YpLG89eStBL0IqKEIrdyl9YS5zYXZlKCksYS5iZWdpblBhdGgoKSxhLm1vdmVUbyhqLG0pLGEubGluZVRvKGssbiksYS5saW5lVG8obCxvKSxhLmNsb3NlUGF0aCgpLGEuY2xpcCgpO3ZhciBDPXAqdCtzKnIrcSp1LXQqci1zKnEtcCp1LEQ9aip0K3MqbCtrKnUtdCpsLXMqay1qKnUsRT1wKmsraipyK3EqbC1rKnItaipxLXAqbCxGPXAqdCpsK3MqaypyK2oqcSp1LWoqdCpyLXMqcSpsLXAqayp1LEc9bSp0K3MqbytuKnUtdCpvLXMqbi1tKnUsSD1wKm4rbSpyK3Eqby1uKnItbSpxLXAqbyxJPXAqdCpvK3MqbipyK20qcSp1LW0qdCpyLXMqcSpvLXAqbip1O2EudHJhbnNmb3JtKEQvQyxHL0MsRS9DLEgvQyxGL0MsSS9DKSxhLmRyYXdJbWFnZShnLDAsMCksYS5yZXN0b3JlKCl9LGIuU3RyaXAucHJvdG90eXBlLnJlbmRlclN0cmlwRmxhdD1mdW5jdGlvbihhKXt2YXIgYj10aGlzLmNvbnRleHQsYz1hLnZlcnRpY2VzLGQ9Yy5sZW5ndGgvMjt0aGlzLmNvdW50KyssYi5iZWdpblBhdGgoKTtmb3IodmFyIGU9MTtkLTI+ZTtlKyspe3ZhciBmPTIqZSxnPWNbZl0saD1jW2YrMl0saT1jW2YrNF0saj1jW2YrMV0saz1jW2YrM10sbD1jW2YrNV07Yi5tb3ZlVG8oZyxqKSxiLmxpbmVUbyhoLGspLGIubGluZVRvKGksbCl9Yi5maWxsU3R5bGU9XCIjRkYwMDAwXCIsYi5maWxsKCksYi5jbG9zZVBhdGgoKX0sYi5TdHJpcC5wcm90b3R5cGUub25UZXh0dXJlVXBkYXRlPWZ1bmN0aW9uKCl7dGhpcy51cGRhdGVGcmFtZT0hMH0sYi5TdHJpcC5wcm90b3R5cGUuZ2V0Qm91bmRzPWZ1bmN0aW9uKGEpe2Zvcih2YXIgYz1hfHx0aGlzLndvcmxkVHJhbnNmb3JtLGQ9Yy5hLGU9Yy5iLGY9Yy5jLGc9Yy5kLGg9Yy50eCxpPWMudHksaj0tMS8wLGs9LTEvMCxsPTEvMCxtPTEvMCxuPXRoaXMudmVydGljZXMsbz0wLHA9bi5sZW5ndGg7cD5vO28rPTIpe3ZhciBxPW5bb10scj1uW28rMV0scz1kKnErZipyK2gsdD1nKnIrZSpxK2k7bD1sPnM/czpsLG09bT50P3Q6bSxqPXM+aj9zOmosaz10Pms/dDprfWlmKGw9PT0tMS8wfHwxLzA9PT1rKXJldHVybiBiLkVtcHR5UmVjdGFuZ2xlO3ZhciB1PXRoaXMuX2JvdW5kcztyZXR1cm4gdS54PWwsdS53aWR0aD1qLWwsdS55PW0sdS5oZWlnaHQ9ay1tLHRoaXMuX2N1cnJlbnRCb3VuZHM9dSx1fSxiLlN0cmlwLkRyYXdNb2Rlcz17VFJJQU5HTEVfU1RSSVA6MCxUUklBTkdMRVM6MX0sYi5Sb3BlPWZ1bmN0aW9uKGEsYyl7Yi5TdHJpcC5jYWxsKHRoaXMsYSksdGhpcy5wb2ludHM9Yyx0aGlzLnZlcnRpY2VzPW5ldyBiLkZsb2F0MzJBcnJheSg0KmMubGVuZ3RoKSx0aGlzLnV2cz1uZXcgYi5GbG9hdDMyQXJyYXkoNCpjLmxlbmd0aCksdGhpcy5jb2xvcnM9bmV3IGIuRmxvYXQzMkFycmF5KDIqYy5sZW5ndGgpLHRoaXMuaW5kaWNlcz1uZXcgYi5VaW50MTZBcnJheSgyKmMubGVuZ3RoKSx0aGlzLnJlZnJlc2goKX0sYi5Sb3BlLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGIuU3RyaXAucHJvdG90eXBlKSxiLlJvcGUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuUm9wZSxiLlJvcGUucHJvdG90eXBlLnJlZnJlc2g9ZnVuY3Rpb24oKXt2YXIgYT10aGlzLnBvaW50cztpZighKGEubGVuZ3RoPDEpKXt2YXIgYj10aGlzLnV2cyxjPWFbMF0sZD10aGlzLmluZGljZXMsZT10aGlzLmNvbG9yczt0aGlzLmNvdW50LT0uMixiWzBdPTAsYlsxXT0wLGJbMl09MCxiWzNdPTEsZVswXT0xLGVbMV09MSxkWzBdPTAsZFsxXT0xO2Zvcih2YXIgZixnLGgsaT1hLmxlbmd0aCxqPTE7aT5qO2orKylmPWFbal0sZz00KmosaD1qLyhpLTEpLGolMj8oYltnXT1oLGJbZysxXT0wLGJbZysyXT1oLGJbZyszXT0xKTooYltnXT1oLGJbZysxXT0wLGJbZysyXT1oLGJbZyszXT0xKSxnPTIqaixlW2ddPTEsZVtnKzFdPTEsZz0yKmosZFtnXT1nLGRbZysxXT1nKzEsYz1mfX0sYi5Sb3BlLnByb3RvdHlwZS51cGRhdGVUcmFuc2Zvcm09ZnVuY3Rpb24oKXt2YXIgYT10aGlzLnBvaW50cztpZighKGEubGVuZ3RoPDEpKXt2YXIgYyxkPWFbMF0sZT17eDowLHk6MH07dGhpcy5jb3VudC09LjI7Zm9yKHZhciBmLGcsaCxpLGosaz10aGlzLnZlcnRpY2VzLGw9YS5sZW5ndGgsbT0wO2w+bTttKyspZj1hW21dLGc9NCptLGM9bTxhLmxlbmd0aC0xP2FbbSsxXTpmLGUueT0tKGMueC1kLngpLGUueD1jLnktZC55LGg9MTAqKDEtbS8obC0xKSksaD4xJiYoaD0xKSxpPU1hdGguc3FydChlLngqZS54K2UueSplLnkpLGo9dGhpcy50ZXh0dXJlLmhlaWdodC8yLGUueC89aSxlLnkvPWksZS54Kj1qLGUueSo9aixrW2ddPWYueCtlLngsa1tnKzFdPWYueStlLnksa1tnKzJdPWYueC1lLngsa1tnKzNdPWYueS1lLnksZD1mO2IuRGlzcGxheU9iamVjdENvbnRhaW5lci5wcm90b3R5cGUudXBkYXRlVHJhbnNmb3JtLmNhbGwodGhpcyl9fSxiLlJvcGUucHJvdG90eXBlLnNldFRleHR1cmU9ZnVuY3Rpb24oYSl7dGhpcy50ZXh0dXJlPWF9LGIuVGlsaW5nU3ByaXRlPWZ1bmN0aW9uKGEsYyxkKXtiLlNwcml0ZS5jYWxsKHRoaXMsYSksdGhpcy5fd2lkdGg9Y3x8MTAwLHRoaXMuX2hlaWdodD1kfHwxMDAsdGhpcy50aWxlU2NhbGU9bmV3IGIuUG9pbnQoMSwxKSx0aGlzLnRpbGVTY2FsZU9mZnNldD1uZXcgYi5Qb2ludCgxLDEpLHRoaXMudGlsZVBvc2l0aW9uPW5ldyBiLlBvaW50KDAsMCksdGhpcy5yZW5kZXJhYmxlPSEwLHRoaXMudGludD0xNjc3NzIxNSx0aGlzLmJsZW5kTW9kZT1iLmJsZW5kTW9kZXMuTk9STUFMfSxiLlRpbGluZ1Nwcml0ZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShiLlNwcml0ZS5wcm90b3R5cGUpLGIuVGlsaW5nU3ByaXRlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLlRpbGluZ1Nwcml0ZSxPYmplY3QuZGVmaW5lUHJvcGVydHkoYi5UaWxpbmdTcHJpdGUucHJvdG90eXBlLFwid2lkdGhcIix7Z2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3dpZHRofSxzZXQ6ZnVuY3Rpb24oYSl7dGhpcy5fd2lkdGg9YX19KSxPYmplY3QuZGVmaW5lUHJvcGVydHkoYi5UaWxpbmdTcHJpdGUucHJvdG90eXBlLFwiaGVpZ2h0XCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLl9oZWlnaHR9LHNldDpmdW5jdGlvbihhKXt0aGlzLl9oZWlnaHQ9YX19KSxiLlRpbGluZ1Nwcml0ZS5wcm90b3R5cGUuc2V0VGV4dHVyZT1mdW5jdGlvbihhKXt0aGlzLnRleHR1cmUhPT1hJiYodGhpcy50ZXh0dXJlPWEsdGhpcy5yZWZyZXNoVGV4dHVyZT0hMCx0aGlzLmNhY2hlZFRpbnQ9MTY3NzcyMTUpfSxiLlRpbGluZ1Nwcml0ZS5wcm90b3R5cGUuX3JlbmRlcldlYkdMPWZ1bmN0aW9uKGEpe2lmKHRoaXMudmlzaWJsZSE9PSExJiYwIT09dGhpcy5hbHBoYSl7dmFyIGIsYztmb3IodGhpcy5fbWFzayYmKGEuc3ByaXRlQmF0Y2guc3RvcCgpLGEubWFza01hbmFnZXIucHVzaE1hc2sodGhpcy5tYXNrLGEpLGEuc3ByaXRlQmF0Y2guc3RhcnQoKSksdGhpcy5fZmlsdGVycyYmKGEuc3ByaXRlQmF0Y2guZmx1c2goKSxhLmZpbHRlck1hbmFnZXIucHVzaEZpbHRlcih0aGlzLl9maWx0ZXJCbG9jaykpLCF0aGlzLnRpbGluZ1RleHR1cmV8fHRoaXMucmVmcmVzaFRleHR1cmU/KHRoaXMuZ2VuZXJhdGVUaWxpbmdUZXh0dXJlKCEwKSx0aGlzLnRpbGluZ1RleHR1cmUmJnRoaXMudGlsaW5nVGV4dHVyZS5uZWVkc1VwZGF0ZSYmKGEucmVuZGVyZXIudXBkYXRlVGV4dHVyZSh0aGlzLnRpbGluZ1RleHR1cmUuYmFzZVRleHR1cmUpLHRoaXMudGlsaW5nVGV4dHVyZS5uZWVkc1VwZGF0ZT0hMSkpOmEuc3ByaXRlQmF0Y2gucmVuZGVyVGlsaW5nU3ByaXRlKHRoaXMpLGI9MCxjPXRoaXMuY2hpbGRyZW4ubGVuZ3RoO2M+YjtiKyspdGhpcy5jaGlsZHJlbltiXS5fcmVuZGVyV2ViR0woYSk7YS5zcHJpdGVCYXRjaC5zdG9wKCksdGhpcy5fZmlsdGVycyYmYS5maWx0ZXJNYW5hZ2VyLnBvcEZpbHRlcigpLHRoaXMuX21hc2smJmEubWFza01hbmFnZXIucG9wTWFzayh0aGlzLl9tYXNrLGEpLGEuc3ByaXRlQmF0Y2guc3RhcnQoKX19LGIuVGlsaW5nU3ByaXRlLnByb3RvdHlwZS5fcmVuZGVyQ2FudmFzPWZ1bmN0aW9uKGEpe2lmKHRoaXMudmlzaWJsZSE9PSExJiYwIT09dGhpcy5hbHBoYSl7dmFyIGM9YS5jb250ZXh0O3RoaXMuX21hc2smJmEubWFza01hbmFnZXIucHVzaE1hc2sodGhpcy5fbWFzayxjKSxjLmdsb2JhbEFscGhhPXRoaXMud29ybGRBbHBoYTt2YXIgZCxlLGY9dGhpcy53b3JsZFRyYW5zZm9ybSxnPWEucmVzb2x1dGlvbjtpZihjLnNldFRyYW5zZm9ybShmLmEqZyxmLmIqZyxmLmMqZyxmLmQqZyxmLnR4KmcsZi50eSpnKSwhdGhpcy5fX3RpbGVQYXR0ZXJufHx0aGlzLnJlZnJlc2hUZXh0dXJlKXtpZih0aGlzLmdlbmVyYXRlVGlsaW5nVGV4dHVyZSghMSksIXRoaXMudGlsaW5nVGV4dHVyZSlyZXR1cm47dGhpcy5fX3RpbGVQYXR0ZXJuPWMuY3JlYXRlUGF0dGVybih0aGlzLnRpbGluZ1RleHR1cmUuYmFzZVRleHR1cmUuc291cmNlLFwicmVwZWF0XCIpfXRoaXMuYmxlbmRNb2RlIT09YS5jdXJyZW50QmxlbmRNb2RlJiYoYS5jdXJyZW50QmxlbmRNb2RlPXRoaXMuYmxlbmRNb2RlLGMuZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uPWIuYmxlbmRNb2Rlc0NhbnZhc1thLmN1cnJlbnRCbGVuZE1vZGVdKTt2YXIgaD10aGlzLnRpbGVQb3NpdGlvbixpPXRoaXMudGlsZVNjYWxlO2ZvcihoLnglPXRoaXMudGlsaW5nVGV4dHVyZS5iYXNlVGV4dHVyZS53aWR0aCxoLnklPXRoaXMudGlsaW5nVGV4dHVyZS5iYXNlVGV4dHVyZS5oZWlnaHQsYy5zY2FsZShpLngsaS55KSxjLnRyYW5zbGF0ZShoLngrdGhpcy5hbmNob3IueCotdGhpcy5fd2lkdGgsaC55K3RoaXMuYW5jaG9yLnkqLXRoaXMuX2hlaWdodCksYy5maWxsU3R5bGU9dGhpcy5fX3RpbGVQYXR0ZXJuLGMuZmlsbFJlY3QoLWgueCwtaC55LHRoaXMuX3dpZHRoL2kueCx0aGlzLl9oZWlnaHQvaS55KSxjLnNjYWxlKDEvaS54LDEvaS55KSxjLnRyYW5zbGF0ZSgtaC54K3RoaXMuYW5jaG9yLngqdGhpcy5fd2lkdGgsLWgueSt0aGlzLmFuY2hvci55KnRoaXMuX2hlaWdodCksdGhpcy5fbWFzayYmYS5tYXNrTWFuYWdlci5wb3BNYXNrKGEuY29udGV4dCksZD0wLGU9dGhpcy5jaGlsZHJlbi5sZW5ndGg7ZT5kO2QrKyl0aGlzLmNoaWxkcmVuW2RdLl9yZW5kZXJDYW52YXMoYSlcbn19LGIuVGlsaW5nU3ByaXRlLnByb3RvdHlwZS5nZXRCb3VuZHM9ZnVuY3Rpb24oKXt2YXIgYT10aGlzLl93aWR0aCxiPXRoaXMuX2hlaWdodCxjPWEqKDEtdGhpcy5hbmNob3IueCksZD1hKi10aGlzLmFuY2hvci54LGU9YiooMS10aGlzLmFuY2hvci55KSxmPWIqLXRoaXMuYW5jaG9yLnksZz10aGlzLndvcmxkVHJhbnNmb3JtLGg9Zy5hLGk9Zy5iLGo9Zy5jLGs9Zy5kLGw9Zy50eCxtPWcudHksbj1oKmQraipmK2wsbz1rKmYraSpkK20scD1oKmMraipmK2wscT1rKmYraSpjK20scj1oKmMraiplK2wscz1rKmUraSpjK20sdD1oKmQraiplK2wsdT1rKmUraSpkK20sdj0tMS8wLHc9LTEvMCx4PTEvMCx5PTEvMDt4PXg+bj9uOngseD14PnA/cDp4LHg9eD5yP3I6eCx4PXg+dD90OngseT15Pm8/bzp5LHk9eT5xP3E6eSx5PXk+cz9zOnkseT15PnU/dTp5LHY9bj52P246dix2PXA+dj9wOnYsdj1yPnY/cjp2LHY9dD52P3Q6dix3PW8+dz9vOncsdz1xPnc/cTp3LHc9cz53P3M6dyx3PXU+dz91Onc7dmFyIHo9dGhpcy5fYm91bmRzO3JldHVybiB6Lng9eCx6LndpZHRoPXYteCx6Lnk9eSx6LmhlaWdodD13LXksdGhpcy5fY3VycmVudEJvdW5kcz16LHp9LGIuVGlsaW5nU3ByaXRlLnByb3RvdHlwZS5vblRleHR1cmVVcGRhdGU9ZnVuY3Rpb24oKXt9LGIuVGlsaW5nU3ByaXRlLnByb3RvdHlwZS5nZW5lcmF0ZVRpbGluZ1RleHR1cmU9ZnVuY3Rpb24oYSl7aWYodGhpcy50ZXh0dXJlLmJhc2VUZXh0dXJlLmhhc0xvYWRlZCl7dmFyIGMsZCxlPXRoaXMub3JpZ2luYWxUZXh0dXJlfHx0aGlzLnRleHR1cmUsZj1lLmZyYW1lLGc9Zi53aWR0aCE9PWUuYmFzZVRleHR1cmUud2lkdGh8fGYuaGVpZ2h0IT09ZS5iYXNlVGV4dHVyZS5oZWlnaHQsaD0hMTtpZihhPyhjPWIuZ2V0TmV4dFBvd2VyT2ZUd28oZi53aWR0aCksZD1iLmdldE5leHRQb3dlck9mVHdvKGYuaGVpZ2h0KSwoZi53aWR0aCE9PWN8fGYuaGVpZ2h0IT09ZHx8ZS5iYXNlVGV4dHVyZS53aWR0aCE9PWN8fGUuYmFzZVRleHR1cmUuaGVpZ2h0fHxkKSYmKGg9ITApKTpnJiYoYz1mLndpZHRoLGQ9Zi5oZWlnaHQsaD0hMCksaCl7dmFyIGk7dGhpcy50aWxpbmdUZXh0dXJlJiZ0aGlzLnRpbGluZ1RleHR1cmUuaXNUaWxpbmc/KGk9dGhpcy50aWxpbmdUZXh0dXJlLmNhbnZhc0J1ZmZlcixpLnJlc2l6ZShjLGQpLHRoaXMudGlsaW5nVGV4dHVyZS5iYXNlVGV4dHVyZS53aWR0aD1jLHRoaXMudGlsaW5nVGV4dHVyZS5iYXNlVGV4dHVyZS5oZWlnaHQ9ZCx0aGlzLnRpbGluZ1RleHR1cmUubmVlZHNVcGRhdGU9ITApOihpPW5ldyBiLkNhbnZhc0J1ZmZlcihjLGQpLHRoaXMudGlsaW5nVGV4dHVyZT1iLlRleHR1cmUuZnJvbUNhbnZhcyhpLmNhbnZhcyksdGhpcy50aWxpbmdUZXh0dXJlLmNhbnZhc0J1ZmZlcj1pLHRoaXMudGlsaW5nVGV4dHVyZS5pc1RpbGluZz0hMCksaS5jb250ZXh0LmRyYXdJbWFnZShlLmJhc2VUZXh0dXJlLnNvdXJjZSxlLmNyb3AueCxlLmNyb3AueSxlLmNyb3Aud2lkdGgsZS5jcm9wLmhlaWdodCwwLDAsYyxkKSx0aGlzLnRpbGVTY2FsZU9mZnNldC54PWYud2lkdGgvYyx0aGlzLnRpbGVTY2FsZU9mZnNldC55PWYuaGVpZ2h0L2R9ZWxzZSB0aGlzLnRpbGluZ1RleHR1cmUmJnRoaXMudGlsaW5nVGV4dHVyZS5pc1RpbGluZyYmdGhpcy50aWxpbmdUZXh0dXJlLmRlc3Ryb3koITApLHRoaXMudGlsZVNjYWxlT2Zmc2V0Lng9MSx0aGlzLnRpbGVTY2FsZU9mZnNldC55PTEsdGhpcy50aWxpbmdUZXh0dXJlPWU7dGhpcy5yZWZyZXNoVGV4dHVyZT0hMSx0aGlzLm9yaWdpbmFsVGV4dHVyZT10aGlzLnRleHR1cmUsdGhpcy50ZXh0dXJlPXRoaXMudGlsaW5nVGV4dHVyZSx0aGlzLnRpbGluZ1RleHR1cmUuYmFzZVRleHR1cmUuX3Bvd2VyT2YyPSEwfX07dmFyIGM9e3JhZERlZzoxODAvTWF0aC5QSSxkZWdSYWQ6TWF0aC5QSS8xODAsdGVtcDpbXSxGbG9hdDMyQXJyYXk6XCJ1bmRlZmluZWRcIj09dHlwZW9mIEZsb2F0MzJBcnJheT9BcnJheTpGbG9hdDMyQXJyYXksVWludDE2QXJyYXk6XCJ1bmRlZmluZWRcIj09dHlwZW9mIFVpbnQxNkFycmF5P0FycmF5OlVpbnQxNkFycmF5fTtjLkJvbmVEYXRhPWZ1bmN0aW9uKGEsYil7dGhpcy5uYW1lPWEsdGhpcy5wYXJlbnQ9Yn0sYy5Cb25lRGF0YS5wcm90b3R5cGU9e2xlbmd0aDowLHg6MCx5OjAscm90YXRpb246MCxzY2FsZVg6MSxzY2FsZVk6MSxpbmhlcml0U2NhbGU6ITAsaW5oZXJpdFJvdGF0aW9uOiEwLGZsaXBYOiExLGZsaXBZOiExfSxjLlNsb3REYXRhPWZ1bmN0aW9uKGEsYil7dGhpcy5uYW1lPWEsdGhpcy5ib25lRGF0YT1ifSxjLlNsb3REYXRhLnByb3RvdHlwZT17cjoxLGc6MSxiOjEsYToxLGF0dGFjaG1lbnROYW1lOm51bGwsYWRkaXRpdmVCbGVuZGluZzohMX0sYy5Ja0NvbnN0cmFpbnREYXRhPWZ1bmN0aW9uKGEpe3RoaXMubmFtZT1hLHRoaXMuYm9uZXM9W119LGMuSWtDb25zdHJhaW50RGF0YS5wcm90b3R5cGU9e3RhcmdldDpudWxsLGJlbmREaXJlY3Rpb246MSxtaXg6MX0sYy5Cb25lPWZ1bmN0aW9uKGEsYixjKXt0aGlzLmRhdGE9YSx0aGlzLnNrZWxldG9uPWIsdGhpcy5wYXJlbnQ9Yyx0aGlzLnNldFRvU2V0dXBQb3NlKCl9LGMuQm9uZS55RG93bj0hMSxjLkJvbmUucHJvdG90eXBlPXt4OjAseTowLHJvdGF0aW9uOjAscm90YXRpb25JSzowLHNjYWxlWDoxLHNjYWxlWToxLGZsaXBYOiExLGZsaXBZOiExLG0wMDowLG0wMTowLHdvcmxkWDowLG0xMDowLG0xMTowLHdvcmxkWTowLHdvcmxkUm90YXRpb246MCx3b3JsZFNjYWxlWDoxLHdvcmxkU2NhbGVZOjEsd29ybGRGbGlwWDohMSx3b3JsZEZsaXBZOiExLHVwZGF0ZVdvcmxkVHJhbnNmb3JtOmZ1bmN0aW9uKCl7dmFyIGE9dGhpcy5wYXJlbnQ7aWYoYSl0aGlzLndvcmxkWD10aGlzLngqYS5tMDArdGhpcy55KmEubTAxK2Eud29ybGRYLHRoaXMud29ybGRZPXRoaXMueCphLm0xMCt0aGlzLnkqYS5tMTErYS53b3JsZFksdGhpcy5kYXRhLmluaGVyaXRTY2FsZT8odGhpcy53b3JsZFNjYWxlWD1hLndvcmxkU2NhbGVYKnRoaXMuc2NhbGVYLHRoaXMud29ybGRTY2FsZVk9YS53b3JsZFNjYWxlWSp0aGlzLnNjYWxlWSk6KHRoaXMud29ybGRTY2FsZVg9dGhpcy5zY2FsZVgsdGhpcy53b3JsZFNjYWxlWT10aGlzLnNjYWxlWSksdGhpcy53b3JsZFJvdGF0aW9uPXRoaXMuZGF0YS5pbmhlcml0Um90YXRpb24/YS53b3JsZFJvdGF0aW9uK3RoaXMucm90YXRpb25JSzp0aGlzLnJvdGF0aW9uSUssdGhpcy53b3JsZEZsaXBYPWEud29ybGRGbGlwWCE9dGhpcy5mbGlwWCx0aGlzLndvcmxkRmxpcFk9YS53b3JsZEZsaXBZIT10aGlzLmZsaXBZO2Vsc2V7dmFyIGI9dGhpcy5za2VsZXRvbi5mbGlwWCxkPXRoaXMuc2tlbGV0b24uZmxpcFk7dGhpcy53b3JsZFg9Yj8tdGhpcy54OnRoaXMueCx0aGlzLndvcmxkWT1kIT1jLkJvbmUueURvd24/LXRoaXMueTp0aGlzLnksdGhpcy53b3JsZFNjYWxlWD10aGlzLnNjYWxlWCx0aGlzLndvcmxkU2NhbGVZPXRoaXMuc2NhbGVZLHRoaXMud29ybGRSb3RhdGlvbj10aGlzLnJvdGF0aW9uSUssdGhpcy53b3JsZEZsaXBYPWIhPXRoaXMuZmxpcFgsdGhpcy53b3JsZEZsaXBZPWQhPXRoaXMuZmxpcFl9dmFyIGU9dGhpcy53b3JsZFJvdGF0aW9uKmMuZGVnUmFkLGY9TWF0aC5jb3MoZSksZz1NYXRoLnNpbihlKTt0aGlzLndvcmxkRmxpcFg/KHRoaXMubTAwPS1mKnRoaXMud29ybGRTY2FsZVgsdGhpcy5tMDE9Zyp0aGlzLndvcmxkU2NhbGVZKToodGhpcy5tMDA9Zip0aGlzLndvcmxkU2NhbGVYLHRoaXMubTAxPS1nKnRoaXMud29ybGRTY2FsZVkpLHRoaXMud29ybGRGbGlwWSE9Yy5Cb25lLnlEb3duPyh0aGlzLm0xMD0tZyp0aGlzLndvcmxkU2NhbGVYLHRoaXMubTExPS1mKnRoaXMud29ybGRTY2FsZVkpOih0aGlzLm0xMD1nKnRoaXMud29ybGRTY2FsZVgsdGhpcy5tMTE9Zip0aGlzLndvcmxkU2NhbGVZKX0sc2V0VG9TZXR1cFBvc2U6ZnVuY3Rpb24oKXt2YXIgYT10aGlzLmRhdGE7dGhpcy54PWEueCx0aGlzLnk9YS55LHRoaXMucm90YXRpb249YS5yb3RhdGlvbix0aGlzLnJvdGF0aW9uSUs9dGhpcy5yb3RhdGlvbix0aGlzLnNjYWxlWD1hLnNjYWxlWCx0aGlzLnNjYWxlWT1hLnNjYWxlWSx0aGlzLmZsaXBYPWEuZmxpcFgsdGhpcy5mbGlwWT1hLmZsaXBZfSx3b3JsZFRvTG9jYWw6ZnVuY3Rpb24oYSl7dmFyIGI9YVswXS10aGlzLndvcmxkWCxkPWFbMV0tdGhpcy53b3JsZFksZT10aGlzLm0wMCxmPXRoaXMubTEwLGc9dGhpcy5tMDEsaD10aGlzLm0xMTt0aGlzLndvcmxkRmxpcFghPSh0aGlzLndvcmxkRmxpcFkhPWMuQm9uZS55RG93bikmJihlPS1lLGg9LWgpO3ZhciBpPTEvKGUqaC1nKmYpO2FbMF09YiplKmktZCpnKmksYVsxXT1kKmgqaS1iKmYqaX0sbG9jYWxUb1dvcmxkOmZ1bmN0aW9uKGEpe3ZhciBiPWFbMF0sYz1hWzFdO2FbMF09Yip0aGlzLm0wMCtjKnRoaXMubTAxK3RoaXMud29ybGRYLGFbMV09Yip0aGlzLm0xMCtjKnRoaXMubTExK3RoaXMud29ybGRZfX0sYy5TbG90PWZ1bmN0aW9uKGEsYil7dGhpcy5kYXRhPWEsdGhpcy5ib25lPWIsdGhpcy5zZXRUb1NldHVwUG9zZSgpfSxjLlNsb3QucHJvdG90eXBlPXtyOjEsZzoxLGI6MSxhOjEsX2F0dGFjaG1lbnRUaW1lOjAsYXR0YWNobWVudDpudWxsLGF0dGFjaG1lbnRWZXJ0aWNlczpbXSxzZXRBdHRhY2htZW50OmZ1bmN0aW9uKGEpe3RoaXMuYXR0YWNobWVudD1hLHRoaXMuX2F0dGFjaG1lbnRUaW1lPXRoaXMuYm9uZS5za2VsZXRvbi50aW1lLHRoaXMuYXR0YWNobWVudFZlcnRpY2VzLmxlbmd0aD0wfSxzZXRBdHRhY2htZW50VGltZTpmdW5jdGlvbihhKXt0aGlzLl9hdHRhY2htZW50VGltZT10aGlzLmJvbmUuc2tlbGV0b24udGltZS1hfSxnZXRBdHRhY2htZW50VGltZTpmdW5jdGlvbigpe3JldHVybiB0aGlzLmJvbmUuc2tlbGV0b24udGltZS10aGlzLl9hdHRhY2htZW50VGltZX0sc2V0VG9TZXR1cFBvc2U6ZnVuY3Rpb24oKXt2YXIgYT10aGlzLmRhdGE7dGhpcy5yPWEucix0aGlzLmc9YS5nLHRoaXMuYj1hLmIsdGhpcy5hPWEuYTtmb3IodmFyIGI9dGhpcy5ib25lLnNrZWxldG9uLmRhdGEuc2xvdHMsYz0wLGQ9Yi5sZW5ndGg7ZD5jO2MrKylpZihiW2NdPT1hKXt0aGlzLnNldEF0dGFjaG1lbnQoYS5hdHRhY2htZW50TmFtZT90aGlzLmJvbmUuc2tlbGV0b24uZ2V0QXR0YWNobWVudEJ5U2xvdEluZGV4KGMsYS5hdHRhY2htZW50TmFtZSk6bnVsbCk7YnJlYWt9fX0sYy5Ja0NvbnN0cmFpbnQ9ZnVuY3Rpb24oYSxiKXt0aGlzLmRhdGE9YSx0aGlzLm1peD1hLm1peCx0aGlzLmJlbmREaXJlY3Rpb249YS5iZW5kRGlyZWN0aW9uLHRoaXMuYm9uZXM9W107Zm9yKHZhciBjPTAsZD1hLmJvbmVzLmxlbmd0aDtkPmM7YysrKXRoaXMuYm9uZXMucHVzaChiLmZpbmRCb25lKGEuYm9uZXNbY10ubmFtZSkpO3RoaXMudGFyZ2V0PWIuZmluZEJvbmUoYS50YXJnZXQubmFtZSl9LGMuSWtDb25zdHJhaW50LnByb3RvdHlwZT17YXBwbHk6ZnVuY3Rpb24oKXt2YXIgYT10aGlzLnRhcmdldCxiPXRoaXMuYm9uZXM7c3dpdGNoKGIubGVuZ3RoKXtjYXNlIDE6Yy5Ja0NvbnN0cmFpbnQuYXBwbHkxKGJbMF0sYS53b3JsZFgsYS53b3JsZFksdGhpcy5taXgpO2JyZWFrO2Nhc2UgMjpjLklrQ29uc3RyYWludC5hcHBseTIoYlswXSxiWzFdLGEud29ybGRYLGEud29ybGRZLHRoaXMuYmVuZERpcmVjdGlvbix0aGlzLm1peCl9fX0sYy5Ja0NvbnN0cmFpbnQuYXBwbHkxPWZ1bmN0aW9uKGEsYixkLGUpe3ZhciBmPWEuZGF0YS5pbmhlcml0Um90YXRpb24mJmEucGFyZW50P2EucGFyZW50LndvcmxkUm90YXRpb246MCxnPWEucm90YXRpb24saD1NYXRoLmF0YW4yKGQtYS53b3JsZFksYi1hLndvcmxkWCkqYy5yYWREZWctZjthLnJvdGF0aW9uSUs9ZysoaC1nKSplfSxjLklrQ29uc3RyYWludC5hcHBseTI9ZnVuY3Rpb24oYSxiLGQsZSxmLGcpe3ZhciBoPWIucm90YXRpb24saT1hLnJvdGF0aW9uO2lmKCFnKXJldHVybiBiLnJvdGF0aW9uSUs9aCx2b2lkKGEucm90YXRpb25JSz1pKTt2YXIgaixrLGw9Yy50ZW1wLG09YS5wYXJlbnQ7bT8obFswXT1kLGxbMV09ZSxtLndvcmxkVG9Mb2NhbChsKSxkPShsWzBdLWEueCkqbS53b3JsZFNjYWxlWCxlPShsWzFdLWEueSkqbS53b3JsZFNjYWxlWSk6KGQtPWEueCxlLT1hLnkpLGIucGFyZW50PT1hPyhqPWIueCxrPWIueSk6KGxbMF09Yi54LGxbMV09Yi55LGIucGFyZW50LmxvY2FsVG9Xb3JsZChsKSxhLndvcmxkVG9Mb2NhbChsKSxqPWxbMF0saz1sWzFdKTt2YXIgbj1qKmEud29ybGRTY2FsZVgsbz1rKmEud29ybGRTY2FsZVkscD1NYXRoLmF0YW4yKG8sbikscT1NYXRoLnNxcnQobipuK28qbykscj1iLmRhdGEubGVuZ3RoKmIud29ybGRTY2FsZVgscz0yKnEqcjtpZigxZS00PnMpcmV0dXJuIHZvaWQoYi5yb3RhdGlvbklLPWgrKE1hdGguYXRhbjIoZSxkKSpjLnJhZERlZy1pLWgpKmcpO3ZhciB0PShkKmQrZSplLXEqcS1yKnIpL3M7LTE+dD90PS0xOnQ+MSYmKHQ9MSk7dmFyIHU9TWF0aC5hY29zKHQpKmYsdj1xK3IqdCx3PXIqTWF0aC5zaW4odSkseD1NYXRoLmF0YW4yKGUqdi1kKncsZCp2K2UqdykseT0oeC1wKSpjLnJhZERlZy1pO3k+MTgwP3ktPTM2MDotMTgwPnkmJih5Kz0zNjApLGEucm90YXRpb25JSz1pK3kqZyx5PSh1K3ApKmMucmFkRGVnLWgseT4xODA/eS09MzYwOi0xODA+eSYmKHkrPTM2MCksYi5yb3RhdGlvbklLPWgrKHkrYS53b3JsZFJvdGF0aW9uLWIucGFyZW50LndvcmxkUm90YXRpb24pKmd9LGMuU2tpbj1mdW5jdGlvbihhKXt0aGlzLm5hbWU9YSx0aGlzLmF0dGFjaG1lbnRzPXt9fSxjLlNraW4ucHJvdG90eXBlPXthZGRBdHRhY2htZW50OmZ1bmN0aW9uKGEsYixjKXt0aGlzLmF0dGFjaG1lbnRzW2ErXCI6XCIrYl09Y30sZ2V0QXR0YWNobWVudDpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLmF0dGFjaG1lbnRzW2ErXCI6XCIrYl19LF9hdHRhY2hBbGw6ZnVuY3Rpb24oYSxiKXtmb3IodmFyIGMgaW4gYi5hdHRhY2htZW50cyl7dmFyIGQ9Yy5pbmRleE9mKFwiOlwiKSxlPXBhcnNlSW50KGMuc3Vic3RyaW5nKDAsZCkpLGY9Yy5zdWJzdHJpbmcoZCsxKSxnPWEuc2xvdHNbZV07aWYoZy5hdHRhY2htZW50JiZnLmF0dGFjaG1lbnQubmFtZT09Zil7dmFyIGg9dGhpcy5nZXRBdHRhY2htZW50KGUsZik7aCYmZy5zZXRBdHRhY2htZW50KGgpfX19fSxjLkFuaW1hdGlvbj1mdW5jdGlvbihhLGIsYyl7dGhpcy5uYW1lPWEsdGhpcy50aW1lbGluZXM9Yix0aGlzLmR1cmF0aW9uPWN9LGMuQW5pbWF0aW9uLnByb3RvdHlwZT17YXBwbHk6ZnVuY3Rpb24oYSxiLGMsZCxlKXtkJiYwIT10aGlzLmR1cmF0aW9uJiYoYyU9dGhpcy5kdXJhdGlvbixiJT10aGlzLmR1cmF0aW9uKTtmb3IodmFyIGY9dGhpcy50aW1lbGluZXMsZz0wLGg9Zi5sZW5ndGg7aD5nO2crKylmW2ddLmFwcGx5KGEsYixjLGUsMSl9LG1peDpmdW5jdGlvbihhLGIsYyxkLGUsZil7ZCYmMCE9dGhpcy5kdXJhdGlvbiYmKGMlPXRoaXMuZHVyYXRpb24sYiU9dGhpcy5kdXJhdGlvbik7Zm9yKHZhciBnPXRoaXMudGltZWxpbmVzLGg9MCxpPWcubGVuZ3RoO2k+aDtoKyspZ1toXS5hcHBseShhLGIsYyxlLGYpfX0sYy5BbmltYXRpb24uYmluYXJ5U2VhcmNoPWZ1bmN0aW9uKGEsYixjKXt2YXIgZD0wLGU9TWF0aC5mbG9vcihhLmxlbmd0aC9jKS0yO2lmKCFlKXJldHVybiBjO2Zvcih2YXIgZj1lPj4+MTs7KXtpZihhWyhmKzEpKmNdPD1iP2Q9ZisxOmU9ZixkPT1lKXJldHVybihkKzEpKmM7Zj1kK2U+Pj4xfX0sYy5BbmltYXRpb24uYmluYXJ5U2VhcmNoMT1mdW5jdGlvbihhLGIpe3ZhciBjPTAsZD1hLmxlbmd0aC0yO2lmKCFkKXJldHVybiAxO2Zvcih2YXIgZT1kPj4+MTs7KXtpZihhW2UrMV08PWI/Yz1lKzE6ZD1lLGM9PWQpcmV0dXJuIGMrMTtlPWMrZD4+PjF9fSxjLkFuaW1hdGlvbi5saW5lYXJTZWFyY2g9ZnVuY3Rpb24oYSxiLGMpe2Zvcih2YXIgZD0wLGU9YS5sZW5ndGgtYztlPj1kO2QrPWMpaWYoYVtkXT5iKXJldHVybiBkO3JldHVybi0xfSxjLkN1cnZlcz1mdW5jdGlvbigpe3RoaXMuY3VydmVzPVtdfSxjLkN1cnZlcy5wcm90b3R5cGU9e3NldExpbmVhcjpmdW5jdGlvbihhKXt0aGlzLmN1cnZlc1sxOSphXT0wfSxzZXRTdGVwcGVkOmZ1bmN0aW9uKGEpe3RoaXMuY3VydmVzWzE5KmFdPTF9LHNldEN1cnZlOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIGY9LjEsZz1mKmYsaD1nKmYsaT0zKmYsaj0zKmcsaz02KmcsbD02KmgsbT0yKi1iK2Qsbj0yKi1jK2Usbz0zKihiLWQpKzEscD0zKihjLWUpKzEscT1iKmkrbSpqK28qaCxyPWMqaStuKmorcCpoLHM9bSprK28qbCx0PW4qaytwKmwsdT1vKmwsdj1wKmwsdz0xOSphLHg9dGhpcy5jdXJ2ZXM7eFt3KytdPTI7Zm9yKHZhciB5PXEsej1yLEE9dysxOS0xO0E+dzt3Kz0yKXhbd109eSx4W3crMV09eixxKz1zLHIrPXQscys9dSx0Kz12LHkrPXEseis9cn0sZ2V0Q3VydmVQZXJjZW50OmZ1bmN0aW9uKGEsYil7Yj0wPmI/MDpiPjE/MTpiO3ZhciBjPXRoaXMuY3VydmVzLGQ9MTkqYSxlPWNbZF07aWYoMD09PWUpcmV0dXJuIGI7aWYoMT09ZSlyZXR1cm4gMDtkKys7Zm9yKHZhciBmPTAsZz1kLGg9ZCsxOS0xO2g+ZDtkKz0yKWlmKGY9Y1tkXSxmPj1iKXt2YXIgaSxqO3JldHVybiBkPT1nPyhpPTAsaj0wKTooaT1jW2QtMl0saj1jW2QtMV0pLGorKGNbZCsxXS1qKSooYi1pKS8oZi1pKX12YXIgaz1jW2QtMV07cmV0dXJuIGsrKDEtaykqKGItZikvKDEtZil9fSxjLlJvdGF0ZVRpbWVsaW5lPWZ1bmN0aW9uKGEpe3RoaXMuY3VydmVzPW5ldyBjLkN1cnZlcyhhKSx0aGlzLmZyYW1lcz1bXSx0aGlzLmZyYW1lcy5sZW5ndGg9MiphfSxjLlJvdGF0ZVRpbWVsaW5lLnByb3RvdHlwZT17Ym9uZUluZGV4OjAsZ2V0RnJhbWVDb3VudDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmZyYW1lcy5sZW5ndGgvMn0sc2V0RnJhbWU6ZnVuY3Rpb24oYSxiLGMpe2EqPTIsdGhpcy5mcmFtZXNbYV09Yix0aGlzLmZyYW1lc1thKzFdPWN9LGFwcGx5OmZ1bmN0aW9uKGEsYixkLGUsZil7dmFyIGc9dGhpcy5mcmFtZXM7aWYoIShkPGdbMF0pKXt2YXIgaD1hLmJvbmVzW3RoaXMuYm9uZUluZGV4XTtpZihkPj1nW2cubGVuZ3RoLTJdKXtmb3IodmFyIGk9aC5kYXRhLnJvdGF0aW9uK2dbZy5sZW5ndGgtMV0taC5yb3RhdGlvbjtpPjE4MDspaS09MzYwO2Zvcig7LTE4MD5pOylpKz0zNjA7cmV0dXJuIHZvaWQoaC5yb3RhdGlvbis9aSpmKX12YXIgaj1jLkFuaW1hdGlvbi5iaW5hcnlTZWFyY2goZyxkLDIpLGs9Z1tqLTFdLGw9Z1tqXSxtPTEtKGQtbCkvKGdbai0yXS1sKTttPXRoaXMuY3VydmVzLmdldEN1cnZlUGVyY2VudChqLzItMSxtKTtmb3IodmFyIGk9Z1tqKzFdLWs7aT4xODA7KWktPTM2MDtmb3IoOy0xODA+aTspaSs9MzYwO2ZvcihpPWguZGF0YS5yb3RhdGlvbisoaytpKm0pLWgucm90YXRpb247aT4xODA7KWktPTM2MDtmb3IoOy0xODA+aTspaSs9MzYwO2gucm90YXRpb24rPWkqZn19fSxjLlRyYW5zbGF0ZVRpbWVsaW5lPWZ1bmN0aW9uKGEpe3RoaXMuY3VydmVzPW5ldyBjLkN1cnZlcyhhKSx0aGlzLmZyYW1lcz1bXSx0aGlzLmZyYW1lcy5sZW5ndGg9MyphfSxjLlRyYW5zbGF0ZVRpbWVsaW5lLnByb3RvdHlwZT17Ym9uZUluZGV4OjAsZ2V0RnJhbWVDb3VudDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmZyYW1lcy5sZW5ndGgvM30sc2V0RnJhbWU6ZnVuY3Rpb24oYSxiLGMsZCl7YSo9Myx0aGlzLmZyYW1lc1thXT1iLHRoaXMuZnJhbWVzW2ErMV09Yyx0aGlzLmZyYW1lc1thKzJdPWR9LGFwcGx5OmZ1bmN0aW9uKGEsYixkLGUsZil7dmFyIGc9dGhpcy5mcmFtZXM7aWYoIShkPGdbMF0pKXt2YXIgaD1hLmJvbmVzW3RoaXMuYm9uZUluZGV4XTtpZihkPj1nW2cubGVuZ3RoLTNdKXJldHVybiBoLngrPShoLmRhdGEueCtnW2cubGVuZ3RoLTJdLWgueCkqZix2b2lkKGgueSs9KGguZGF0YS55K2dbZy5sZW5ndGgtMV0taC55KSpmKTt2YXIgaT1jLkFuaW1hdGlvbi5iaW5hcnlTZWFyY2goZyxkLDMpLGo9Z1tpLTJdLGs9Z1tpLTFdLGw9Z1tpXSxtPTEtKGQtbCkvKGdbaSstM10tbCk7bT10aGlzLmN1cnZlcy5nZXRDdXJ2ZVBlcmNlbnQoaS8zLTEsbSksaC54Kz0oaC5kYXRhLngraisoZ1tpKzFdLWopKm0taC54KSpmLGgueSs9KGguZGF0YS55K2srKGdbaSsyXS1rKSptLWgueSkqZn19fSxjLlNjYWxlVGltZWxpbmU9ZnVuY3Rpb24oYSl7dGhpcy5jdXJ2ZXM9bmV3IGMuQ3VydmVzKGEpLHRoaXMuZnJhbWVzPVtdLHRoaXMuZnJhbWVzLmxlbmd0aD0zKmF9LGMuU2NhbGVUaW1lbGluZS5wcm90b3R5cGU9e2JvbmVJbmRleDowLGdldEZyYW1lQ291bnQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5mcmFtZXMubGVuZ3RoLzN9LHNldEZyYW1lOmZ1bmN0aW9uKGEsYixjLGQpe2EqPTMsdGhpcy5mcmFtZXNbYV09Yix0aGlzLmZyYW1lc1thKzFdPWMsdGhpcy5mcmFtZXNbYSsyXT1kfSxhcHBseTpmdW5jdGlvbihhLGIsZCxlLGYpe3ZhciBnPXRoaXMuZnJhbWVzO2lmKCEoZDxnWzBdKSl7dmFyIGg9YS5ib25lc1t0aGlzLmJvbmVJbmRleF07aWYoZD49Z1tnLmxlbmd0aC0zXSlyZXR1cm4gaC5zY2FsZVgrPShoLmRhdGEuc2NhbGVYKmdbZy5sZW5ndGgtMl0taC5zY2FsZVgpKmYsdm9pZChoLnNjYWxlWSs9KGguZGF0YS5zY2FsZVkqZ1tnLmxlbmd0aC0xXS1oLnNjYWxlWSkqZik7dmFyIGk9Yy5BbmltYXRpb24uYmluYXJ5U2VhcmNoKGcsZCwzKSxqPWdbaS0yXSxrPWdbaS0xXSxsPWdbaV0sbT0xLShkLWwpLyhnW2krLTNdLWwpO209dGhpcy5jdXJ2ZXMuZ2V0Q3VydmVQZXJjZW50KGkvMy0xLG0pLGguc2NhbGVYKz0oaC5kYXRhLnNjYWxlWCooaisoZ1tpKzFdLWopKm0pLWguc2NhbGVYKSpmLGguc2NhbGVZKz0oaC5kYXRhLnNjYWxlWSooaysoZ1tpKzJdLWspKm0pLWguc2NhbGVZKSpmfX19LGMuQ29sb3JUaW1lbGluZT1mdW5jdGlvbihhKXt0aGlzLmN1cnZlcz1uZXcgYy5DdXJ2ZXMoYSksdGhpcy5mcmFtZXM9W10sdGhpcy5mcmFtZXMubGVuZ3RoPTUqYX0sYy5Db2xvclRpbWVsaW5lLnByb3RvdHlwZT17c2xvdEluZGV4OjAsZ2V0RnJhbWVDb3VudDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmZyYW1lcy5sZW5ndGgvNX0sc2V0RnJhbWU6ZnVuY3Rpb24oYSxiLGMsZCxlLGYpe2EqPTUsdGhpcy5mcmFtZXNbYV09Yix0aGlzLmZyYW1lc1thKzFdPWMsdGhpcy5mcmFtZXNbYSsyXT1kLHRoaXMuZnJhbWVzW2ErM109ZSx0aGlzLmZyYW1lc1thKzRdPWZ9LGFwcGx5OmZ1bmN0aW9uKGEsYixkLGUsZil7dmFyIGc9dGhpcy5mcmFtZXM7aWYoIShkPGdbMF0pKXt2YXIgaCxpLGosaztpZihkPj1nW2cubGVuZ3RoLTVdKXt2YXIgbD1nLmxlbmd0aC0xO2g9Z1tsLTNdLGk9Z1tsLTJdLGo9Z1tsLTFdLGs9Z1tsXX1lbHNle3ZhciBtPWMuQW5pbWF0aW9uLmJpbmFyeVNlYXJjaChnLGQsNSksbj1nW20tNF0sbz1nW20tM10scD1nW20tMl0scT1nW20tMV0scj1nW21dLHM9MS0oZC1yKS8oZ1ttLTVdLXIpO3M9dGhpcy5jdXJ2ZXMuZ2V0Q3VydmVQZXJjZW50KG0vNS0xLHMpLGg9bisoZ1ttKzFdLW4pKnMsaT1vKyhnW20rMl0tbykqcyxqPXArKGdbbSszXS1wKSpzLGs9cSsoZ1ttKzRdLXEpKnN9dmFyIHQ9YS5zbG90c1t0aGlzLnNsb3RJbmRleF07MT5mPyh0LnIrPShoLXQucikqZix0LmcrPShpLXQuZykqZix0LmIrPShqLXQuYikqZix0LmErPShrLXQuYSkqZik6KHQucj1oLHQuZz1pLHQuYj1qLHQuYT1rKX19fSxjLkF0dGFjaG1lbnRUaW1lbGluZT1mdW5jdGlvbihhKXt0aGlzLmN1cnZlcz1uZXcgYy5DdXJ2ZXMoYSksdGhpcy5mcmFtZXM9W10sdGhpcy5mcmFtZXMubGVuZ3RoPWEsdGhpcy5hdHRhY2htZW50TmFtZXM9W10sdGhpcy5hdHRhY2htZW50TmFtZXMubGVuZ3RoPWF9LGMuQXR0YWNobWVudFRpbWVsaW5lLnByb3RvdHlwZT17c2xvdEluZGV4OjAsZ2V0RnJhbWVDb3VudDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmZyYW1lcy5sZW5ndGh9LHNldEZyYW1lOmZ1bmN0aW9uKGEsYixjKXt0aGlzLmZyYW1lc1thXT1iLHRoaXMuYXR0YWNobWVudE5hbWVzW2FdPWN9LGFwcGx5OmZ1bmN0aW9uKGEsYixkKXt2YXIgZT10aGlzLmZyYW1lcztpZihkPGVbMF0pcmV0dXJuIHZvaWQoYj5kJiZ0aGlzLmFwcGx5KGEsYixOdW1iZXIuTUFYX1ZBTFVFLG51bGwsMCkpO2I+ZCYmKGI9LTEpO3ZhciBmPWQ+PWVbZS5sZW5ndGgtMV0/ZS5sZW5ndGgtMTpjLkFuaW1hdGlvbi5iaW5hcnlTZWFyY2gxKGUsZCktMTtpZighKGVbZl08Yikpe3ZhciBnPXRoaXMuYXR0YWNobWVudE5hbWVzW2ZdO2Euc2xvdHNbdGhpcy5zbG90SW5kZXhdLnNldEF0dGFjaG1lbnQoZz9hLmdldEF0dGFjaG1lbnRCeVNsb3RJbmRleCh0aGlzLnNsb3RJbmRleCxnKTpudWxsKX19fSxjLkV2ZW50VGltZWxpbmU9ZnVuY3Rpb24oYSl7dGhpcy5mcmFtZXM9W10sdGhpcy5mcmFtZXMubGVuZ3RoPWEsdGhpcy5ldmVudHM9W10sdGhpcy5ldmVudHMubGVuZ3RoPWF9LGMuRXZlbnRUaW1lbGluZS5wcm90b3R5cGU9e2dldEZyYW1lQ291bnQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5mcmFtZXMubGVuZ3RofSxzZXRGcmFtZTpmdW5jdGlvbihhLGIsYyl7dGhpcy5mcmFtZXNbYV09Yix0aGlzLmV2ZW50c1thXT1jfSxhcHBseTpmdW5jdGlvbihhLGIsZCxlLGYpe2lmKGUpe3ZhciBnPXRoaXMuZnJhbWVzLGg9Zy5sZW5ndGg7aWYoYj5kKXRoaXMuYXBwbHkoYSxiLE51bWJlci5NQVhfVkFMVUUsZSxmKSxiPS0xO2Vsc2UgaWYoYj49Z1toLTFdKXJldHVybjtpZighKGQ8Z1swXSkpe3ZhciBpO2lmKGI8Z1swXSlpPTA7ZWxzZXtpPWMuQW5pbWF0aW9uLmJpbmFyeVNlYXJjaDEoZyxiKTtmb3IodmFyIGo9Z1tpXTtpPjAmJmdbaS0xXT09ajspaS0tfWZvcih2YXIgaz10aGlzLmV2ZW50cztoPmkmJmQ+PWdbaV07aSsrKWUucHVzaChrW2ldKX19fX0sYy5EcmF3T3JkZXJUaW1lbGluZT1mdW5jdGlvbihhKXt0aGlzLmZyYW1lcz1bXSx0aGlzLmZyYW1lcy5sZW5ndGg9YSx0aGlzLmRyYXdPcmRlcnM9W10sdGhpcy5kcmF3T3JkZXJzLmxlbmd0aD1hfSxjLkRyYXdPcmRlclRpbWVsaW5lLnByb3RvdHlwZT17Z2V0RnJhbWVDb3VudDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmZyYW1lcy5sZW5ndGh9LHNldEZyYW1lOmZ1bmN0aW9uKGEsYixjKXt0aGlzLmZyYW1lc1thXT1iLHRoaXMuZHJhd09yZGVyc1thXT1jfSxhcHBseTpmdW5jdGlvbihhLGIsZCl7dmFyIGU9dGhpcy5mcmFtZXM7aWYoIShkPGVbMF0pKXt2YXIgZjtmPWQ+PWVbZS5sZW5ndGgtMV0/ZS5sZW5ndGgtMTpjLkFuaW1hdGlvbi5iaW5hcnlTZWFyY2gxKGUsZCktMTt2YXIgZz1hLmRyYXdPcmRlcixoPWEuc2xvdHMsaT10aGlzLmRyYXdPcmRlcnNbZl07aWYoaSlmb3IodmFyIGo9MCxrPWkubGVuZ3RoO2s+ajtqKyspZ1tqXT1hLnNsb3RzW2lbal1dO2Vsc2UgZm9yKHZhciBqPTAsaz1oLmxlbmd0aDtrPmo7aisrKWdbal09aFtqXX19fSxjLkZmZFRpbWVsaW5lPWZ1bmN0aW9uKGEpe3RoaXMuY3VydmVzPW5ldyBjLkN1cnZlcyhhKSx0aGlzLmZyYW1lcz1bXSx0aGlzLmZyYW1lcy5sZW5ndGg9YSx0aGlzLmZyYW1lVmVydGljZXM9W10sdGhpcy5mcmFtZVZlcnRpY2VzLmxlbmd0aD1hfSxjLkZmZFRpbWVsaW5lLnByb3RvdHlwZT17c2xvdEluZGV4OjAsYXR0YWNobWVudDowLGdldEZyYW1lQ291bnQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5mcmFtZXMubGVuZ3RofSxzZXRGcmFtZTpmdW5jdGlvbihhLGIsYyl7dGhpcy5mcmFtZXNbYV09Yix0aGlzLmZyYW1lVmVydGljZXNbYV09Y30sYXBwbHk6ZnVuY3Rpb24oYSxiLGQsZSxmKXt2YXIgZz1hLnNsb3RzW3RoaXMuc2xvdEluZGV4XTtpZihnLmF0dGFjaG1lbnQ9PXRoaXMuYXR0YWNobWVudCl7dmFyIGg9dGhpcy5mcmFtZXM7aWYoIShkPGhbMF0pKXt2YXIgaT10aGlzLmZyYW1lVmVydGljZXMsaj1pWzBdLmxlbmd0aCxrPWcuYXR0YWNobWVudFZlcnRpY2VzO2lmKGsubGVuZ3RoIT1qJiYoZj0xKSxrLmxlbmd0aD1qLGQ+PWhbaC5sZW5ndGgtMV0pe3ZhciBsPWlbaC5sZW5ndGgtMV07aWYoMT5mKWZvcih2YXIgbT0wO2o+bTttKyspa1ttXSs9KGxbbV0ta1ttXSkqZjtlbHNlIGZvcih2YXIgbT0wO2o+bTttKyspa1ttXT1sW21dfWVsc2V7dmFyIG49Yy5BbmltYXRpb24uYmluYXJ5U2VhcmNoMShoLGQpLG89aFtuXSxwPTEtKGQtbykvKGhbbi0xXS1vKTtwPXRoaXMuY3VydmVzLmdldEN1cnZlUGVyY2VudChuLTEsMD5wPzA6cD4xPzE6cCk7dmFyIHE9aVtuLTFdLHI9aVtuXTtpZigxPmYpZm9yKHZhciBtPTA7aj5tO20rKyl7dmFyIHM9cVttXTtrW21dKz0ocysoclttXS1zKSpwLWtbbV0pKmZ9ZWxzZSBmb3IodmFyIG09MDtqPm07bSsrKXt2YXIgcz1xW21dO2tbbV09cysoclttXS1zKSpwfX19fX19LGMuSWtDb25zdHJhaW50VGltZWxpbmU9ZnVuY3Rpb24oYSl7dGhpcy5jdXJ2ZXM9bmV3IGMuQ3VydmVzKGEpLHRoaXMuZnJhbWVzPVtdLHRoaXMuZnJhbWVzLmxlbmd0aD0zKmF9LGMuSWtDb25zdHJhaW50VGltZWxpbmUucHJvdG90eXBlPXtpa0NvbnN0cmFpbnRJbmRleDowLGdldEZyYW1lQ291bnQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5mcmFtZXMubGVuZ3RoLzN9LHNldEZyYW1lOmZ1bmN0aW9uKGEsYixjLGQpe2EqPTMsdGhpcy5mcmFtZXNbYV09Yix0aGlzLmZyYW1lc1thKzFdPWMsdGhpcy5mcmFtZXNbYSsyXT1kfSxhcHBseTpmdW5jdGlvbihhLGIsZCxlLGYpe3ZhciBnPXRoaXMuZnJhbWVzO2lmKCEoZDxnWzBdKSl7dmFyIGg9YS5pa0NvbnN0cmFpbnRzW3RoaXMuaWtDb25zdHJhaW50SW5kZXhdO2lmKGQ+PWdbZy5sZW5ndGgtM10pcmV0dXJuIGgubWl4Kz0oZ1tnLmxlbmd0aC0yXS1oLm1peCkqZix2b2lkKGguYmVuZERpcmVjdGlvbj1nW2cubGVuZ3RoLTFdKTt2YXIgaT1jLkFuaW1hdGlvbi5iaW5hcnlTZWFyY2goZyxkLDMpLGo9Z1tpKy0yXSxrPWdbaV0sbD0xLShkLWspLyhnW2krLTNdLWspO2w9dGhpcy5jdXJ2ZXMuZ2V0Q3VydmVQZXJjZW50KGkvMy0xLGwpO3ZhciBtPWorKGdbaSsxXS1qKSpsO2gubWl4Kz0obS1oLm1peCkqZixoLmJlbmREaXJlY3Rpb249Z1tpKy0xXX19fSxjLkZsaXBYVGltZWxpbmU9ZnVuY3Rpb24oYSl7dGhpcy5jdXJ2ZXM9bmV3IGMuQ3VydmVzKGEpLHRoaXMuZnJhbWVzPVtdLHRoaXMuZnJhbWVzLmxlbmd0aD0yKmF9LGMuRmxpcFhUaW1lbGluZS5wcm90b3R5cGU9e2JvbmVJbmRleDowLGdldEZyYW1lQ291bnQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5mcmFtZXMubGVuZ3RoLzJ9LHNldEZyYW1lOmZ1bmN0aW9uKGEsYixjKXthKj0yLHRoaXMuZnJhbWVzW2FdPWIsdGhpcy5mcmFtZXNbYSsxXT1jPzE6MH0sYXBwbHk6ZnVuY3Rpb24oYSxiLGQpe3ZhciBlPXRoaXMuZnJhbWVzO2lmKGQ8ZVswXSlyZXR1cm4gdm9pZChiPmQmJnRoaXMuYXBwbHkoYSxiLE51bWJlci5NQVhfVkFMVUUsbnVsbCwwKSk7Yj5kJiYoYj0tMSk7dmFyIGY9KGQ+PWVbZS5sZW5ndGgtMl0/ZS5sZW5ndGg6Yy5BbmltYXRpb24uYmluYXJ5U2VhcmNoKGUsZCwyKSktMjtlW2ZdPGJ8fChhLmJvbmVzW2JvbmVJbmRleF0uZmxpcFg9MCE9ZVtmKzFdKX19LGMuRmxpcFlUaW1lbGluZT1mdW5jdGlvbihhKXt0aGlzLmN1cnZlcz1uZXcgYy5DdXJ2ZXMoYSksdGhpcy5mcmFtZXM9W10sdGhpcy5mcmFtZXMubGVuZ3RoPTIqYX0sYy5GbGlwWVRpbWVsaW5lLnByb3RvdHlwZT17Ym9uZUluZGV4OjAsZ2V0RnJhbWVDb3VudDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmZyYW1lcy5sZW5ndGgvMn0sc2V0RnJhbWU6ZnVuY3Rpb24oYSxiLGMpe2EqPTIsdGhpcy5mcmFtZXNbYV09Yix0aGlzLmZyYW1lc1thKzFdPWM/MTowfSxhcHBseTpmdW5jdGlvbihhLGIsZCl7dmFyIGU9dGhpcy5mcmFtZXM7aWYoZDxlWzBdKXJldHVybiB2b2lkKGI+ZCYmdGhpcy5hcHBseShhLGIsTnVtYmVyLk1BWF9WQUxVRSxudWxsLDApKTtiPmQmJihiPS0xKTt2YXIgZj0oZD49ZVtlLmxlbmd0aC0yXT9lLmxlbmd0aDpjLkFuaW1hdGlvbi5iaW5hcnlTZWFyY2goZSxkLDIpKS0yO2VbZl08Ynx8KGEuYm9uZXNbYm9uZUluZGV4XS5mbGlwWT0wIT1lW2YrMV0pfX0sYy5Ta2VsZXRvbkRhdGE9ZnVuY3Rpb24oKXt0aGlzLmJvbmVzPVtdLHRoaXMuc2xvdHM9W10sdGhpcy5za2lucz1bXSx0aGlzLmV2ZW50cz1bXSx0aGlzLmFuaW1hdGlvbnM9W10sdGhpcy5pa0NvbnN0cmFpbnRzPVtdfSxjLlNrZWxldG9uRGF0YS5wcm90b3R5cGU9e25hbWU6bnVsbCxkZWZhdWx0U2tpbjpudWxsLHdpZHRoOjAsaGVpZ2h0OjAsdmVyc2lvbjpudWxsLGhhc2g6bnVsbCxmaW5kQm9uZTpmdW5jdGlvbihhKXtmb3IodmFyIGI9dGhpcy5ib25lcyxjPTAsZD1iLmxlbmd0aDtkPmM7YysrKWlmKGJbY10ubmFtZT09YSlyZXR1cm4gYltjXTtyZXR1cm4gbnVsbH0sZmluZEJvbmVJbmRleDpmdW5jdGlvbihhKXtmb3IodmFyIGI9dGhpcy5ib25lcyxjPTAsZD1iLmxlbmd0aDtkPmM7YysrKWlmKGJbY10ubmFtZT09YSlyZXR1cm4gYztyZXR1cm4tMX0sZmluZFNsb3Q6ZnVuY3Rpb24oYSl7Zm9yKHZhciBiPXRoaXMuc2xvdHMsYz0wLGQ9Yi5sZW5ndGg7ZD5jO2MrKylpZihiW2NdLm5hbWU9PWEpcmV0dXJuIHNsb3RbY107cmV0dXJuIG51bGx9LGZpbmRTbG90SW5kZXg6ZnVuY3Rpb24oYSl7Zm9yKHZhciBiPXRoaXMuc2xvdHMsYz0wLGQ9Yi5sZW5ndGg7ZD5jO2MrKylpZihiW2NdLm5hbWU9PWEpcmV0dXJuIGM7cmV0dXJuLTF9LGZpbmRTa2luOmZ1bmN0aW9uKGEpe2Zvcih2YXIgYj10aGlzLnNraW5zLGM9MCxkPWIubGVuZ3RoO2Q+YztjKyspaWYoYltjXS5uYW1lPT1hKXJldHVybiBiW2NdO3JldHVybiBudWxsfSxmaW5kRXZlbnQ6ZnVuY3Rpb24oYSl7Zm9yKHZhciBiPXRoaXMuZXZlbnRzLGM9MCxkPWIubGVuZ3RoO2Q+YztjKyspaWYoYltjXS5uYW1lPT1hKXJldHVybiBiW2NdO3JldHVybiBudWxsfSxmaW5kQW5pbWF0aW9uOmZ1bmN0aW9uKGEpe2Zvcih2YXIgYj10aGlzLmFuaW1hdGlvbnMsYz0wLGQ9Yi5sZW5ndGg7ZD5jO2MrKylpZihiW2NdLm5hbWU9PWEpcmV0dXJuIGJbY107cmV0dXJuIG51bGx9LGZpbmRJa0NvbnN0cmFpbnQ6ZnVuY3Rpb24oYSl7Zm9yKHZhciBiPXRoaXMuaWtDb25zdHJhaW50cyxjPTAsZD1iLmxlbmd0aDtkPmM7YysrKWlmKGJbY10ubmFtZT09YSlyZXR1cm4gYltjXTtyZXR1cm4gbnVsbH19LGMuU2tlbGV0b249ZnVuY3Rpb24oYSl7dGhpcy5kYXRhPWEsdGhpcy5ib25lcz1bXTtmb3IodmFyIGI9MCxkPWEuYm9uZXMubGVuZ3RoO2Q+YjtiKyspe3ZhciBlPWEuYm9uZXNbYl0sZj1lLnBhcmVudD90aGlzLmJvbmVzW2EuYm9uZXMuaW5kZXhPZihlLnBhcmVudCldOm51bGw7dGhpcy5ib25lcy5wdXNoKG5ldyBjLkJvbmUoZSx0aGlzLGYpKX10aGlzLnNsb3RzPVtdLHRoaXMuZHJhd09yZGVyPVtdO2Zvcih2YXIgYj0wLGQ9YS5zbG90cy5sZW5ndGg7ZD5iO2IrKyl7dmFyIGc9YS5zbG90c1tiXSxoPXRoaXMuYm9uZXNbYS5ib25lcy5pbmRleE9mKGcuYm9uZURhdGEpXSxpPW5ldyBjLlNsb3QoZyxoKTt0aGlzLnNsb3RzLnB1c2goaSksdGhpcy5kcmF3T3JkZXIucHVzaChpKX10aGlzLmlrQ29uc3RyYWludHM9W107Zm9yKHZhciBiPTAsZD1hLmlrQ29uc3RyYWludHMubGVuZ3RoO2Q+YjtiKyspdGhpcy5pa0NvbnN0cmFpbnRzLnB1c2gobmV3IGMuSWtDb25zdHJhaW50KGEuaWtDb25zdHJhaW50c1tiXSx0aGlzKSk7dGhpcy5ib25lQ2FjaGU9W10sdGhpcy51cGRhdGVDYWNoZSgpfSxjLlNrZWxldG9uLnByb3RvdHlwZT17eDowLHk6MCxza2luOm51bGwscjoxLGc6MSxiOjEsYToxLHRpbWU6MCxmbGlwWDohMSxmbGlwWTohMSx1cGRhdGVDYWNoZTpmdW5jdGlvbigpe3ZhciBhPXRoaXMuaWtDb25zdHJhaW50cyxiPWEubGVuZ3RoLGM9YisxLGQ9dGhpcy5ib25lQ2FjaGU7ZC5sZW5ndGg+YyYmKGQubGVuZ3RoPWMpO2Zvcih2YXIgZT0wLGY9ZC5sZW5ndGg7Zj5lO2UrKylkW2VdLmxlbmd0aD0wO2Zvcig7ZC5sZW5ndGg8YzspZFtkLmxlbmd0aF09W107dmFyIGc9ZFswXSxoPXRoaXMuYm9uZXM7YTpmb3IodmFyIGU9MCxmPWgubGVuZ3RoO2Y+ZTtlKyspe3ZhciBpPWhbZV0saj1pO2Rve2Zvcih2YXIgaz0wO2I+aztrKyspZm9yKHZhciBsPWFba10sbT1sLmJvbmVzWzBdLG49bC5ib25lc1tsLmJvbmVzLmxlbmd0aC0xXTs7KXtpZihqPT1uKXtkW2tdLnB1c2goaSksZFtrKzFdLnB1c2goaSk7Y29udGludWUgYX1pZihuPT1tKWJyZWFrO249bi5wYXJlbnR9aj1qLnBhcmVudH13aGlsZShqKTtnW2cubGVuZ3RoXT1pfX0sdXBkYXRlV29ybGRUcmFuc2Zvcm06ZnVuY3Rpb24oKXtmb3IodmFyIGE9dGhpcy5ib25lcyxiPTAsYz1hLmxlbmd0aDtjPmI7YisrKXt2YXIgZD1hW2JdO2Qucm90YXRpb25JSz1kLnJvdGF0aW9ufWZvcih2YXIgYj0wLGU9dGhpcy5ib25lQ2FjaGUubGVuZ3RoLTE7Oyl7Zm9yKHZhciBmPXRoaXMuYm9uZUNhY2hlW2JdLGc9MCxoPWYubGVuZ3RoO2g+ZztnKyspZltnXS51cGRhdGVXb3JsZFRyYW5zZm9ybSgpO2lmKGI9PWUpYnJlYWs7dGhpcy5pa0NvbnN0cmFpbnRzW2JdLmFwcGx5KCksYisrfX0sc2V0VG9TZXR1cFBvc2U6ZnVuY3Rpb24oKXt0aGlzLnNldEJvbmVzVG9TZXR1cFBvc2UoKSx0aGlzLnNldFNsb3RzVG9TZXR1cFBvc2UoKX0sc2V0Qm9uZXNUb1NldHVwUG9zZTpmdW5jdGlvbigpe2Zvcih2YXIgYT10aGlzLmJvbmVzLGI9MCxjPWEubGVuZ3RoO2M+YjtiKyspYVtiXS5zZXRUb1NldHVwUG9zZSgpO2Zvcih2YXIgZD10aGlzLmlrQ29uc3RyYWludHMsYj0wLGM9ZC5sZW5ndGg7Yz5iO2IrKyl7dmFyIGU9ZFtiXTtlLmJlbmREaXJlY3Rpb249ZS5kYXRhLmJlbmREaXJlY3Rpb24sZS5taXg9ZS5kYXRhLm1peH19LHNldFNsb3RzVG9TZXR1cFBvc2U6ZnVuY3Rpb24oKXtmb3IodmFyIGE9dGhpcy5zbG90cyxiPXRoaXMuZHJhd09yZGVyLGM9MCxkPWEubGVuZ3RoO2Q+YztjKyspYltjXT1hW2NdLGFbY10uc2V0VG9TZXR1cFBvc2UoYyl9LGdldFJvb3RCb25lOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYm9uZXMubGVuZ3RoP3RoaXMuYm9uZXNbMF06bnVsbH0sZmluZEJvbmU6ZnVuY3Rpb24oYSl7Zm9yKHZhciBiPXRoaXMuYm9uZXMsYz0wLGQ9Yi5sZW5ndGg7ZD5jO2MrKylpZihiW2NdLmRhdGEubmFtZT09YSlyZXR1cm4gYltjXTtyZXR1cm4gbnVsbH0sZmluZEJvbmVJbmRleDpmdW5jdGlvbihhKXtmb3IodmFyIGI9dGhpcy5ib25lcyxjPTAsZD1iLmxlbmd0aDtkPmM7YysrKWlmKGJbY10uZGF0YS5uYW1lPT1hKXJldHVybiBjO3JldHVybi0xfSxmaW5kU2xvdDpmdW5jdGlvbihhKXtmb3IodmFyIGI9dGhpcy5zbG90cyxjPTAsZD1iLmxlbmd0aDtkPmM7YysrKWlmKGJbY10uZGF0YS5uYW1lPT1hKXJldHVybiBiW2NdO3JldHVybiBudWxsfSxmaW5kU2xvdEluZGV4OmZ1bmN0aW9uKGEpe2Zvcih2YXIgYj10aGlzLnNsb3RzLGM9MCxkPWIubGVuZ3RoO2Q+YztjKyspaWYoYltjXS5kYXRhLm5hbWU9PWEpcmV0dXJuIGM7cmV0dXJuLTF9LHNldFNraW5CeU5hbWU6ZnVuY3Rpb24oYSl7dmFyIGI9dGhpcy5kYXRhLmZpbmRTa2luKGEpO2lmKCFiKXRocm93XCJTa2luIG5vdCBmb3VuZDogXCIrYTt0aGlzLnNldFNraW4oYil9LHNldFNraW46ZnVuY3Rpb24oYSl7aWYoYSlpZih0aGlzLnNraW4pYS5fYXR0YWNoQWxsKHRoaXMsdGhpcy5za2luKTtlbHNlIGZvcih2YXIgYj10aGlzLnNsb3RzLGM9MCxkPWIubGVuZ3RoO2Q+YztjKyspe3ZhciBlPWJbY10sZj1lLmRhdGEuYXR0YWNobWVudE5hbWU7aWYoZil7dmFyIGc9YS5nZXRBdHRhY2htZW50KGMsZik7ZyYmZS5zZXRBdHRhY2htZW50KGcpfX10aGlzLnNraW49YX0sZ2V0QXR0YWNobWVudEJ5U2xvdE5hbWU6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5nZXRBdHRhY2htZW50QnlTbG90SW5kZXgodGhpcy5kYXRhLmZpbmRTbG90SW5kZXgoYSksYil9LGdldEF0dGFjaG1lbnRCeVNsb3RJbmRleDpmdW5jdGlvbihhLGIpe2lmKHRoaXMuc2tpbil7dmFyIGM9dGhpcy5za2luLmdldEF0dGFjaG1lbnQoYSxiKTtpZihjKXJldHVybiBjfXJldHVybiB0aGlzLmRhdGEuZGVmYXVsdFNraW4/dGhpcy5kYXRhLmRlZmF1bHRTa2luLmdldEF0dGFjaG1lbnQoYSxiKTpudWxsfSxzZXRBdHRhY2htZW50OmZ1bmN0aW9uKGEsYil7Zm9yKHZhciBjPXRoaXMuc2xvdHMsZD0wLGU9Yy5sZW5ndGg7ZT5kO2QrKyl7dmFyIGY9Y1tkXTtpZihmLmRhdGEubmFtZT09YSl7dmFyIGc9bnVsbDtpZihiJiYoZz10aGlzLmdldEF0dGFjaG1lbnRCeVNsb3RJbmRleChkLGIpLCFnKSl0aHJvd1wiQXR0YWNobWVudCBub3QgZm91bmQ6IFwiK2IrXCIsIGZvciBzbG90OiBcIithO3JldHVybiB2b2lkIGYuc2V0QXR0YWNobWVudChnKX19dGhyb3dcIlNsb3Qgbm90IGZvdW5kOiBcIithfSxmaW5kSWtDb25zdHJhaW50OmZ1bmN0aW9uKGEpe2Zvcih2YXIgYj10aGlzLmlrQ29uc3RyYWludHMsYz0wLGQ9Yi5sZW5ndGg7ZD5jO2MrKylpZihiW2NdLmRhdGEubmFtZT09YSlyZXR1cm4gYltjXTtyZXR1cm4gbnVsbH0sdXBkYXRlOmZ1bmN0aW9uKGEpe3RoaXMudGltZSs9YX19LGMuRXZlbnREYXRhPWZ1bmN0aW9uKGEpe3RoaXMubmFtZT1hfSxjLkV2ZW50RGF0YS5wcm90b3R5cGU9e2ludFZhbHVlOjAsZmxvYXRWYWx1ZTowLHN0cmluZ1ZhbHVlOm51bGx9LGMuRXZlbnQ9ZnVuY3Rpb24oYSl7dGhpcy5kYXRhPWF9LGMuRXZlbnQucHJvdG90eXBlPXtpbnRWYWx1ZTowLGZsb2F0VmFsdWU6MCxzdHJpbmdWYWx1ZTpudWxsfSxjLkF0dGFjaG1lbnRUeXBlPXtyZWdpb246MCxib3VuZGluZ2JveDoxLG1lc2g6Mixza2lubmVkbWVzaDozfSxjLlJlZ2lvbkF0dGFjaG1lbnQ9ZnVuY3Rpb24oYSl7dGhpcy5uYW1lPWEsdGhpcy5vZmZzZXQ9W10sdGhpcy5vZmZzZXQubGVuZ3RoPTgsdGhpcy51dnM9W10sdGhpcy51dnMubGVuZ3RoPTh9LGMuUmVnaW9uQXR0YWNobWVudC5wcm90b3R5cGU9e3R5cGU6Yy5BdHRhY2htZW50VHlwZS5yZWdpb24seDowLHk6MCxyb3RhdGlvbjowLHNjYWxlWDoxLHNjYWxlWToxLHdpZHRoOjAsaGVpZ2h0OjAscjoxLGc6MSxiOjEsYToxLHBhdGg6bnVsbCxyZW5kZXJlck9iamVjdDpudWxsLHJlZ2lvbk9mZnNldFg6MCxyZWdpb25PZmZzZXRZOjAscmVnaW9uV2lkdGg6MCxyZWdpb25IZWlnaHQ6MCxyZWdpb25PcmlnaW5hbFdpZHRoOjAscmVnaW9uT3JpZ2luYWxIZWlnaHQ6MCxzZXRVVnM6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgZj10aGlzLnV2cztlPyhmWzJdPWEsZlszXT1kLGZbNF09YSxmWzVdPWIsZls2XT1jLGZbN109YixmWzBdPWMsZlsxXT1kKTooZlswXT1hLGZbMV09ZCxmWzJdPWEsZlszXT1iLGZbNF09YyxmWzVdPWIsZls2XT1jLGZbN109ZCl9LHVwZGF0ZU9mZnNldDpmdW5jdGlvbigpe3ZhciBhPXRoaXMud2lkdGgvdGhpcy5yZWdpb25PcmlnaW5hbFdpZHRoKnRoaXMuc2NhbGVYLGI9dGhpcy5oZWlnaHQvdGhpcy5yZWdpb25PcmlnaW5hbEhlaWdodCp0aGlzLnNjYWxlWSxkPS10aGlzLndpZHRoLzIqdGhpcy5zY2FsZVgrdGhpcy5yZWdpb25PZmZzZXRYKmEsZT0tdGhpcy5oZWlnaHQvMip0aGlzLnNjYWxlWSt0aGlzLnJlZ2lvbk9mZnNldFkqYixmPWQrdGhpcy5yZWdpb25XaWR0aCphLGc9ZSt0aGlzLnJlZ2lvbkhlaWdodCpiLGg9dGhpcy5yb3RhdGlvbipjLmRlZ1JhZCxpPU1hdGguY29zKGgpLGo9TWF0aC5zaW4oaCksaz1kKmkrdGhpcy54LGw9ZCpqLG09ZSppK3RoaXMueSxuPWUqaixvPWYqaSt0aGlzLngscD1mKmoscT1nKmkrdGhpcy55LHI9ZypqLHM9dGhpcy5vZmZzZXQ7c1swXT1rLW4sc1sxXT1tK2wsc1syXT1rLXIsc1szXT1xK2wsc1s0XT1vLXIsc1s1XT1xK3Asc1s2XT1vLW4sc1s3XT1tK3B9LGNvbXB1dGVWZXJ0aWNlczpmdW5jdGlvbihhLGIsYyxkKXthKz1jLndvcmxkWCxiKz1jLndvcmxkWTt2YXIgZT1jLm0wMCxmPWMubTAxLGc9Yy5tMTAsaD1jLm0xMSxpPXRoaXMub2Zmc2V0O2RbMF09aVswXSplK2lbMV0qZithLGRbMV09aVswXSpnK2lbMV0qaCtiLGRbMl09aVsyXSplK2lbM10qZithLGRbM109aVsyXSpnK2lbM10qaCtiLGRbNF09aVs0XSplK2lbNV0qZithLGRbNV09aVs0XSpnK2lbNV0qaCtiLGRbNl09aVs2XSplK2lbN10qZithLGRbN109aVs2XSpnK2lbN10qaCtifX0sYy5NZXNoQXR0YWNobWVudD1mdW5jdGlvbihhKXt0aGlzLm5hbWU9YX0sYy5NZXNoQXR0YWNobWVudC5wcm90b3R5cGU9e3R5cGU6Yy5BdHRhY2htZW50VHlwZS5tZXNoLHZlcnRpY2VzOm51bGwsdXZzOm51bGwscmVnaW9uVVZzOm51bGwsdHJpYW5nbGVzOm51bGwsaHVsbExlbmd0aDowLHI6MSxnOjEsYjoxLGE6MSxwYXRoOm51bGwscmVuZGVyZXJPYmplY3Q6bnVsbCxyZWdpb25VOjAscmVnaW9uVjowLHJlZ2lvblUyOjAscmVnaW9uVjI6MCxyZWdpb25Sb3RhdGU6ITEscmVnaW9uT2Zmc2V0WDowLHJlZ2lvbk9mZnNldFk6MCxyZWdpb25XaWR0aDowLHJlZ2lvbkhlaWdodDowLHJlZ2lvbk9yaWdpbmFsV2lkdGg6MCxyZWdpb25PcmlnaW5hbEhlaWdodDowLGVkZ2VzOm51bGwsd2lkdGg6MCxoZWlnaHQ6MCx1cGRhdGVVVnM6ZnVuY3Rpb24oKXt2YXIgYT10aGlzLnJlZ2lvblUyLXRoaXMucmVnaW9uVSxiPXRoaXMucmVnaW9uVjItdGhpcy5yZWdpb25WLGQ9dGhpcy5yZWdpb25VVnMubGVuZ3RoO2lmKHRoaXMudXZzJiZ0aGlzLnV2cy5sZW5ndGg9PWR8fCh0aGlzLnV2cz1uZXcgYy5GbG9hdDMyQXJyYXkoZCkpLHRoaXMucmVnaW9uUm90YXRlKWZvcih2YXIgZT0wO2Q+ZTtlKz0yKXRoaXMudXZzW2VdPXRoaXMucmVnaW9uVSt0aGlzLnJlZ2lvblVWc1tlKzFdKmEsdGhpcy51dnNbZSsxXT10aGlzLnJlZ2lvblYrYi10aGlzLnJlZ2lvblVWc1tlXSpiO2Vsc2UgZm9yKHZhciBlPTA7ZD5lO2UrPTIpdGhpcy51dnNbZV09dGhpcy5yZWdpb25VK3RoaXMucmVnaW9uVVZzW2VdKmEsdGhpcy51dnNbZSsxXT10aGlzLnJlZ2lvblYrdGhpcy5yZWdpb25VVnNbZSsxXSpifSxjb21wdXRlV29ybGRWZXJ0aWNlczpmdW5jdGlvbihhLGIsYyxkKXt2YXIgZT1jLmJvbmU7YSs9ZS53b3JsZFgsYis9ZS53b3JsZFk7dmFyIGY9ZS5tMDAsZz1lLm0wMSxoPWUubTEwLGk9ZS5tMTEsaj10aGlzLnZlcnRpY2VzLGs9ai5sZW5ndGg7Yy5hdHRhY2htZW50VmVydGljZXMubGVuZ3RoPT1rJiYoaj1jLmF0dGFjaG1lbnRWZXJ0aWNlcyk7Zm9yKHZhciBsPTA7az5sO2wrPTIpe3ZhciBtPWpbbF0sbj1qW2wrMV07ZFtsXT1tKmYrbipnK2EsZFtsKzFdPW0qaCtuKmkrYn19fSxjLlNraW5uZWRNZXNoQXR0YWNobWVudD1mdW5jdGlvbihhKXt0aGlzLm5hbWU9YX0sYy5Ta2lubmVkTWVzaEF0dGFjaG1lbnQucHJvdG90eXBlPXt0eXBlOmMuQXR0YWNobWVudFR5cGUuc2tpbm5lZG1lc2gsYm9uZXM6bnVsbCx3ZWlnaHRzOm51bGwsdXZzOm51bGwscmVnaW9uVVZzOm51bGwsdHJpYW5nbGVzOm51bGwsaHVsbExlbmd0aDowLHI6MSxnOjEsYjoxLGE6MSxwYXRoOm51bGwscmVuZGVyZXJPYmplY3Q6bnVsbCxyZWdpb25VOjAscmVnaW9uVjowLHJlZ2lvblUyOjAscmVnaW9uVjI6MCxyZWdpb25Sb3RhdGU6ITEscmVnaW9uT2Zmc2V0WDowLHJlZ2lvbk9mZnNldFk6MCxyZWdpb25XaWR0aDowLHJlZ2lvbkhlaWdodDowLHJlZ2lvbk9yaWdpbmFsV2lkdGg6MCxyZWdpb25PcmlnaW5hbEhlaWdodDowLGVkZ2VzOm51bGwsd2lkdGg6MCxoZWlnaHQ6MCx1cGRhdGVVVnM6ZnVuY3Rpb24oKXt2YXIgYT10aGlzLnJlZ2lvblUyLXRoaXMucmVnaW9uVSxiPXRoaXMucmVnaW9uVjItdGhpcy5yZWdpb25WLGQ9dGhpcy5yZWdpb25VVnMubGVuZ3RoO2lmKHRoaXMudXZzJiZ0aGlzLnV2cy5sZW5ndGg9PWR8fCh0aGlzLnV2cz1uZXcgYy5GbG9hdDMyQXJyYXkoZCkpLHRoaXMucmVnaW9uUm90YXRlKWZvcih2YXIgZT0wO2Q+ZTtlKz0yKXRoaXMudXZzW2VdPXRoaXMucmVnaW9uVSt0aGlzLnJlZ2lvblVWc1tlKzFdKmEsdGhpcy51dnNbZSsxXT10aGlzLnJlZ2lvblYrYi10aGlzLnJlZ2lvblVWc1tlXSpiO2Vsc2UgZm9yKHZhciBlPTA7ZD5lO2UrPTIpdGhpcy51dnNbZV09dGhpcy5yZWdpb25VK3RoaXMucmVnaW9uVVZzW2VdKmEsdGhpcy51dnNbZSsxXT10aGlzLnJlZ2lvblYrdGhpcy5yZWdpb25VVnNbZSsxXSpifSxjb21wdXRlV29ybGRWZXJ0aWNlczpmdW5jdGlvbihhLGIsYyxkKXt2YXIgZSxmLGcsaCxpLGosayxsPWMuYm9uZS5za2VsZXRvbi5ib25lcyxtPXRoaXMud2VpZ2h0cyxuPXRoaXMuYm9uZXMsbz0wLHA9MCxxPTAscj0wLHM9bi5sZW5ndGg7aWYoYy5hdHRhY2htZW50VmVydGljZXMubGVuZ3RoKWZvcih2YXIgdD1jLmF0dGFjaG1lbnRWZXJ0aWNlcztzPnA7bys9Mil7Zm9yKGY9MCxnPTAsZT1uW3ArK10rcDtlPnA7cCsrLHErPTMscis9MiloPWxbbltwXV0saT1tW3FdK3Rbcl0saj1tW3ErMV0rdFtyKzFdLGs9bVtxKzJdLGYrPShpKmgubTAwK2oqaC5tMDEraC53b3JsZFgpKmssZys9KGkqaC5tMTAraipoLm0xMStoLndvcmxkWSkqaztkW29dPWYrYSxkW28rMV09ZytifWVsc2UgZm9yKDtzPnA7bys9Mil7Zm9yKGY9MCxnPTAsZT1uW3ArK10rcDtlPnA7cCsrLHErPTMpaD1sW25bcF1dLGk9bVtxXSxqPW1bcSsxXSxrPW1bcSsyXSxmKz0oaSpoLm0wMCtqKmgubTAxK2gud29ybGRYKSprLGcrPShpKmgubTEwK2oqaC5tMTEraC53b3JsZFkpKms7ZFtvXT1mK2EsZFtvKzFdPWcrYn19fSxjLkJvdW5kaW5nQm94QXR0YWNobWVudD1mdW5jdGlvbihhKXt0aGlzLm5hbWU9YSx0aGlzLnZlcnRpY2VzPVtdfSxjLkJvdW5kaW5nQm94QXR0YWNobWVudC5wcm90b3R5cGU9e3R5cGU6Yy5BdHRhY2htZW50VHlwZS5ib3VuZGluZ2JveCxjb21wdXRlV29ybGRWZXJ0aWNlczpmdW5jdGlvbihhLGIsYyxkKXthKz1jLndvcmxkWCxiKz1jLndvcmxkWTtmb3IodmFyIGU9Yy5tMDAsZj1jLm0wMSxnPWMubTEwLGg9Yy5tMTEsaT10aGlzLnZlcnRpY2VzLGo9MCxrPWkubGVuZ3RoO2s+ajtqKz0yKXt2YXIgbD1pW2pdLG09aVtqKzFdO2Rbal09bCplK20qZithLGRbaisxXT1sKmcrbSpoK2J9fX0sYy5BbmltYXRpb25TdGF0ZURhdGE9ZnVuY3Rpb24oYSl7dGhpcy5za2VsZXRvbkRhdGE9YSx0aGlzLmFuaW1hdGlvblRvTWl4VGltZT17fX0sYy5BbmltYXRpb25TdGF0ZURhdGEucHJvdG90eXBlPXtkZWZhdWx0TWl4OjAsc2V0TWl4QnlOYW1lOmZ1bmN0aW9uKGEsYixjKXt2YXIgZD10aGlzLnNrZWxldG9uRGF0YS5maW5kQW5pbWF0aW9uKGEpO2lmKCFkKXRocm93XCJBbmltYXRpb24gbm90IGZvdW5kOiBcIithO3ZhciBlPXRoaXMuc2tlbGV0b25EYXRhLmZpbmRBbmltYXRpb24oYik7aWYoIWUpdGhyb3dcIkFuaW1hdGlvbiBub3QgZm91bmQ6IFwiK2I7dGhpcy5zZXRNaXgoZCxlLGMpfSxzZXRNaXg6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuYW5pbWF0aW9uVG9NaXhUaW1lW2EubmFtZStcIjpcIitiLm5hbWVdPWN9LGdldE1peDpmdW5jdGlvbihhLGIpe3ZhciBjPWEubmFtZStcIjpcIitiLm5hbWU7cmV0dXJuIHRoaXMuYW5pbWF0aW9uVG9NaXhUaW1lLmhhc093blByb3BlcnR5KGMpP3RoaXMuYW5pbWF0aW9uVG9NaXhUaW1lW2NdOnRoaXMuZGVmYXVsdE1peH19LGMuVHJhY2tFbnRyeT1mdW5jdGlvbigpe30sYy5UcmFja0VudHJ5LnByb3RvdHlwZT17bmV4dDpudWxsLHByZXZpb3VzOm51bGwsYW5pbWF0aW9uOm51bGwsbG9vcDohMSxkZWxheTowLHRpbWU6MCxsYXN0VGltZTotMSxlbmRUaW1lOjAsdGltZVNjYWxlOjEsbWl4VGltZTowLG1peER1cmF0aW9uOjAsbWl4OjEsb25TdGFydDpudWxsLG9uRW5kOm51bGwsb25Db21wbGV0ZTpudWxsLG9uRXZlbnQ6bnVsbH0sYy5BbmltYXRpb25TdGF0ZT1mdW5jdGlvbihhKXt0aGlzLmRhdGE9YSx0aGlzLnRyYWNrcz1bXSx0aGlzLmV2ZW50cz1bXX0sYy5BbmltYXRpb25TdGF0ZS5wcm90b3R5cGU9e29uU3RhcnQ6bnVsbCxvbkVuZDpudWxsLG9uQ29tcGxldGU6bnVsbCxvbkV2ZW50Om51bGwsdGltZVNjYWxlOjEsdXBkYXRlOmZ1bmN0aW9uKGEpe2EqPXRoaXMudGltZVNjYWxlO2Zvcih2YXIgYj0wO2I8dGhpcy50cmFja3MubGVuZ3RoO2IrKyl7dmFyIGM9dGhpcy50cmFja3NbYl07aWYoYyl7aWYoYy50aW1lKz1hKmMudGltZVNjYWxlLGMucHJldmlvdXMpe3ZhciBkPWEqYy5wcmV2aW91cy50aW1lU2NhbGU7Yy5wcmV2aW91cy50aW1lKz1kLGMubWl4VGltZSs9ZH12YXIgZT1jLm5leHQ7ZT8oZS50aW1lPWMubGFzdFRpbWUtZS5kZWxheSxlLnRpbWU+PTAmJnRoaXMuc2V0Q3VycmVudChiLGUpKTohYy5sb29wJiZjLmxhc3RUaW1lPj1jLmVuZFRpbWUmJnRoaXMuY2xlYXJUcmFjayhiKX19fSxhcHBseTpmdW5jdGlvbihhKXtmb3IodmFyIGI9MDtiPHRoaXMudHJhY2tzLmxlbmd0aDtiKyspe3ZhciBjPXRoaXMudHJhY2tzW2JdO2lmKGMpe3RoaXMuZXZlbnRzLmxlbmd0aD0wO3ZhciBkPWMudGltZSxlPWMubGFzdFRpbWUsZj1jLmVuZFRpbWUsZz1jLmxvb3A7IWcmJmQ+ZiYmKGQ9Zik7dmFyIGg9Yy5wcmV2aW91cztpZihoKXt2YXIgaT1oLnRpbWU7IWgubG9vcCYmaT5oLmVuZFRpbWUmJihpPWguZW5kVGltZSksaC5hbmltYXRpb24uYXBwbHkoYSxpLGksaC5sb29wLG51bGwpO3ZhciBqPWMubWl4VGltZS9jLm1peER1cmF0aW9uKmMubWl4O2o+PTEmJihqPTEsYy5wcmV2aW91cz1udWxsKSxjLmFuaW1hdGlvbi5taXgoYSxjLmxhc3RUaW1lLGQsZyx0aGlzLmV2ZW50cyxqKX1lbHNlIDE9PWMubWl4P2MuYW5pbWF0aW9uLmFwcGx5KGEsYy5sYXN0VGltZSxkLGcsdGhpcy5ldmVudHMpOmMuYW5pbWF0aW9uLm1peChhLGMubGFzdFRpbWUsZCxnLHRoaXMuZXZlbnRzLGMubWl4KTtmb3IodmFyIGs9MCxsPXRoaXMuZXZlbnRzLmxlbmd0aDtsPms7aysrKXt2YXIgbT10aGlzLmV2ZW50c1trXTtjLm9uRXZlbnQmJmMub25FdmVudChiLG0pLHRoaXMub25FdmVudCYmdGhpcy5vbkV2ZW50KGIsbSl9aWYoZz9lJWY+ZCVmOmY+ZSYmZD49Zil7dmFyIG49TWF0aC5mbG9vcihkL2YpO2Mub25Db21wbGV0ZSYmYy5vbkNvbXBsZXRlKGIsbiksdGhpcy5vbkNvbXBsZXRlJiZ0aGlzLm9uQ29tcGxldGUoYixuKX1jLmxhc3RUaW1lPWMudGltZX19fSxjbGVhclRyYWNrczpmdW5jdGlvbigpe2Zvcih2YXIgYT0wLGI9dGhpcy50cmFja3MubGVuZ3RoO2I+YTthKyspdGhpcy5jbGVhclRyYWNrKGEpO3RoaXMudHJhY2tzLmxlbmd0aD0wfSxjbGVhclRyYWNrOmZ1bmN0aW9uKGEpe2lmKCEoYT49dGhpcy50cmFja3MubGVuZ3RoKSl7dmFyIGI9dGhpcy50cmFja3NbYV07YiYmKGIub25FbmQmJmIub25FbmQoYSksdGhpcy5vbkVuZCYmdGhpcy5vbkVuZChhKSx0aGlzLnRyYWNrc1thXT1udWxsKX19LF9leHBhbmRUb0luZGV4OmZ1bmN0aW9uKGEpe2lmKGE8dGhpcy50cmFja3MubGVuZ3RoKXJldHVybiB0aGlzLnRyYWNrc1thXTtmb3IoO2E+PXRoaXMudHJhY2tzLmxlbmd0aDspdGhpcy50cmFja3MucHVzaChudWxsKTtyZXR1cm4gbnVsbH0sc2V0Q3VycmVudDpmdW5jdGlvbihhLGIpe3ZhciBjPXRoaXMuX2V4cGFuZFRvSW5kZXgoYSk7aWYoYyl7dmFyIGQ9Yy5wcmV2aW91cztjLnByZXZpb3VzPW51bGwsYy5vbkVuZCYmYy5vbkVuZChhKSx0aGlzLm9uRW5kJiZ0aGlzLm9uRW5kKGEpLGIubWl4RHVyYXRpb249dGhpcy5kYXRhLmdldE1peChjLmFuaW1hdGlvbixiLmFuaW1hdGlvbiksYi5taXhEdXJhdGlvbj4wJiYoYi5taXhUaW1lPTAsYi5wcmV2aW91cz1kJiZjLm1peFRpbWUvYy5taXhEdXJhdGlvbjwuNT9kOmMpfXRoaXMudHJhY2tzW2FdPWIsYi5vblN0YXJ0JiZiLm9uU3RhcnQoYSksdGhpcy5vblN0YXJ0JiZ0aGlzLm9uU3RhcnQoYSl9LHNldEFuaW1hdGlvbkJ5TmFtZTpmdW5jdGlvbihhLGIsYyl7dmFyIGQ9dGhpcy5kYXRhLnNrZWxldG9uRGF0YS5maW5kQW5pbWF0aW9uKGIpO2lmKCFkKXRocm93XCJBbmltYXRpb24gbm90IGZvdW5kOiBcIitiO3JldHVybiB0aGlzLnNldEFuaW1hdGlvbihhLGQsYyl9LHNldEFuaW1hdGlvbjpmdW5jdGlvbihhLGIsZCl7dmFyIGU9bmV3IGMuVHJhY2tFbnRyeTtyZXR1cm4gZS5hbmltYXRpb249YixlLmxvb3A9ZCxlLmVuZFRpbWU9Yi5kdXJhdGlvbix0aGlzLnNldEN1cnJlbnQoYSxlKSxlfSxhZGRBbmltYXRpb25CeU5hbWU6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIGU9dGhpcy5kYXRhLnNrZWxldG9uRGF0YS5maW5kQW5pbWF0aW9uKGIpO2lmKCFlKXRocm93XCJBbmltYXRpb24gbm90IGZvdW5kOiBcIitiO3JldHVybiB0aGlzLmFkZEFuaW1hdGlvbihhLGUsYyxkKX0sYWRkQW5pbWF0aW9uOmZ1bmN0aW9uKGEsYixkLGUpe3ZhciBmPW5ldyBjLlRyYWNrRW50cnk7Zi5hbmltYXRpb249YixmLmxvb3A9ZCxmLmVuZFRpbWU9Yi5kdXJhdGlvbjt2YXIgZz10aGlzLl9leHBhbmRUb0luZGV4KGEpO2lmKGcpe2Zvcig7Zy5uZXh0OylnPWcubmV4dDtnLm5leHQ9Zn1lbHNlIHRoaXMudHJhY2tzW2FdPWY7cmV0dXJuIDA+PWUmJihnP2UrPWcuZW5kVGltZS10aGlzLmRhdGEuZ2V0TWl4KGcuYW5pbWF0aW9uLGIpOmU9MCksZi5kZWxheT1lLGZ9LGdldEN1cnJlbnQ6ZnVuY3Rpb24oYSl7cmV0dXJuIGE+PXRoaXMudHJhY2tzLmxlbmd0aD9udWxsOnRoaXMudHJhY2tzW2FdfX0sYy5Ta2VsZXRvbkpzb249ZnVuY3Rpb24oYSl7dGhpcy5hdHRhY2htZW50TG9hZGVyPWF9LGMuU2tlbGV0b25Kc29uLnByb3RvdHlwZT17c2NhbGU6MSxyZWFkU2tlbGV0b25EYXRhOmZ1bmN0aW9uKGEsYil7dmFyIGQ9bmV3IGMuU2tlbGV0b25EYXRhO2QubmFtZT1iO3ZhciBlPWEuc2tlbGV0b247ZSYmKGQuaGFzaD1lLmhhc2gsZC52ZXJzaW9uPWUuc3BpbmUsZC53aWR0aD1lLndpZHRofHwwLGQuaGVpZ2h0PWUuaGVpZ2h0fHwwKTtmb3IodmFyIGY9YS5ib25lcyxnPTAsaD1mLmxlbmd0aDtoPmc7ZysrKXt2YXIgaT1mW2ddLGo9bnVsbDtpZihpLnBhcmVudCYmKGo9ZC5maW5kQm9uZShpLnBhcmVudCksIWopKXRocm93XCJQYXJlbnQgYm9uZSBub3QgZm91bmQ6IFwiK2kucGFyZW50O3ZhciBrPW5ldyBjLkJvbmVEYXRhKGkubmFtZSxqKTtrLmxlbmd0aD0oaS5sZW5ndGh8fDApKnRoaXMuc2NhbGUsay54PShpLnh8fDApKnRoaXMuc2NhbGUsay55PShpLnl8fDApKnRoaXMuc2NhbGUsay5yb3RhdGlvbj1pLnJvdGF0aW9ufHwwLGsuc2NhbGVYPWkuaGFzT3duUHJvcGVydHkoXCJzY2FsZVhcIik/aS5zY2FsZVg6MSxrLnNjYWxlWT1pLmhhc093blByb3BlcnR5KFwic2NhbGVZXCIpP2kuc2NhbGVZOjEsay5pbmhlcml0U2NhbGU9aS5oYXNPd25Qcm9wZXJ0eShcImluaGVyaXRTY2FsZVwiKT9pLmluaGVyaXRTY2FsZTohMCxrLmluaGVyaXRSb3RhdGlvbj1pLmhhc093blByb3BlcnR5KFwiaW5oZXJpdFJvdGF0aW9uXCIpP2kuaW5oZXJpdFJvdGF0aW9uOiEwLGQuYm9uZXMucHVzaChrKX12YXIgbD1hLmlrO2lmKGwpZm9yKHZhciBnPTAsaD1sLmxlbmd0aDtoPmc7ZysrKXtmb3IodmFyIG09bFtnXSxuPW5ldyBjLklrQ29uc3RyYWludERhdGEobS5uYW1lKSxmPW0uYm9uZXMsbz0wLHA9Zi5sZW5ndGg7cD5vO28rKyl7dmFyIHE9ZC5maW5kQm9uZShmW29dKTtpZighcSl0aHJvd1wiSUsgYm9uZSBub3QgZm91bmQ6IFwiK2Zbb107bi5ib25lcy5wdXNoKHEpfWlmKG4udGFyZ2V0PWQuZmluZEJvbmUobS50YXJnZXQpLCFuLnRhcmdldCl0aHJvd1wiVGFyZ2V0IGJvbmUgbm90IGZvdW5kOiBcIittLnRhcmdldDtuLmJlbmREaXJlY3Rpb249IW0uaGFzT3duUHJvcGVydHkoXCJiZW5kUG9zaXRpdmVcIil8fG0uYmVuZFBvc2l0aXZlPzE6LTEsbi5taXg9bS5oYXNPd25Qcm9wZXJ0eShcIm1peFwiKT9tLm1peDoxLGQuaWtDb25zdHJhaW50cy5wdXNoKG4pfWZvcih2YXIgcj1hLnNsb3RzLGc9MCxoPXIubGVuZ3RoO2g+ZztnKyspe3ZhciBzPXJbZ10saz1kLmZpbmRCb25lKHMuYm9uZSk7aWYoIWspdGhyb3dcIlNsb3QgYm9uZSBub3QgZm91bmQ6IFwiK3MuYm9uZTt2YXIgdD1uZXcgYy5TbG90RGF0YShzLm5hbWUsayksdT1zLmNvbG9yO3UmJih0LnI9dGhpcy50b0NvbG9yKHUsMCksdC5nPXRoaXMudG9Db2xvcih1LDEpLHQuYj10aGlzLnRvQ29sb3IodSwyKSx0LmE9dGhpcy50b0NvbG9yKHUsMykpLHQuYXR0YWNobWVudE5hbWU9cy5hdHRhY2htZW50LHQuYWRkaXRpdmVCbGVuZGluZz1zLmFkZGl0aXZlJiZcInRydWVcIj09cy5hZGRpdGl2ZSxkLnNsb3RzLnB1c2godCl9dmFyIHY9YS5za2lucztmb3IodmFyIHcgaW4gdilpZih2Lmhhc093blByb3BlcnR5KHcpKXt2YXIgeD12W3ddLHk9bmV3IGMuU2tpbih3KTtmb3IodmFyIHogaW4geClpZih4Lmhhc093blByb3BlcnR5KHopKXt2YXIgQT1kLmZpbmRTbG90SW5kZXgoeiksQj14W3pdO2Zvcih2YXIgQyBpbiBCKWlmKEIuaGFzT3duUHJvcGVydHkoQykpe3ZhciBEPXRoaXMucmVhZEF0dGFjaG1lbnQoeSxDLEJbQ10pO0QmJnkuYWRkQXR0YWNobWVudChBLEMsRCl9fWQuc2tpbnMucHVzaCh5KSxcImRlZmF1bHRcIj09eS5uYW1lJiYoZC5kZWZhdWx0U2tpbj15KX12YXIgRT1hLmV2ZW50cztmb3IodmFyIEYgaW4gRSlpZihFLmhhc093blByb3BlcnR5KEYpKXt2YXIgRz1FW0ZdLEg9bmV3IGMuRXZlbnREYXRhKEYpO0guaW50VmFsdWU9R1tcImludFwiXXx8MCxILmZsb2F0VmFsdWU9R1tcImZsb2F0XCJdfHwwLEguc3RyaW5nVmFsdWU9Ry5zdHJpbmd8fG51bGwsZC5ldmVudHMucHVzaChIKX12YXIgST1hLmFuaW1hdGlvbnM7Zm9yKHZhciBKIGluIEkpSS5oYXNPd25Qcm9wZXJ0eShKKSYmdGhpcy5yZWFkQW5pbWF0aW9uKEosSVtKXSxkKTtyZXR1cm4gZH0scmVhZEF0dGFjaG1lbnQ6ZnVuY3Rpb24oYSxiLGQpe2I9ZC5uYW1lfHxiO3ZhciBlPWMuQXR0YWNobWVudFR5cGVbZC50eXBlfHxcInJlZ2lvblwiXSxmPWQucGF0aHx8YixnPXRoaXMuc2NhbGU7aWYoZT09Yy5BdHRhY2htZW50VHlwZS5yZWdpb24pe3ZhciBoPXRoaXMuYXR0YWNobWVudExvYWRlci5uZXdSZWdpb25BdHRhY2htZW50KGEsYixmKTtpZighaClyZXR1cm4gbnVsbDtoLnBhdGg9ZixoLng9KGQueHx8MCkqZyxoLnk9KGQueXx8MCkqZyxoLnNjYWxlWD1kLmhhc093blByb3BlcnR5KFwic2NhbGVYXCIpP2Quc2NhbGVYOjEsaC5zY2FsZVk9ZC5oYXNPd25Qcm9wZXJ0eShcInNjYWxlWVwiKT9kLnNjYWxlWToxLGgucm90YXRpb249ZC5yb3RhdGlvbnx8MCxoLndpZHRoPShkLndpZHRofHwwKSpnLGguaGVpZ2h0PShkLmhlaWdodHx8MCkqZzt2YXIgaT1kLmNvbG9yO3JldHVybiBpJiYoaC5yPXRoaXMudG9Db2xvcihpLDApLGguZz10aGlzLnRvQ29sb3IoaSwxKSxoLmI9dGhpcy50b0NvbG9yKGksMiksaC5hPXRoaXMudG9Db2xvcihpLDMpKSxoLnVwZGF0ZU9mZnNldCgpLGh9aWYoZT09Yy5BdHRhY2htZW50VHlwZS5tZXNoKXt2YXIgaj10aGlzLmF0dGFjaG1lbnRMb2FkZXIubmV3TWVzaEF0dGFjaG1lbnQoYSxiLGYpO3JldHVybiBqPyhqLnBhdGg9ZixqLnZlcnRpY2VzPXRoaXMuZ2V0RmxvYXRBcnJheShkLFwidmVydGljZXNcIixnKSxqLnRyaWFuZ2xlcz10aGlzLmdldEludEFycmF5KGQsXCJ0cmlhbmdsZXNcIiksai5yZWdpb25VVnM9dGhpcy5nZXRGbG9hdEFycmF5KGQsXCJ1dnNcIiwxKSxqLnVwZGF0ZVVWcygpLGk9ZC5jb2xvcixpJiYoai5yPXRoaXMudG9Db2xvcihpLDApLGouZz10aGlzLnRvQ29sb3IoaSwxKSxqLmI9dGhpcy50b0NvbG9yKGksMiksai5hPXRoaXMudG9Db2xvcihpLDMpKSxqLmh1bGxMZW5ndGg9MiooZC5odWxsfHwwKSxkLmVkZ2VzJiYoai5lZGdlcz10aGlzLmdldEludEFycmF5KGQsXCJlZGdlc1wiKSksai53aWR0aD0oZC53aWR0aHx8MCkqZyxqLmhlaWdodD0oZC5oZWlnaHR8fDApKmcsaik6bnVsbH1pZihlPT1jLkF0dGFjaG1lbnRUeXBlLnNraW5uZWRtZXNoKXt2YXIgaj10aGlzLmF0dGFjaG1lbnRMb2FkZXIubmV3U2tpbm5lZE1lc2hBdHRhY2htZW50KGEsYixmKTtpZighailyZXR1cm4gbnVsbDtqLnBhdGg9Zjtmb3IodmFyIGs9dGhpcy5nZXRGbG9hdEFycmF5KGQsXCJ1dnNcIiwxKSxsPXRoaXMuZ2V0RmxvYXRBcnJheShkLFwidmVydGljZXNcIiwxKSxtPVtdLG49W10sbz0wLHA9bC5sZW5ndGg7cD5vOyl7dmFyIHE9MHxsW28rK107bltuLmxlbmd0aF09cTtmb3IodmFyIHI9bys0KnE7cj5vOyluW24ubGVuZ3RoXT1sW29dLG1bbS5sZW5ndGhdPWxbbysxXSpnLG1bbS5sZW5ndGhdPWxbbysyXSpnLG1bbS5sZW5ndGhdPWxbbyszXSxvKz00fXJldHVybiBqLmJvbmVzPW4sai53ZWlnaHRzPW0sai50cmlhbmdsZXM9dGhpcy5nZXRJbnRBcnJheShkLFwidHJpYW5nbGVzXCIpLGoucmVnaW9uVVZzPWssai51cGRhdGVVVnMoKSxpPWQuY29sb3IsaSYmKGoucj10aGlzLnRvQ29sb3IoaSwwKSxqLmc9dGhpcy50b0NvbG9yKGksMSksai5iPXRoaXMudG9Db2xvcihpLDIpLGouYT10aGlzLnRvQ29sb3IoaSwzKSksai5odWxsTGVuZ3RoPTIqKGQuaHVsbHx8MCksZC5lZGdlcyYmKGouZWRnZXM9dGhpcy5nZXRJbnRBcnJheShkLFwiZWRnZXNcIikpLGoud2lkdGg9KGQud2lkdGh8fDApKmcsai5oZWlnaHQ9KGQuaGVpZ2h0fHwwKSpnLGpcbn1pZihlPT1jLkF0dGFjaG1lbnRUeXBlLmJvdW5kaW5nYm94KXtmb3IodmFyIHM9dGhpcy5hdHRhY2htZW50TG9hZGVyLm5ld0JvdW5kaW5nQm94QXR0YWNobWVudChhLGIpLGw9ZC52ZXJ0aWNlcyxvPTAscD1sLmxlbmd0aDtwPm87bysrKXMudmVydGljZXMucHVzaChsW29dKmcpO3JldHVybiBzfXRocm93XCJVbmtub3duIGF0dGFjaG1lbnQgdHlwZTogXCIrZX0scmVhZEFuaW1hdGlvbjpmdW5jdGlvbihhLGIsZCl7dmFyIGU9W10sZj0wLGc9Yi5zbG90cztmb3IodmFyIGggaW4gZylpZihnLmhhc093blByb3BlcnR5KGgpKXt2YXIgaT1nW2hdLGo9ZC5maW5kU2xvdEluZGV4KGgpO2Zvcih2YXIgayBpbiBpKWlmKGkuaGFzT3duUHJvcGVydHkoaykpe3ZhciBsPWlba107aWYoXCJjb2xvclwiPT1rKXt2YXIgbT1uZXcgYy5Db2xvclRpbWVsaW5lKGwubGVuZ3RoKTttLnNsb3RJbmRleD1qO2Zvcih2YXIgbj0wLG89MCxwPWwubGVuZ3RoO3A+bztvKyspe3ZhciBxPWxbb10scj1xLmNvbG9yLHM9dGhpcy50b0NvbG9yKHIsMCksdD10aGlzLnRvQ29sb3IociwxKSx1PXRoaXMudG9Db2xvcihyLDIpLHY9dGhpcy50b0NvbG9yKHIsMyk7bS5zZXRGcmFtZShuLHEudGltZSxzLHQsdSx2KSx0aGlzLnJlYWRDdXJ2ZShtLG4scSksbisrfWUucHVzaChtKSxmPU1hdGgubWF4KGYsbS5mcmFtZXNbNSptLmdldEZyYW1lQ291bnQoKS01XSl9ZWxzZXtpZihcImF0dGFjaG1lbnRcIiE9ayl0aHJvd1wiSW52YWxpZCB0aW1lbGluZSB0eXBlIGZvciBhIHNsb3Q6IFwiK2srXCIgKFwiK2grXCIpXCI7dmFyIG09bmV3IGMuQXR0YWNobWVudFRpbWVsaW5lKGwubGVuZ3RoKTttLnNsb3RJbmRleD1qO2Zvcih2YXIgbj0wLG89MCxwPWwubGVuZ3RoO3A+bztvKyspe3ZhciBxPWxbb107bS5zZXRGcmFtZShuKysscS50aW1lLHEubmFtZSl9ZS5wdXNoKG0pLGY9TWF0aC5tYXgoZixtLmZyYW1lc1ttLmdldEZyYW1lQ291bnQoKS0xXSl9fX12YXIgdz1iLmJvbmVzO2Zvcih2YXIgeCBpbiB3KWlmKHcuaGFzT3duUHJvcGVydHkoeCkpe3ZhciB5PWQuZmluZEJvbmVJbmRleCh4KTtpZigtMT09eSl0aHJvd1wiQm9uZSBub3QgZm91bmQ6IFwiK3g7dmFyIHo9d1t4XTtmb3IodmFyIGsgaW4geilpZih6Lmhhc093blByb3BlcnR5KGspKXt2YXIgbD16W2tdO2lmKFwicm90YXRlXCI9PWspe3ZhciBtPW5ldyBjLlJvdGF0ZVRpbWVsaW5lKGwubGVuZ3RoKTttLmJvbmVJbmRleD15O2Zvcih2YXIgbj0wLG89MCxwPWwubGVuZ3RoO3A+bztvKyspe3ZhciBxPWxbb107bS5zZXRGcmFtZShuLHEudGltZSxxLmFuZ2xlKSx0aGlzLnJlYWRDdXJ2ZShtLG4scSksbisrfWUucHVzaChtKSxmPU1hdGgubWF4KGYsbS5mcmFtZXNbMiptLmdldEZyYW1lQ291bnQoKS0yXSl9ZWxzZSBpZihcInRyYW5zbGF0ZVwiPT1rfHxcInNjYWxlXCI9PWspe3ZhciBtLEE9MTtcInNjYWxlXCI9PWs/bT1uZXcgYy5TY2FsZVRpbWVsaW5lKGwubGVuZ3RoKToobT1uZXcgYy5UcmFuc2xhdGVUaW1lbGluZShsLmxlbmd0aCksQT10aGlzLnNjYWxlKSxtLmJvbmVJbmRleD15O2Zvcih2YXIgbj0wLG89MCxwPWwubGVuZ3RoO3A+bztvKyspe3ZhciBxPWxbb10sQj0ocS54fHwwKSpBLEM9KHEueXx8MCkqQTttLnNldEZyYW1lKG4scS50aW1lLEIsQyksdGhpcy5yZWFkQ3VydmUobSxuLHEpLG4rK31lLnB1c2gobSksZj1NYXRoLm1heChmLG0uZnJhbWVzWzMqbS5nZXRGcmFtZUNvdW50KCktM10pfWVsc2V7aWYoXCJmbGlwWFwiIT1rJiZcImZsaXBZXCIhPWspdGhyb3dcIkludmFsaWQgdGltZWxpbmUgdHlwZSBmb3IgYSBib25lOiBcIitrK1wiIChcIit4K1wiKVwiO3ZhciBCPVwiZmxpcFhcIj09ayxtPUI/bmV3IGMuRmxpcFhUaW1lbGluZShsLmxlbmd0aCk6bmV3IGMuRmxpcFlUaW1lbGluZShsLmxlbmd0aCk7bS5ib25lSW5kZXg9eTtmb3IodmFyIEQ9Qj9cInhcIjpcInlcIixuPTAsbz0wLHA9bC5sZW5ndGg7cD5vO28rKyl7dmFyIHE9bFtvXTttLnNldEZyYW1lKG4scS50aW1lLHFbRF18fCExKSxuKyt9ZS5wdXNoKG0pLGY9TWF0aC5tYXgoZixtLmZyYW1lc1syKm0uZ2V0RnJhbWVDb3VudCgpLTJdKX19fXZhciBFPWIuaWs7Zm9yKHZhciBGIGluIEUpaWYoRS5oYXNPd25Qcm9wZXJ0eShGKSl7dmFyIEc9ZC5maW5kSWtDb25zdHJhaW50KEYpLGw9RVtGXSxtPW5ldyBjLklrQ29uc3RyYWludFRpbWVsaW5lKGwubGVuZ3RoKTttLmlrQ29uc3RyYWludEluZGV4PWQuaWtDb25zdHJhaW50cy5pbmRleE9mKEcpO2Zvcih2YXIgbj0wLG89MCxwPWwubGVuZ3RoO3A+bztvKyspe3ZhciBxPWxbb10sSD1xLmhhc093blByb3BlcnR5KFwibWl4XCIpP3EubWl4OjEsST0hcS5oYXNPd25Qcm9wZXJ0eShcImJlbmRQb3NpdGl2ZVwiKXx8cS5iZW5kUG9zaXRpdmU/MTotMTttLnNldEZyYW1lKG4scS50aW1lLEgsSSksdGhpcy5yZWFkQ3VydmUobSxuLHEpLG4rK31lLnB1c2gobSksZj1NYXRoLm1heChmLG0uZnJhbWVzWzMqbS5mcmFtZUNvdW50LTNdKX12YXIgSj1iLmZmZDtmb3IodmFyIEsgaW4gSil7dmFyIEw9ZC5maW5kU2tpbihLKSxpPUpbS107Zm9yKGggaW4gaSl7dmFyIGo9ZC5maW5kU2xvdEluZGV4KGgpLE09aVtoXTtmb3IodmFyIE4gaW4gTSl7dmFyIGw9TVtOXSxtPW5ldyBjLkZmZFRpbWVsaW5lKGwubGVuZ3RoKSxPPUwuZ2V0QXR0YWNobWVudChqLE4pO2lmKCFPKXRocm93XCJGRkQgYXR0YWNobWVudCBub3QgZm91bmQ6IFwiK047bS5zbG90SW5kZXg9aixtLmF0dGFjaG1lbnQ9Tzt2YXIgUCxRPU8udHlwZT09Yy5BdHRhY2htZW50VHlwZS5tZXNoO1A9UT9PLnZlcnRpY2VzLmxlbmd0aDpPLndlaWdodHMubGVuZ3RoLzMqMjtmb3IodmFyIG49MCxvPTAscD1sLmxlbmd0aDtwPm87bysrKXt2YXIgUixxPWxbb107aWYocS52ZXJ0aWNlcyl7dmFyIFM9cS52ZXJ0aWNlcyxSPVtdO1IubGVuZ3RoPVA7dmFyIFQ9cS5vZmZzZXR8fDAsVT1TLmxlbmd0aDtpZigxPT10aGlzLnNjYWxlKWZvcih2YXIgVj0wO1U+VjtWKyspUltWK1RdPVNbVl07ZWxzZSBmb3IodmFyIFY9MDtVPlY7VisrKVJbVitUXT1TW1ZdKnRoaXMuc2NhbGU7aWYoUSlmb3IodmFyIFc9Ty52ZXJ0aWNlcyxWPTAsVT1SLmxlbmd0aDtVPlY7VisrKVJbVl0rPVdbVl19ZWxzZSBRP1I9Ty52ZXJ0aWNlczooUj1bXSxSLmxlbmd0aD1QKTttLnNldEZyYW1lKG4scS50aW1lLFIpLHRoaXMucmVhZEN1cnZlKG0sbixxKSxuKyt9ZVtlLmxlbmd0aF09bSxmPU1hdGgubWF4KGYsbS5mcmFtZXNbbS5mcmFtZUNvdW50LTFdKX19fXZhciBYPWIuZHJhd09yZGVyO2lmKFh8fChYPWIuZHJhd29yZGVyKSxYKXtmb3IodmFyIG09bmV3IGMuRHJhd09yZGVyVGltZWxpbmUoWC5sZW5ndGgpLFk9ZC5zbG90cy5sZW5ndGgsbj0wLG89MCxwPVgubGVuZ3RoO3A+bztvKyspe3ZhciBaPVhbb10sJD1udWxsO2lmKFoub2Zmc2V0cyl7JD1bXSwkLmxlbmd0aD1ZO2Zvcih2YXIgVj1ZLTE7Vj49MDtWLS0pJFtWXT0tMTt2YXIgXz1aLm9mZnNldHMsYWI9W107YWIubGVuZ3RoPVktXy5sZW5ndGg7Zm9yKHZhciBiYj0wLGNiPTAsVj0wLFU9Xy5sZW5ndGg7VT5WO1YrKyl7dmFyIGRiPV9bVl0saj1kLmZpbmRTbG90SW5kZXgoZGIuc2xvdCk7aWYoLTE9PWopdGhyb3dcIlNsb3Qgbm90IGZvdW5kOiBcIitkYi5zbG90O2Zvcig7YmIhPWo7KWFiW2NiKytdPWJiKys7JFtiYitkYi5vZmZzZXRdPWJiKyt9Zm9yKDtZPmJiOylhYltjYisrXT1iYisrO2Zvcih2YXIgVj1ZLTE7Vj49MDtWLS0pLTE9PSRbVl0mJigkW1ZdPWFiWy0tY2JdKX1tLnNldEZyYW1lKG4rKyxaLnRpbWUsJCl9ZS5wdXNoKG0pLGY9TWF0aC5tYXgoZixtLmZyYW1lc1ttLmdldEZyYW1lQ291bnQoKS0xXSl9dmFyIGViPWIuZXZlbnRzO2lmKGViKXtmb3IodmFyIG09bmV3IGMuRXZlbnRUaW1lbGluZShlYi5sZW5ndGgpLG49MCxvPTAscD1lYi5sZW5ndGg7cD5vO28rKyl7dmFyIGZiPWViW29dLGdiPWQuZmluZEV2ZW50KGZiLm5hbWUpO2lmKCFnYil0aHJvd1wiRXZlbnQgbm90IGZvdW5kOiBcIitmYi5uYW1lO3ZhciBoYj1uZXcgYy5FdmVudChnYik7aGIuaW50VmFsdWU9ZmIuaGFzT3duUHJvcGVydHkoXCJpbnRcIik/ZmJbXCJpbnRcIl06Z2IuaW50VmFsdWUsaGIuZmxvYXRWYWx1ZT1mYi5oYXNPd25Qcm9wZXJ0eShcImZsb2F0XCIpP2ZiW1wiZmxvYXRcIl06Z2IuZmxvYXRWYWx1ZSxoYi5zdHJpbmdWYWx1ZT1mYi5oYXNPd25Qcm9wZXJ0eShcInN0cmluZ1wiKT9mYi5zdHJpbmc6Z2Iuc3RyaW5nVmFsdWUsbS5zZXRGcmFtZShuKyssZmIudGltZSxoYil9ZS5wdXNoKG0pLGY9TWF0aC5tYXgoZixtLmZyYW1lc1ttLmdldEZyYW1lQ291bnQoKS0xXSl9ZC5hbmltYXRpb25zLnB1c2gobmV3IGMuQW5pbWF0aW9uKGEsZSxmKSl9LHJlYWRDdXJ2ZTpmdW5jdGlvbihhLGIsYyl7dmFyIGQ9Yy5jdXJ2ZTtkP1wic3RlcHBlZFwiPT1kP2EuY3VydmVzLnNldFN0ZXBwZWQoYik6ZCBpbnN0YW5jZW9mIEFycmF5JiZhLmN1cnZlcy5zZXRDdXJ2ZShiLGRbMF0sZFsxXSxkWzJdLGRbM10pOmEuY3VydmVzLnNldExpbmVhcihiKX0sdG9Db2xvcjpmdW5jdGlvbihhLGIpe2lmKDghPWEubGVuZ3RoKXRocm93XCJDb2xvciBoZXhpZGVjaW1hbCBsZW5ndGggbXVzdCBiZSA4LCByZWNpZXZlZDogXCIrYTtyZXR1cm4gcGFyc2VJbnQoYS5zdWJzdHJpbmcoMipiLDIqYisyKSwxNikvMjU1fSxnZXRGbG9hdEFycmF5OmZ1bmN0aW9uKGEsYixkKXt2YXIgZT1hW2JdLGY9bmV3IGMuRmxvYXQzMkFycmF5KGUubGVuZ3RoKSxnPTAsaD1lLmxlbmd0aDtpZigxPT1kKWZvcig7aD5nO2crKylmW2ddPWVbZ107ZWxzZSBmb3IoO2g+ZztnKyspZltnXT1lW2ddKmQ7cmV0dXJuIGZ9LGdldEludEFycmF5OmZ1bmN0aW9uKGEsYil7Zm9yKHZhciBkPWFbYl0sZT1uZXcgYy5VaW50MTZBcnJheShkLmxlbmd0aCksZj0wLGc9ZC5sZW5ndGg7Zz5mO2YrKyllW2ZdPTB8ZFtmXTtyZXR1cm4gZX19LGMuQXRsYXM9ZnVuY3Rpb24oYSxiKXt0aGlzLnRleHR1cmVMb2FkZXI9Yix0aGlzLnBhZ2VzPVtdLHRoaXMucmVnaW9ucz1bXTt2YXIgZD1uZXcgYy5BdGxhc1JlYWRlcihhKSxlPVtdO2UubGVuZ3RoPTQ7Zm9yKHZhciBmPW51bGw7Oyl7dmFyIGc9ZC5yZWFkTGluZSgpO2lmKG51bGw9PT1nKWJyZWFrO2lmKGc9ZC50cmltKGcpLGcubGVuZ3RoKWlmKGYpe3ZhciBoPW5ldyBjLkF0bGFzUmVnaW9uO2gubmFtZT1nLGgucGFnZT1mLGgucm90YXRlPVwidHJ1ZVwiPT1kLnJlYWRWYWx1ZSgpLGQucmVhZFR1cGxlKGUpO3ZhciBpPXBhcnNlSW50KGVbMF0pLGo9cGFyc2VJbnQoZVsxXSk7ZC5yZWFkVHVwbGUoZSk7dmFyIGs9cGFyc2VJbnQoZVswXSksbD1wYXJzZUludChlWzFdKTtoLnU9aS9mLndpZHRoLGgudj1qL2YuaGVpZ2h0LGgucm90YXRlPyhoLnUyPShpK2wpL2Yud2lkdGgsaC52Mj0oaitrKS9mLmhlaWdodCk6KGgudTI9KGkraykvZi53aWR0aCxoLnYyPShqK2wpL2YuaGVpZ2h0KSxoLng9aSxoLnk9aixoLndpZHRoPU1hdGguYWJzKGspLGguaGVpZ2h0PU1hdGguYWJzKGwpLDQ9PWQucmVhZFR1cGxlKGUpJiYoaC5zcGxpdHM9W3BhcnNlSW50KGVbMF0pLHBhcnNlSW50KGVbMV0pLHBhcnNlSW50KGVbMl0pLHBhcnNlSW50KGVbM10pXSw0PT1kLnJlYWRUdXBsZShlKSYmKGgucGFkcz1bcGFyc2VJbnQoZVswXSkscGFyc2VJbnQoZVsxXSkscGFyc2VJbnQoZVsyXSkscGFyc2VJbnQoZVszXSldLGQucmVhZFR1cGxlKGUpKSksaC5vcmlnaW5hbFdpZHRoPXBhcnNlSW50KGVbMF0pLGgub3JpZ2luYWxIZWlnaHQ9cGFyc2VJbnQoZVsxXSksZC5yZWFkVHVwbGUoZSksaC5vZmZzZXRYPXBhcnNlSW50KGVbMF0pLGgub2Zmc2V0WT1wYXJzZUludChlWzFdKSxoLmluZGV4PXBhcnNlSW50KGQucmVhZFZhbHVlKCkpLHRoaXMucmVnaW9ucy5wdXNoKGgpfWVsc2V7Zj1uZXcgYy5BdGxhc1BhZ2UsZi5uYW1lPWcsMj09ZC5yZWFkVHVwbGUoZSkmJihmLndpZHRoPXBhcnNlSW50KGVbMF0pLGYuaGVpZ2h0PXBhcnNlSW50KGVbMV0pLGQucmVhZFR1cGxlKGUpKSxmLmZvcm1hdD1jLkF0bGFzLkZvcm1hdFtlWzBdXSxkLnJlYWRUdXBsZShlKSxmLm1pbkZpbHRlcj1jLkF0bGFzLlRleHR1cmVGaWx0ZXJbZVswXV0sZi5tYWdGaWx0ZXI9Yy5BdGxhcy5UZXh0dXJlRmlsdGVyW2VbMV1dO3ZhciBtPWQucmVhZFZhbHVlKCk7Zi51V3JhcD1jLkF0bGFzLlRleHR1cmVXcmFwLmNsYW1wVG9FZGdlLGYudldyYXA9Yy5BdGxhcy5UZXh0dXJlV3JhcC5jbGFtcFRvRWRnZSxcInhcIj09bT9mLnVXcmFwPWMuQXRsYXMuVGV4dHVyZVdyYXAucmVwZWF0OlwieVwiPT1tP2YudldyYXA9Yy5BdGxhcy5UZXh0dXJlV3JhcC5yZXBlYXQ6XCJ4eVwiPT1tJiYoZi51V3JhcD1mLnZXcmFwPWMuQXRsYXMuVGV4dHVyZVdyYXAucmVwZWF0KSxiLmxvYWQoZixnLHRoaXMpLHRoaXMucGFnZXMucHVzaChmKX1lbHNlIGY9bnVsbH19LGMuQXRsYXMucHJvdG90eXBlPXtmaW5kUmVnaW9uOmZ1bmN0aW9uKGEpe2Zvcih2YXIgYj10aGlzLnJlZ2lvbnMsYz0wLGQ9Yi5sZW5ndGg7ZD5jO2MrKylpZihiW2NdLm5hbWU9PWEpcmV0dXJuIGJbY107cmV0dXJuIG51bGx9LGRpc3Bvc2U6ZnVuY3Rpb24oKXtmb3IodmFyIGE9dGhpcy5wYWdlcyxiPTAsYz1hLmxlbmd0aDtjPmI7YisrKXRoaXMudGV4dHVyZUxvYWRlci51bmxvYWQoYVtiXS5yZW5kZXJlck9iamVjdCl9LHVwZGF0ZVVWczpmdW5jdGlvbihhKXtmb3IodmFyIGI9dGhpcy5yZWdpb25zLGM9MCxkPWIubGVuZ3RoO2Q+YztjKyspe3ZhciBlPWJbY107ZS5wYWdlPT1hJiYoZS51PWUueC9hLndpZHRoLGUudj1lLnkvYS5oZWlnaHQsZS5yb3RhdGU/KGUudTI9KGUueCtlLmhlaWdodCkvYS53aWR0aCxlLnYyPShlLnkrZS53aWR0aCkvYS5oZWlnaHQpOihlLnUyPShlLngrZS53aWR0aCkvYS53aWR0aCxlLnYyPShlLnkrZS5oZWlnaHQpL2EuaGVpZ2h0KSl9fX0sYy5BdGxhcy5Gb3JtYXQ9e2FscGhhOjAsaW50ZW5zaXR5OjEsbHVtaW5hbmNlQWxwaGE6MixyZ2I1NjU6MyxyZ2JhNDQ0NDo0LHJnYjg4ODo1LHJnYmE4ODg4OjZ9LGMuQXRsYXMuVGV4dHVyZUZpbHRlcj17bmVhcmVzdDowLGxpbmVhcjoxLG1pcE1hcDoyLG1pcE1hcE5lYXJlc3ROZWFyZXN0OjMsbWlwTWFwTGluZWFyTmVhcmVzdDo0LG1pcE1hcE5lYXJlc3RMaW5lYXI6NSxtaXBNYXBMaW5lYXJMaW5lYXI6Nn0sYy5BdGxhcy5UZXh0dXJlV3JhcD17bWlycm9yZWRSZXBlYXQ6MCxjbGFtcFRvRWRnZToxLHJlcGVhdDoyfSxjLkF0bGFzUGFnZT1mdW5jdGlvbigpe30sYy5BdGxhc1BhZ2UucHJvdG90eXBlPXtuYW1lOm51bGwsZm9ybWF0Om51bGwsbWluRmlsdGVyOm51bGwsbWFnRmlsdGVyOm51bGwsdVdyYXA6bnVsbCx2V3JhcDpudWxsLHJlbmRlcmVyT2JqZWN0Om51bGwsd2lkdGg6MCxoZWlnaHQ6MH0sYy5BdGxhc1JlZ2lvbj1mdW5jdGlvbigpe30sYy5BdGxhc1JlZ2lvbi5wcm90b3R5cGU9e3BhZ2U6bnVsbCxuYW1lOm51bGwseDowLHk6MCx3aWR0aDowLGhlaWdodDowLHU6MCx2OjAsdTI6MCx2MjowLG9mZnNldFg6MCxvZmZzZXRZOjAsb3JpZ2luYWxXaWR0aDowLG9yaWdpbmFsSGVpZ2h0OjAsaW5kZXg6MCxyb3RhdGU6ITEsc3BsaXRzOm51bGwscGFkczpudWxsfSxjLkF0bGFzUmVhZGVyPWZ1bmN0aW9uKGEpe3RoaXMubGluZXM9YS5zcGxpdCgvXFxyXFxufFxccnxcXG4vKX0sYy5BdGxhc1JlYWRlci5wcm90b3R5cGU9e2luZGV4OjAsdHJpbTpmdW5jdGlvbihhKXtyZXR1cm4gYS5yZXBsYWNlKC9eXFxzK3xcXHMrJC9nLFwiXCIpfSxyZWFkTGluZTpmdW5jdGlvbigpe3JldHVybiB0aGlzLmluZGV4Pj10aGlzLmxpbmVzLmxlbmd0aD9udWxsOnRoaXMubGluZXNbdGhpcy5pbmRleCsrXX0scmVhZFZhbHVlOmZ1bmN0aW9uKCl7dmFyIGE9dGhpcy5yZWFkTGluZSgpLGI9YS5pbmRleE9mKFwiOlwiKTtpZigtMT09Yil0aHJvd1wiSW52YWxpZCBsaW5lOiBcIithO3JldHVybiB0aGlzLnRyaW0oYS5zdWJzdHJpbmcoYisxKSl9LHJlYWRUdXBsZTpmdW5jdGlvbihhKXt2YXIgYj10aGlzLnJlYWRMaW5lKCksYz1iLmluZGV4T2YoXCI6XCIpO2lmKC0xPT1jKXRocm93XCJJbnZhbGlkIGxpbmU6IFwiK2I7Zm9yKHZhciBkPTAsZT1jKzE7Mz5kO2QrKyl7dmFyIGY9Yi5pbmRleE9mKFwiLFwiLGUpO2lmKC0xPT1mKWJyZWFrO2FbZF09dGhpcy50cmltKGIuc3Vic3RyKGUsZi1lKSksZT1mKzF9cmV0dXJuIGFbZF09dGhpcy50cmltKGIuc3Vic3RyaW5nKGUpKSxkKzF9fSxjLkF0bGFzQXR0YWNobWVudExvYWRlcj1mdW5jdGlvbihhKXt0aGlzLmF0bGFzPWF9LGMuQXRsYXNBdHRhY2htZW50TG9hZGVyLnByb3RvdHlwZT17bmV3UmVnaW9uQXR0YWNobWVudDpmdW5jdGlvbihhLGIsZCl7dmFyIGU9dGhpcy5hdGxhcy5maW5kUmVnaW9uKGQpO2lmKCFlKXRocm93XCJSZWdpb24gbm90IGZvdW5kIGluIGF0bGFzOiBcIitkK1wiIChyZWdpb24gYXR0YWNobWVudDogXCIrYitcIilcIjt2YXIgZj1uZXcgYy5SZWdpb25BdHRhY2htZW50KGIpO3JldHVybiBmLnJlbmRlcmVyT2JqZWN0PWUsZi5zZXRVVnMoZS51LGUudixlLnUyLGUudjIsZS5yb3RhdGUpLGYucmVnaW9uT2Zmc2V0WD1lLm9mZnNldFgsZi5yZWdpb25PZmZzZXRZPWUub2Zmc2V0WSxmLnJlZ2lvbldpZHRoPWUud2lkdGgsZi5yZWdpb25IZWlnaHQ9ZS5oZWlnaHQsZi5yZWdpb25PcmlnaW5hbFdpZHRoPWUub3JpZ2luYWxXaWR0aCxmLnJlZ2lvbk9yaWdpbmFsSGVpZ2h0PWUub3JpZ2luYWxIZWlnaHQsZn0sbmV3TWVzaEF0dGFjaG1lbnQ6ZnVuY3Rpb24oYSxiLGQpe3ZhciBlPXRoaXMuYXRsYXMuZmluZFJlZ2lvbihkKTtpZighZSl0aHJvd1wiUmVnaW9uIG5vdCBmb3VuZCBpbiBhdGxhczogXCIrZCtcIiAobWVzaCBhdHRhY2htZW50OiBcIitiK1wiKVwiO3ZhciBmPW5ldyBjLk1lc2hBdHRhY2htZW50KGIpO3JldHVybiBmLnJlbmRlcmVyT2JqZWN0PWUsZi5yZWdpb25VPWUudSxmLnJlZ2lvblY9ZS52LGYucmVnaW9uVTI9ZS51MixmLnJlZ2lvblYyPWUudjIsZi5yZWdpb25Sb3RhdGU9ZS5yb3RhdGUsZi5yZWdpb25PZmZzZXRYPWUub2Zmc2V0WCxmLnJlZ2lvbk9mZnNldFk9ZS5vZmZzZXRZLGYucmVnaW9uV2lkdGg9ZS53aWR0aCxmLnJlZ2lvbkhlaWdodD1lLmhlaWdodCxmLnJlZ2lvbk9yaWdpbmFsV2lkdGg9ZS5vcmlnaW5hbFdpZHRoLGYucmVnaW9uT3JpZ2luYWxIZWlnaHQ9ZS5vcmlnaW5hbEhlaWdodCxmfSxuZXdTa2lubmVkTWVzaEF0dGFjaG1lbnQ6ZnVuY3Rpb24oYSxiLGQpe3ZhciBlPXRoaXMuYXRsYXMuZmluZFJlZ2lvbihkKTtpZighZSl0aHJvd1wiUmVnaW9uIG5vdCBmb3VuZCBpbiBhdGxhczogXCIrZCtcIiAoc2tpbm5lZCBtZXNoIGF0dGFjaG1lbnQ6IFwiK2IrXCIpXCI7dmFyIGY9bmV3IGMuU2tpbm5lZE1lc2hBdHRhY2htZW50KGIpO3JldHVybiBmLnJlbmRlcmVyT2JqZWN0PWUsZi5yZWdpb25VPWUudSxmLnJlZ2lvblY9ZS52LGYucmVnaW9uVTI9ZS51MixmLnJlZ2lvblYyPWUudjIsZi5yZWdpb25Sb3RhdGU9ZS5yb3RhdGUsZi5yZWdpb25PZmZzZXRYPWUub2Zmc2V0WCxmLnJlZ2lvbk9mZnNldFk9ZS5vZmZzZXRZLGYucmVnaW9uV2lkdGg9ZS53aWR0aCxmLnJlZ2lvbkhlaWdodD1lLmhlaWdodCxmLnJlZ2lvbk9yaWdpbmFsV2lkdGg9ZS5vcmlnaW5hbFdpZHRoLGYucmVnaW9uT3JpZ2luYWxIZWlnaHQ9ZS5vcmlnaW5hbEhlaWdodCxmfSxuZXdCb3VuZGluZ0JveEF0dGFjaG1lbnQ6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IGMuQm91bmRpbmdCb3hBdHRhY2htZW50KGIpfX0sYy5Ta2VsZXRvbkJvdW5kcz1mdW5jdGlvbigpe3RoaXMucG9seWdvblBvb2w9W10sdGhpcy5wb2x5Z29ucz1bXSx0aGlzLmJvdW5kaW5nQm94ZXM9W119LGMuU2tlbGV0b25Cb3VuZHMucHJvdG90eXBlPXttaW5YOjAsbWluWTowLG1heFg6MCxtYXhZOjAsdXBkYXRlOmZ1bmN0aW9uKGEsYil7dmFyIGQ9YS5zbG90cyxlPWQubGVuZ3RoLGY9YS54LGc9YS55LGg9dGhpcy5ib3VuZGluZ0JveGVzLGk9dGhpcy5wb2x5Z29uUG9vbCxqPXRoaXMucG9seWdvbnM7aC5sZW5ndGg9MDtmb3IodmFyIGs9MCxsPWoubGVuZ3RoO2w+aztrKyspaS5wdXNoKGpba10pO2oubGVuZ3RoPTA7Zm9yKHZhciBrPTA7ZT5rO2srKyl7dmFyIG09ZFtrXSxuPW0uYXR0YWNobWVudDtpZihuLnR5cGU9PWMuQXR0YWNobWVudFR5cGUuYm91bmRpbmdib3gpe2gucHVzaChuKTt2YXIgbyxwPWkubGVuZ3RoO3A+MD8obz1pW3AtMV0saS5zcGxpY2UocC0xLDEpKTpvPVtdLGoucHVzaChvKSxvLmxlbmd0aD1uLnZlcnRpY2VzLmxlbmd0aCxuLmNvbXB1dGVXb3JsZFZlcnRpY2VzKGYsZyxtLmJvbmUsbyl9fWImJnRoaXMuYWFiYkNvbXB1dGUoKX0sYWFiYkNvbXB1dGU6ZnVuY3Rpb24oKXtmb3IodmFyIGE9dGhpcy5wb2x5Z29ucyxiPU51bWJlci5NQVhfVkFMVUUsYz1OdW1iZXIuTUFYX1ZBTFVFLGQ9TnVtYmVyLk1JTl9WQUxVRSxlPU51bWJlci5NSU5fVkFMVUUsZj0wLGc9YS5sZW5ndGg7Zz5mO2YrKylmb3IodmFyIGg9YVtmXSxpPTAsaj1oLmxlbmd0aDtqPmk7aSs9Mil7dmFyIGs9aFtpXSxsPWhbaSsxXTtiPU1hdGgubWluKGIsayksYz1NYXRoLm1pbihjLGwpLGQ9TWF0aC5tYXgoZCxrKSxlPU1hdGgubWF4KGUsbCl9dGhpcy5taW5YPWIsdGhpcy5taW5ZPWMsdGhpcy5tYXhYPWQsdGhpcy5tYXhZPWV9LGFhYmJDb250YWluc1BvaW50OmZ1bmN0aW9uKGEsYil7cmV0dXJuIGE+PXRoaXMubWluWCYmYTw9dGhpcy5tYXhYJiZiPj10aGlzLm1pblkmJmI8PXRoaXMubWF4WX0sYWFiYkludGVyc2VjdHNTZWdtZW50OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBlPXRoaXMubWluWCxmPXRoaXMubWluWSxnPXRoaXMubWF4WCxoPXRoaXMubWF4WTtpZihlPj1hJiZlPj1jfHxmPj1iJiZmPj1kfHxhPj1nJiZjPj1nfHxiPj1oJiZkPj1oKXJldHVybiExO3ZhciBpPShkLWIpLyhjLWEpLGo9aSooZS1hKStiO2lmKGo+ZiYmaD5qKXJldHVybiEwO2lmKGo9aSooZy1hKStiLGo+ZiYmaD5qKXJldHVybiEwO3ZhciBrPShmLWIpL2krYTtyZXR1cm4gaz5lJiZnPms/ITA6KGs9KGgtYikvaSthLGs+ZSYmZz5rPyEwOiExKX0sYWFiYkludGVyc2VjdHNTa2VsZXRvbjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5taW5YPGEubWF4WCYmdGhpcy5tYXhYPmEubWluWCYmdGhpcy5taW5ZPGEubWF4WSYmdGhpcy5tYXhZPmEubWluWX0sY29udGFpbnNQb2ludDpmdW5jdGlvbihhLGIpe2Zvcih2YXIgYz10aGlzLnBvbHlnb25zLGQ9MCxlPWMubGVuZ3RoO2U+ZDtkKyspaWYodGhpcy5wb2x5Z29uQ29udGFpbnNQb2ludChjW2RdLGEsYikpcmV0dXJuIHRoaXMuYm91bmRpbmdCb3hlc1tkXTtyZXR1cm4gbnVsbH0saW50ZXJzZWN0c1NlZ21lbnQ6ZnVuY3Rpb24oYSxiLGMsZCl7Zm9yKHZhciBlPXRoaXMucG9seWdvbnMsZj0wLGc9ZS5sZW5ndGg7Zz5mO2YrKylpZihlW2ZdLmludGVyc2VjdHNTZWdtZW50KGEsYixjLGQpKXJldHVybiB0aGlzLmJvdW5kaW5nQm94ZXNbZl07cmV0dXJuIG51bGx9LHBvbHlnb25Db250YWluc1BvaW50OmZ1bmN0aW9uKGEsYixjKXtmb3IodmFyIGQ9YS5sZW5ndGgsZT1kLTIsZj0hMSxnPTA7ZD5nO2crPTIpe3ZhciBoPWFbZysxXSxpPWFbZSsxXTtpZihjPmgmJmk+PWN8fGM+aSYmaD49Yyl7dmFyIGo9YVtnXTtqKyhjLWgpLyhpLWgpKihhW2VdLWopPGImJihmPSFmKX1lPWd9cmV0dXJuIGZ9LHBvbHlnb25JbnRlcnNlY3RzU2VnbWVudDpmdW5jdGlvbihhLGIsYyxkLGUpe2Zvcih2YXIgZj1hLmxlbmd0aCxnPWItZCxoPWMtZSxpPWIqZS1jKmQsaj1hW2YtMl0saz1hW2YtMV0sbD0wO2Y+bDtsKz0yKXt2YXIgbT1hW2xdLG49YVtsKzFdLG89aipuLWsqbSxwPWotbSxxPWstbixyPWcqcS1oKnAscz0oaSpwLWcqbykvcjtpZigocz49aiYmbT49c3x8cz49bSYmaj49cykmJihzPj1iJiZkPj1zfHxzPj1kJiZiPj1zKSl7dmFyIHQ9KGkqcS1oKm8pL3I7aWYoKHQ+PWsmJm4+PXR8fHQ+PW4mJms+PXQpJiYodD49YyYmZT49dHx8dD49ZSYmYz49dCkpcmV0dXJuITB9aj1tLGs9bn1yZXR1cm4hMX0sZ2V0UG9seWdvbjpmdW5jdGlvbihhKXt2YXIgYj10aGlzLmJvdW5kaW5nQm94ZXMuaW5kZXhPZihhKTtyZXR1cm4tMT09Yj9udWxsOnRoaXMucG9seWdvbnNbYl19LGdldFdpZHRoOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMubWF4WC10aGlzLm1pblh9LGdldEhlaWdodDpmdW5jdGlvbigpe3JldHVybiB0aGlzLm1heFktdGhpcy5taW5ZfX0sYy5Cb25lLnlEb3duPSEwLGIuQW5pbUNhY2hlPXt9LGIuU3BpbmVUZXh0dXJlTG9hZGVyPWZ1bmN0aW9uKGEsYyl7Yi5FdmVudFRhcmdldC5jYWxsKHRoaXMpLHRoaXMuYmFzZVBhdGg9YSx0aGlzLmNyb3Nzb3JpZ2luPWMsdGhpcy5sb2FkaW5nQ291bnQ9MH0sYi5TcGluZVRleHR1cmVMb2FkZXIucHJvdG90eXBlPWIuU3BpbmVUZXh0dXJlTG9hZGVyLGIuU3BpbmVUZXh0dXJlTG9hZGVyLnByb3RvdHlwZS5sb2FkPWZ1bmN0aW9uKGEsYyl7aWYoYS5yZW5kZXJlck9iamVjdD1iLkJhc2VUZXh0dXJlLmZyb21JbWFnZSh0aGlzLmJhc2VQYXRoK1wiL1wiK2MsdGhpcy5jcm9zc29yaWdpbiksIWEucmVuZGVyZXJPYmplY3QuaGFzTG9hZGVkKXt2YXIgZD10aGlzOysrZC5sb2FkaW5nQ291bnQsYS5yZW5kZXJlck9iamVjdC5hZGRFdmVudExpc3RlbmVyKFwibG9hZGVkXCIsZnVuY3Rpb24oKXstLWQubG9hZGluZ0NvdW50LGQuZGlzcGF0Y2hFdmVudCh7dHlwZTpcImxvYWRlZEJhc2VUZXh0dXJlXCIsY29udGVudDpkfSl9KX19LGIuU3BpbmVUZXh0dXJlTG9hZGVyLnByb3RvdHlwZS51bmxvYWQ9ZnVuY3Rpb24oYSl7YS5kZXN0cm95KCEwKX0sYi5TcGluZT1mdW5jdGlvbihhKXtpZihiLkRpc3BsYXlPYmplY3RDb250YWluZXIuY2FsbCh0aGlzKSx0aGlzLnNwaW5lRGF0YT1iLkFuaW1DYWNoZVthXSwhdGhpcy5zcGluZURhdGEpdGhyb3cgbmV3IEVycm9yKFwiU3BpbmUgZGF0YSBtdXN0IGJlIHByZWxvYWRlZCB1c2luZyBQSVhJLlNwaW5lTG9hZGVyIG9yIFBJWEkuQXNzZXRMb2FkZXI6IFwiK2EpO3RoaXMuc2tlbGV0b249bmV3IGMuU2tlbGV0b24odGhpcy5zcGluZURhdGEpLHRoaXMuc2tlbGV0b24udXBkYXRlV29ybGRUcmFuc2Zvcm0oKSx0aGlzLnN0YXRlRGF0YT1uZXcgYy5BbmltYXRpb25TdGF0ZURhdGEodGhpcy5zcGluZURhdGEpLHRoaXMuc3RhdGU9bmV3IGMuQW5pbWF0aW9uU3RhdGUodGhpcy5zdGF0ZURhdGEpLHRoaXMuc2xvdENvbnRhaW5lcnM9W107Zm9yKHZhciBkPTAsZT10aGlzLnNrZWxldG9uLmRyYXdPcmRlci5sZW5ndGg7ZT5kO2QrKyl7dmFyIGY9dGhpcy5za2VsZXRvbi5kcmF3T3JkZXJbZF0sZz1mLmF0dGFjaG1lbnQsaD1uZXcgYi5EaXNwbGF5T2JqZWN0Q29udGFpbmVyO2lmKHRoaXMuc2xvdENvbnRhaW5lcnMucHVzaChoKSx0aGlzLmFkZENoaWxkKGgpLGcgaW5zdGFuY2VvZiBjLlJlZ2lvbkF0dGFjaG1lbnQpe3ZhciBpPWcucmVuZGVyZXJPYmplY3QubmFtZSxqPXRoaXMuY3JlYXRlU3ByaXRlKGYsZyk7Zi5jdXJyZW50U3ByaXRlPWosZi5jdXJyZW50U3ByaXRlTmFtZT1pLGguYWRkQ2hpbGQoail9ZWxzZXtpZighKGcgaW5zdGFuY2VvZiBjLk1lc2hBdHRhY2htZW50KSljb250aW51ZTt2YXIgaz10aGlzLmNyZWF0ZU1lc2goZixnKTtmLmN1cnJlbnRNZXNoPWssZi5jdXJyZW50TWVzaE5hbWU9Zy5uYW1lLGguYWRkQ2hpbGQoayl9fXRoaXMuYXV0b1VwZGF0ZT0hMH0sYi5TcGluZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShiLkRpc3BsYXlPYmplY3RDb250YWluZXIucHJvdG90eXBlKSxiLlNwaW5lLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLlNwaW5lLE9iamVjdC5kZWZpbmVQcm9wZXJ0eShiLlNwaW5lLnByb3RvdHlwZSxcImF1dG9VcGRhdGVcIix7Z2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudXBkYXRlVHJhbnNmb3JtPT09Yi5TcGluZS5wcm90b3R5cGUuYXV0b1VwZGF0ZVRyYW5zZm9ybX0sc2V0OmZ1bmN0aW9uKGEpe3RoaXMudXBkYXRlVHJhbnNmb3JtPWE/Yi5TcGluZS5wcm90b3R5cGUuYXV0b1VwZGF0ZVRyYW5zZm9ybTpiLkRpc3BsYXlPYmplY3RDb250YWluZXIucHJvdG90eXBlLnVwZGF0ZVRyYW5zZm9ybX19KSxiLlNwaW5lLnByb3RvdHlwZS51cGRhdGU9ZnVuY3Rpb24oYSl7dGhpcy5zdGF0ZS51cGRhdGUoYSksdGhpcy5zdGF0ZS5hcHBseSh0aGlzLnNrZWxldG9uKSx0aGlzLnNrZWxldG9uLnVwZGF0ZVdvcmxkVHJhbnNmb3JtKCk7Zm9yKHZhciBkPXRoaXMuc2tlbGV0b24uZHJhd09yZGVyLGU9MCxmPWQubGVuZ3RoO2Y+ZTtlKyspe3ZhciBnPWRbZV0saD1nLmF0dGFjaG1lbnQsaT10aGlzLnNsb3RDb250YWluZXJzW2VdO2lmKGgpe3ZhciBqPWgudHlwZTtpZihqPT09Yy5BdHRhY2htZW50VHlwZS5yZWdpb24pe2lmKGgucmVuZGVyZXJPYmplY3QmJighZy5jdXJyZW50U3ByaXRlTmFtZXx8Zy5jdXJyZW50U3ByaXRlTmFtZSE9PWgubmFtZSkpe3ZhciBrPWgucmVuZGVyZXJPYmplY3QubmFtZTtpZih2b2lkIDAhPT1nLmN1cnJlbnRTcHJpdGUmJihnLmN1cnJlbnRTcHJpdGUudmlzaWJsZT0hMSksZy5zcHJpdGVzPWcuc3ByaXRlc3x8e30sdm9pZCAwIT09Zy5zcHJpdGVzW2tdKWcuc3ByaXRlc1trXS52aXNpYmxlPSEwO2Vsc2V7dmFyIGw9dGhpcy5jcmVhdGVTcHJpdGUoZyxoKTtpLmFkZENoaWxkKGwpfWcuY3VycmVudFNwcml0ZT1nLnNwcml0ZXNba10sZy5jdXJyZW50U3ByaXRlTmFtZT1rfXZhciBtPWcuYm9uZTtpLnBvc2l0aW9uLng9bS53b3JsZFgraC54Km0ubTAwK2gueSptLm0wMSxpLnBvc2l0aW9uLnk9bS53b3JsZFkraC54Km0ubTEwK2gueSptLm0xMSxpLnNjYWxlLng9bS53b3JsZFNjYWxlWCxpLnNjYWxlLnk9bS53b3JsZFNjYWxlWSxpLnJvdGF0aW9uPS0oZy5ib25lLndvcmxkUm90YXRpb24qYy5kZWdSYWQpLGcuY3VycmVudFNwcml0ZS50aW50PWIucmdiMmhleChbZy5yLGcuZyxnLmJdKX1lbHNle2lmKGohPT1jLkF0dGFjaG1lbnRUeXBlLnNraW5uZWRtZXNoKXtpLnZpc2libGU9ITE7Y29udGludWV9aWYoIWcuY3VycmVudE1lc2hOYW1lfHxnLmN1cnJlbnRNZXNoTmFtZSE9PWgubmFtZSl7dmFyIG49aC5uYW1lO2lmKHZvaWQgMCE9PWcuY3VycmVudE1lc2gmJihnLmN1cnJlbnRNZXNoLnZpc2libGU9ITEpLGcubWVzaGVzPWcubWVzaGVzfHx7fSx2b2lkIDAhPT1nLm1lc2hlc1tuXSlnLm1lc2hlc1tuXS52aXNpYmxlPSEwO2Vsc2V7dmFyIG89dGhpcy5jcmVhdGVNZXNoKGcsaCk7aS5hZGRDaGlsZChvKX1nLmN1cnJlbnRNZXNoPWcubWVzaGVzW25dLGcuY3VycmVudE1lc2hOYW1lPW59aC5jb21wdXRlV29ybGRWZXJ0aWNlcyhnLmJvbmUuc2tlbGV0b24ueCxnLmJvbmUuc2tlbGV0b24ueSxnLGcuY3VycmVudE1lc2gudmVydGljZXMpfWkudmlzaWJsZT0hMCxpLmFscGhhPWcuYX1lbHNlIGkudmlzaWJsZT0hMX19LGIuU3BpbmUucHJvdG90eXBlLmF1dG9VcGRhdGVUcmFuc2Zvcm09ZnVuY3Rpb24oKXt0aGlzLmxhc3RUaW1lPXRoaXMubGFzdFRpbWV8fERhdGUubm93KCk7dmFyIGE9LjAwMSooRGF0ZS5ub3coKS10aGlzLmxhc3RUaW1lKTt0aGlzLmxhc3RUaW1lPURhdGUubm93KCksdGhpcy51cGRhdGUoYSksYi5EaXNwbGF5T2JqZWN0Q29udGFpbmVyLnByb3RvdHlwZS51cGRhdGVUcmFuc2Zvcm0uY2FsbCh0aGlzKX0sYi5TcGluZS5wcm90b3R5cGUuY3JlYXRlU3ByaXRlPWZ1bmN0aW9uKGEsZCl7dmFyIGU9ZC5yZW5kZXJlck9iamVjdCxmPWUucGFnZS5yZW5kZXJlck9iamVjdCxnPW5ldyBiLlJlY3RhbmdsZShlLngsZS55LGUucm90YXRlP2UuaGVpZ2h0OmUud2lkdGgsZS5yb3RhdGU/ZS53aWR0aDplLmhlaWdodCksaD1uZXcgYi5UZXh0dXJlKGYsZyksaT1uZXcgYi5TcHJpdGUoaCksaj1lLnJvdGF0ZT8uNSpNYXRoLlBJOjA7cmV0dXJuIGkuc2NhbGUuc2V0KGUud2lkdGgvZS5vcmlnaW5hbFdpZHRoLGUuaGVpZ2h0L2Uub3JpZ2luYWxIZWlnaHQpLGkucm90YXRpb249ai1kLnJvdGF0aW9uKmMuZGVnUmFkLGkuYW5jaG9yLng9aS5hbmNob3IueT0uNSxhLnNwcml0ZXM9YS5zcHJpdGVzfHx7fSxhLnNwcml0ZXNbZS5uYW1lXT1pLGl9LGIuU3BpbmUucHJvdG90eXBlLmNyZWF0ZU1lc2g9ZnVuY3Rpb24oYSxjKXt2YXIgZD1jLnJlbmRlcmVyT2JqZWN0LGU9ZC5wYWdlLnJlbmRlcmVyT2JqZWN0LGY9bmV3IGIuVGV4dHVyZShlKSxnPW5ldyBiLlN0cmlwKGYpO3JldHVybiBnLmRyYXdNb2RlPWIuU3RyaXAuRHJhd01vZGVzLlRSSUFOR0xFUyxnLmNhbnZhc1BhZGRpbmc9MS41LGcudmVydGljZXM9bmV3IGIuRmxvYXQzMkFycmF5KGMudXZzLmxlbmd0aCksZy51dnM9Yy51dnMsZy5pbmRpY2VzPWMudHJpYW5nbGVzLGEubWVzaGVzPWEubWVzaGVzfHx7fSxhLm1lc2hlc1tjLm5hbWVdPWcsZ30sYi5CYXNlVGV4dHVyZUNhY2hlPXt9LGIuQmFzZVRleHR1cmVDYWNoZUlkR2VuZXJhdG9yPTAsYi5CYXNlVGV4dHVyZT1mdW5jdGlvbihhLGMpe2lmKHRoaXMucmVzb2x1dGlvbj0xLHRoaXMud2lkdGg9MTAwLHRoaXMuaGVpZ2h0PTEwMCx0aGlzLnNjYWxlTW9kZT1jfHxiLnNjYWxlTW9kZXMuREVGQVVMVCx0aGlzLmhhc0xvYWRlZD0hMSx0aGlzLnNvdXJjZT1hLHRoaXMuX1VJRD1iLl9VSUQrKyx0aGlzLnByZW11bHRpcGxpZWRBbHBoYT0hMCx0aGlzLl9nbFRleHR1cmVzPVtdLHRoaXMubWlwbWFwPSExLHRoaXMuX2RpcnR5PVshMCwhMCwhMCwhMF0sYSl7aWYoKHRoaXMuc291cmNlLmNvbXBsZXRlfHx0aGlzLnNvdXJjZS5nZXRDb250ZXh0KSYmdGhpcy5zb3VyY2Uud2lkdGgmJnRoaXMuc291cmNlLmhlaWdodCl0aGlzLmhhc0xvYWRlZD0hMCx0aGlzLndpZHRoPXRoaXMuc291cmNlLm5hdHVyYWxXaWR0aHx8dGhpcy5zb3VyY2Uud2lkdGgsdGhpcy5oZWlnaHQ9dGhpcy5zb3VyY2UubmF0dXJhbEhlaWdodHx8dGhpcy5zb3VyY2UuaGVpZ2h0LHRoaXMuZGlydHkoKTtlbHNle3ZhciBkPXRoaXM7dGhpcy5zb3VyY2Uub25sb2FkPWZ1bmN0aW9uKCl7ZC5oYXNMb2FkZWQ9ITAsZC53aWR0aD1kLnNvdXJjZS5uYXR1cmFsV2lkdGh8fGQuc291cmNlLndpZHRoLGQuaGVpZ2h0PWQuc291cmNlLm5hdHVyYWxIZWlnaHR8fGQuc291cmNlLmhlaWdodCxkLmRpcnR5KCksZC5kaXNwYXRjaEV2ZW50KHt0eXBlOlwibG9hZGVkXCIsY29udGVudDpkfSl9LHRoaXMuc291cmNlLm9uZXJyb3I9ZnVuY3Rpb24oKXtkLmRpc3BhdGNoRXZlbnQoe3R5cGU6XCJlcnJvclwiLGNvbnRlbnQ6ZH0pfX10aGlzLmltYWdlVXJsPW51bGwsdGhpcy5fcG93ZXJPZjI9ITF9fSxiLkJhc2VUZXh0dXJlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLkJhc2VUZXh0dXJlLGIuRXZlbnRUYXJnZXQubWl4aW4oYi5CYXNlVGV4dHVyZS5wcm90b3R5cGUpLGIuQmFzZVRleHR1cmUucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oKXt0aGlzLmltYWdlVXJsPyhkZWxldGUgYi5CYXNlVGV4dHVyZUNhY2hlW3RoaXMuaW1hZ2VVcmxdLGRlbGV0ZSBiLlRleHR1cmVDYWNoZVt0aGlzLmltYWdlVXJsXSx0aGlzLmltYWdlVXJsPW51bGwsbmF2aWdhdG9yLmlzQ29jb29uSlN8fCh0aGlzLnNvdXJjZS5zcmM9XCJcIikpOnRoaXMuc291cmNlJiZ0aGlzLnNvdXJjZS5fcGl4aUlkJiZkZWxldGUgYi5CYXNlVGV4dHVyZUNhY2hlW3RoaXMuc291cmNlLl9waXhpSWRdLHRoaXMuc291cmNlPW51bGwsdGhpcy51bmxvYWRGcm9tR1BVKCl9LGIuQmFzZVRleHR1cmUucHJvdG90eXBlLnVwZGF0ZVNvdXJjZUltYWdlPWZ1bmN0aW9uKGEpe3RoaXMuaGFzTG9hZGVkPSExLHRoaXMuc291cmNlLnNyYz1udWxsLHRoaXMuc291cmNlLnNyYz1hfSxiLkJhc2VUZXh0dXJlLnByb3RvdHlwZS5kaXJ0eT1mdW5jdGlvbigpe2Zvcih2YXIgYT0wO2E8dGhpcy5fZ2xUZXh0dXJlcy5sZW5ndGg7YSsrKXRoaXMuX2RpcnR5W2FdPSEwfSxiLkJhc2VUZXh0dXJlLnByb3RvdHlwZS51bmxvYWRGcm9tR1BVPWZ1bmN0aW9uKCl7dGhpcy5kaXJ0eSgpO2Zvcih2YXIgYT10aGlzLl9nbFRleHR1cmVzLmxlbmd0aC0xO2E+PTA7YS0tKXt2YXIgYz10aGlzLl9nbFRleHR1cmVzW2FdLGQ9Yi5nbENvbnRleHRzW2FdO2QmJmMmJmQuZGVsZXRlVGV4dHVyZShjKX10aGlzLl9nbFRleHR1cmVzLmxlbmd0aD0wLHRoaXMuZGlydHkoKX0sYi5CYXNlVGV4dHVyZS5mcm9tSW1hZ2U9ZnVuY3Rpb24oYSxjLGQpe3ZhciBlPWIuQmFzZVRleHR1cmVDYWNoZVthXTtpZih2b2lkIDA9PT1jJiYtMT09PWEuaW5kZXhPZihcImRhdGE6XCIpJiYoYz0hMCksIWUpe3ZhciBmPW5ldyBJbWFnZTtjJiYoZi5jcm9zc09yaWdpbj1cIlwiKSxmLnNyYz1hLGU9bmV3IGIuQmFzZVRleHR1cmUoZixkKSxlLmltYWdlVXJsPWEsYi5CYXNlVGV4dHVyZUNhY2hlW2FdPWUsLTEhPT1hLmluZGV4T2YoYi5SRVRJTkFfUFJFRklYK1wiLlwiKSYmKGUucmVzb2x1dGlvbj0yKX1yZXR1cm4gZX0sYi5CYXNlVGV4dHVyZS5mcm9tQ2FudmFzPWZ1bmN0aW9uKGEsYyl7YS5fcGl4aUlkfHwoYS5fcGl4aUlkPVwiY2FudmFzX1wiK2IuVGV4dHVyZUNhY2hlSWRHZW5lcmF0b3IrKyk7dmFyIGQ9Yi5CYXNlVGV4dHVyZUNhY2hlW2EuX3BpeGlJZF07cmV0dXJuIGR8fChkPW5ldyBiLkJhc2VUZXh0dXJlKGEsYyksYi5CYXNlVGV4dHVyZUNhY2hlW2EuX3BpeGlJZF09ZCksZH0sYi5UZXh0dXJlQ2FjaGU9e30sYi5GcmFtZUNhY2hlPXt9LGIuVGV4dHVyZUNhY2hlSWRHZW5lcmF0b3I9MCxiLlRleHR1cmU9ZnVuY3Rpb24oYSxjLGQsZSl7dGhpcy5ub0ZyYW1lPSExLGN8fCh0aGlzLm5vRnJhbWU9ITAsYz1uZXcgYi5SZWN0YW5nbGUoMCwwLDEsMSkpLGEgaW5zdGFuY2VvZiBiLlRleHR1cmUmJihhPWEuYmFzZVRleHR1cmUpLHRoaXMuYmFzZVRleHR1cmU9YSx0aGlzLmZyYW1lPWMsdGhpcy50cmltPWUsdGhpcy52YWxpZD0hMSx0aGlzLnJlcXVpcmVzVXBkYXRlPSExLHRoaXMuX3V2cz1udWxsLHRoaXMud2lkdGg9MCx0aGlzLmhlaWdodD0wLHRoaXMuY3JvcD1kfHxuZXcgYi5SZWN0YW5nbGUoMCwwLDEsMSksYS5oYXNMb2FkZWQ/KHRoaXMubm9GcmFtZSYmKGM9bmV3IGIuUmVjdGFuZ2xlKDAsMCxhLndpZHRoLGEuaGVpZ2h0KSksdGhpcy5zZXRGcmFtZShjKSk6YS5hZGRFdmVudExpc3RlbmVyKFwibG9hZGVkXCIsdGhpcy5vbkJhc2VUZXh0dXJlTG9hZGVkLmJpbmQodGhpcykpfSxiLlRleHR1cmUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuVGV4dHVyZSxiLkV2ZW50VGFyZ2V0Lm1peGluKGIuVGV4dHVyZS5wcm90b3R5cGUpLGIuVGV4dHVyZS5wcm90b3R5cGUub25CYXNlVGV4dHVyZUxvYWRlZD1mdW5jdGlvbigpe3ZhciBhPXRoaXMuYmFzZVRleHR1cmU7YS5yZW1vdmVFdmVudExpc3RlbmVyKFwibG9hZGVkXCIsdGhpcy5vbkxvYWRlZCksdGhpcy5ub0ZyYW1lJiYodGhpcy5mcmFtZT1uZXcgYi5SZWN0YW5nbGUoMCwwLGEud2lkdGgsYS5oZWlnaHQpKSx0aGlzLnNldEZyYW1lKHRoaXMuZnJhbWUpLHRoaXMuZGlzcGF0Y2hFdmVudCh7dHlwZTpcInVwZGF0ZVwiLGNvbnRlbnQ6dGhpc30pfSxiLlRleHR1cmUucHJvdG90eXBlLmRlc3Ryb3k9ZnVuY3Rpb24oYSl7YSYmdGhpcy5iYXNlVGV4dHVyZS5kZXN0cm95KCksdGhpcy52YWxpZD0hMX0sYi5UZXh0dXJlLnByb3RvdHlwZS5zZXRGcmFtZT1mdW5jdGlvbihhKXtpZih0aGlzLm5vRnJhbWU9ITEsdGhpcy5mcmFtZT1hLHRoaXMud2lkdGg9YS53aWR0aCx0aGlzLmhlaWdodD1hLmhlaWdodCx0aGlzLmNyb3AueD1hLngsdGhpcy5jcm9wLnk9YS55LHRoaXMuY3JvcC53aWR0aD1hLndpZHRoLHRoaXMuY3JvcC5oZWlnaHQ9YS5oZWlnaHQsIXRoaXMudHJpbSYmKGEueCthLndpZHRoPnRoaXMuYmFzZVRleHR1cmUud2lkdGh8fGEueSthLmhlaWdodD50aGlzLmJhc2VUZXh0dXJlLmhlaWdodCkpdGhyb3cgbmV3IEVycm9yKFwiVGV4dHVyZSBFcnJvcjogZnJhbWUgZG9lcyBub3QgZml0IGluc2lkZSB0aGUgYmFzZSBUZXh0dXJlIGRpbWVuc2lvbnMgXCIrdGhpcyk7dGhpcy52YWxpZD1hJiZhLndpZHRoJiZhLmhlaWdodCYmdGhpcy5iYXNlVGV4dHVyZS5zb3VyY2UmJnRoaXMuYmFzZVRleHR1cmUuaGFzTG9hZGVkLHRoaXMudHJpbSYmKHRoaXMud2lkdGg9dGhpcy50cmltLndpZHRoLHRoaXMuaGVpZ2h0PXRoaXMudHJpbS5oZWlnaHQsdGhpcy5mcmFtZS53aWR0aD10aGlzLnRyaW0ud2lkdGgsdGhpcy5mcmFtZS5oZWlnaHQ9dGhpcy50cmltLmhlaWdodCksdGhpcy52YWxpZCYmdGhpcy5fdXBkYXRlVXZzKCl9LGIuVGV4dHVyZS5wcm90b3R5cGUuX3VwZGF0ZVV2cz1mdW5jdGlvbigpe3RoaXMuX3V2c3x8KHRoaXMuX3V2cz1uZXcgYi5UZXh0dXJlVXZzKTt2YXIgYT10aGlzLmNyb3AsYz10aGlzLmJhc2VUZXh0dXJlLndpZHRoLGQ9dGhpcy5iYXNlVGV4dHVyZS5oZWlnaHQ7dGhpcy5fdXZzLngwPWEueC9jLHRoaXMuX3V2cy55MD1hLnkvZCx0aGlzLl91dnMueDE9KGEueCthLndpZHRoKS9jLHRoaXMuX3V2cy55MT1hLnkvZCx0aGlzLl91dnMueDI9KGEueCthLndpZHRoKS9jLHRoaXMuX3V2cy55Mj0oYS55K2EuaGVpZ2h0KS9kLHRoaXMuX3V2cy54Mz1hLngvYyx0aGlzLl91dnMueTM9KGEueSthLmhlaWdodCkvZH0sYi5UZXh0dXJlLmZyb21JbWFnZT1mdW5jdGlvbihhLGMsZCl7dmFyIGU9Yi5UZXh0dXJlQ2FjaGVbYV07cmV0dXJuIGV8fChlPW5ldyBiLlRleHR1cmUoYi5CYXNlVGV4dHVyZS5mcm9tSW1hZ2UoYSxjLGQpKSxiLlRleHR1cmVDYWNoZVthXT1lKSxlfSxiLlRleHR1cmUuZnJvbUZyYW1lPWZ1bmN0aW9uKGEpe3ZhciBjPWIuVGV4dHVyZUNhY2hlW2FdO2lmKCFjKXRocm93IG5ldyBFcnJvcignVGhlIGZyYW1lSWQgXCInK2ErJ1wiIGRvZXMgbm90IGV4aXN0IGluIHRoZSB0ZXh0dXJlIGNhY2hlICcpO3JldHVybiBjfSxiLlRleHR1cmUuZnJvbUNhbnZhcz1mdW5jdGlvbihhLGMpe3ZhciBkPWIuQmFzZVRleHR1cmUuZnJvbUNhbnZhcyhhLGMpO3JldHVybiBuZXcgYi5UZXh0dXJlKGQpfSxiLlRleHR1cmUuYWRkVGV4dHVyZVRvQ2FjaGU9ZnVuY3Rpb24oYSxjKXtiLlRleHR1cmVDYWNoZVtjXT1hfSxiLlRleHR1cmUucmVtb3ZlVGV4dHVyZUZyb21DYWNoZT1mdW5jdGlvbihhKXt2YXIgYz1iLlRleHR1cmVDYWNoZVthXTtyZXR1cm4gZGVsZXRlIGIuVGV4dHVyZUNhY2hlW2FdLGRlbGV0ZSBiLkJhc2VUZXh0dXJlQ2FjaGVbYV0sY30sYi5UZXh0dXJlVXZzPWZ1bmN0aW9uKCl7dGhpcy54MD0wLHRoaXMueTA9MCx0aGlzLngxPTAsdGhpcy55MT0wLHRoaXMueDI9MCx0aGlzLnkyPTAsdGhpcy54Mz0wLHRoaXMueTM9MH0sYi5UZXh0dXJlLmVtcHR5VGV4dHVyZT1uZXcgYi5UZXh0dXJlKG5ldyBiLkJhc2VUZXh0dXJlKSxiLlJlbmRlclRleHR1cmU9ZnVuY3Rpb24oYSxjLGQsZSxmKXtpZih0aGlzLndpZHRoPWF8fDEwMCx0aGlzLmhlaWdodD1jfHwxMDAsdGhpcy5yZXNvbHV0aW9uPWZ8fDEsdGhpcy5mcmFtZT1uZXcgYi5SZWN0YW5nbGUoMCwwLHRoaXMud2lkdGgqdGhpcy5yZXNvbHV0aW9uLHRoaXMuaGVpZ2h0KnRoaXMucmVzb2x1dGlvbiksdGhpcy5jcm9wPW5ldyBiLlJlY3RhbmdsZSgwLDAsdGhpcy53aWR0aCp0aGlzLnJlc29sdXRpb24sdGhpcy5oZWlnaHQqdGhpcy5yZXNvbHV0aW9uKSx0aGlzLmJhc2VUZXh0dXJlPW5ldyBiLkJhc2VUZXh0dXJlLHRoaXMuYmFzZVRleHR1cmUud2lkdGg9dGhpcy53aWR0aCp0aGlzLnJlc29sdXRpb24sdGhpcy5iYXNlVGV4dHVyZS5oZWlnaHQ9dGhpcy5oZWlnaHQqdGhpcy5yZXNvbHV0aW9uLHRoaXMuYmFzZVRleHR1cmUuX2dsVGV4dHVyZXM9W10sdGhpcy5iYXNlVGV4dHVyZS5yZXNvbHV0aW9uPXRoaXMucmVzb2x1dGlvbix0aGlzLmJhc2VUZXh0dXJlLnNjYWxlTW9kZT1lfHxiLnNjYWxlTW9kZXMuREVGQVVMVCx0aGlzLmJhc2VUZXh0dXJlLmhhc0xvYWRlZD0hMCxiLlRleHR1cmUuY2FsbCh0aGlzLHRoaXMuYmFzZVRleHR1cmUsbmV3IGIuUmVjdGFuZ2xlKDAsMCx0aGlzLndpZHRoLHRoaXMuaGVpZ2h0KSksdGhpcy5yZW5kZXJlcj1kfHxiLmRlZmF1bHRSZW5kZXJlcix0aGlzLnJlbmRlcmVyLnR5cGU9PT1iLldFQkdMX1JFTkRFUkVSKXt2YXIgZz10aGlzLnJlbmRlcmVyLmdsO3RoaXMuYmFzZVRleHR1cmUuX2RpcnR5W2cuaWRdPSExLHRoaXMudGV4dHVyZUJ1ZmZlcj1uZXcgYi5GaWx0ZXJUZXh0dXJlKGcsdGhpcy53aWR0aCp0aGlzLnJlc29sdXRpb24sdGhpcy5oZWlnaHQqdGhpcy5yZXNvbHV0aW9uLHRoaXMuYmFzZVRleHR1cmUuc2NhbGVNb2RlKSx0aGlzLmJhc2VUZXh0dXJlLl9nbFRleHR1cmVzW2cuaWRdPXRoaXMudGV4dHVyZUJ1ZmZlci50ZXh0dXJlLHRoaXMucmVuZGVyPXRoaXMucmVuZGVyV2ViR0wsdGhpcy5wcm9qZWN0aW9uPW5ldyBiLlBvaW50KC41KnRoaXMud2lkdGgsLjUqLXRoaXMuaGVpZ2h0KX1lbHNlIHRoaXMucmVuZGVyPXRoaXMucmVuZGVyQ2FudmFzLHRoaXMudGV4dHVyZUJ1ZmZlcj1uZXcgYi5DYW52YXNCdWZmZXIodGhpcy53aWR0aCp0aGlzLnJlc29sdXRpb24sdGhpcy5oZWlnaHQqdGhpcy5yZXNvbHV0aW9uKSx0aGlzLmJhc2VUZXh0dXJlLnNvdXJjZT10aGlzLnRleHR1cmVCdWZmZXIuY2FudmFzO3RoaXMudmFsaWQ9ITAsdGhpcy5fdXBkYXRlVXZzKCl9LGIuUmVuZGVyVGV4dHVyZS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShiLlRleHR1cmUucHJvdG90eXBlKSxiLlJlbmRlclRleHR1cmUucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuUmVuZGVyVGV4dHVyZSxiLlJlbmRlclRleHR1cmUucHJvdG90eXBlLnJlc2l6ZT1mdW5jdGlvbihhLGMsZCl7KGEhPT10aGlzLndpZHRofHxjIT09dGhpcy5oZWlnaHQpJiYodGhpcy52YWxpZD1hPjAmJmM+MCx0aGlzLndpZHRoPXRoaXMuZnJhbWUud2lkdGg9dGhpcy5jcm9wLndpZHRoPWEsdGhpcy5oZWlnaHQ9dGhpcy5mcmFtZS5oZWlnaHQ9dGhpcy5jcm9wLmhlaWdodD1jLGQmJih0aGlzLmJhc2VUZXh0dXJlLndpZHRoPXRoaXMud2lkdGgsdGhpcy5iYXNlVGV4dHVyZS5oZWlnaHQ9dGhpcy5oZWlnaHQpLHRoaXMucmVuZGVyZXIudHlwZT09PWIuV0VCR0xfUkVOREVSRVImJih0aGlzLnByb2plY3Rpb24ueD10aGlzLndpZHRoLzIsdGhpcy5wcm9qZWN0aW9uLnk9LXRoaXMuaGVpZ2h0LzIpLHRoaXMudmFsaWQmJnRoaXMudGV4dHVyZUJ1ZmZlci5yZXNpemUodGhpcy53aWR0aCp0aGlzLnJlc29sdXRpb24sdGhpcy5oZWlnaHQqdGhpcy5yZXNvbHV0aW9uKSl9LGIuUmVuZGVyVGV4dHVyZS5wcm90b3R5cGUuY2xlYXI9ZnVuY3Rpb24oKXt0aGlzLnZhbGlkJiYodGhpcy5yZW5kZXJlci50eXBlPT09Yi5XRUJHTF9SRU5ERVJFUiYmdGhpcy5yZW5kZXJlci5nbC5iaW5kRnJhbWVidWZmZXIodGhpcy5yZW5kZXJlci5nbC5GUkFNRUJVRkZFUix0aGlzLnRleHR1cmVCdWZmZXIuZnJhbWVCdWZmZXIpLHRoaXMudGV4dHVyZUJ1ZmZlci5jbGVhcigpKX0sYi5SZW5kZXJUZXh0dXJlLnByb3RvdHlwZS5yZW5kZXJXZWJHTD1mdW5jdGlvbihhLGIsYyl7aWYodGhpcy52YWxpZCl7dmFyIGQ9YS53b3JsZFRyYW5zZm9ybTtkLmlkZW50aXR5KCksZC50cmFuc2xhdGUoMCwyKnRoaXMucHJvamVjdGlvbi55KSxiJiZkLmFwcGVuZChiKSxkLnNjYWxlKDEsLTEpLGEud29ybGRBbHBoYT0xO2Zvcih2YXIgZT1hLmNoaWxkcmVuLGY9MCxnPWUubGVuZ3RoO2c+ZjtmKyspZVtmXS51cGRhdGVUcmFuc2Zvcm0oKTt2YXIgaD10aGlzLnJlbmRlcmVyLmdsO2gudmlld3BvcnQoMCwwLHRoaXMud2lkdGgqdGhpcy5yZXNvbHV0aW9uLHRoaXMuaGVpZ2h0KnRoaXMucmVzb2x1dGlvbiksaC5iaW5kRnJhbWVidWZmZXIoaC5GUkFNRUJVRkZFUix0aGlzLnRleHR1cmVCdWZmZXIuZnJhbWVCdWZmZXIpLGMmJnRoaXMudGV4dHVyZUJ1ZmZlci5jbGVhcigpLHRoaXMucmVuZGVyZXIuc3ByaXRlQmF0Y2guZGlydHk9ITAsdGhpcy5yZW5kZXJlci5yZW5kZXJEaXNwbGF5T2JqZWN0KGEsdGhpcy5wcm9qZWN0aW9uLHRoaXMudGV4dHVyZUJ1ZmZlci5mcmFtZUJ1ZmZlciksdGhpcy5yZW5kZXJlci5zcHJpdGVCYXRjaC5kaXJ0eT0hMH19LGIuUmVuZGVyVGV4dHVyZS5wcm90b3R5cGUucmVuZGVyQ2FudmFzPWZ1bmN0aW9uKGEsYixjKXtpZih0aGlzLnZhbGlkKXt2YXIgZD1hLndvcmxkVHJhbnNmb3JtO2QuaWRlbnRpdHkoKSxiJiZkLmFwcGVuZChiKSxhLndvcmxkQWxwaGE9MTtmb3IodmFyIGU9YS5jaGlsZHJlbixmPTAsZz1lLmxlbmd0aDtnPmY7ZisrKWVbZl0udXBkYXRlVHJhbnNmb3JtKCk7YyYmdGhpcy50ZXh0dXJlQnVmZmVyLmNsZWFyKCk7dmFyIGg9dGhpcy50ZXh0dXJlQnVmZmVyLmNvbnRleHQsaT10aGlzLnJlbmRlcmVyLnJlc29sdXRpb247dGhpcy5yZW5kZXJlci5yZXNvbHV0aW9uPXRoaXMucmVzb2x1dGlvbix0aGlzLnJlbmRlcmVyLnJlbmRlckRpc3BsYXlPYmplY3QoYSxoKSx0aGlzLnJlbmRlcmVyLnJlc29sdXRpb249aX19LGIuUmVuZGVyVGV4dHVyZS5wcm90b3R5cGUuZ2V0SW1hZ2U9ZnVuY3Rpb24oKXt2YXIgYT1uZXcgSW1hZ2U7cmV0dXJuIGEuc3JjPXRoaXMuZ2V0QmFzZTY0KCksYX0sYi5SZW5kZXJUZXh0dXJlLnByb3RvdHlwZS5nZXRCYXNlNjQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5nZXRDYW52YXMoKS50b0RhdGFVUkwoKX0sYi5SZW5kZXJUZXh0dXJlLnByb3RvdHlwZS5nZXRDYW52YXM9ZnVuY3Rpb24oKXtpZih0aGlzLnJlbmRlcmVyLnR5cGU9PT1iLldFQkdMX1JFTkRFUkVSKXt2YXIgYT10aGlzLnJlbmRlcmVyLmdsLGM9dGhpcy50ZXh0dXJlQnVmZmVyLndpZHRoLGQ9dGhpcy50ZXh0dXJlQnVmZmVyLmhlaWdodCxlPW5ldyBVaW50OEFycmF5KDQqYypkKTthLmJpbmRGcmFtZWJ1ZmZlcihhLkZSQU1FQlVGRkVSLHRoaXMudGV4dHVyZUJ1ZmZlci5mcmFtZUJ1ZmZlciksYS5yZWFkUGl4ZWxzKDAsMCxjLGQsYS5SR0JBLGEuVU5TSUdORURfQllURSxlKSxhLmJpbmRGcmFtZWJ1ZmZlcihhLkZSQU1FQlVGRkVSLG51bGwpO3ZhciBmPW5ldyBiLkNhbnZhc0J1ZmZlcihjLGQpLGc9Zi5jb250ZXh0LmdldEltYWdlRGF0YSgwLDAsYyxkKTtyZXR1cm4gZy5kYXRhLnNldChlKSxmLmNvbnRleHQucHV0SW1hZ2VEYXRhKGcsMCwwKSxmLmNhbnZhc31yZXR1cm4gdGhpcy50ZXh0dXJlQnVmZmVyLmNhbnZhc30sYi5SZW5kZXJUZXh0dXJlLnRlbXBNYXRyaXg9bmV3IGIuTWF0cml4LGIuVmlkZW9UZXh0dXJlPWZ1bmN0aW9uKGEsYyl7aWYoIWEpdGhyb3cgbmV3IEVycm9yKFwiTm8gdmlkZW8gc291cmNlIGVsZW1lbnQgc3BlY2lmaWVkLlwiKTsoYS5yZWFkeVN0YXRlPT09YS5IQVZFX0VOT1VHSF9EQVRBfHxhLnJlYWR5U3RhdGU9PT1hLkhBVkVfRlVUVVJFX0RBVEEpJiZhLndpZHRoJiZhLmhlaWdodCYmKGEuY29tcGxldGU9ITApLGIuQmFzZVRleHR1cmUuY2FsbCh0aGlzLGEsYyksdGhpcy5hdXRvVXBkYXRlPSExLHRoaXMudXBkYXRlQm91bmQ9dGhpcy5fb25VcGRhdGUuYmluZCh0aGlzKSxhLmNvbXBsZXRlfHwodGhpcy5fb25DYW5QbGF5PXRoaXMub25DYW5QbGF5LmJpbmQodGhpcyksYS5hZGRFdmVudExpc3RlbmVyKFwiY2FucGxheVwiLHRoaXMuX29uQ2FuUGxheSksYS5hZGRFdmVudExpc3RlbmVyKFwiY2FucGxheXRocm91Z2hcIix0aGlzLl9vbkNhblBsYXkpLGEuYWRkRXZlbnRMaXN0ZW5lcihcInBsYXlcIix0aGlzLm9uUGxheVN0YXJ0LmJpbmQodGhpcykpLGEuYWRkRXZlbnRMaXN0ZW5lcihcInBhdXNlXCIsdGhpcy5vblBsYXlTdG9wLmJpbmQodGhpcykpKX0sYi5WaWRlb1RleHR1cmUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoYi5CYXNlVGV4dHVyZS5wcm90b3R5cGUpLGIuVmlkZW9UZXh0dXJlLmNvbnN0cnVjdG9yPWIuVmlkZW9UZXh0dXJlLGIuVmlkZW9UZXh0dXJlLnByb3RvdHlwZS5fb25VcGRhdGU9ZnVuY3Rpb24oKXt0aGlzLmF1dG9VcGRhdGUmJih3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKHRoaXMudXBkYXRlQm91bmQpLHRoaXMuZGlydHkoKSl9LGIuVmlkZW9UZXh0dXJlLnByb3RvdHlwZS5vblBsYXlTdGFydD1mdW5jdGlvbigpe3RoaXMuYXV0b1VwZGF0ZXx8KHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUodGhpcy51cGRhdGVCb3VuZCksdGhpcy5hdXRvVXBkYXRlPSEwKX0sYi5WaWRlb1RleHR1cmUucHJvdG90eXBlLm9uUGxheVN0b3A9ZnVuY3Rpb24oKXt0aGlzLmF1dG9VcGRhdGU9ITF9LGIuVmlkZW9UZXh0dXJlLnByb3RvdHlwZS5vbkNhblBsYXk9ZnVuY3Rpb24oKXtcImNhbnBsYXl0aHJvdWdoXCI9PT1ldmVudC50eXBlJiYodGhpcy5oYXNMb2FkZWQ9ITAsdGhpcy5zb3VyY2UmJih0aGlzLnNvdXJjZS5yZW1vdmVFdmVudExpc3RlbmVyKFwiY2FucGxheVwiLHRoaXMuX29uQ2FuUGxheSksdGhpcy5zb3VyY2UucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImNhbnBsYXl0aHJvdWdoXCIsdGhpcy5fb25DYW5QbGF5KSx0aGlzLndpZHRoPXRoaXMuc291cmNlLnZpZGVvV2lkdGgsdGhpcy5oZWlnaHQ9dGhpcy5zb3VyY2UudmlkZW9IZWlnaHQsdGhpcy5fX2xvYWRlZHx8KHRoaXMuX19sb2FkZWQ9ITAsdGhpcy5kaXNwYXRjaEV2ZW50KHt0eXBlOlwibG9hZGVkXCIsY29udGVudDp0aGlzfSkpKSl9LGIuVmlkZW9UZXh0dXJlLnByb3RvdHlwZS5kZXN0cm95PWZ1bmN0aW9uKCl7dGhpcy5zb3VyY2UmJnRoaXMuc291cmNlLl9waXhpSWQmJihiLkJhc2VUZXh0dXJlQ2FjaGVbdGhpcy5zb3VyY2UuX3BpeGlJZF09bnVsbCxkZWxldGUgYi5CYXNlVGV4dHVyZUNhY2hlW3RoaXMuc291cmNlLl9waXhpSWRdLHRoaXMuc291cmNlLl9waXhpSWQ9bnVsbCxkZWxldGUgdGhpcy5zb3VyY2UuX3BpeGlJZCksYi5CYXNlVGV4dHVyZS5wcm90b3R5cGUuZGVzdHJveS5jYWxsKHRoaXMpfSxiLlZpZGVvVGV4dHVyZS5iYXNlVGV4dHVyZUZyb21WaWRlbz1mdW5jdGlvbihhLGMpe2EuX3BpeGlJZHx8KGEuX3BpeGlJZD1cInZpZGVvX1wiK2IuVGV4dHVyZUNhY2hlSWRHZW5lcmF0b3IrKyk7dmFyIGQ9Yi5CYXNlVGV4dHVyZUNhY2hlW2EuX3BpeGlJZF07cmV0dXJuIGR8fChkPW5ldyBiLlZpZGVvVGV4dHVyZShhLGMpLGIuQmFzZVRleHR1cmVDYWNoZVthLl9waXhpSWRdPWQpLGR9LGIuVmlkZW9UZXh0dXJlLnRleHR1cmVGcm9tVmlkZW89ZnVuY3Rpb24oYSxjKXt2YXIgZD1iLlZpZGVvVGV4dHVyZS5iYXNlVGV4dHVyZUZyb21WaWRlbyhhLGMpO3JldHVybiBuZXcgYi5UZXh0dXJlKGQpfSxiLlZpZGVvVGV4dHVyZS5mcm9tVXJsPWZ1bmN0aW9uKGEsYyl7dmFyIGQ9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInZpZGVvXCIpO3JldHVybiBkLnNyYz1hLGQuYXV0b1BsYXk9ITAsZC5wbGF5KCksYi5WaWRlb1RleHR1cmUudGV4dHVyZUZyb21WaWRlbyhkLGMpfSxiLkFzc2V0TG9hZGVyPWZ1bmN0aW9uKGEsYyl7dGhpcy5hc3NldFVSTHM9YSx0aGlzLmNyb3Nzb3JpZ2luPWMsdGhpcy5sb2FkZXJzQnlUeXBlPXtqcGc6Yi5JbWFnZUxvYWRlcixqcGVnOmIuSW1hZ2VMb2FkZXIscG5nOmIuSW1hZ2VMb2FkZXIsZ2lmOmIuSW1hZ2VMb2FkZXIsd2VicDpiLkltYWdlTG9hZGVyLGpzb246Yi5Kc29uTG9hZGVyLGF0bGFzOmIuQXRsYXNMb2FkZXIsYW5pbTpiLlNwaW5lTG9hZGVyLHhtbDpiLkJpdG1hcEZvbnRMb2FkZXIsZm50OmIuQml0bWFwRm9udExvYWRlcn19LGIuRXZlbnRUYXJnZXQubWl4aW4oYi5Bc3NldExvYWRlci5wcm90b3R5cGUpLGIuQXNzZXRMb2FkZXIucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuQXNzZXRMb2FkZXIsYi5Bc3NldExvYWRlci5wcm90b3R5cGUuX2dldERhdGFUeXBlPWZ1bmN0aW9uKGEpe3ZhciBiPVwiZGF0YTpcIixjPWEuc2xpY2UoMCxiLmxlbmd0aCkudG9Mb3dlckNhc2UoKTtpZihjPT09Yil7dmFyIGQ9YS5zbGljZShiLmxlbmd0aCksZT1kLmluZGV4T2YoXCIsXCIpO2lmKC0xPT09ZSlyZXR1cm4gbnVsbDt2YXIgZj1kLnNsaWNlKDAsZSkuc3BsaXQoXCI7XCIpWzBdO3JldHVybiBmJiZcInRleHQvcGxhaW5cIiE9PWYudG9Mb3dlckNhc2UoKT9mLnNwbGl0KFwiL1wiKS5wb3AoKS50b0xvd2VyQ2FzZSgpOlwidHh0XCJ9cmV0dXJuIG51bGx9LGIuQXNzZXRMb2FkZXIucHJvdG90eXBlLmxvYWQ9ZnVuY3Rpb24oKXtmdW5jdGlvbiBhKGEpe2Iub25Bc3NldExvYWRlZChhLmRhdGEuY29udGVudCl9dmFyIGI9dGhpczt0aGlzLmxvYWRDb3VudD10aGlzLmFzc2V0VVJMcy5sZW5ndGg7Zm9yKHZhciBjPTA7Yzx0aGlzLmFzc2V0VVJMcy5sZW5ndGg7YysrKXt2YXIgZD10aGlzLmFzc2V0VVJMc1tjXSxlPXRoaXMuX2dldERhdGFUeXBlKGQpO2V8fChlPWQuc3BsaXQoXCI/XCIpLnNoaWZ0KCkuc3BsaXQoXCIuXCIpLnBvcCgpLnRvTG93ZXJDYXNlKCkpO3ZhciBmPXRoaXMubG9hZGVyc0J5VHlwZVtlXTtpZighZil0aHJvdyBuZXcgRXJyb3IoZStcIiBpcyBhbiB1bnN1cHBvcnRlZCBmaWxlIHR5cGVcIik7dmFyIGc9bmV3IGYoZCx0aGlzLmNyb3Nzb3JpZ2luKTtnLm9uKFwibG9hZGVkXCIsYSksZy5sb2FkKCl9fSxiLkFzc2V0TG9hZGVyLnByb3RvdHlwZS5vbkFzc2V0TG9hZGVkPWZ1bmN0aW9uKGEpe3RoaXMubG9hZENvdW50LS0sdGhpcy5lbWl0KFwib25Qcm9ncmVzc1wiLHtjb250ZW50OnRoaXMsbG9hZGVyOmF9KSx0aGlzLm9uUHJvZ3Jlc3MmJnRoaXMub25Qcm9ncmVzcyhhKSx0aGlzLmxvYWRDb3VudHx8KHRoaXMuZW1pdChcIm9uQ29tcGxldGVcIix7Y29udGVudDp0aGlzfSksdGhpcy5vbkNvbXBsZXRlJiZ0aGlzLm9uQ29tcGxldGUoKSl9LGIuSnNvbkxvYWRlcj1mdW5jdGlvbihhLGIpe3RoaXMudXJsPWEsdGhpcy5jcm9zc29yaWdpbj1iLHRoaXMuYmFzZVVybD1hLnJlcGxhY2UoL1teXFwvXSokLyxcIlwiKSx0aGlzLmxvYWRlZD0hMX0sYi5Kc29uTG9hZGVyLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLkpzb25Mb2FkZXIsYi5FdmVudFRhcmdldC5taXhpbihiLkpzb25Mb2FkZXIucHJvdG90eXBlKSxiLkpzb25Mb2FkZXIucHJvdG90eXBlLmxvYWQ9ZnVuY3Rpb24oKXt3aW5kb3cuWERvbWFpblJlcXVlc3QmJnRoaXMuY3Jvc3NvcmlnaW4/KHRoaXMuYWpheFJlcXVlc3Q9bmV3IHdpbmRvdy5YRG9tYWluUmVxdWVzdCx0aGlzLmFqYXhSZXF1ZXN0LnRpbWVvdXQ9M2UzLHRoaXMuYWpheFJlcXVlc3Qub25lcnJvcj10aGlzLm9uRXJyb3IuYmluZCh0aGlzKSx0aGlzLmFqYXhSZXF1ZXN0Lm9udGltZW91dD10aGlzLm9uRXJyb3IuYmluZCh0aGlzKSx0aGlzLmFqYXhSZXF1ZXN0Lm9ucHJvZ3Jlc3M9ZnVuY3Rpb24oKXt9LHRoaXMuYWpheFJlcXVlc3Qub25sb2FkPXRoaXMub25KU09OTG9hZGVkLmJpbmQodGhpcykpOih0aGlzLmFqYXhSZXF1ZXN0PXdpbmRvdy5YTUxIdHRwUmVxdWVzdD9uZXcgd2luZG93LlhNTEh0dHBSZXF1ZXN0Om5ldyB3aW5kb3cuQWN0aXZlWE9iamVjdChcIk1pY3Jvc29mdC5YTUxIVFRQXCIpLHRoaXMuYWpheFJlcXVlc3Qub25yZWFkeXN0YXRlY2hhbmdlPXRoaXMub25SZWFkeVN0YXRlQ2hhbmdlZC5iaW5kKHRoaXMpKSx0aGlzLmFqYXhSZXF1ZXN0Lm9wZW4oXCJHRVRcIix0aGlzLnVybCwhMCksdGhpcy5hamF4UmVxdWVzdC5zZW5kKCl9LGIuSnNvbkxvYWRlci5wcm90b3R5cGUub25SZWFkeVN0YXRlQ2hhbmdlZD1mdW5jdGlvbigpezQhPT10aGlzLmFqYXhSZXF1ZXN0LnJlYWR5U3RhdGV8fDIwMCE9PXRoaXMuYWpheFJlcXVlc3Quc3RhdHVzJiYtMSE9PXdpbmRvdy5sb2NhdGlvbi5ocmVmLmluZGV4T2YoXCJodHRwXCIpfHx0aGlzLm9uSlNPTkxvYWRlZCgpfSxiLkpzb25Mb2FkZXIucHJvdG90eXBlLm9uSlNPTkxvYWRlZD1mdW5jdGlvbigpe2lmKCF0aGlzLmFqYXhSZXF1ZXN0LnJlc3BvbnNlVGV4dClyZXR1cm4gdm9pZCB0aGlzLm9uRXJyb3IoKTtpZih0aGlzLmpzb249SlNPTi5wYXJzZSh0aGlzLmFqYXhSZXF1ZXN0LnJlc3BvbnNlVGV4dCksdGhpcy5qc29uLmZyYW1lcyYmdGhpcy5qc29uLm1ldGEmJnRoaXMuanNvbi5tZXRhLmltYWdlKXt2YXIgYT10aGlzLmJhc2VVcmwrdGhpcy5qc29uLm1ldGEuaW1hZ2UsZD1uZXcgYi5JbWFnZUxvYWRlcihhLHRoaXMuY3Jvc3NvcmlnaW4pLGU9dGhpcy5qc29uLmZyYW1lczt0aGlzLnRleHR1cmU9ZC50ZXh0dXJlLmJhc2VUZXh0dXJlLGQuYWRkRXZlbnRMaXN0ZW5lcihcImxvYWRlZFwiLHRoaXMub25Mb2FkZWQuYmluZCh0aGlzKSk7Zm9yKHZhciBmIGluIGUpe3ZhciBnPWVbZl0uZnJhbWU7aWYoZyl7dmFyIGg9bmV3IGIuUmVjdGFuZ2xlKGcueCxnLnksZy53LGcuaCksaT1oLmNsb25lKCksaj1udWxsO2lmKGVbZl0udHJpbW1lZCl7dmFyIGs9ZVtmXS5zb3VyY2VTaXplLGw9ZVtmXS5zcHJpdGVTb3VyY2VTaXplO2o9bmV3IGIuUmVjdGFuZ2xlKGwueCxsLnksay53LGsuaCl9Yi5UZXh0dXJlQ2FjaGVbZl09bmV3IGIuVGV4dHVyZSh0aGlzLnRleHR1cmUsaCxpLGopfX1kLmxvYWQoKX1lbHNlIGlmKHRoaXMuanNvbi5ib25lcylpZihiLkFuaW1DYWNoZVt0aGlzLnVybF0pdGhpcy5vbkxvYWRlZCgpO2Vsc2V7dmFyIG09dGhpcy51cmwuc3Vic3RyKDAsdGhpcy51cmwubGFzdEluZGV4T2YoXCIuXCIpKStcIi5hdGxhc1wiLG49bmV3IGIuSnNvbkxvYWRlcihtLHRoaXMuY3Jvc3NvcmlnaW4pLG89dGhpcztuLm9uSlNPTkxvYWRlZD1mdW5jdGlvbigpe2lmKCF0aGlzLmFqYXhSZXF1ZXN0LnJlc3BvbnNlVGV4dClyZXR1cm4gdm9pZCB0aGlzLm9uRXJyb3IoKTt2YXIgYT1uZXcgYi5TcGluZVRleHR1cmVMb2FkZXIodGhpcy51cmwuc3Vic3RyaW5nKDAsdGhpcy51cmwubGFzdEluZGV4T2YoXCIvXCIpKSksZD1uZXcgYy5BdGxhcyh0aGlzLmFqYXhSZXF1ZXN0LnJlc3BvbnNlVGV4dCxhKSxlPW5ldyBjLkF0bGFzQXR0YWNobWVudExvYWRlcihkKSxmPW5ldyBjLlNrZWxldG9uSnNvbihlKSxnPWYucmVhZFNrZWxldG9uRGF0YShvLmpzb24pO2IuQW5pbUNhY2hlW28udXJsXT1nLG8uc3BpbmU9ZyxvLnNwaW5lQXRsYXM9ZCxvLnNwaW5lQXRsYXNMb2FkZXI9bixhLmxvYWRpbmdDb3VudD4wP2EuYWRkRXZlbnRMaXN0ZW5lcihcImxvYWRlZEJhc2VUZXh0dXJlXCIsZnVuY3Rpb24oYSl7YS5jb250ZW50LmNvbnRlbnQubG9hZGluZ0NvdW50PD0wJiZvLm9uTG9hZGVkKCl9KTpvLm9uTG9hZGVkKCl9LG4ubG9hZCgpfWVsc2UgdGhpcy5vbkxvYWRlZCgpfSxiLkpzb25Mb2FkZXIucHJvdG90eXBlLm9uTG9hZGVkPWZ1bmN0aW9uKCl7dGhpcy5sb2FkZWQ9ITAsdGhpcy5kaXNwYXRjaEV2ZW50KHt0eXBlOlwibG9hZGVkXCIsY29udGVudDp0aGlzfSl9LGIuSnNvbkxvYWRlci5wcm90b3R5cGUub25FcnJvcj1mdW5jdGlvbigpe3RoaXMuZGlzcGF0Y2hFdmVudCh7dHlwZTpcImVycm9yXCIsY29udGVudDp0aGlzfSl9LGIuQXRsYXNMb2FkZXI9ZnVuY3Rpb24oYSxiKXt0aGlzLnVybD1hLHRoaXMuYmFzZVVybD1hLnJlcGxhY2UoL1teXFwvXSokLyxcIlwiKSx0aGlzLmNyb3Nzb3JpZ2luPWIsdGhpcy5sb2FkZWQ9ITF9LGIuQXRsYXNMb2FkZXIuY29uc3RydWN0b3I9Yi5BdGxhc0xvYWRlcixiLkV2ZW50VGFyZ2V0Lm1peGluKGIuQXRsYXNMb2FkZXIucHJvdG90eXBlKSxiLkF0bGFzTG9hZGVyLnByb3RvdHlwZS5sb2FkPWZ1bmN0aW9uKCl7dGhpcy5hamF4UmVxdWVzdD1uZXcgYi5BamF4UmVxdWVzdCx0aGlzLmFqYXhSZXF1ZXN0Lm9ucmVhZHlzdGF0ZWNoYW5nZT10aGlzLm9uQXRsYXNMb2FkZWQuYmluZCh0aGlzKSx0aGlzLmFqYXhSZXF1ZXN0Lm9wZW4oXCJHRVRcIix0aGlzLnVybCwhMCksdGhpcy5hamF4UmVxdWVzdC5vdmVycmlkZU1pbWVUeXBlJiZ0aGlzLmFqYXhSZXF1ZXN0Lm92ZXJyaWRlTWltZVR5cGUoXCJhcHBsaWNhdGlvbi9qc29uXCIpLHRoaXMuYWpheFJlcXVlc3Quc2VuZChudWxsKX0sYi5BdGxhc0xvYWRlci5wcm90b3R5cGUub25BdGxhc0xvYWRlZD1mdW5jdGlvbigpe2lmKDQ9PT10aGlzLmFqYXhSZXF1ZXN0LnJlYWR5U3RhdGUpaWYoMjAwPT09dGhpcy5hamF4UmVxdWVzdC5zdGF0dXN8fC0xPT09d2luZG93LmxvY2F0aW9uLmhyZWYuaW5kZXhPZihcImh0dHBcIikpe3RoaXMuYXRsYXM9e21ldGE6e2ltYWdlOltdfSxmcmFtZXM6W119O3ZhciBhPXRoaXMuYWpheFJlcXVlc3QucmVzcG9uc2VUZXh0LnNwbGl0KC9cXHI/XFxuLyksYz0tMyxkPTAsZT1udWxsLGY9ITEsZz0wLGg9MCxpPXRoaXMub25Mb2FkZWQuYmluZCh0aGlzKTtmb3IoZz0wO2c8YS5sZW5ndGg7ZysrKWlmKGFbZ109YVtnXS5yZXBsYWNlKC9eXFxzK3xcXHMrJC9nLFwiXCIpLFwiXCI9PT1hW2ddJiYoZj1nKzEpLGFbZ10ubGVuZ3RoPjApe2lmKGY9PT1nKXRoaXMuYXRsYXMubWV0YS5pbWFnZS5wdXNoKGFbZ10pLGQ9dGhpcy5hdGxhcy5tZXRhLmltYWdlLmxlbmd0aC0xLHRoaXMuYXRsYXMuZnJhbWVzLnB1c2goe30pLGM9LTM7ZWxzZSBpZihjPjApaWYoYyU3PT09MSludWxsIT1lJiYodGhpcy5hdGxhcy5mcmFtZXNbZF1bZS5uYW1lXT1lKSxlPXtuYW1lOmFbZ10sZnJhbWU6e319O2Vsc2V7dmFyIGo9YVtnXS5zcGxpdChcIiBcIik7aWYoYyU3PT09MyllLmZyYW1lLng9TnVtYmVyKGpbMV0ucmVwbGFjZShcIixcIixcIlwiKSksZS5mcmFtZS55PU51bWJlcihqWzJdKTtcbmVsc2UgaWYoYyU3PT09NCllLmZyYW1lLnc9TnVtYmVyKGpbMV0ucmVwbGFjZShcIixcIixcIlwiKSksZS5mcmFtZS5oPU51bWJlcihqWzJdKTtlbHNlIGlmKGMlNz09PTUpe3ZhciBrPXt4OjAseTowLHc6TnVtYmVyKGpbMV0ucmVwbGFjZShcIixcIixcIlwiKSksaDpOdW1iZXIoalsyXSl9O2sudz5lLmZyYW1lLnd8fGsuaD5lLmZyYW1lLmg/KGUudHJpbW1lZD0hMCxlLnJlYWxTaXplPWspOmUudHJpbW1lZD0hMX19YysrfWlmKG51bGwhPWUmJih0aGlzLmF0bGFzLmZyYW1lc1tkXVtlLm5hbWVdPWUpLHRoaXMuYXRsYXMubWV0YS5pbWFnZS5sZW5ndGg+MCl7Zm9yKHRoaXMuaW1hZ2VzPVtdLGg9MDtoPHRoaXMuYXRsYXMubWV0YS5pbWFnZS5sZW5ndGg7aCsrKXt2YXIgbD10aGlzLmJhc2VVcmwrdGhpcy5hdGxhcy5tZXRhLmltYWdlW2hdLG09dGhpcy5hdGxhcy5mcmFtZXNbaF07dGhpcy5pbWFnZXMucHVzaChuZXcgYi5JbWFnZUxvYWRlcihsLHRoaXMuY3Jvc3NvcmlnaW4pKTtmb3IoZyBpbiBtKXt2YXIgbj1tW2ddLmZyYW1lO24mJihiLlRleHR1cmVDYWNoZVtnXT1uZXcgYi5UZXh0dXJlKHRoaXMuaW1hZ2VzW2hdLnRleHR1cmUuYmFzZVRleHR1cmUse3g6bi54LHk6bi55LHdpZHRoOm4udyxoZWlnaHQ6bi5ofSksbVtnXS50cmltbWVkJiYoYi5UZXh0dXJlQ2FjaGVbZ10ucmVhbFNpemU9bVtnXS5yZWFsU2l6ZSxiLlRleHR1cmVDYWNoZVtnXS50cmltLng9MCxiLlRleHR1cmVDYWNoZVtnXS50cmltLnk9MCkpfX1mb3IodGhpcy5jdXJyZW50SW1hZ2VJZD0wLGg9MDtoPHRoaXMuaW1hZ2VzLmxlbmd0aDtoKyspdGhpcy5pbWFnZXNbaF0ub24oXCJsb2FkZWRcIixpKTt0aGlzLmltYWdlc1t0aGlzLmN1cnJlbnRJbWFnZUlkXS5sb2FkKCl9ZWxzZSB0aGlzLm9uTG9hZGVkKCl9ZWxzZSB0aGlzLm9uRXJyb3IoKX0sYi5BdGxhc0xvYWRlci5wcm90b3R5cGUub25Mb2FkZWQ9ZnVuY3Rpb24oKXt0aGlzLmltYWdlcy5sZW5ndGgtMT50aGlzLmN1cnJlbnRJbWFnZUlkPyh0aGlzLmN1cnJlbnRJbWFnZUlkKyssdGhpcy5pbWFnZXNbdGhpcy5jdXJyZW50SW1hZ2VJZF0ubG9hZCgpKToodGhpcy5sb2FkZWQ9ITAsdGhpcy5lbWl0KFwibG9hZGVkXCIse2NvbnRlbnQ6dGhpc30pKX0sYi5BdGxhc0xvYWRlci5wcm90b3R5cGUub25FcnJvcj1mdW5jdGlvbigpe3RoaXMuZW1pdChcImVycm9yXCIse2NvbnRlbnQ6dGhpc30pfSxiLlNwcml0ZVNoZWV0TG9hZGVyPWZ1bmN0aW9uKGEsYil7dGhpcy51cmw9YSx0aGlzLmNyb3Nzb3JpZ2luPWIsdGhpcy5iYXNlVXJsPWEucmVwbGFjZSgvW15cXC9dKiQvLFwiXCIpLHRoaXMudGV4dHVyZT1udWxsLHRoaXMuZnJhbWVzPXt9fSxiLlNwcml0ZVNoZWV0TG9hZGVyLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLlNwcml0ZVNoZWV0TG9hZGVyLGIuRXZlbnRUYXJnZXQubWl4aW4oYi5TcHJpdGVTaGVldExvYWRlci5wcm90b3R5cGUpLGIuU3ByaXRlU2hlZXRMb2FkZXIucHJvdG90eXBlLmxvYWQ9ZnVuY3Rpb24oKXt2YXIgYT10aGlzLGM9bmV3IGIuSnNvbkxvYWRlcih0aGlzLnVybCx0aGlzLmNyb3Nzb3JpZ2luKTtjLm9uKFwibG9hZGVkXCIsZnVuY3Rpb24oYil7YS5qc29uPWIuZGF0YS5jb250ZW50Lmpzb24sYS5vbkxvYWRlZCgpfSksYy5sb2FkKCl9LGIuU3ByaXRlU2hlZXRMb2FkZXIucHJvdG90eXBlLm9uTG9hZGVkPWZ1bmN0aW9uKCl7dGhpcy5lbWl0KFwibG9hZGVkXCIse2NvbnRlbnQ6dGhpc30pfSxiLkltYWdlTG9hZGVyPWZ1bmN0aW9uKGEsYyl7dGhpcy50ZXh0dXJlPWIuVGV4dHVyZS5mcm9tSW1hZ2UoYSxjKSx0aGlzLmZyYW1lcz1bXX0sYi5JbWFnZUxvYWRlci5wcm90b3R5cGUuY29uc3RydWN0b3I9Yi5JbWFnZUxvYWRlcixiLkV2ZW50VGFyZ2V0Lm1peGluKGIuSW1hZ2VMb2FkZXIucHJvdG90eXBlKSxiLkltYWdlTG9hZGVyLnByb3RvdHlwZS5sb2FkPWZ1bmN0aW9uKCl7dGhpcy50ZXh0dXJlLmJhc2VUZXh0dXJlLmhhc0xvYWRlZD90aGlzLm9uTG9hZGVkKCk6dGhpcy50ZXh0dXJlLmJhc2VUZXh0dXJlLm9uKFwibG9hZGVkXCIsdGhpcy5vbkxvYWRlZC5iaW5kKHRoaXMpKX0sYi5JbWFnZUxvYWRlci5wcm90b3R5cGUub25Mb2FkZWQ9ZnVuY3Rpb24oKXt0aGlzLmVtaXQoXCJsb2FkZWRcIix7Y29udGVudDp0aGlzfSl9LGIuSW1hZ2VMb2FkZXIucHJvdG90eXBlLmxvYWRGcmFtZWRTcHJpdGVTaGVldD1mdW5jdGlvbihhLGMsZCl7dGhpcy5mcmFtZXM9W107Zm9yKHZhciBlPU1hdGguZmxvb3IodGhpcy50ZXh0dXJlLndpZHRoL2EpLGY9TWF0aC5mbG9vcih0aGlzLnRleHR1cmUuaGVpZ2h0L2MpLGc9MCxoPTA7Zj5oO2grKylmb3IodmFyIGk9MDtlPmk7aSsrLGcrKyl7dmFyIGo9bmV3IGIuVGV4dHVyZSh0aGlzLnRleHR1cmUuYmFzZVRleHR1cmUse3g6aSphLHk6aCpjLHdpZHRoOmEsaGVpZ2h0OmN9KTt0aGlzLmZyYW1lcy5wdXNoKGopLGQmJihiLlRleHR1cmVDYWNoZVtkK1wiLVwiK2ddPWopfXRoaXMubG9hZCgpfSxiLkJpdG1hcEZvbnRMb2FkZXI9ZnVuY3Rpb24oYSxiKXt0aGlzLnVybD1hLHRoaXMuY3Jvc3NvcmlnaW49Yix0aGlzLmJhc2VVcmw9YS5yZXBsYWNlKC9bXlxcL10qJC8sXCJcIiksdGhpcy50ZXh0dXJlPW51bGx9LGIuQml0bWFwRm9udExvYWRlci5wcm90b3R5cGUuY29uc3RydWN0b3I9Yi5CaXRtYXBGb250TG9hZGVyLGIuRXZlbnRUYXJnZXQubWl4aW4oYi5CaXRtYXBGb250TG9hZGVyLnByb3RvdHlwZSksYi5CaXRtYXBGb250TG9hZGVyLnByb3RvdHlwZS5sb2FkPWZ1bmN0aW9uKCl7dGhpcy5hamF4UmVxdWVzdD1uZXcgYi5BamF4UmVxdWVzdCx0aGlzLmFqYXhSZXF1ZXN0Lm9ucmVhZHlzdGF0ZWNoYW5nZT10aGlzLm9uWE1MTG9hZGVkLmJpbmQodGhpcyksdGhpcy5hamF4UmVxdWVzdC5vcGVuKFwiR0VUXCIsdGhpcy51cmwsITApLHRoaXMuYWpheFJlcXVlc3Qub3ZlcnJpZGVNaW1lVHlwZSYmdGhpcy5hamF4UmVxdWVzdC5vdmVycmlkZU1pbWVUeXBlKFwiYXBwbGljYXRpb24veG1sXCIpLHRoaXMuYWpheFJlcXVlc3Quc2VuZChudWxsKX0sYi5CaXRtYXBGb250TG9hZGVyLnByb3RvdHlwZS5vblhNTExvYWRlZD1mdW5jdGlvbigpe2lmKDQ9PT10aGlzLmFqYXhSZXF1ZXN0LnJlYWR5U3RhdGUmJigyMDA9PT10aGlzLmFqYXhSZXF1ZXN0LnN0YXR1c3x8LTE9PT13aW5kb3cubG9jYXRpb24ucHJvdG9jb2wuaW5kZXhPZihcImh0dHBcIikpKXt2YXIgYT10aGlzLmFqYXhSZXF1ZXN0LnJlc3BvbnNlWE1MO2lmKCFhfHwvTVNJRSA5L2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KXx8bmF2aWdhdG9yLmlzQ29jb29uSlMpaWYoXCJmdW5jdGlvblwiPT10eXBlb2Ygd2luZG93LkRPTVBhcnNlcil7dmFyIGM9bmV3IERPTVBhcnNlcjthPWMucGFyc2VGcm9tU3RyaW5nKHRoaXMuYWpheFJlcXVlc3QucmVzcG9uc2VUZXh0LFwidGV4dC94bWxcIil9ZWxzZXt2YXIgZD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO2QuaW5uZXJIVE1MPXRoaXMuYWpheFJlcXVlc3QucmVzcG9uc2VUZXh0LGE9ZH12YXIgZT10aGlzLmJhc2VVcmwrYS5nZXRFbGVtZW50c0J5VGFnTmFtZShcInBhZ2VcIilbMF0uZ2V0QXR0cmlidXRlKFwiZmlsZVwiKSxmPW5ldyBiLkltYWdlTG9hZGVyKGUsdGhpcy5jcm9zc29yaWdpbik7dGhpcy50ZXh0dXJlPWYudGV4dHVyZS5iYXNlVGV4dHVyZTt2YXIgZz17fSxoPWEuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJpbmZvXCIpWzBdLGk9YS5nZXRFbGVtZW50c0J5VGFnTmFtZShcImNvbW1vblwiKVswXTtnLmZvbnQ9aC5nZXRBdHRyaWJ1dGUoXCJmYWNlXCIpLGcuc2l6ZT1wYXJzZUludChoLmdldEF0dHJpYnV0ZShcInNpemVcIiksMTApLGcubGluZUhlaWdodD1wYXJzZUludChpLmdldEF0dHJpYnV0ZShcImxpbmVIZWlnaHRcIiksMTApLGcuY2hhcnM9e307Zm9yKHZhciBqPWEuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJjaGFyXCIpLGs9MDtrPGoubGVuZ3RoO2srKyl7dmFyIGw9cGFyc2VJbnQoaltrXS5nZXRBdHRyaWJ1dGUoXCJpZFwiKSwxMCksbT1uZXcgYi5SZWN0YW5nbGUocGFyc2VJbnQoaltrXS5nZXRBdHRyaWJ1dGUoXCJ4XCIpLDEwKSxwYXJzZUludChqW2tdLmdldEF0dHJpYnV0ZShcInlcIiksMTApLHBhcnNlSW50KGpba10uZ2V0QXR0cmlidXRlKFwid2lkdGhcIiksMTApLHBhcnNlSW50KGpba10uZ2V0QXR0cmlidXRlKFwiaGVpZ2h0XCIpLDEwKSk7Zy5jaGFyc1tsXT17eE9mZnNldDpwYXJzZUludChqW2tdLmdldEF0dHJpYnV0ZShcInhvZmZzZXRcIiksMTApLHlPZmZzZXQ6cGFyc2VJbnQoaltrXS5nZXRBdHRyaWJ1dGUoXCJ5b2Zmc2V0XCIpLDEwKSx4QWR2YW5jZTpwYXJzZUludChqW2tdLmdldEF0dHJpYnV0ZShcInhhZHZhbmNlXCIpLDEwKSxrZXJuaW5nOnt9LHRleHR1cmU6Yi5UZXh0dXJlQ2FjaGVbbF09bmV3IGIuVGV4dHVyZSh0aGlzLnRleHR1cmUsbSl9fXZhciBuPWEuZ2V0RWxlbWVudHNCeVRhZ05hbWUoXCJrZXJuaW5nXCIpO2ZvcihrPTA7azxuLmxlbmd0aDtrKyspe3ZhciBvPXBhcnNlSW50KG5ba10uZ2V0QXR0cmlidXRlKFwiZmlyc3RcIiksMTApLHA9cGFyc2VJbnQobltrXS5nZXRBdHRyaWJ1dGUoXCJzZWNvbmRcIiksMTApLHE9cGFyc2VJbnQobltrXS5nZXRBdHRyaWJ1dGUoXCJhbW91bnRcIiksMTApO2cuY2hhcnNbcF0ua2VybmluZ1tvXT1xfWIuQml0bWFwVGV4dC5mb250c1tnLmZvbnRdPWcsZi5hZGRFdmVudExpc3RlbmVyKFwibG9hZGVkXCIsdGhpcy5vbkxvYWRlZC5iaW5kKHRoaXMpKSxmLmxvYWQoKX19LGIuQml0bWFwRm9udExvYWRlci5wcm90b3R5cGUub25Mb2FkZWQ9ZnVuY3Rpb24oKXt0aGlzLmVtaXQoXCJsb2FkZWRcIix7Y29udGVudDp0aGlzfSl9LGIuU3BpbmVMb2FkZXI9ZnVuY3Rpb24oYSxiKXt0aGlzLnVybD1hLHRoaXMuY3Jvc3NvcmlnaW49Yix0aGlzLmxvYWRlZD0hMX0sYi5TcGluZUxvYWRlci5wcm90b3R5cGUuY29uc3RydWN0b3I9Yi5TcGluZUxvYWRlcixiLkV2ZW50VGFyZ2V0Lm1peGluKGIuU3BpbmVMb2FkZXIucHJvdG90eXBlKSxiLlNwaW5lTG9hZGVyLnByb3RvdHlwZS5sb2FkPWZ1bmN0aW9uKCl7dmFyIGE9dGhpcyxjPW5ldyBiLkpzb25Mb2FkZXIodGhpcy51cmwsdGhpcy5jcm9zc29yaWdpbik7Yy5vbihcImxvYWRlZFwiLGZ1bmN0aW9uKGIpe2EuanNvbj1iLmRhdGEuY29udGVudC5qc29uLGEub25Mb2FkZWQoKX0pLGMubG9hZCgpfSxiLlNwaW5lTG9hZGVyLnByb3RvdHlwZS5vbkxvYWRlZD1mdW5jdGlvbigpe3RoaXMubG9hZGVkPSEwLHRoaXMuZW1pdChcImxvYWRlZFwiLHtjb250ZW50OnRoaXN9KX0sYi5BYnN0cmFjdEZpbHRlcj1mdW5jdGlvbihhLGIpe3RoaXMucGFzc2VzPVt0aGlzXSx0aGlzLnNoYWRlcnM9W10sdGhpcy5kaXJ0eT0hMCx0aGlzLnBhZGRpbmc9MCx0aGlzLnVuaWZvcm1zPWJ8fHt9LHRoaXMuZnJhZ21lbnRTcmM9YXx8W119LGIuQWJzdHJhY3RGaWx0ZXIucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuQWJzdHJhY3RGaWx0ZXIsYi5BYnN0cmFjdEZpbHRlci5wcm90b3R5cGUuc3luY1VuaWZvcm1zPWZ1bmN0aW9uKCl7Zm9yKHZhciBhPTAsYj10aGlzLnNoYWRlcnMubGVuZ3RoO2I+YTthKyspdGhpcy5zaGFkZXJzW2FdLmRpcnR5PSEwfSxiLkFscGhhTWFza0ZpbHRlcj1mdW5jdGlvbihhKXtiLkFic3RyYWN0RmlsdGVyLmNhbGwodGhpcyksdGhpcy5wYXNzZXM9W3RoaXNdLGEuYmFzZVRleHR1cmUuX3Bvd2VyT2YyPSEwLHRoaXMudW5pZm9ybXM9e21hc2s6e3R5cGU6XCJzYW1wbGVyMkRcIix2YWx1ZTphfSxtYXBEaW1lbnNpb25zOnt0eXBlOlwiMmZcIix2YWx1ZTp7eDoxLHk6NTExMn19LGRpbWVuc2lvbnM6e3R5cGU6XCI0ZnZcIix2YWx1ZTpbMCwwLDAsMF19fSxhLmJhc2VUZXh0dXJlLmhhc0xvYWRlZD8odGhpcy51bmlmb3Jtcy5tYXNrLnZhbHVlLng9YS53aWR0aCx0aGlzLnVuaWZvcm1zLm1hc2sudmFsdWUueT1hLmhlaWdodCk6KHRoaXMuYm91bmRMb2FkZWRGdW5jdGlvbj10aGlzLm9uVGV4dHVyZUxvYWRlZC5iaW5kKHRoaXMpLGEuYmFzZVRleHR1cmUub24oXCJsb2FkZWRcIix0aGlzLmJvdW5kTG9hZGVkRnVuY3Rpb24pKSx0aGlzLmZyYWdtZW50U3JjPVtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1wiLFwidmFyeWluZyB2ZWMyIHZUZXh0dXJlQ29vcmQ7XCIsXCJ2YXJ5aW5nIHZlYzQgdkNvbG9yO1wiLFwidW5pZm9ybSBzYW1wbGVyMkQgbWFzaztcIixcInVuaWZvcm0gc2FtcGxlcjJEIHVTYW1wbGVyO1wiLFwidW5pZm9ybSB2ZWMyIG9mZnNldDtcIixcInVuaWZvcm0gdmVjNCBkaW1lbnNpb25zO1wiLFwidW5pZm9ybSB2ZWMyIG1hcERpbWVuc2lvbnM7XCIsXCJ2b2lkIG1haW4odm9pZCkge1wiLFwiICAgdmVjMiBtYXBDb3JkcyA9IHZUZXh0dXJlQ29vcmQueHk7XCIsXCIgICBtYXBDb3JkcyArPSAoZGltZW5zaW9ucy56dyArIG9mZnNldCkvIGRpbWVuc2lvbnMueHkgO1wiLFwiICAgbWFwQ29yZHMueSAqPSAtMS4wO1wiLFwiICAgbWFwQ29yZHMueSArPSAxLjA7XCIsXCIgICBtYXBDb3JkcyAqPSBkaW1lbnNpb25zLnh5IC8gbWFwRGltZW5zaW9ucztcIixcIiAgIHZlYzQgb3JpZ2luYWwgPSAgdGV4dHVyZTJEKHVTYW1wbGVyLCB2VGV4dHVyZUNvb3JkKTtcIixcIiAgIGZsb2F0IG1hc2tBbHBoYSA9ICB0ZXh0dXJlMkQobWFzaywgbWFwQ29yZHMpLnI7XCIsXCIgICBvcmlnaW5hbCAqPSBtYXNrQWxwaGE7XCIsXCIgICBnbF9GcmFnQ29sb3IgPSAgb3JpZ2luYWw7XCIsXCJ9XCJdfSxiLkFscGhhTWFza0ZpbHRlci5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShiLkFic3RyYWN0RmlsdGVyLnByb3RvdHlwZSksYi5BbHBoYU1hc2tGaWx0ZXIucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuQWxwaGFNYXNrRmlsdGVyLGIuQWxwaGFNYXNrRmlsdGVyLnByb3RvdHlwZS5vblRleHR1cmVMb2FkZWQ9ZnVuY3Rpb24oKXt0aGlzLnVuaWZvcm1zLm1hcERpbWVuc2lvbnMudmFsdWUueD10aGlzLnVuaWZvcm1zLm1hc2sudmFsdWUud2lkdGgsdGhpcy51bmlmb3Jtcy5tYXBEaW1lbnNpb25zLnZhbHVlLnk9dGhpcy51bmlmb3Jtcy5tYXNrLnZhbHVlLmhlaWdodCx0aGlzLnVuaWZvcm1zLm1hc2sudmFsdWUuYmFzZVRleHR1cmUub2ZmKFwibG9hZGVkXCIsdGhpcy5ib3VuZExvYWRlZEZ1bmN0aW9uKX0sT2JqZWN0LmRlZmluZVByb3BlcnR5KGIuQWxwaGFNYXNrRmlsdGVyLnByb3RvdHlwZSxcIm1hcFwiLHtnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy51bmlmb3Jtcy5tYXNrLnZhbHVlfSxzZXQ6ZnVuY3Rpb24oYSl7dGhpcy51bmlmb3Jtcy5tYXNrLnZhbHVlPWF9fSksYi5Db2xvck1hdHJpeEZpbHRlcj1mdW5jdGlvbigpe2IuQWJzdHJhY3RGaWx0ZXIuY2FsbCh0aGlzKSx0aGlzLnBhc3Nlcz1bdGhpc10sdGhpcy51bmlmb3Jtcz17bWF0cml4Ont0eXBlOlwibWF0NFwiLHZhbHVlOlsxLDAsMCwwLDAsMSwwLDAsMCwwLDEsMCwwLDAsMCwxXX19LHRoaXMuZnJhZ21lbnRTcmM9W1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XCIsXCJ2YXJ5aW5nIHZlYzIgdlRleHR1cmVDb29yZDtcIixcInZhcnlpbmcgdmVjNCB2Q29sb3I7XCIsXCJ1bmlmb3JtIGZsb2F0IGludmVydDtcIixcInVuaWZvcm0gbWF0NCBtYXRyaXg7XCIsXCJ1bmlmb3JtIHNhbXBsZXIyRCB1U2FtcGxlcjtcIixcInZvaWQgbWFpbih2b2lkKSB7XCIsXCIgICBnbF9GcmFnQ29sb3IgPSB0ZXh0dXJlMkQodVNhbXBsZXIsIHZUZXh0dXJlQ29vcmQpICogbWF0cml4O1wiLFwifVwiXX0sYi5Db2xvck1hdHJpeEZpbHRlci5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShiLkFic3RyYWN0RmlsdGVyLnByb3RvdHlwZSksYi5Db2xvck1hdHJpeEZpbHRlci5wcm90b3R5cGUuY29uc3RydWN0b3I9Yi5Db2xvck1hdHJpeEZpbHRlcixPYmplY3QuZGVmaW5lUHJvcGVydHkoYi5Db2xvck1hdHJpeEZpbHRlci5wcm90b3R5cGUsXCJtYXRyaXhcIix7Z2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudW5pZm9ybXMubWF0cml4LnZhbHVlfSxzZXQ6ZnVuY3Rpb24oYSl7dGhpcy51bmlmb3Jtcy5tYXRyaXgudmFsdWU9YX19KSxiLkdyYXlGaWx0ZXI9ZnVuY3Rpb24oKXtiLkFic3RyYWN0RmlsdGVyLmNhbGwodGhpcyksdGhpcy5wYXNzZXM9W3RoaXNdLHRoaXMudW5pZm9ybXM9e2dyYXk6e3R5cGU6XCIxZlwiLHZhbHVlOjF9fSx0aGlzLmZyYWdtZW50U3JjPVtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1wiLFwidmFyeWluZyB2ZWMyIHZUZXh0dXJlQ29vcmQ7XCIsXCJ2YXJ5aW5nIHZlYzQgdkNvbG9yO1wiLFwidW5pZm9ybSBzYW1wbGVyMkQgdVNhbXBsZXI7XCIsXCJ1bmlmb3JtIGZsb2F0IGdyYXk7XCIsXCJ2b2lkIG1haW4odm9pZCkge1wiLFwiICAgZ2xfRnJhZ0NvbG9yID0gdGV4dHVyZTJEKHVTYW1wbGVyLCB2VGV4dHVyZUNvb3JkKTtcIixcIiAgIGdsX0ZyYWdDb2xvci5yZ2IgPSBtaXgoZ2xfRnJhZ0NvbG9yLnJnYiwgdmVjMygwLjIxMjYqZ2xfRnJhZ0NvbG9yLnIgKyAwLjcxNTIqZ2xfRnJhZ0NvbG9yLmcgKyAwLjA3MjIqZ2xfRnJhZ0NvbG9yLmIpLCBncmF5KTtcIixcIn1cIl19LGIuR3JheUZpbHRlci5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShiLkFic3RyYWN0RmlsdGVyLnByb3RvdHlwZSksYi5HcmF5RmlsdGVyLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLkdyYXlGaWx0ZXIsT2JqZWN0LmRlZmluZVByb3BlcnR5KGIuR3JheUZpbHRlci5wcm90b3R5cGUsXCJncmF5XCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLnVuaWZvcm1zLmdyYXkudmFsdWV9LHNldDpmdW5jdGlvbihhKXt0aGlzLnVuaWZvcm1zLmdyYXkudmFsdWU9YX19KSxiLkRpc3BsYWNlbWVudEZpbHRlcj1mdW5jdGlvbihhKXtiLkFic3RyYWN0RmlsdGVyLmNhbGwodGhpcyksdGhpcy5wYXNzZXM9W3RoaXNdLGEuYmFzZVRleHR1cmUuX3Bvd2VyT2YyPSEwLHRoaXMudW5pZm9ybXM9e2Rpc3BsYWNlbWVudE1hcDp7dHlwZTpcInNhbXBsZXIyRFwiLHZhbHVlOmF9LHNjYWxlOnt0eXBlOlwiMmZcIix2YWx1ZTp7eDozMCx5OjMwfX0sb2Zmc2V0Ont0eXBlOlwiMmZcIix2YWx1ZTp7eDowLHk6MH19LG1hcERpbWVuc2lvbnM6e3R5cGU6XCIyZlwiLHZhbHVlOnt4OjEseTo1MTEyfX0sZGltZW5zaW9uczp7dHlwZTpcIjRmdlwiLHZhbHVlOlswLDAsMCwwXX19LGEuYmFzZVRleHR1cmUuaGFzTG9hZGVkPyh0aGlzLnVuaWZvcm1zLm1hcERpbWVuc2lvbnMudmFsdWUueD1hLndpZHRoLHRoaXMudW5pZm9ybXMubWFwRGltZW5zaW9ucy52YWx1ZS55PWEuaGVpZ2h0KToodGhpcy5ib3VuZExvYWRlZEZ1bmN0aW9uPXRoaXMub25UZXh0dXJlTG9hZGVkLmJpbmQodGhpcyksYS5iYXNlVGV4dHVyZS5vbihcImxvYWRlZFwiLHRoaXMuYm91bmRMb2FkZWRGdW5jdGlvbikpLHRoaXMuZnJhZ21lbnRTcmM9W1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XCIsXCJ2YXJ5aW5nIHZlYzIgdlRleHR1cmVDb29yZDtcIixcInZhcnlpbmcgdmVjNCB2Q29sb3I7XCIsXCJ1bmlmb3JtIHNhbXBsZXIyRCBkaXNwbGFjZW1lbnRNYXA7XCIsXCJ1bmlmb3JtIHNhbXBsZXIyRCB1U2FtcGxlcjtcIixcInVuaWZvcm0gdmVjMiBzY2FsZTtcIixcInVuaWZvcm0gdmVjMiBvZmZzZXQ7XCIsXCJ1bmlmb3JtIHZlYzQgZGltZW5zaW9ucztcIixcInVuaWZvcm0gdmVjMiBtYXBEaW1lbnNpb25zO1wiLFwidm9pZCBtYWluKHZvaWQpIHtcIixcIiAgIHZlYzIgbWFwQ29yZHMgPSB2VGV4dHVyZUNvb3JkLnh5O1wiLFwiICAgbWFwQ29yZHMgKz0gKGRpbWVuc2lvbnMuencgKyBvZmZzZXQpLyBkaW1lbnNpb25zLnh5IDtcIixcIiAgIG1hcENvcmRzLnkgKj0gLTEuMDtcIixcIiAgIG1hcENvcmRzLnkgKz0gMS4wO1wiLFwiICAgdmVjMiBtYXRTYW1wbGUgPSB0ZXh0dXJlMkQoZGlzcGxhY2VtZW50TWFwLCBtYXBDb3JkcykueHk7XCIsXCIgICBtYXRTYW1wbGUgLT0gMC41O1wiLFwiICAgbWF0U2FtcGxlICo9IHNjYWxlO1wiLFwiICAgbWF0U2FtcGxlIC89IG1hcERpbWVuc2lvbnM7XCIsXCIgICBnbF9GcmFnQ29sb3IgPSB0ZXh0dXJlMkQodVNhbXBsZXIsIHZlYzIodlRleHR1cmVDb29yZC54ICsgbWF0U2FtcGxlLngsIHZUZXh0dXJlQ29vcmQueSArIG1hdFNhbXBsZS55KSk7XCIsXCIgICBnbF9GcmFnQ29sb3IucmdiID0gbWl4KCBnbF9GcmFnQ29sb3IucmdiLCBnbF9GcmFnQ29sb3IucmdiLCAxLjApO1wiLFwiICAgdmVjMiBjb3JkID0gdlRleHR1cmVDb29yZDtcIixcIn1cIl19LGIuRGlzcGxhY2VtZW50RmlsdGVyLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGIuQWJzdHJhY3RGaWx0ZXIucHJvdG90eXBlKSxiLkRpc3BsYWNlbWVudEZpbHRlci5wcm90b3R5cGUuY29uc3RydWN0b3I9Yi5EaXNwbGFjZW1lbnRGaWx0ZXIsYi5EaXNwbGFjZW1lbnRGaWx0ZXIucHJvdG90eXBlLm9uVGV4dHVyZUxvYWRlZD1mdW5jdGlvbigpe3RoaXMudW5pZm9ybXMubWFwRGltZW5zaW9ucy52YWx1ZS54PXRoaXMudW5pZm9ybXMuZGlzcGxhY2VtZW50TWFwLnZhbHVlLndpZHRoLHRoaXMudW5pZm9ybXMubWFwRGltZW5zaW9ucy52YWx1ZS55PXRoaXMudW5pZm9ybXMuZGlzcGxhY2VtZW50TWFwLnZhbHVlLmhlaWdodCx0aGlzLnVuaWZvcm1zLmRpc3BsYWNlbWVudE1hcC52YWx1ZS5iYXNlVGV4dHVyZS5vZmYoXCJsb2FkZWRcIix0aGlzLmJvdW5kTG9hZGVkRnVuY3Rpb24pfSxPYmplY3QuZGVmaW5lUHJvcGVydHkoYi5EaXNwbGFjZW1lbnRGaWx0ZXIucHJvdG90eXBlLFwibWFwXCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLnVuaWZvcm1zLmRpc3BsYWNlbWVudE1hcC52YWx1ZX0sc2V0OmZ1bmN0aW9uKGEpe3RoaXMudW5pZm9ybXMuZGlzcGxhY2VtZW50TWFwLnZhbHVlPWF9fSksT2JqZWN0LmRlZmluZVByb3BlcnR5KGIuRGlzcGxhY2VtZW50RmlsdGVyLnByb3RvdHlwZSxcInNjYWxlXCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLnVuaWZvcm1zLnNjYWxlLnZhbHVlfSxzZXQ6ZnVuY3Rpb24oYSl7dGhpcy51bmlmb3Jtcy5zY2FsZS52YWx1ZT1hfX0pLE9iamVjdC5kZWZpbmVQcm9wZXJ0eShiLkRpc3BsYWNlbWVudEZpbHRlci5wcm90b3R5cGUsXCJvZmZzZXRcIix7Z2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudW5pZm9ybXMub2Zmc2V0LnZhbHVlfSxzZXQ6ZnVuY3Rpb24oYSl7dGhpcy51bmlmb3Jtcy5vZmZzZXQudmFsdWU9YX19KSxiLlBpeGVsYXRlRmlsdGVyPWZ1bmN0aW9uKCl7Yi5BYnN0cmFjdEZpbHRlci5jYWxsKHRoaXMpLHRoaXMucGFzc2VzPVt0aGlzXSx0aGlzLnVuaWZvcm1zPXtpbnZlcnQ6e3R5cGU6XCIxZlwiLHZhbHVlOjB9LGRpbWVuc2lvbnM6e3R5cGU6XCI0ZnZcIix2YWx1ZTpuZXcgYi5GbG9hdDMyQXJyYXkoWzFlNCwxMDAsMTAsMTBdKX0scGl4ZWxTaXplOnt0eXBlOlwiMmZcIix2YWx1ZTp7eDoxMCx5OjEwfX19LHRoaXMuZnJhZ21lbnRTcmM9W1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XCIsXCJ2YXJ5aW5nIHZlYzIgdlRleHR1cmVDb29yZDtcIixcInZhcnlpbmcgdmVjNCB2Q29sb3I7XCIsXCJ1bmlmb3JtIHZlYzIgdGVzdERpbTtcIixcInVuaWZvcm0gdmVjNCBkaW1lbnNpb25zO1wiLFwidW5pZm9ybSB2ZWMyIHBpeGVsU2l6ZTtcIixcInVuaWZvcm0gc2FtcGxlcjJEIHVTYW1wbGVyO1wiLFwidm9pZCBtYWluKHZvaWQpIHtcIixcIiAgIHZlYzIgY29vcmQgPSB2VGV4dHVyZUNvb3JkO1wiLFwiICAgdmVjMiBzaXplID0gZGltZW5zaW9ucy54eS9waXhlbFNpemU7XCIsXCIgICB2ZWMyIGNvbG9yID0gZmxvb3IoICggdlRleHR1cmVDb29yZCAqIHNpemUgKSApIC8gc2l6ZSArIHBpeGVsU2l6ZS9kaW1lbnNpb25zLnh5ICogMC41O1wiLFwiICAgZ2xfRnJhZ0NvbG9yID0gdGV4dHVyZTJEKHVTYW1wbGVyLCBjb2xvcik7XCIsXCJ9XCJdfSxiLlBpeGVsYXRlRmlsdGVyLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGIuQWJzdHJhY3RGaWx0ZXIucHJvdG90eXBlKSxiLlBpeGVsYXRlRmlsdGVyLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLlBpeGVsYXRlRmlsdGVyLE9iamVjdC5kZWZpbmVQcm9wZXJ0eShiLlBpeGVsYXRlRmlsdGVyLnByb3RvdHlwZSxcInNpemVcIix7Z2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudW5pZm9ybXMucGl4ZWxTaXplLnZhbHVlfSxzZXQ6ZnVuY3Rpb24oYSl7dGhpcy5kaXJ0eT0hMCx0aGlzLnVuaWZvcm1zLnBpeGVsU2l6ZS52YWx1ZT1hfX0pLGIuQmx1clhGaWx0ZXI9ZnVuY3Rpb24oKXtiLkFic3RyYWN0RmlsdGVyLmNhbGwodGhpcyksdGhpcy5wYXNzZXM9W3RoaXNdLHRoaXMudW5pZm9ybXM9e2JsdXI6e3R5cGU6XCIxZlwiLHZhbHVlOjEvNTEyfX0sdGhpcy5mcmFnbWVudFNyYz1bXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcIixcInZhcnlpbmcgdmVjMiB2VGV4dHVyZUNvb3JkO1wiLFwidmFyeWluZyB2ZWM0IHZDb2xvcjtcIixcInVuaWZvcm0gZmxvYXQgYmx1cjtcIixcInVuaWZvcm0gc2FtcGxlcjJEIHVTYW1wbGVyO1wiLFwidm9pZCBtYWluKHZvaWQpIHtcIixcIiAgIHZlYzQgc3VtID0gdmVjNCgwLjApO1wiLFwiICAgc3VtICs9IHRleHR1cmUyRCh1U2FtcGxlciwgdmVjMih2VGV4dHVyZUNvb3JkLnggLSA0LjAqYmx1ciwgdlRleHR1cmVDb29yZC55KSkgKiAwLjA1O1wiLFwiICAgc3VtICs9IHRleHR1cmUyRCh1U2FtcGxlciwgdmVjMih2VGV4dHVyZUNvb3JkLnggLSAzLjAqYmx1ciwgdlRleHR1cmVDb29yZC55KSkgKiAwLjA5O1wiLFwiICAgc3VtICs9IHRleHR1cmUyRCh1U2FtcGxlciwgdmVjMih2VGV4dHVyZUNvb3JkLnggLSAyLjAqYmx1ciwgdlRleHR1cmVDb29yZC55KSkgKiAwLjEyO1wiLFwiICAgc3VtICs9IHRleHR1cmUyRCh1U2FtcGxlciwgdmVjMih2VGV4dHVyZUNvb3JkLnggLSBibHVyLCB2VGV4dHVyZUNvb3JkLnkpKSAqIDAuMTU7XCIsXCIgICBzdW0gKz0gdGV4dHVyZTJEKHVTYW1wbGVyLCB2ZWMyKHZUZXh0dXJlQ29vcmQueCwgdlRleHR1cmVDb29yZC55KSkgKiAwLjE2O1wiLFwiICAgc3VtICs9IHRleHR1cmUyRCh1U2FtcGxlciwgdmVjMih2VGV4dHVyZUNvb3JkLnggKyBibHVyLCB2VGV4dHVyZUNvb3JkLnkpKSAqIDAuMTU7XCIsXCIgICBzdW0gKz0gdGV4dHVyZTJEKHVTYW1wbGVyLCB2ZWMyKHZUZXh0dXJlQ29vcmQueCArIDIuMCpibHVyLCB2VGV4dHVyZUNvb3JkLnkpKSAqIDAuMTI7XCIsXCIgICBzdW0gKz0gdGV4dHVyZTJEKHVTYW1wbGVyLCB2ZWMyKHZUZXh0dXJlQ29vcmQueCArIDMuMCpibHVyLCB2VGV4dHVyZUNvb3JkLnkpKSAqIDAuMDk7XCIsXCIgICBzdW0gKz0gdGV4dHVyZTJEKHVTYW1wbGVyLCB2ZWMyKHZUZXh0dXJlQ29vcmQueCArIDQuMCpibHVyLCB2VGV4dHVyZUNvb3JkLnkpKSAqIDAuMDU7XCIsXCIgICBnbF9GcmFnQ29sb3IgPSBzdW07XCIsXCJ9XCJdfSxiLkJsdXJYRmlsdGVyLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGIuQWJzdHJhY3RGaWx0ZXIucHJvdG90eXBlKSxiLkJsdXJYRmlsdGVyLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLkJsdXJYRmlsdGVyLE9iamVjdC5kZWZpbmVQcm9wZXJ0eShiLkJsdXJYRmlsdGVyLnByb3RvdHlwZSxcImJsdXJcIix7Z2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudW5pZm9ybXMuYmx1ci52YWx1ZS8oMS83ZTMpfSxzZXQ6ZnVuY3Rpb24oYSl7dGhpcy5kaXJ0eT0hMCx0aGlzLnVuaWZvcm1zLmJsdXIudmFsdWU9MS83ZTMqYX19KSxiLkJsdXJZRmlsdGVyPWZ1bmN0aW9uKCl7Yi5BYnN0cmFjdEZpbHRlci5jYWxsKHRoaXMpLHRoaXMucGFzc2VzPVt0aGlzXSx0aGlzLnVuaWZvcm1zPXtibHVyOnt0eXBlOlwiMWZcIix2YWx1ZToxLzUxMn19LHRoaXMuZnJhZ21lbnRTcmM9W1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XCIsXCJ2YXJ5aW5nIHZlYzIgdlRleHR1cmVDb29yZDtcIixcInZhcnlpbmcgdmVjNCB2Q29sb3I7XCIsXCJ1bmlmb3JtIGZsb2F0IGJsdXI7XCIsXCJ1bmlmb3JtIHNhbXBsZXIyRCB1U2FtcGxlcjtcIixcInZvaWQgbWFpbih2b2lkKSB7XCIsXCIgICB2ZWM0IHN1bSA9IHZlYzQoMC4wKTtcIixcIiAgIHN1bSArPSB0ZXh0dXJlMkQodVNhbXBsZXIsIHZlYzIodlRleHR1cmVDb29yZC54LCB2VGV4dHVyZUNvb3JkLnkgLSA0LjAqYmx1cikpICogMC4wNTtcIixcIiAgIHN1bSArPSB0ZXh0dXJlMkQodVNhbXBsZXIsIHZlYzIodlRleHR1cmVDb29yZC54LCB2VGV4dHVyZUNvb3JkLnkgLSAzLjAqYmx1cikpICogMC4wOTtcIixcIiAgIHN1bSArPSB0ZXh0dXJlMkQodVNhbXBsZXIsIHZlYzIodlRleHR1cmVDb29yZC54LCB2VGV4dHVyZUNvb3JkLnkgLSAyLjAqYmx1cikpICogMC4xMjtcIixcIiAgIHN1bSArPSB0ZXh0dXJlMkQodVNhbXBsZXIsIHZlYzIodlRleHR1cmVDb29yZC54LCB2VGV4dHVyZUNvb3JkLnkgLSBibHVyKSkgKiAwLjE1O1wiLFwiICAgc3VtICs9IHRleHR1cmUyRCh1U2FtcGxlciwgdmVjMih2VGV4dHVyZUNvb3JkLngsIHZUZXh0dXJlQ29vcmQueSkpICogMC4xNjtcIixcIiAgIHN1bSArPSB0ZXh0dXJlMkQodVNhbXBsZXIsIHZlYzIodlRleHR1cmVDb29yZC54LCB2VGV4dHVyZUNvb3JkLnkgKyBibHVyKSkgKiAwLjE1O1wiLFwiICAgc3VtICs9IHRleHR1cmUyRCh1U2FtcGxlciwgdmVjMih2VGV4dHVyZUNvb3JkLngsIHZUZXh0dXJlQ29vcmQueSArIDIuMCpibHVyKSkgKiAwLjEyO1wiLFwiICAgc3VtICs9IHRleHR1cmUyRCh1U2FtcGxlciwgdmVjMih2VGV4dHVyZUNvb3JkLngsIHZUZXh0dXJlQ29vcmQueSArIDMuMCpibHVyKSkgKiAwLjA5O1wiLFwiICAgc3VtICs9IHRleHR1cmUyRCh1U2FtcGxlciwgdmVjMih2VGV4dHVyZUNvb3JkLngsIHZUZXh0dXJlQ29vcmQueSArIDQuMCpibHVyKSkgKiAwLjA1O1wiLFwiICAgZ2xfRnJhZ0NvbG9yID0gc3VtO1wiLFwifVwiXX0sYi5CbHVyWUZpbHRlci5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShiLkFic3RyYWN0RmlsdGVyLnByb3RvdHlwZSksYi5CbHVyWUZpbHRlci5wcm90b3R5cGUuY29uc3RydWN0b3I9Yi5CbHVyWUZpbHRlcixPYmplY3QuZGVmaW5lUHJvcGVydHkoYi5CbHVyWUZpbHRlci5wcm90b3R5cGUsXCJibHVyXCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLnVuaWZvcm1zLmJsdXIudmFsdWUvKDEvN2UzKX0sc2V0OmZ1bmN0aW9uKGEpe3RoaXMudW5pZm9ybXMuYmx1ci52YWx1ZT0xLzdlMyphfX0pLGIuQmx1ckZpbHRlcj1mdW5jdGlvbigpe3RoaXMuYmx1clhGaWx0ZXI9bmV3IGIuQmx1clhGaWx0ZXIsdGhpcy5ibHVyWUZpbHRlcj1uZXcgYi5CbHVyWUZpbHRlcix0aGlzLnBhc3Nlcz1bdGhpcy5ibHVyWEZpbHRlcix0aGlzLmJsdXJZRmlsdGVyXX0sYi5CbHVyRmlsdGVyLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGIuQWJzdHJhY3RGaWx0ZXIucHJvdG90eXBlKSxiLkJsdXJGaWx0ZXIucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuQmx1ckZpbHRlcixPYmplY3QuZGVmaW5lUHJvcGVydHkoYi5CbHVyRmlsdGVyLnByb3RvdHlwZSxcImJsdXJcIix7Z2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYmx1clhGaWx0ZXIuYmx1cn0sc2V0OmZ1bmN0aW9uKGEpe3RoaXMuYmx1clhGaWx0ZXIuYmx1cj10aGlzLmJsdXJZRmlsdGVyLmJsdXI9YX19KSxPYmplY3QuZGVmaW5lUHJvcGVydHkoYi5CbHVyRmlsdGVyLnByb3RvdHlwZSxcImJsdXJYXCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmJsdXJYRmlsdGVyLmJsdXJ9LHNldDpmdW5jdGlvbihhKXt0aGlzLmJsdXJYRmlsdGVyLmJsdXI9YX19KSxPYmplY3QuZGVmaW5lUHJvcGVydHkoYi5CbHVyRmlsdGVyLnByb3RvdHlwZSxcImJsdXJZXCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmJsdXJZRmlsdGVyLmJsdXJ9LHNldDpmdW5jdGlvbihhKXt0aGlzLmJsdXJZRmlsdGVyLmJsdXI9YX19KSxiLkludmVydEZpbHRlcj1mdW5jdGlvbigpe2IuQWJzdHJhY3RGaWx0ZXIuY2FsbCh0aGlzKSx0aGlzLnBhc3Nlcz1bdGhpc10sdGhpcy51bmlmb3Jtcz17aW52ZXJ0Ont0eXBlOlwiMWZcIix2YWx1ZToxfX0sdGhpcy5mcmFnbWVudFNyYz1bXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcIixcInZhcnlpbmcgdmVjMiB2VGV4dHVyZUNvb3JkO1wiLFwidmFyeWluZyB2ZWM0IHZDb2xvcjtcIixcInVuaWZvcm0gZmxvYXQgaW52ZXJ0O1wiLFwidW5pZm9ybSBzYW1wbGVyMkQgdVNhbXBsZXI7XCIsXCJ2b2lkIG1haW4odm9pZCkge1wiLFwiICAgZ2xfRnJhZ0NvbG9yID0gdGV4dHVyZTJEKHVTYW1wbGVyLCB2VGV4dHVyZUNvb3JkKTtcIixcIiAgIGdsX0ZyYWdDb2xvci5yZ2IgPSBtaXgoICh2ZWMzKDEpLWdsX0ZyYWdDb2xvci5yZ2IpICogZ2xfRnJhZ0NvbG9yLmEsIGdsX0ZyYWdDb2xvci5yZ2IsIDEuMCAtIGludmVydCk7XCIsXCJ9XCJdfSxiLkludmVydEZpbHRlci5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShiLkFic3RyYWN0RmlsdGVyLnByb3RvdHlwZSksYi5JbnZlcnRGaWx0ZXIucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuSW52ZXJ0RmlsdGVyLE9iamVjdC5kZWZpbmVQcm9wZXJ0eShiLkludmVydEZpbHRlci5wcm90b3R5cGUsXCJpbnZlcnRcIix7Z2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudW5pZm9ybXMuaW52ZXJ0LnZhbHVlfSxzZXQ6ZnVuY3Rpb24oYSl7dGhpcy51bmlmb3Jtcy5pbnZlcnQudmFsdWU9YX19KSxiLlNlcGlhRmlsdGVyPWZ1bmN0aW9uKCl7Yi5BYnN0cmFjdEZpbHRlci5jYWxsKHRoaXMpLHRoaXMucGFzc2VzPVt0aGlzXSx0aGlzLnVuaWZvcm1zPXtzZXBpYTp7dHlwZTpcIjFmXCIsdmFsdWU6MX19LHRoaXMuZnJhZ21lbnRTcmM9W1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XCIsXCJ2YXJ5aW5nIHZlYzIgdlRleHR1cmVDb29yZDtcIixcInZhcnlpbmcgdmVjNCB2Q29sb3I7XCIsXCJ1bmlmb3JtIGZsb2F0IHNlcGlhO1wiLFwidW5pZm9ybSBzYW1wbGVyMkQgdVNhbXBsZXI7XCIsXCJjb25zdCBtYXQzIHNlcGlhTWF0cml4ID0gbWF0MygwLjM1ODgsIDAuNzA0NCwgMC4xMzY4LCAwLjI5OTAsIDAuNTg3MCwgMC4xMTQwLCAwLjIzOTIsIDAuNDY5NiwgMC4wOTEyKTtcIixcInZvaWQgbWFpbih2b2lkKSB7XCIsXCIgICBnbF9GcmFnQ29sb3IgPSB0ZXh0dXJlMkQodVNhbXBsZXIsIHZUZXh0dXJlQ29vcmQpO1wiLFwiICAgZ2xfRnJhZ0NvbG9yLnJnYiA9IG1peCggZ2xfRnJhZ0NvbG9yLnJnYiwgZ2xfRnJhZ0NvbG9yLnJnYiAqIHNlcGlhTWF0cml4LCBzZXBpYSk7XCIsXCJ9XCJdfSxiLlNlcGlhRmlsdGVyLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGIuQWJzdHJhY3RGaWx0ZXIucHJvdG90eXBlKSxiLlNlcGlhRmlsdGVyLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLlNlcGlhRmlsdGVyLE9iamVjdC5kZWZpbmVQcm9wZXJ0eShiLlNlcGlhRmlsdGVyLnByb3RvdHlwZSxcInNlcGlhXCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLnVuaWZvcm1zLnNlcGlhLnZhbHVlfSxzZXQ6ZnVuY3Rpb24oYSl7dGhpcy51bmlmb3Jtcy5zZXBpYS52YWx1ZT1hfX0pLGIuVHdpc3RGaWx0ZXI9ZnVuY3Rpb24oKXtiLkFic3RyYWN0RmlsdGVyLmNhbGwodGhpcyksdGhpcy5wYXNzZXM9W3RoaXNdLHRoaXMudW5pZm9ybXM9e3JhZGl1czp7dHlwZTpcIjFmXCIsdmFsdWU6LjV9LGFuZ2xlOnt0eXBlOlwiMWZcIix2YWx1ZTo1fSxvZmZzZXQ6e3R5cGU6XCIyZlwiLHZhbHVlOnt4Oi41LHk6LjV9fX0sdGhpcy5mcmFnbWVudFNyYz1bXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcIixcInZhcnlpbmcgdmVjMiB2VGV4dHVyZUNvb3JkO1wiLFwidmFyeWluZyB2ZWM0IHZDb2xvcjtcIixcInVuaWZvcm0gdmVjNCBkaW1lbnNpb25zO1wiLFwidW5pZm9ybSBzYW1wbGVyMkQgdVNhbXBsZXI7XCIsXCJ1bmlmb3JtIGZsb2F0IHJhZGl1cztcIixcInVuaWZvcm0gZmxvYXQgYW5nbGU7XCIsXCJ1bmlmb3JtIHZlYzIgb2Zmc2V0O1wiLFwidm9pZCBtYWluKHZvaWQpIHtcIixcIiAgIHZlYzIgY29vcmQgPSB2VGV4dHVyZUNvb3JkIC0gb2Zmc2V0O1wiLFwiICAgZmxvYXQgZGlzdGFuY2UgPSBsZW5ndGgoY29vcmQpO1wiLFwiICAgaWYgKGRpc3RhbmNlIDwgcmFkaXVzKSB7XCIsXCIgICAgICAgZmxvYXQgcmF0aW8gPSAocmFkaXVzIC0gZGlzdGFuY2UpIC8gcmFkaXVzO1wiLFwiICAgICAgIGZsb2F0IGFuZ2xlTW9kID0gcmF0aW8gKiByYXRpbyAqIGFuZ2xlO1wiLFwiICAgICAgIGZsb2F0IHMgPSBzaW4oYW5nbGVNb2QpO1wiLFwiICAgICAgIGZsb2F0IGMgPSBjb3MoYW5nbGVNb2QpO1wiLFwiICAgICAgIGNvb3JkID0gdmVjMihjb29yZC54ICogYyAtIGNvb3JkLnkgKiBzLCBjb29yZC54ICogcyArIGNvb3JkLnkgKiBjKTtcIixcIiAgIH1cIixcIiAgIGdsX0ZyYWdDb2xvciA9IHRleHR1cmUyRCh1U2FtcGxlciwgY29vcmQrb2Zmc2V0KTtcIixcIn1cIl19LGIuVHdpc3RGaWx0ZXIucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoYi5BYnN0cmFjdEZpbHRlci5wcm90b3R5cGUpLGIuVHdpc3RGaWx0ZXIucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuVHdpc3RGaWx0ZXIsT2JqZWN0LmRlZmluZVByb3BlcnR5KGIuVHdpc3RGaWx0ZXIucHJvdG90eXBlLFwib2Zmc2V0XCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLnVuaWZvcm1zLm9mZnNldC52YWx1ZX0sc2V0OmZ1bmN0aW9uKGEpe3RoaXMuZGlydHk9ITAsdGhpcy51bmlmb3Jtcy5vZmZzZXQudmFsdWU9YX19KSxPYmplY3QuZGVmaW5lUHJvcGVydHkoYi5Ud2lzdEZpbHRlci5wcm90b3R5cGUsXCJyYWRpdXNcIix7Z2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudW5pZm9ybXMucmFkaXVzLnZhbHVlfSxzZXQ6ZnVuY3Rpb24oYSl7dGhpcy5kaXJ0eT0hMCx0aGlzLnVuaWZvcm1zLnJhZGl1cy52YWx1ZT1hfX0pLE9iamVjdC5kZWZpbmVQcm9wZXJ0eShiLlR3aXN0RmlsdGVyLnByb3RvdHlwZSxcImFuZ2xlXCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLnVuaWZvcm1zLmFuZ2xlLnZhbHVlfSxzZXQ6ZnVuY3Rpb24oYSl7dGhpcy5kaXJ0eT0hMCx0aGlzLnVuaWZvcm1zLmFuZ2xlLnZhbHVlPWF9fSksYi5Db2xvclN0ZXBGaWx0ZXI9ZnVuY3Rpb24oKXtiLkFic3RyYWN0RmlsdGVyLmNhbGwodGhpcyksdGhpcy5wYXNzZXM9W3RoaXNdLHRoaXMudW5pZm9ybXM9e3N0ZXA6e3R5cGU6XCIxZlwiLHZhbHVlOjV9fSx0aGlzLmZyYWdtZW50U3JjPVtcInByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1wiLFwidmFyeWluZyB2ZWMyIHZUZXh0dXJlQ29vcmQ7XCIsXCJ2YXJ5aW5nIHZlYzQgdkNvbG9yO1wiLFwidW5pZm9ybSBzYW1wbGVyMkQgdVNhbXBsZXI7XCIsXCJ1bmlmb3JtIGZsb2F0IHN0ZXA7XCIsXCJ2b2lkIG1haW4odm9pZCkge1wiLFwiICAgdmVjNCBjb2xvciA9IHRleHR1cmUyRCh1U2FtcGxlciwgdlRleHR1cmVDb29yZCk7XCIsXCIgICBjb2xvciA9IGZsb29yKGNvbG9yICogc3RlcCkgLyBzdGVwO1wiLFwiICAgZ2xfRnJhZ0NvbG9yID0gY29sb3I7XCIsXCJ9XCJdfSxiLkNvbG9yU3RlcEZpbHRlci5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShiLkFic3RyYWN0RmlsdGVyLnByb3RvdHlwZSksYi5Db2xvclN0ZXBGaWx0ZXIucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuQ29sb3JTdGVwRmlsdGVyLE9iamVjdC5kZWZpbmVQcm9wZXJ0eShiLkNvbG9yU3RlcEZpbHRlci5wcm90b3R5cGUsXCJzdGVwXCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLnVuaWZvcm1zLnN0ZXAudmFsdWV9LHNldDpmdW5jdGlvbihhKXt0aGlzLnVuaWZvcm1zLnN0ZXAudmFsdWU9YX19KSxiLkRvdFNjcmVlbkZpbHRlcj1mdW5jdGlvbigpe2IuQWJzdHJhY3RGaWx0ZXIuY2FsbCh0aGlzKSx0aGlzLnBhc3Nlcz1bdGhpc10sdGhpcy51bmlmb3Jtcz17c2NhbGU6e3R5cGU6XCIxZlwiLHZhbHVlOjF9LGFuZ2xlOnt0eXBlOlwiMWZcIix2YWx1ZTo1fSxkaW1lbnNpb25zOnt0eXBlOlwiNGZ2XCIsdmFsdWU6WzAsMCwwLDBdfX0sdGhpcy5mcmFnbWVudFNyYz1bXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcIixcInZhcnlpbmcgdmVjMiB2VGV4dHVyZUNvb3JkO1wiLFwidmFyeWluZyB2ZWM0IHZDb2xvcjtcIixcInVuaWZvcm0gdmVjNCBkaW1lbnNpb25zO1wiLFwidW5pZm9ybSBzYW1wbGVyMkQgdVNhbXBsZXI7XCIsXCJ1bmlmb3JtIGZsb2F0IGFuZ2xlO1wiLFwidW5pZm9ybSBmbG9hdCBzY2FsZTtcIixcImZsb2F0IHBhdHRlcm4oKSB7XCIsXCIgICBmbG9hdCBzID0gc2luKGFuZ2xlKSwgYyA9IGNvcyhhbmdsZSk7XCIsXCIgICB2ZWMyIHRleCA9IHZUZXh0dXJlQ29vcmQgKiBkaW1lbnNpb25zLnh5O1wiLFwiICAgdmVjMiBwb2ludCA9IHZlYzIoXCIsXCIgICAgICAgYyAqIHRleC54IC0gcyAqIHRleC55LFwiLFwiICAgICAgIHMgKiB0ZXgueCArIGMgKiB0ZXgueVwiLFwiICAgKSAqIHNjYWxlO1wiLFwiICAgcmV0dXJuIChzaW4ocG9pbnQueCkgKiBzaW4ocG9pbnQueSkpICogNC4wO1wiLFwifVwiLFwidm9pZCBtYWluKCkge1wiLFwiICAgdmVjNCBjb2xvciA9IHRleHR1cmUyRCh1U2FtcGxlciwgdlRleHR1cmVDb29yZCk7XCIsXCIgICBmbG9hdCBhdmVyYWdlID0gKGNvbG9yLnIgKyBjb2xvci5nICsgY29sb3IuYikgLyAzLjA7XCIsXCIgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KHZlYzMoYXZlcmFnZSAqIDEwLjAgLSA1LjAgKyBwYXR0ZXJuKCkpLCBjb2xvci5hKTtcIixcIn1cIl19LGIuRG90U2NyZWVuRmlsdGVyLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGIuQWJzdHJhY3RGaWx0ZXIucHJvdG90eXBlKSxiLkRvdFNjcmVlbkZpbHRlci5wcm90b3R5cGUuY29uc3RydWN0b3I9Yi5Eb3RTY3JlZW5GaWx0ZXIsT2JqZWN0LmRlZmluZVByb3BlcnR5KGIuRG90U2NyZWVuRmlsdGVyLnByb3RvdHlwZSxcInNjYWxlXCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLnVuaWZvcm1zLnNjYWxlLnZhbHVlfSxzZXQ6ZnVuY3Rpb24oYSl7dGhpcy5kaXJ0eT0hMCx0aGlzLnVuaWZvcm1zLnNjYWxlLnZhbHVlPWF9fSksT2JqZWN0LmRlZmluZVByb3BlcnR5KGIuRG90U2NyZWVuRmlsdGVyLnByb3RvdHlwZSxcImFuZ2xlXCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLnVuaWZvcm1zLmFuZ2xlLnZhbHVlfSxzZXQ6ZnVuY3Rpb24oYSl7dGhpcy5kaXJ0eT0hMCx0aGlzLnVuaWZvcm1zLmFuZ2xlLnZhbHVlPWF9fSksYi5Dcm9zc0hhdGNoRmlsdGVyPWZ1bmN0aW9uKCl7Yi5BYnN0cmFjdEZpbHRlci5jYWxsKHRoaXMpLHRoaXMucGFzc2VzPVt0aGlzXSx0aGlzLnVuaWZvcm1zPXtibHVyOnt0eXBlOlwiMWZcIix2YWx1ZToxLzUxMn19LHRoaXMuZnJhZ21lbnRTcmM9W1wicHJlY2lzaW9uIG1lZGl1bXAgZmxvYXQ7XCIsXCJ2YXJ5aW5nIHZlYzIgdlRleHR1cmVDb29yZDtcIixcInZhcnlpbmcgdmVjNCB2Q29sb3I7XCIsXCJ1bmlmb3JtIGZsb2F0IGJsdXI7XCIsXCJ1bmlmb3JtIHNhbXBsZXIyRCB1U2FtcGxlcjtcIixcInZvaWQgbWFpbih2b2lkKSB7XCIsXCIgICAgZmxvYXQgbHVtID0gbGVuZ3RoKHRleHR1cmUyRCh1U2FtcGxlciwgdlRleHR1cmVDb29yZC54eSkucmdiKTtcIixcIiAgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KDEuMCwgMS4wLCAxLjAsIDEuMCk7XCIsXCIgICAgaWYgKGx1bSA8IDEuMDApIHtcIixcIiAgICAgICAgaWYgKG1vZChnbF9GcmFnQ29vcmQueCArIGdsX0ZyYWdDb29yZC55LCAxMC4wKSA9PSAwLjApIHtcIixcIiAgICAgICAgICAgIGdsX0ZyYWdDb2xvciA9IHZlYzQoMC4wLCAwLjAsIDAuMCwgMS4wKTtcIixcIiAgICAgICAgfVwiLFwiICAgIH1cIixcIiAgICBpZiAobHVtIDwgMC43NSkge1wiLFwiICAgICAgICBpZiAobW9kKGdsX0ZyYWdDb29yZC54IC0gZ2xfRnJhZ0Nvb3JkLnksIDEwLjApID09IDAuMCkge1wiLFwiICAgICAgICAgICAgZ2xfRnJhZ0NvbG9yID0gdmVjNCgwLjAsIDAuMCwgMC4wLCAxLjApO1wiLFwiICAgICAgICB9XCIsXCIgICAgfVwiLFwiICAgIGlmIChsdW0gPCAwLjUwKSB7XCIsXCIgICAgICAgIGlmIChtb2QoZ2xfRnJhZ0Nvb3JkLnggKyBnbF9GcmFnQ29vcmQueSAtIDUuMCwgMTAuMCkgPT0gMC4wKSB7XCIsXCIgICAgICAgICAgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KDAuMCwgMC4wLCAwLjAsIDEuMCk7XCIsXCIgICAgICAgIH1cIixcIiAgICB9XCIsXCIgICAgaWYgKGx1bSA8IDAuMykge1wiLFwiICAgICAgICBpZiAobW9kKGdsX0ZyYWdDb29yZC54IC0gZ2xfRnJhZ0Nvb3JkLnkgLSA1LjAsIDEwLjApID09IDAuMCkge1wiLFwiICAgICAgICAgICAgZ2xfRnJhZ0NvbG9yID0gdmVjNCgwLjAsIDAuMCwgMC4wLCAxLjApO1wiLFwiICAgICAgICB9XCIsXCIgICAgfVwiLFwifVwiXX0sYi5Dcm9zc0hhdGNoRmlsdGVyLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGIuQWJzdHJhY3RGaWx0ZXIucHJvdG90eXBlKSxiLkNyb3NzSGF0Y2hGaWx0ZXIucHJvdG90eXBlLmNvbnN0cnVjdG9yPWIuQ3Jvc3NIYXRjaEZpbHRlcixPYmplY3QuZGVmaW5lUHJvcGVydHkoYi5Dcm9zc0hhdGNoRmlsdGVyLnByb3RvdHlwZSxcImJsdXJcIix7Z2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudW5pZm9ybXMuYmx1ci52YWx1ZS8oMS83ZTMpfSxzZXQ6ZnVuY3Rpb24oYSl7dGhpcy51bmlmb3Jtcy5ibHVyLnZhbHVlPTEvN2UzKmF9fSksYi5SR0JTcGxpdEZpbHRlcj1mdW5jdGlvbigpe2IuQWJzdHJhY3RGaWx0ZXIuY2FsbCh0aGlzKSx0aGlzLnBhc3Nlcz1bdGhpc10sdGhpcy51bmlmb3Jtcz17cmVkOnt0eXBlOlwiMmZcIix2YWx1ZTp7eDoyMCx5OjIwfX0sZ3JlZW46e3R5cGU6XCIyZlwiLHZhbHVlOnt4Oi0yMCx5OjIwfX0sYmx1ZTp7dHlwZTpcIjJmXCIsdmFsdWU6e3g6MjAseTotMjB9fSxkaW1lbnNpb25zOnt0eXBlOlwiNGZ2XCIsdmFsdWU6WzAsMCwwLDBdfX0sdGhpcy5mcmFnbWVudFNyYz1bXCJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcIixcInZhcnlpbmcgdmVjMiB2VGV4dHVyZUNvb3JkO1wiLFwidmFyeWluZyB2ZWM0IHZDb2xvcjtcIixcInVuaWZvcm0gdmVjMiByZWQ7XCIsXCJ1bmlmb3JtIHZlYzIgZ3JlZW47XCIsXCJ1bmlmb3JtIHZlYzIgYmx1ZTtcIixcInVuaWZvcm0gdmVjNCBkaW1lbnNpb25zO1wiLFwidW5pZm9ybSBzYW1wbGVyMkQgdVNhbXBsZXI7XCIsXCJ2b2lkIG1haW4odm9pZCkge1wiLFwiICAgZ2xfRnJhZ0NvbG9yLnIgPSB0ZXh0dXJlMkQodVNhbXBsZXIsIHZUZXh0dXJlQ29vcmQgKyByZWQvZGltZW5zaW9ucy54eSkucjtcIixcIiAgIGdsX0ZyYWdDb2xvci5nID0gdGV4dHVyZTJEKHVTYW1wbGVyLCB2VGV4dHVyZUNvb3JkICsgZ3JlZW4vZGltZW5zaW9ucy54eSkuZztcIixcIiAgIGdsX0ZyYWdDb2xvci5iID0gdGV4dHVyZTJEKHVTYW1wbGVyLCB2VGV4dHVyZUNvb3JkICsgYmx1ZS9kaW1lbnNpb25zLnh5KS5iO1wiLFwiICAgZ2xfRnJhZ0NvbG9yLmEgPSB0ZXh0dXJlMkQodVNhbXBsZXIsIHZUZXh0dXJlQ29vcmQpLmE7XCIsXCJ9XCJdfSxiLlJHQlNwbGl0RmlsdGVyLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGIuQWJzdHJhY3RGaWx0ZXIucHJvdG90eXBlKSxiLlJHQlNwbGl0RmlsdGVyLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1iLlJHQlNwbGl0RmlsdGVyLE9iamVjdC5kZWZpbmVQcm9wZXJ0eShiLlJHQlNwbGl0RmlsdGVyLnByb3RvdHlwZSxcInJlZFwiLHtnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy51bmlmb3Jtcy5yZWQudmFsdWV9LHNldDpmdW5jdGlvbihhKXt0aGlzLnVuaWZvcm1zLnJlZC52YWx1ZT1hfX0pLE9iamVjdC5kZWZpbmVQcm9wZXJ0eShiLlJHQlNwbGl0RmlsdGVyLnByb3RvdHlwZSxcImdyZWVuXCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLnVuaWZvcm1zLmdyZWVuLnZhbHVlfSxzZXQ6ZnVuY3Rpb24oYSl7dGhpcy51bmlmb3Jtcy5ncmVlbi52YWx1ZT1hfX0pLE9iamVjdC5kZWZpbmVQcm9wZXJ0eShiLlJHQlNwbGl0RmlsdGVyLnByb3RvdHlwZSxcImJsdWVcIix7Z2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudW5pZm9ybXMuYmx1ZS52YWx1ZX0sc2V0OmZ1bmN0aW9uKGEpe3RoaXMudW5pZm9ybXMuYmx1ZS52YWx1ZT1hfX0pLFwidW5kZWZpbmVkXCIhPXR5cGVvZiBleHBvcnRzPyhcInVuZGVmaW5lZFwiIT10eXBlb2YgbW9kdWxlJiZtb2R1bGUuZXhwb3J0cyYmKGV4cG9ydHM9bW9kdWxlLmV4cG9ydHM9YiksZXhwb3J0cy5QSVhJPWIpOlwidW5kZWZpbmVkXCIhPXR5cGVvZiBkZWZpbmUmJmRlZmluZS5hbWQ/ZGVmaW5lKGIpOmEuUElYST1ifSkuY2FsbCh0aGlzKTsiLCI7KGZ1bmN0aW9uKHJvb3QsIGZhY3RvcnkpIHtcblxuICAvLyBTdXBwb3J0IEFNRFxuICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgZGVmaW5lKFtdLCBmYWN0b3J5KTtcblxuICAvLyBTdXBwb3J0IENvbW1vbkpTXG4gIH0gZWxzZSBpZiAodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnKSB7XG4gICAgdmFyIHJhbmRvbUNvbG9yID0gZmFjdG9yeSgpO1xuICAgIFxuICAgIC8vIFN1cHBvcnQgTm9kZUpTICYgQ29tcG9uZW50LCB3aGljaCBhbGxvdyBtb2R1bGUuZXhwb3J0cyB0byBiZSBhIGZ1bmN0aW9uXG4gICAgaWYgKHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnICYmIG1vZHVsZSAmJiBtb2R1bGUuZXhwb3J0cykge1xuICAgICAgZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0gcmFuZG9tQ29sb3I7XG4gICAgfVxuICAgIFxuICAgIC8vIFN1cHBvcnQgQ29tbW9uSlMgMS4xLjEgc3BlY1xuICAgIGV4cG9ydHMucmFuZG9tQ29sb3IgPSByYW5kb21Db2xvcjtcbiAgXG4gIC8vIFN1cHBvcnQgdmFuaWxsYSBzY3JpcHQgbG9hZGluZ1xuICB9IGVsc2Uge1xuICAgIHJvb3QucmFuZG9tQ29sb3IgPSBmYWN0b3J5KCk7XG4gIH07XG5cbn0odGhpcywgZnVuY3Rpb24oKSB7XG5cbiAgLy8gU2hhcmVkIGNvbG9yIGRpY3Rpb25hcnlcbiAgdmFyIGNvbG9yRGljdGlvbmFyeSA9IHt9O1xuXG4gIC8vIFBvcHVsYXRlIHRoZSBjb2xvciBkaWN0aW9uYXJ5XG4gIGxvYWRDb2xvckJvdW5kcygpO1xuXG4gIHZhciByYW5kb21Db2xvciA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICAgIHZhciBILFMsQjtcblxuICAgIC8vIENoZWNrIGlmIHdlIG5lZWQgdG8gZ2VuZXJhdGUgbXVsdGlwbGUgY29sb3JzXG4gICAgaWYgKG9wdGlvbnMuY291bnQpIHtcblxuICAgICAgdmFyIHRvdGFsQ29sb3JzID0gb3B0aW9ucy5jb3VudCxcbiAgICAgICAgICBjb2xvcnMgPSBbXTtcblxuICAgICAgb3B0aW9ucy5jb3VudCA9IGZhbHNlO1xuXG4gICAgICB3aGlsZSAodG90YWxDb2xvcnMgPiBjb2xvcnMubGVuZ3RoKSB7XG4gICAgICAgIGNvbG9ycy5wdXNoKHJhbmRvbUNvbG9yKG9wdGlvbnMpKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNvbG9ycztcbiAgICB9XG5cbiAgICAvLyBGaXJzdCB3ZSBwaWNrIGEgaHVlIChIKVxuICAgIEggPSBwaWNrSHVlKG9wdGlvbnMpO1xuXG4gICAgLy8gVGhlbiB1c2UgSCB0byBkZXRlcm1pbmUgc2F0dXJhdGlvbiAoUylcbiAgICBTID0gcGlja1NhdHVyYXRpb24oSCwgb3B0aW9ucyk7XG5cbiAgICAvLyBUaGVuIHVzZSBTIGFuZCBIIHRvIGRldGVybWluZSBicmlnaHRuZXNzIChCKS5cbiAgICBCID0gcGlja0JyaWdodG5lc3MoSCwgUywgb3B0aW9ucyk7XG5cbiAgICAvLyBUaGVuIHdlIHJldHVybiB0aGUgSFNCIGNvbG9yIGluIHRoZSBkZXNpcmVkIGZvcm1hdFxuICAgIHJldHVybiBzZXRGb3JtYXQoW0gsUyxCXSwgb3B0aW9ucyk7XG4gIH07XG5cbiAgZnVuY3Rpb24gcGlja0h1ZSAob3B0aW9ucykge1xuXG4gICAgdmFyIGh1ZVJhbmdlID0gZ2V0SHVlUmFuZ2Uob3B0aW9ucy5odWUpLFxuICAgICAgICBodWUgPSByYW5kb21XaXRoaW4oaHVlUmFuZ2UpO1xuXG4gICAgLy8gSW5zdGVhZCBvZiBzdG9yaW5nIHJlZCBhcyB0d28gc2VwZXJhdGUgcmFuZ2VzLFxuICAgIC8vIHdlIGdyb3VwIHRoZW0sIHVzaW5nIG5lZ2F0aXZlIG51bWJlcnNcbiAgICBpZiAoaHVlIDwgMCkge2h1ZSA9IDM2MCArIGh1ZX1cblxuICAgIHJldHVybiBodWU7XG5cbiAgfVxuXG4gIGZ1bmN0aW9uIHBpY2tTYXR1cmF0aW9uIChodWUsIG9wdGlvbnMpIHtcblxuICAgIGlmIChvcHRpb25zLmx1bWlub3NpdHkgPT09ICdyYW5kb20nKSB7XG4gICAgICByZXR1cm4gcmFuZG9tV2l0aGluKFswLDEwMF0pO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLmh1ZSA9PT0gJ21vbm9jaHJvbWUnKSB7XG4gICAgICByZXR1cm4gMDtcbiAgICB9XG5cbiAgICB2YXIgc2F0dXJhdGlvblJhbmdlID0gZ2V0U2F0dXJhdGlvblJhbmdlKGh1ZSk7XG5cbiAgICB2YXIgc01pbiA9IHNhdHVyYXRpb25SYW5nZVswXSxcbiAgICAgICAgc01heCA9IHNhdHVyYXRpb25SYW5nZVsxXTtcblxuICAgIHN3aXRjaCAob3B0aW9ucy5sdW1pbm9zaXR5KSB7XG5cbiAgICAgIGNhc2UgJ2JyaWdodCc6XG4gICAgICAgIHNNaW4gPSA1NTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ2RhcmsnOlxuICAgICAgICBzTWluID0gc01heCAtIDEwO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnbGlnaHQnOlxuICAgICAgICBzTWF4ID0gNTU7XG4gICAgICAgIGJyZWFrO1xuICAgfVxuXG4gICAgcmV0dXJuIHJhbmRvbVdpdGhpbihbc01pbiwgc01heF0pO1xuXG4gIH1cblxuICBmdW5jdGlvbiBwaWNrQnJpZ2h0bmVzcyAoSCwgUywgb3B0aW9ucykge1xuXG4gICAgdmFyIGJyaWdodG5lc3MsXG4gICAgICAgIGJNaW4gPSBnZXRNaW5pbXVtQnJpZ2h0bmVzcyhILCBTKSxcbiAgICAgICAgYk1heCA9IDEwMDtcblxuICAgIHN3aXRjaCAob3B0aW9ucy5sdW1pbm9zaXR5KSB7XG5cbiAgICAgIGNhc2UgJ2RhcmsnOlxuICAgICAgICBiTWF4ID0gYk1pbiArIDIwO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnbGlnaHQnOlxuICAgICAgICBiTWluID0gKGJNYXggKyBiTWluKS8yO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAncmFuZG9tJzpcbiAgICAgICAgYk1pbiA9IDA7XG4gICAgICAgIGJNYXggPSAxMDA7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIHJldHVybiByYW5kb21XaXRoaW4oW2JNaW4sIGJNYXhdKTtcblxuICB9XG5cbiAgZnVuY3Rpb24gc2V0Rm9ybWF0IChoc3YsIG9wdGlvbnMpIHtcblxuICAgIHN3aXRjaCAob3B0aW9ucy5mb3JtYXQpIHtcblxuICAgICAgY2FzZSAnaHN2QXJyYXknOlxuICAgICAgICByZXR1cm4gaHN2O1xuXG4gICAgICBjYXNlICdoc3YnOlxuICAgICAgICByZXR1cm4gY29sb3JTdHJpbmcoJ2hzdicsIGhzdik7XG5cbiAgICAgIGNhc2UgJ3JnYkFycmF5JzpcbiAgICAgICAgcmV0dXJuIEhTVnRvUkdCKGhzdik7XG5cbiAgICAgIGNhc2UgJ3JnYic6XG4gICAgICAgIHJldHVybiBjb2xvclN0cmluZygncmdiJywgSFNWdG9SR0IoaHN2KSk7XG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiBIU1Z0b0hleChoc3YpO1xuICAgIH1cblxuICB9XG5cbiAgZnVuY3Rpb24gZ2V0TWluaW11bUJyaWdodG5lc3MoSCwgUykge1xuXG4gICAgdmFyIGxvd2VyQm91bmRzID0gZ2V0Q29sb3JJbmZvKEgpLmxvd2VyQm91bmRzO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsb3dlckJvdW5kcy5sZW5ndGggLSAxOyBpKyspIHtcblxuICAgICAgdmFyIHMxID0gbG93ZXJCb3VuZHNbaV1bMF0sXG4gICAgICAgICAgdjEgPSBsb3dlckJvdW5kc1tpXVsxXTtcblxuICAgICAgdmFyIHMyID0gbG93ZXJCb3VuZHNbaSsxXVswXSxcbiAgICAgICAgICB2MiA9IGxvd2VyQm91bmRzW2krMV1bMV07XG5cbiAgICAgIGlmIChTID49IHMxICYmIFMgPD0gczIpIHtcblxuICAgICAgICAgdmFyIG0gPSAodjIgLSB2MSkvKHMyIC0gczEpLFxuICAgICAgICAgICAgIGIgPSB2MSAtIG0qczE7XG5cbiAgICAgICAgIHJldHVybiBtKlMgKyBiO1xuICAgICAgfVxuXG4gICAgfVxuXG4gICAgcmV0dXJuIDA7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRIdWVSYW5nZSAoY29sb3JJbnB1dCkge1xuXG4gICAgaWYgKHR5cGVvZiBwYXJzZUludChjb2xvcklucHV0KSA9PT0gJ251bWJlcicpIHtcblxuICAgICAgdmFyIG51bWJlciA9IHBhcnNlSW50KGNvbG9ySW5wdXQpO1xuXG4gICAgICBpZiAobnVtYmVyIDwgMzYwICYmIG51bWJlciA+IDApIHtcbiAgICAgICAgcmV0dXJuIFtudW1iZXIsIG51bWJlcl07XG4gICAgICB9XG5cbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGNvbG9ySW5wdXQgPT09ICdzdHJpbmcnKSB7XG5cbiAgICAgIGlmIChjb2xvckRpY3Rpb25hcnlbY29sb3JJbnB1dF0pIHtcbiAgICAgICAgdmFyIGNvbG9yID0gY29sb3JEaWN0aW9uYXJ5W2NvbG9ySW5wdXRdO1xuICAgICAgICBpZiAoY29sb3IuaHVlUmFuZ2UpIHtyZXR1cm4gY29sb3IuaHVlUmFuZ2V9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIFswLDM2MF07XG5cbiAgfVxuXG4gIGZ1bmN0aW9uIGdldFNhdHVyYXRpb25SYW5nZSAoaHVlKSB7XG4gICAgcmV0dXJuIGdldENvbG9ySW5mbyhodWUpLnNhdHVyYXRpb25SYW5nZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldENvbG9ySW5mbyAoaHVlKSB7XG5cbiAgICAvLyBNYXBzIHJlZCBjb2xvcnMgdG8gbWFrZSBwaWNraW5nIGh1ZSBlYXNpZXJcbiAgICBpZiAoaHVlID49IDMzNCAmJiBodWUgPD0gMzYwKSB7XG4gICAgICBodWUtPSAzNjA7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgY29sb3JOYW1lIGluIGNvbG9yRGljdGlvbmFyeSkge1xuICAgICAgIHZhciBjb2xvciA9IGNvbG9yRGljdGlvbmFyeVtjb2xvck5hbWVdO1xuICAgICAgIGlmIChjb2xvci5odWVSYW5nZSAmJlxuICAgICAgICAgICBodWUgPj0gY29sb3IuaHVlUmFuZ2VbMF0gJiZcbiAgICAgICAgICAgaHVlIDw9IGNvbG9yLmh1ZVJhbmdlWzFdKSB7XG4gICAgICAgICAgcmV0dXJuIGNvbG9yRGljdGlvbmFyeVtjb2xvck5hbWVdO1xuICAgICAgIH1cbiAgICB9IHJldHVybiAnQ29sb3Igbm90IGZvdW5kJztcbiAgfVxuXG4gIGZ1bmN0aW9uIHJhbmRvbVdpdGhpbiAocmFuZ2UpIHtcbiAgICByZXR1cm4gTWF0aC5mbG9vcihyYW5nZVswXSArIE1hdGgucmFuZG9tKCkqKHJhbmdlWzFdICsgMSAtIHJhbmdlWzBdKSk7XG4gIH1cblxuICBmdW5jdGlvbiBzaGlmdEh1ZSAoaCwgZGVncmVlcykge1xuICAgIHJldHVybiAoaCArIGRlZ3JlZXMpJTM2MDtcbiAgfVxuXG4gIGZ1bmN0aW9uIEhTVnRvSGV4IChoc3Ype1xuXG4gICAgdmFyIHJnYiA9IEhTVnRvUkdCKGhzdik7XG5cbiAgICBmdW5jdGlvbiBjb21wb25lbnRUb0hleChjKSB7XG4gICAgICAgIHZhciBoZXggPSBjLnRvU3RyaW5nKDE2KTtcbiAgICAgICAgcmV0dXJuIGhleC5sZW5ndGggPT0gMSA/IFwiMFwiICsgaGV4IDogaGV4O1xuICAgIH1cblxuICAgIHZhciBoZXggPSBcIiNcIiArIGNvbXBvbmVudFRvSGV4KHJnYlswXSkgKyBjb21wb25lbnRUb0hleChyZ2JbMV0pICsgY29tcG9uZW50VG9IZXgocmdiWzJdKTtcblxuICAgIHJldHVybiBoZXg7XG5cbiAgfVxuXG4gIGZ1bmN0aW9uIGRlZmluZUNvbG9yIChuYW1lLCBodWVSYW5nZSwgbG93ZXJCb3VuZHMpIHtcblxuICAgIHZhciBzTWluID0gbG93ZXJCb3VuZHNbMF1bMF0sXG4gICAgICAgIHNNYXggPSBsb3dlckJvdW5kc1tsb3dlckJvdW5kcy5sZW5ndGggLSAxXVswXSxcblxuICAgICAgICBiTWluID0gbG93ZXJCb3VuZHNbbG93ZXJCb3VuZHMubGVuZ3RoIC0gMV1bMV0sXG4gICAgICAgIGJNYXggPSBsb3dlckJvdW5kc1swXVsxXTtcblxuICAgIGNvbG9yRGljdGlvbmFyeVtuYW1lXSA9IHtcbiAgICAgIGh1ZVJhbmdlOiBodWVSYW5nZSxcbiAgICAgIGxvd2VyQm91bmRzOiBsb3dlckJvdW5kcyxcbiAgICAgIHNhdHVyYXRpb25SYW5nZTogW3NNaW4sIHNNYXhdLFxuICAgICAgYnJpZ2h0bmVzc1JhbmdlOiBbYk1pbiwgYk1heF1cbiAgICB9O1xuXG4gIH1cblxuICBmdW5jdGlvbiBsb2FkQ29sb3JCb3VuZHMgKCkge1xuXG4gICAgZGVmaW5lQ29sb3IoXG4gICAgICAnbW9ub2Nocm9tZScsXG4gICAgICBudWxsLFxuICAgICAgW1swLDBdLFsxMDAsMF1dXG4gICAgKTtcblxuICAgIGRlZmluZUNvbG9yKFxuICAgICAgJ3JlZCcsXG4gICAgICBbLTI2LDE4XSxcbiAgICAgIFtbMjAsMTAwXSxbMzAsOTJdLFs0MCw4OV0sWzUwLDg1XSxbNjAsNzhdLFs3MCw3MF0sWzgwLDYwXSxbOTAsNTVdLFsxMDAsNTBdXVxuICAgICk7XG5cbiAgICBkZWZpbmVDb2xvcihcbiAgICAgICdvcmFuZ2UnLFxuICAgICAgWzE5LDQ2XSxcbiAgICAgIFtbMjAsMTAwXSxbMzAsOTNdLFs0MCw4OF0sWzUwLDg2XSxbNjAsODVdLFs3MCw3MF0sWzEwMCw3MF1dXG4gICAgKTtcblxuICAgIGRlZmluZUNvbG9yKFxuICAgICAgJ3llbGxvdycsXG4gICAgICBbNDcsNjJdLFxuICAgICAgW1syNSwxMDBdLFs0MCw5NF0sWzUwLDg5XSxbNjAsODZdLFs3MCw4NF0sWzgwLDgyXSxbOTAsODBdLFsxMDAsNzVdXVxuICAgICk7XG5cbiAgICBkZWZpbmVDb2xvcihcbiAgICAgICdncmVlbicsXG4gICAgICBbNjMsMTU4XSxcbiAgICAgIFtbMzAsMTAwXSxbNDAsOTBdLFs1MCw4NV0sWzYwLDgxXSxbNzAsNzRdLFs4MCw2NF0sWzkwLDUwXSxbMTAwLDQwXV1cbiAgICApO1xuXG4gICAgZGVmaW5lQ29sb3IoXG4gICAgICAnYmx1ZScsXG4gICAgICBbMTU5LCAyNTddLFxuICAgICAgW1syMCwxMDBdLFszMCw4Nl0sWzQwLDgwXSxbNTAsNzRdLFs2MCw2MF0sWzcwLDUyXSxbODAsNDRdLFs5MCwzOV0sWzEwMCwzNV1dXG4gICAgKTtcblxuICAgIGRlZmluZUNvbG9yKFxuICAgICAgJ3B1cnBsZScsXG4gICAgICBbMjU4LCAyODJdLFxuICAgICAgW1syMCwxMDBdLFszMCw4N10sWzQwLDc5XSxbNTAsNzBdLFs2MCw2NV0sWzcwLDU5XSxbODAsNTJdLFs5MCw0NV0sWzEwMCw0Ml1dXG4gICAgKTtcblxuICAgIGRlZmluZUNvbG9yKFxuICAgICAgJ3BpbmsnLFxuICAgICAgWzI4MywgMzM0XSxcbiAgICAgIFtbMjAsMTAwXSxbMzAsOTBdLFs0MCw4Nl0sWzYwLDg0XSxbODAsODBdLFs5MCw3NV0sWzEwMCw3M11dXG4gICAgKTtcblxuICB9XG5cbiAgZnVuY3Rpb24gSFNWdG9SR0IgKGhzdikge1xuXG4gICAgLy8gdGhpcyBkb2Vzbid0IHdvcmsgZm9yIHRoZSB2YWx1ZXMgb2YgMCBhbmQgMzYwXG4gICAgLy8gaGVyZSdzIHRoZSBoYWNreSBmaXhcbiAgICB2YXIgaCA9IGhzdlswXTtcbiAgICBpZiAoaCA9PT0gMCkge2ggPSAxfVxuICAgIGlmIChoID09PSAzNjApIHtoID0gMzU5fVxuXG4gICAgLy8gUmViYXNlIHRoZSBoLHMsdiB2YWx1ZXNcbiAgICBoID0gaC8zNjA7XG4gICAgdmFyIHMgPSBoc3ZbMV0vMTAwLFxuICAgICAgICB2ID0gaHN2WzJdLzEwMDtcblxuICAgIHZhciBoX2kgPSBNYXRoLmZsb29yKGgqNiksXG4gICAgICBmID0gaCAqIDYgLSBoX2ksXG4gICAgICBwID0gdiAqICgxIC0gcyksXG4gICAgICBxID0gdiAqICgxIC0gZipzKSxcbiAgICAgIHQgPSB2ICogKDEgLSAoMSAtIGYpKnMpLFxuICAgICAgciA9IDI1NixcbiAgICAgIGcgPSAyNTYsXG4gICAgICBiID0gMjU2O1xuXG4gICAgc3dpdGNoKGhfaSkge1xuICAgICAgY2FzZSAwOiByID0gdiwgZyA9IHQsIGIgPSBwOyAgYnJlYWs7XG4gICAgICBjYXNlIDE6IHIgPSBxLCBnID0gdiwgYiA9IHA7ICBicmVhaztcbiAgICAgIGNhc2UgMjogciA9IHAsIGcgPSB2LCBiID0gdDsgIGJyZWFrO1xuICAgICAgY2FzZSAzOiByID0gcCwgZyA9IHEsIGIgPSB2OyAgYnJlYWs7XG4gICAgICBjYXNlIDQ6IHIgPSB0LCBnID0gcCwgYiA9IHY7ICBicmVhaztcbiAgICAgIGNhc2UgNTogciA9IHYsIGcgPSBwLCBiID0gcTsgIGJyZWFrO1xuICAgIH1cbiAgICB2YXIgcmVzdWx0ID0gW01hdGguZmxvb3IocioyNTUpLCBNYXRoLmZsb29yKGcqMjU1KSwgTWF0aC5mbG9vcihiKjI1NSldO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiBjb2xvclN0cmluZyAocHJlZml4LCB2YWx1ZXMpIHtcbiAgICByZXR1cm4gcHJlZml4ICsgJygnICsgdmFsdWVzLmpvaW4oJywgJykgKyAnKSc7XG4gIH1cblxuICByZXR1cm4gcmFuZG9tQ29sb3I7XG59KSk7Il19