From 300868edff433f0f895a83482e0e7d92fa9e815e Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Thu, 5 Mar 2015 01:52:47 +0100 Subject: clean up web builds --- libmproxy/web/fonts/fontawesome-webfont.eot | Bin 56006 -> 0 bytes libmproxy/web/fonts/fontawesome-webfont.svg | 520 - libmproxy/web/fonts/fontawesome-webfont.ttf | Bin 112160 -> 0 bytes libmproxy/web/fonts/fontawesome-webfont.woff | Bin 65452 -> 0 bytes libmproxy/web/images/chrome-devtools/LICENSE | 30 - .../web/images/chrome-devtools/resourceCSSIcon.png | Bin 1005 -> 0 bytes .../chrome-devtools/resourceDocumentIcon.png | Bin 951 -> 0 bytes .../web/images/chrome-devtools/resourceJSIcon.png | Bin 787 -> 0 bytes .../images/chrome-devtools/resourcePlainIcon.png | Bin 295 -> 0 bytes libmproxy/web/images/resourceExecutableIcon.png | Bin 853 -> 0 bytes libmproxy/web/images/resourceFlashIcon.png | Bin 921 -> 0 bytes libmproxy/web/images/resourceImageIcon.png | Bin 976 -> 0 bytes libmproxy/web/images/resourceJavaIcon.png | Bin 861 -> 0 bytes libmproxy/web/images/resourceNotModifiedIcon.png | Bin 1072 -> 0 bytes libmproxy/web/images/resourceRedirectIcon.png | Bin 1174 -> 0 bytes libmproxy/web/static/app.js | 21 +- libmproxy/web/static/vendor.css | 286 +- libmproxy/web/static/vendor.js | 20582 +++++++++++-------- 18 files changed, 11853 insertions(+), 9586 deletions(-) delete mode 100644 libmproxy/web/fonts/fontawesome-webfont.eot delete mode 100644 libmproxy/web/fonts/fontawesome-webfont.svg delete mode 100644 libmproxy/web/fonts/fontawesome-webfont.ttf delete mode 100644 libmproxy/web/fonts/fontawesome-webfont.woff delete mode 100644 libmproxy/web/images/chrome-devtools/LICENSE delete mode 100644 libmproxy/web/images/chrome-devtools/resourceCSSIcon.png delete mode 100644 libmproxy/web/images/chrome-devtools/resourceDocumentIcon.png delete mode 100644 libmproxy/web/images/chrome-devtools/resourceJSIcon.png delete mode 100644 libmproxy/web/images/chrome-devtools/resourcePlainIcon.png delete mode 100644 libmproxy/web/images/resourceExecutableIcon.png delete mode 100644 libmproxy/web/images/resourceFlashIcon.png delete mode 100644 libmproxy/web/images/resourceImageIcon.png delete mode 100644 libmproxy/web/images/resourceJavaIcon.png delete mode 100644 libmproxy/web/images/resourceNotModifiedIcon.png delete mode 100644 libmproxy/web/images/resourceRedirectIcon.png (limited to 'libmproxy/web') diff --git a/libmproxy/web/fonts/fontawesome-webfont.eot b/libmproxy/web/fonts/fontawesome-webfont.eot deleted file mode 100644 index 84677bc0..00000000 Binary files a/libmproxy/web/fonts/fontawesome-webfont.eot and /dev/null differ diff --git a/libmproxy/web/fonts/fontawesome-webfont.svg b/libmproxy/web/fonts/fontawesome-webfont.svg deleted file mode 100644 index d907b25a..00000000 --- a/libmproxy/web/fonts/fontawesome-webfont.svg +++ /dev/null @@ -1,520 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/libmproxy/web/fonts/fontawesome-webfont.ttf b/libmproxy/web/fonts/fontawesome-webfont.ttf deleted file mode 100644 index 96a3639c..00000000 Binary files a/libmproxy/web/fonts/fontawesome-webfont.ttf and /dev/null differ diff --git a/libmproxy/web/fonts/fontawesome-webfont.woff b/libmproxy/web/fonts/fontawesome-webfont.woff deleted file mode 100644 index 628b6a52..00000000 Binary files a/libmproxy/web/fonts/fontawesome-webfont.woff and /dev/null differ diff --git a/libmproxy/web/images/chrome-devtools/LICENSE b/libmproxy/web/images/chrome-devtools/LICENSE deleted file mode 100644 index 6e4f8b9f..00000000 --- a/libmproxy/web/images/chrome-devtools/LICENSE +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// -// The Chromium Authors can be found at -// http://src.chromium.org/svn/trunk/src/AUTHORS -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/libmproxy/web/images/chrome-devtools/resourceCSSIcon.png b/libmproxy/web/images/chrome-devtools/resourceCSSIcon.png deleted file mode 100644 index 18828d06..00000000 Binary files a/libmproxy/web/images/chrome-devtools/resourceCSSIcon.png and /dev/null differ diff --git a/libmproxy/web/images/chrome-devtools/resourceDocumentIcon.png b/libmproxy/web/images/chrome-devtools/resourceDocumentIcon.png deleted file mode 100644 index fdc10e47..00000000 Binary files a/libmproxy/web/images/chrome-devtools/resourceDocumentIcon.png and /dev/null differ diff --git a/libmproxy/web/images/chrome-devtools/resourceJSIcon.png b/libmproxy/web/images/chrome-devtools/resourceJSIcon.png deleted file mode 100644 index c1b72189..00000000 Binary files a/libmproxy/web/images/chrome-devtools/resourceJSIcon.png and /dev/null differ diff --git a/libmproxy/web/images/chrome-devtools/resourcePlainIcon.png b/libmproxy/web/images/chrome-devtools/resourcePlainIcon.png deleted file mode 100644 index 8c82a4c7..00000000 Binary files a/libmproxy/web/images/chrome-devtools/resourcePlainIcon.png and /dev/null differ diff --git a/libmproxy/web/images/resourceExecutableIcon.png b/libmproxy/web/images/resourceExecutableIcon.png deleted file mode 100644 index fa70c2fd..00000000 Binary files a/libmproxy/web/images/resourceExecutableIcon.png and /dev/null differ diff --git a/libmproxy/web/images/resourceFlashIcon.png b/libmproxy/web/images/resourceFlashIcon.png deleted file mode 100644 index ead5a4d0..00000000 Binary files a/libmproxy/web/images/resourceFlashIcon.png and /dev/null differ diff --git a/libmproxy/web/images/resourceImageIcon.png b/libmproxy/web/images/resourceImageIcon.png deleted file mode 100644 index 23163042..00000000 Binary files a/libmproxy/web/images/resourceImageIcon.png and /dev/null differ diff --git a/libmproxy/web/images/resourceJavaIcon.png b/libmproxy/web/images/resourceJavaIcon.png deleted file mode 100644 index 553b3391..00000000 Binary files a/libmproxy/web/images/resourceJavaIcon.png and /dev/null differ diff --git a/libmproxy/web/images/resourceNotModifiedIcon.png b/libmproxy/web/images/resourceNotModifiedIcon.png deleted file mode 100644 index 9c6a879d..00000000 Binary files a/libmproxy/web/images/resourceNotModifiedIcon.png and /dev/null differ diff --git a/libmproxy/web/images/resourceRedirectIcon.png b/libmproxy/web/images/resourceRedirectIcon.png deleted file mode 100644 index 58fe3ac1..00000000 Binary files a/libmproxy/web/images/resourceRedirectIcon.png and /dev/null differ diff --git a/libmproxy/web/static/app.js b/libmproxy/web/static/app.js index ef8113e3..9e7df2b5 100644 --- a/libmproxy/web/static/app.js +++ b/libmproxy/web/static/app.js @@ -422,6 +422,7 @@ module.exports = { FlowActions: FlowActions, StoreCmds: StoreCmds }; + },{"jquery":"jquery"}],3:[function(require,module,exports){ var React = require("react"); @@ -440,6 +441,7 @@ $(function () { }); + },{"./components/proxyapp.js":12,"./connection":14,"jquery":"jquery","react":"react","react-router":"react-router"}],4:[function(require,module,exports){ var React = require("react"); var ReactRouter = require("react-router"); @@ -635,6 +637,7 @@ module.exports = { AutoScrollMixin: AutoScrollMixin, Splitter: Splitter } + },{"lodash":"lodash","react":"react","react-router":"react-router"}],5:[function(require,module,exports){ var React = require("react"); var common = require("./common.js"); @@ -791,6 +794,7 @@ var EventLog = React.createClass({displayName: "EventLog", }); module.exports = EventLog; + },{"../store/view.js":19,"./common.js":4,"./virtualscroll.js":13,"react":"react"}],6:[function(require,module,exports){ var React = require("react"); var _ = require("lodash"); @@ -1191,6 +1195,7 @@ var FlowDetail = React.createClass({displayName: "FlowDetail", module.exports = { FlowDetail: FlowDetail }; + },{"../actions.js":2,"../flow/utils.js":17,"../utils.js":20,"./common.js":4,"lodash":"lodash","react":"react"}],7:[function(require,module,exports){ var React = require("react"); var flowutils = require("../flow/utils.js"); @@ -1357,6 +1362,7 @@ module.exports = all_columns; + },{"../flow/utils.js":17,"../utils.js":20,"react":"react"}],8:[function(require,module,exports){ var React = require("react"); var common = require("./common.js"); @@ -1495,6 +1501,7 @@ var FlowTable = React.createClass({displayName: "FlowTable", module.exports = FlowTable; + },{"./common.js":4,"./flowtable-columns.js":7,"./virtualscroll.js":13,"react":"react"}],9:[function(require,module,exports){ var React = require("react"); @@ -1513,6 +1520,7 @@ var Footer = React.createClass({displayName: "Footer", }); module.exports = Footer; + },{"react":"react"}],10:[function(require,module,exports){ var React = require("react"); var $ = require("jquery"); @@ -1903,6 +1911,7 @@ var Header = React.createClass({displayName: "Header", module.exports = { Header: Header } + },{"../filt/filt.js":16,"../utils.js":20,"./common.js":4,"jquery":"jquery","react":"react"}],11:[function(require,module,exports){ var React = require("react"); @@ -2137,6 +2146,7 @@ var MainView = React.createClass({displayName: "MainView", module.exports = MainView; + },{"../filt/filt.js":16,"../store/view.js":19,"../utils.js":20,"./common.js":4,"./flowdetail.js":6,"./flowtable.js":8,"react":"react"}],12:[function(require,module,exports){ var React = require("react"); var ReactRouter = require("react-router"); @@ -2231,6 +2241,7 @@ module.exports = { }; + },{"../store/store.js":18,"./common.js":4,"./eventlog.js":5,"./footer.js":9,"./header.js":10,"./mainview.js":11,"lodash":"lodash","react":"react","react-router":"react-router"}],13:[function(require,module,exports){ var React = require("react"); @@ -2317,6 +2328,7 @@ var VirtualScrollMixin = { }; module.exports = VirtualScrollMixin; + },{"react":"react"}],14:[function(require,module,exports){ var actions = require("./actions.js"); @@ -2346,6 +2358,7 @@ function Connection(url) { } module.exports = Connection; + },{"./actions.js":2}],15:[function(require,module,exports){ var flux = require("flux"); @@ -2369,6 +2382,7 @@ AppDispatcher.dispatchServerAction = function (action) { module.exports = { AppDispatcher: AppDispatcher }; + },{"flux":"flux"}],16:[function(require,module,exports){ module.exports = (function() { /* @@ -4144,6 +4158,7 @@ module.exports = (function() { parse: parse }; })(); + },{"../flow/utils.js":17}],17:[function(require,module,exports){ var _ = require("lodash"); @@ -4211,6 +4226,7 @@ module.exports = { RequestUtils: RequestUtils } + },{"lodash":"lodash"}],18:[function(require,module,exports){ var _ = require("lodash"); @@ -4393,6 +4409,7 @@ module.exports = { SettingsStore: SettingsStore, FlowStore: FlowStore }; + },{"../actions.js":2,"../dispatcher.js":15,"../utils.js":20,"events":1,"jquery":"jquery","lodash":"lodash"}],19:[function(require,module,exports){ var EventEmitter = require('events').EventEmitter; @@ -4504,6 +4521,7 @@ _.extend(StoreView.prototype, EventEmitter.prototype, { module.exports = { StoreView: StoreView }; + },{"../utils.js":20,"events":1,"lodash":"lodash"}],20:[function(require,module,exports){ var $ = require("jquery"); @@ -4596,5 +4614,6 @@ module.exports = { formatTimeStamp: formatTimeStamp, Key: Key }; + },{"jquery":"jquery"}]},{},[3]) -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsInNyYy9qcy9hY3Rpb25zLmpzIiwic3JjL2pzL2FwcC5qcyIsInNyYy9qcy9jb21wb25lbnRzL2NvbW1vbi5qcyIsInNyYy9qcy9jb21wb25lbnRzL2V2ZW50bG9nLmpzIiwic3JjL2pzL2NvbXBvbmVudHMvZmxvd2RldGFpbC5qcyIsInNyYy9qcy9jb21wb25lbnRzL2Zsb3d0YWJsZS1jb2x1bW5zLmpzIiwic3JjL2pzL2NvbXBvbmVudHMvZmxvd3RhYmxlLmpzIiwic3JjL2pzL2NvbXBvbmVudHMvZm9vdGVyLmpzIiwic3JjL2pzL2NvbXBvbmVudHMvaGVhZGVyLmpzIiwic3JjL2pzL2NvbXBvbmVudHMvbWFpbnZpZXcuanMiLCJzcmMvanMvY29tcG9uZW50cy9wcm94eWFwcC5qcyIsInNyYy9qcy9jb21wb25lbnRzL3ZpcnR1YWxzY3JvbGwuanMiLCJzcmMvanMvY29ubmVjdGlvbi5qcyIsInNyYy9qcy9kaXNwYXRjaGVyLmpzIiwic3JjL2pzL2ZpbHQvZmlsdC5qcyIsInNyYy9qcy9mbG93L3V0aWxzLmpzIiwic3JjL2pzL3N0b3JlL3N0b3JlLmpzIiwic3JjL2pzL3N0b3JlL3ZpZXcuanMiLCJzcmMvanMvdXRpbHMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDak1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5WUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BZQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzd1REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiLy8gQ29weXJpZ2h0IEpveWVudCwgSW5jLiBhbmQgb3RoZXIgTm9kZSBjb250cmlidXRvcnMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGFcbi8vIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGVcbi8vIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZ1xuLy8gd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLFxuLy8gZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdFxuLy8gcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlXG4vLyBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZFxuLy8gaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTU1xuLy8gT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRlxuLy8gTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTlxuLy8gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sXG4vLyBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1Jcbi8vIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEVcbi8vIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbmZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHtcbiAgdGhpcy5fZXZlbnRzID0gdGhpcy5fZXZlbnRzIHx8IHt9O1xuICB0aGlzLl9tYXhMaXN0ZW5lcnMgPSB0aGlzLl9tYXhMaXN0ZW5lcnMgfHwgdW5kZWZpbmVkO1xufVxubW9kdWxlLmV4cG9ydHMgPSBFdmVudEVtaXR0ZXI7XG5cbi8vIEJhY2t3YXJkcy1jb21wYXQgd2l0aCBub2RlIDAuMTAueFxuRXZlbnRFbWl0dGVyLkV2ZW50RW1pdHRlciA9IEV2ZW50RW1pdHRlcjtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5fZXZlbnRzID0gdW5kZWZpbmVkO1xuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5fbWF4TGlzdGVuZXJzID0gdW5kZWZpbmVkO1xuXG4vLyBCeSBkZWZhdWx0IEV2ZW50RW1pdHRlcnMgd2lsbCBwcmludCBhIHdhcm5pbmcgaWYgbW9yZSB0aGFuIDEwIGxpc3RlbmVycyBhcmVcbi8vIGFkZGVkIHRvIGl0LiBUaGlzIGlzIGEgdXNlZnVsIGRlZmF1bHQgd2hpY2ggaGVscHMgZmluZGluZyBtZW1vcnkgbGVha3MuXG5FdmVudEVtaXR0ZXIuZGVmYXVsdE1heExpc3RlbmVycyA9IDEwO1xuXG4vLyBPYnZpb3VzbHkgbm90IGFsbCBFbWl0dGVycyBzaG91bGQgYmUgbGltaXRlZCB0byAxMC4gVGhpcyBmdW5jdGlvbiBhbGxvd3Ncbi8vIHRoYXQgdG8gYmUgaW5jcmVhc2VkLiBTZXQgdG8gemVybyBmb3IgdW5saW1pdGVkLlxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5zZXRNYXhMaXN0ZW5lcnMgPSBmdW5jdGlvbihuKSB7XG4gIGlmICghaXNOdW1iZXIobikgfHwgbiA8IDAgfHwgaXNOYU4obikpXG4gICAgdGhyb3cgVHlwZUVycm9yKCduIG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXInKTtcbiAgdGhpcy5fbWF4TGlzdGVuZXJzID0gbjtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmVtaXQgPSBmdW5jdGlvbih0eXBlKSB7XG4gIHZhciBlciwgaGFuZGxlciwgbGVuLCBhcmdzLCBpLCBsaXN0ZW5lcnM7XG5cbiAgaWYgKCF0aGlzLl9ldmVudHMpXG4gICAgdGhpcy5fZXZlbnRzID0ge307XG5cbiAgLy8gSWYgdGhlcmUgaXMgbm8gJ2Vycm9yJyBldmVudCBsaXN0ZW5lciB0aGVuIHRocm93LlxuICBpZiAodHlwZSA9PT0gJ2Vycm9yJykge1xuICAgIGlmICghdGhpcy5fZXZlbnRzLmVycm9yIHx8XG4gICAgICAgIChpc09iamVjdCh0aGlzLl9ldmVudHMuZXJyb3IpICYmICF0aGlzLl9ldmVudHMuZXJyb3IubGVuZ3RoKSkge1xuICAgICAgZXIgPSBhcmd1bWVudHNbMV07XG4gICAgICBpZiAoZXIgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICB0aHJvdyBlcjsgLy8gVW5oYW5kbGVkICdlcnJvcicgZXZlbnRcbiAgICAgIH1cbiAgICAgIHRocm93IFR5cGVFcnJvcignVW5jYXVnaHQsIHVuc3BlY2lmaWVkIFwiZXJyb3JcIiBldmVudC4nKTtcbiAgICB9XG4gIH1cblxuICBoYW5kbGVyID0gdGhpcy5fZXZlbnRzW3R5cGVdO1xuXG4gIGlmIChpc1VuZGVmaW5lZChoYW5kbGVyKSlcbiAgICByZXR1cm4gZmFsc2U7XG5cbiAgaWYgKGlzRnVuY3Rpb24oaGFuZGxlcikpIHtcbiAgICBzd2l0Y2ggKGFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgIC8vIGZhc3QgY2FzZXNcbiAgICAgIGNhc2UgMTpcbiAgICAgICAgaGFuZGxlci5jYWxsKHRoaXMpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMjpcbiAgICAgICAgaGFuZGxlci5jYWxsKHRoaXMsIGFyZ3VtZW50c1sxXSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAzOlxuICAgICAgICBoYW5kbGVyLmNhbGwodGhpcywgYXJndW1lbnRzWzFdLCBhcmd1bWVudHNbMl0pO1xuICAgICAgICBicmVhaztcbiAgICAgIC8vIHNsb3dlclxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgbGVuID0gYXJndW1lbnRzLmxlbmd0aDtcbiAgICAgICAgYXJncyA9IG5ldyBBcnJheShsZW4gLSAxKTtcbiAgICAgICAgZm9yIChpID0gMTsgaSA8IGxlbjsgaSsrKVxuICAgICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgICBoYW5kbGVyLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChpc09iamVjdChoYW5kbGVyKSkge1xuICAgIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgYXJncyA9IG5ldyBBcnJheShsZW4gLSAxKTtcbiAgICBmb3IgKGkgPSAxOyBpIDwgbGVuOyBpKyspXG4gICAgICBhcmdzW2kgLSAxXSA9IGFyZ3VtZW50c1tpXTtcblxuICAgIGxpc3RlbmVycyA9IGhhbmRsZXIuc2xpY2UoKTtcbiAgICBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoO1xuICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKylcbiAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBhcmdzKTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBtO1xuXG4gIGlmICghaXNGdW5jdGlvbihsaXN0ZW5lcikpXG4gICAgdGhyb3cgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcblxuICBpZiAoIXRoaXMuX2V2ZW50cylcbiAgICB0aGlzLl9ldmVudHMgPSB7fTtcblxuICAvLyBUbyBhdm9pZCByZWN1cnNpb24gaW4gdGhlIGNhc2UgdGhhdCB0eXBlID09PSBcIm5ld0xpc3RlbmVyXCIhIEJlZm9yZVxuICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gIGlmICh0aGlzLl9ldmVudHMubmV3TGlzdGVuZXIpXG4gICAgdGhpcy5lbWl0KCduZXdMaXN0ZW5lcicsIHR5cGUsXG4gICAgICAgICAgICAgIGlzRnVuY3Rpb24obGlzdGVuZXIubGlzdGVuZXIpID9cbiAgICAgICAgICAgICAgbGlzdGVuZXIubGlzdGVuZXIgOiBsaXN0ZW5lcik7XG5cbiAgaWYgKCF0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgdGhpcy5fZXZlbnRzW3R5cGVdID0gbGlzdGVuZXI7XG4gIGVsc2UgaWYgKGlzT2JqZWN0KHRoaXMuX2V2ZW50c1t0eXBlXSkpXG4gICAgLy8gSWYgd2UndmUgYWxyZWFkeSBnb3QgYW4gYXJyYXksIGp1c3QgYXBwZW5kLlxuICAgIHRoaXMuX2V2ZW50c1t0eXBlXS5wdXNoKGxpc3RlbmVyKTtcbiAgZWxzZVxuICAgIC8vIEFkZGluZyB0aGUgc2Vjb25kIGVsZW1lbnQsIG5lZWQgdG8gY2hhbmdlIHRvIGFycmF5LlxuICAgIHRoaXMuX2V2ZW50c1t0eXBlXSA9IFt0aGlzLl9ldmVudHNbdHlwZV0sIGxpc3RlbmVyXTtcblxuICAvLyBDaGVjayBmb3IgbGlzdGVuZXIgbGVha1xuICBpZiAoaXNPYmplY3QodGhpcy5fZXZlbnRzW3R5cGVdKSAmJiAhdGhpcy5fZXZlbnRzW3R5cGVdLndhcm5lZCkge1xuICAgIHZhciBtO1xuICAgIGlmICghaXNVbmRlZmluZWQodGhpcy5fbWF4TGlzdGVuZXJzKSkge1xuICAgICAgbSA9IHRoaXMuX21heExpc3RlbmVycztcbiAgICB9IGVsc2Uge1xuICAgICAgbSA9IEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzO1xuICAgIH1cblxuICAgIGlmIChtICYmIG0gPiAwICYmIHRoaXMuX2V2ZW50c1t0eXBlXS5sZW5ndGggPiBtKSB7XG4gICAgICB0aGlzLl9ldmVudHNbdHlwZV0ud2FybmVkID0gdHJ1ZTtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJyhub2RlKSB3YXJuaW5nOiBwb3NzaWJsZSBFdmVudEVtaXR0ZXIgbWVtb3J5ICcgK1xuICAgICAgICAgICAgICAgICAgICAnbGVhayBkZXRlY3RlZC4gJWQgbGlzdGVuZXJzIGFkZGVkLiAnICtcbiAgICAgICAgICAgICAgICAgICAgJ1VzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvIGluY3JlYXNlIGxpbWl0LicsXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2V2ZW50c1t0eXBlXS5sZW5ndGgpO1xuICAgICAgaWYgKHR5cGVvZiBjb25zb2xlLnRyYWNlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIC8vIG5vdCBzdXBwb3J0ZWQgaW4gSUUgMTBcbiAgICAgICAgY29uc29sZS50cmFjZSgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5vbiA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGUuYWRkTGlzdGVuZXI7XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub25jZSA9IGZ1bmN0aW9uKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGlmICghaXNGdW5jdGlvbihsaXN0ZW5lcikpXG4gICAgdGhyb3cgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcblxuICB2YXIgZmlyZWQgPSBmYWxzZTtcblxuICBmdW5jdGlvbiBnKCkge1xuICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIodHlwZSwgZyk7XG5cbiAgICBpZiAoIWZpcmVkKSB7XG4gICAgICBmaXJlZCA9IHRydWU7XG4gICAgICBsaXN0ZW5lci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgfVxuXG4gIGcubGlzdGVuZXIgPSBsaXN0ZW5lcjtcbiAgdGhpcy5vbih0eXBlLCBnKTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cbi8vIGVtaXRzIGEgJ3JlbW92ZUxpc3RlbmVyJyBldmVudCBpZmYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnJlbW92ZUxpc3RlbmVyID0gZnVuY3Rpb24odHlwZSwgbGlzdGVuZXIpIHtcbiAgdmFyIGxpc3QsIHBvc2l0aW9uLCBsZW5ndGgsIGk7XG5cbiAgaWYgKCFpc0Z1bmN0aW9uKGxpc3RlbmVyKSlcbiAgICB0aHJvdyBUeXBlRXJyb3IoJ2xpc3RlbmVyIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuXG4gIGlmICghdGhpcy5fZXZlbnRzIHx8ICF0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgcmV0dXJuIHRoaXM7XG5cbiAgbGlzdCA9IHRoaXMuX2V2ZW50c1t0eXBlXTtcbiAgbGVuZ3RoID0gbGlzdC5sZW5ndGg7XG4gIHBvc2l0aW9uID0gLTE7XG5cbiAgaWYgKGxpc3QgPT09IGxpc3RlbmVyIHx8XG4gICAgICAoaXNGdW5jdGlvbihsaXN0Lmxpc3RlbmVyKSAmJiBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikpIHtcbiAgICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuICAgIGlmICh0aGlzLl9ldmVudHMucmVtb3ZlTGlzdGVuZXIpXG4gICAgICB0aGlzLmVtaXQoJ3JlbW92ZUxpc3RlbmVyJywgdHlwZSwgbGlzdGVuZXIpO1xuXG4gIH0gZWxzZSBpZiAoaXNPYmplY3QobGlzdCkpIHtcbiAgICBmb3IgKGkgPSBsZW5ndGg7IGktLSA+IDA7KSB7XG4gICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHxcbiAgICAgICAgICAobGlzdFtpXS5saXN0ZW5lciAmJiBsaXN0W2ldLmxpc3RlbmVyID09PSBsaXN0ZW5lcikpIHtcbiAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAocG9zaXRpb24gPCAwKVxuICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpIHtcbiAgICAgIGxpc3QubGVuZ3RoID0gMDtcbiAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHNbdHlwZV07XG4gICAgfSBlbHNlIHtcbiAgICAgIGxpc3Quc3BsaWNlKHBvc2l0aW9uLCAxKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgdGhpcy5lbWl0KCdyZW1vdmVMaXN0ZW5lcicsIHR5cGUsIGxpc3RlbmVyKTtcbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBmdW5jdGlvbih0eXBlKSB7XG4gIHZhciBrZXksIGxpc3RlbmVycztcblxuICBpZiAoIXRoaXMuX2V2ZW50cylcbiAgICByZXR1cm4gdGhpcztcblxuICAvLyBub3QgbGlzdGVuaW5nIGZvciByZW1vdmVMaXN0ZW5lciwgbm8gbmVlZCB0byBlbWl0XG4gIGlmICghdGhpcy5fZXZlbnRzLnJlbW92ZUxpc3RlbmVyKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApXG4gICAgICB0aGlzLl9ldmVudHMgPSB7fTtcbiAgICBlbHNlIGlmICh0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLy8gZW1pdCByZW1vdmVMaXN0ZW5lciBmb3IgYWxsIGxpc3RlbmVycyBvbiBhbGwgZXZlbnRzXG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgZm9yIChrZXkgaW4gdGhpcy5fZXZlbnRzKSB7XG4gICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKGtleSk7XG4gICAgfVxuICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgIHRoaXMuX2V2ZW50cyA9IHt9O1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgbGlzdGVuZXJzID0gdGhpcy5fZXZlbnRzW3R5cGVdO1xuXG4gIGlmIChpc0Z1bmN0aW9uKGxpc3RlbmVycykpIHtcbiAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVycyk7XG4gIH0gZWxzZSB7XG4gICAgLy8gTElGTyBvcmRlclxuICAgIHdoaWxlIChsaXN0ZW5lcnMubGVuZ3RoKVxuICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnNbbGlzdGVuZXJzLmxlbmd0aCAtIDFdKTtcbiAgfVxuICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuXG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5saXN0ZW5lcnMgPSBmdW5jdGlvbih0eXBlKSB7XG4gIHZhciByZXQ7XG4gIGlmICghdGhpcy5fZXZlbnRzIHx8ICF0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgcmV0ID0gW107XG4gIGVsc2UgaWYgKGlzRnVuY3Rpb24odGhpcy5fZXZlbnRzW3R5cGVdKSlcbiAgICByZXQgPSBbdGhpcy5fZXZlbnRzW3R5cGVdXTtcbiAgZWxzZVxuICAgIHJldCA9IHRoaXMuX2V2ZW50c1t0eXBlXS5zbGljZSgpO1xuICByZXR1cm4gcmV0O1xufTtcblxuRXZlbnRFbWl0dGVyLmxpc3RlbmVyQ291bnQgPSBmdW5jdGlvbihlbWl0dGVyLCB0eXBlKSB7XG4gIHZhciByZXQ7XG4gIGlmICghZW1pdHRlci5fZXZlbnRzIHx8ICFlbWl0dGVyLl9ldmVudHNbdHlwZV0pXG4gICAgcmV0ID0gMDtcbiAgZWxzZSBpZiAoaXNGdW5jdGlvbihlbWl0dGVyLl9ldmVudHNbdHlwZV0pKVxuICAgIHJldCA9IDE7XG4gIGVsc2VcbiAgICByZXQgPSBlbWl0dGVyLl9ldmVudHNbdHlwZV0ubGVuZ3RoO1xuICByZXR1cm4gcmV0O1xufTtcblxuZnVuY3Rpb24gaXNGdW5jdGlvbihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdmdW5jdGlvbic7XG59XG5cbmZ1bmN0aW9uIGlzTnVtYmVyKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ251bWJlcic7XG59XG5cbmZ1bmN0aW9uIGlzT2JqZWN0KGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ29iamVjdCcgJiYgYXJnICE9PSBudWxsO1xufVxuXG5mdW5jdGlvbiBpc1VuZGVmaW5lZChhcmcpIHtcbiAgcmV0dXJuIGFyZyA9PT0gdm9pZCAwO1xufVxuIiwidmFyICQgPSByZXF1aXJlKFwianF1ZXJ5XCIpO1xuXG52YXIgQWN0aW9uVHlwZXMgPSB7XG4gICAgLy8gQ29ubmVjdGlvblxuICAgIENPTk5FQ1RJT05fT1BFTjogXCJjb25uZWN0aW9uX29wZW5cIixcbiAgICBDT05ORUNUSU9OX0NMT1NFOiBcImNvbm5lY3Rpb25fY2xvc2VcIixcbiAgICBDT05ORUNUSU9OX0VSUk9SOiBcImNvbm5lY3Rpb25fZXJyb3JcIixcblxuICAgIC8vIFN0b3Jlc1xuICAgIFNFVFRJTkdTX1NUT1JFOiBcInNldHRpbmdzXCIsXG4gICAgRVZFTlRfU1RPUkU6IFwiZXZlbnRzXCIsXG4gICAgRkxPV19TVE9SRTogXCJmbG93c1wiLFxufTtcblxudmFyIFN0b3JlQ21kcyA9IHtcbiAgICBBREQ6IFwiYWRkXCIsXG4gICAgVVBEQVRFOiBcInVwZGF0ZVwiLFxuICAgIFJFTU9WRTogXCJyZW1vdmVcIixcbiAgICBSRVNFVDogXCJyZXNldFwiXG59O1xuXG52YXIgQ29ubmVjdGlvbkFjdGlvbnMgPSB7XG4gICAgb3BlbjogZnVuY3Rpb24gKCkge1xuICAgICAgICBBcHBEaXNwYXRjaGVyLmRpc3BhdGNoVmlld0FjdGlvbih7XG4gICAgICAgICAgICB0eXBlOiBBY3Rpb25UeXBlcy5DT05ORUNUSU9OX09QRU5cbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBjbG9zZTogZnVuY3Rpb24gKCkge1xuICAgICAgICBBcHBEaXNwYXRjaGVyLmRpc3BhdGNoVmlld0FjdGlvbih7XG4gICAgICAgICAgICB0eXBlOiBBY3Rpb25UeXBlcy5DT05ORUNUSU9OX0NMT1NFXG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgZXJyb3I6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgQXBwRGlzcGF0Y2hlci5kaXNwYXRjaFZpZXdBY3Rpb24oe1xuICAgICAgICAgICAgdHlwZTogQWN0aW9uVHlwZXMuQ09OTkVDVElPTl9FUlJPUlxuICAgICAgICB9KTtcbiAgICB9XG59O1xuXG52YXIgU2V0dGluZ3NBY3Rpb25zID0ge1xuICAgIHVwZGF0ZTogZnVuY3Rpb24gKHNldHRpbmdzKSB7XG5cbiAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgIHR5cGU6IFwiUFVUXCIsXG4gICAgICAgICAgICB1cmw6IFwiL3NldHRpbmdzXCIsXG4gICAgICAgICAgICBkYXRhOiBzZXR0aW5nc1xuICAgICAgICB9KTtcblxuICAgICAgICAvKlxuICAgICAgICAvL0ZhY2Vib29rIEZsdXg6IFdlIGRvIGFuIG9wdGltaXN0aWMgdXBkYXRlIG9uIHRoZSBjbGllbnQgYWxyZWFkeS5cbiAgICAgICAgQXBwRGlzcGF0Y2hlci5kaXNwYXRjaFZpZXdBY3Rpb24oe1xuICAgICAgICAgICAgdHlwZTogQWN0aW9uVHlwZXMuU0VUVElOR1NfU1RPUkUsXG4gICAgICAgICAgICBjbWQ6IFN0b3JlQ21kcy5VUERBVEUsXG4gICAgICAgICAgICBkYXRhOiBzZXR0aW5nc1xuICAgICAgICB9KTtcbiAgICAgICAgKi9cbiAgICB9XG59O1xuXG52YXIgRXZlbnRMb2dBY3Rpb25zX2V2ZW50X2lkID0gMDtcbnZhciBFdmVudExvZ0FjdGlvbnMgPSB7XG4gICAgYWRkX2V2ZW50OiBmdW5jdGlvbiAobWVzc2FnZSkge1xuICAgICAgICBBcHBEaXNwYXRjaGVyLmRpc3BhdGNoVmlld0FjdGlvbih7XG4gICAgICAgICAgICB0eXBlOiBBY3Rpb25UeXBlcy5FVkVOVF9TVE9SRSxcbiAgICAgICAgICAgIGNtZDogU3RvcmVDbWRzLkFERCxcbiAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBtZXNzYWdlLFxuICAgICAgICAgICAgICAgIGxldmVsOiBcIndlYlwiLFxuICAgICAgICAgICAgICAgIGlkOiBcInZpZXdBY3Rpb24tXCIgKyBFdmVudExvZ0FjdGlvbnNfZXZlbnRfaWQrK1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG59O1xuXG52YXIgRmxvd0FjdGlvbnMgPSB7XG4gICAgYWNjZXB0OiBmdW5jdGlvbiAoZmxvdykge1xuICAgICAgICAkLnBvc3QoXCIvZmxvd3MvXCIgKyBmbG93LmlkICsgXCIvYWNjZXB0XCIpO1xuICAgIH0sXG4gICAgYWNjZXB0X2FsbDogZnVuY3Rpb24oKXtcbiAgICAgICAgJC5wb3N0KFwiL2Zsb3dzL2FjY2VwdFwiKTtcbiAgICB9LFxuICAgIFwiZGVsZXRlXCI6IGZ1bmN0aW9uKGZsb3cpe1xuICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgdHlwZTpcIkRFTEVURVwiLFxuICAgICAgICAgICAgdXJsOiBcIi9mbG93cy9cIiArIGZsb3cuaWRcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBkdXBsaWNhdGU6IGZ1bmN0aW9uKGZsb3cpe1xuICAgICAgICAkLnBvc3QoXCIvZmxvd3MvXCIgKyBmbG93LmlkICsgXCIvZHVwbGljYXRlXCIpO1xuICAgIH0sXG4gICAgcmVwbGF5OiBmdW5jdGlvbihmbG93KXtcbiAgICAgICAgJC5wb3N0KFwiL2Zsb3dzL1wiICsgZmxvdy5pZCArIFwiL3JlcGxheVwiKTtcbiAgICB9LFxuICAgIHJldmVydDogZnVuY3Rpb24oZmxvdyl7XG4gICAgICAgICQucG9zdChcIi9mbG93cy9cIiArIGZsb3cuaWQgKyBcIi9yZXZlcnRcIik7XG4gICAgfSxcbiAgICB1cGRhdGU6IGZ1bmN0aW9uIChmbG93KSB7XG4gICAgICAgIEFwcERpc3BhdGNoZXIuZGlzcGF0Y2hWaWV3QWN0aW9uKHtcbiAgICAgICAgICAgIHR5cGU6IEFjdGlvblR5cGVzLkZMT1dfU1RPUkUsXG4gICAgICAgICAgICBjbWQ6IFN0b3JlQ21kcy5VUERBVEUsXG4gICAgICAgICAgICBkYXRhOiBmbG93XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgY2xlYXI6IGZ1bmN0aW9uKCl7XG4gICAgICAgICQucG9zdChcIi9jbGVhclwiKTtcbiAgICB9XG59O1xuXG5RdWVyeSA9IHtcbiAgICBGSUxURVI6IFwiZlwiLFxuICAgIEhJR0hMSUdIVDogXCJoXCIsXG4gICAgU0hPV19FVkVOVExPRzogXCJlXCJcbn07XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIEFjdGlvblR5cGVzOiBBY3Rpb25UeXBlcyxcbiAgICBDb25uZWN0aW9uQWN0aW9uczogQ29ubmVjdGlvbkFjdGlvbnMsXG4gICAgRmxvd0FjdGlvbnM6IEZsb3dBY3Rpb25zLFxuICAgIFN0b3JlQ21kczogU3RvcmVDbWRzXG59OyIsIlxudmFyIFJlYWN0ID0gcmVxdWlyZShcInJlYWN0XCIpO1xudmFyIFJlYWN0Um91dGVyID0gcmVxdWlyZShcInJlYWN0LXJvdXRlclwiKTtcbnZhciAkID0gcmVxdWlyZShcImpxdWVyeVwiKTtcblxudmFyIENvbm5lY3Rpb24gPSByZXF1aXJlKFwiLi9jb25uZWN0aW9uXCIpO1xudmFyIHByb3h5YXBwID0gcmVxdWlyZShcIi4vY29tcG9uZW50cy9wcm94eWFwcC5qc1wiKTtcblxuJChmdW5jdGlvbiAoKSB7XG4gICAgd2luZG93LndzID0gbmV3IENvbm5lY3Rpb24oXCIvdXBkYXRlc1wiKTtcblxuICAgIFJlYWN0Um91dGVyLnJ1bihwcm94eWFwcC5yb3V0ZXMsIGZ1bmN0aW9uIChIYW5kbGVyKSB7XG4gICAgICAgIFJlYWN0LnJlbmRlcihSZWFjdC5jcmVhdGVFbGVtZW50KEhhbmRsZXIsIG51bGwpLCBkb2N1bWVudC5ib2R5KTtcbiAgICB9KTtcbn0pO1xuXG4iLCJ2YXIgUmVhY3QgPSByZXF1aXJlKFwicmVhY3RcIik7XG52YXIgUmVhY3RSb3V0ZXIgPSByZXF1aXJlKFwicmVhY3Qtcm91dGVyXCIpO1xudmFyIF8gPSByZXF1aXJlKFwibG9kYXNoXCIpO1xuXG4vLyBodHRwOi8vYmxvZy52amV1eC5jb20vMjAxMy9qYXZhc2NyaXB0L3Njcm9sbC1wb3NpdGlvbi13aXRoLXJlYWN0Lmh0bWwgKGFsc28gY29udGFpbnMgaW52ZXJzZSBleGFtcGxlKVxudmFyIEF1dG9TY3JvbGxNaXhpbiA9IHtcbiAgICBjb21wb25lbnRXaWxsVXBkYXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBub2RlID0gdGhpcy5nZXRET01Ob2RlKCk7XG4gICAgICAgIHRoaXMuX3Nob3VsZFNjcm9sbEJvdHRvbSA9IChcbiAgICAgICAgICAgIG5vZGUuc2Nyb2xsVG9wICE9PSAwICYmXG4gICAgICAgICAgICBub2RlLnNjcm9sbFRvcCArIG5vZGUuY2xpZW50SGVpZ2h0ID09PSBub2RlLnNjcm9sbEhlaWdodFxuICAgICAgICApO1xuICAgIH0sXG4gICAgY29tcG9uZW50RGlkVXBkYXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLl9zaG91bGRTY3JvbGxCb3R0b20pIHtcbiAgICAgICAgICAgIHZhciBub2RlID0gdGhpcy5nZXRET01Ob2RlKCk7XG4gICAgICAgICAgICBub2RlLnNjcm9sbFRvcCA9IG5vZGUuc2Nyb2xsSGVpZ2h0O1xuICAgICAgICB9XG4gICAgfSxcbn07XG5cblxudmFyIFN0aWNreUhlYWRNaXhpbiA9IHtcbiAgICBhZGp1c3RIZWFkOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIEFidXNpbmcgQ1NTIHRyYW5zZm9ybXMgdG8gc2V0IHRoZSBlbGVtZW50XG4gICAgICAgIC8vIHJlZmVyZW5jZWQgYXMgaGVhZCBpbnRvIHNvbWUga2luZCBvZiBwb3NpdGlvbjpzdGlja3kuXG4gICAgICAgIHZhciBoZWFkID0gdGhpcy5yZWZzLmhlYWQuZ2V0RE9NTm9kZSgpO1xuICAgICAgICBoZWFkLnN0eWxlLnRyYW5zZm9ybSA9IFwidHJhbnNsYXRlKDAsXCIgKyB0aGlzLmdldERPTU5vZGUoKS5zY3JvbGxUb3AgKyBcInB4KVwiO1xuICAgIH1cbn07XG5cblxudmFyIE5hdmlnYXRpb24gPSBfLmV4dGVuZCh7fSwgUmVhY3RSb3V0ZXIuTmF2aWdhdGlvbiwge1xuICAgIHNldFF1ZXJ5OiBmdW5jdGlvbiAoZGljdCkge1xuICAgICAgICB2YXIgcSA9IHRoaXMuY29udGV4dC5nZXRDdXJyZW50UXVlcnkoKTtcbiAgICAgICAgZm9yKHZhciBpIGluIGRpY3Qpe1xuICAgICAgICAgICAgaWYoZGljdC5oYXNPd25Qcm9wZXJ0eShpKSl7XG4gICAgICAgICAgICAgICAgcVtpXSA9IGRpY3RbaV0gfHwgdW5kZWZpbmVkOyAvL2ZhbHNleSB2YWx1ZXMgc2hhbGwgYmUgcmVtb3ZlZC5cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBxLl8gPSBcIl9cIjsgLy8gd29ya2Fyb3VuZCBmb3IgaHR0cHM6Ly9naXRodWIuY29tL3JhY2t0L3JlYWN0LXJvdXRlci9wdWxsLzU5OVxuICAgICAgICB0aGlzLnJlcGxhY2VXaXRoKHRoaXMuY29udGV4dC5nZXRDdXJyZW50UGF0aCgpLCB0aGlzLmNvbnRleHQuZ2V0Q3VycmVudFBhcmFtcygpLCBxKTtcbiAgICB9LFxuICAgIHJlcGxhY2VXaXRoOiBmdW5jdGlvbihyb3V0ZU5hbWVPclBhdGgsIHBhcmFtcywgcXVlcnkpIHtcbiAgICAgICAgaWYocm91dGVOYW1lT3JQYXRoID09PSB1bmRlZmluZWQpe1xuICAgICAgICAgICAgcm91dGVOYW1lT3JQYXRoID0gdGhpcy5jb250ZXh0LmdldEN1cnJlbnRQYXRoKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYocGFyYW1zID09PSB1bmRlZmluZWQpe1xuICAgICAgICAgICAgcGFyYW1zID0gdGhpcy5jb250ZXh0LmdldEN1cnJlbnRQYXJhbXMoKTtcbiAgICAgICAgfVxuICAgICAgICBpZihxdWVyeSA9PT0gdW5kZWZpbmVkKXtcbiAgICAgICAgICAgIHF1ZXJ5ID0gdGhpcy5jb250ZXh0LmdldEN1cnJlbnRRdWVyeSgpO1xuICAgICAgICB9XG4gICAgICAgIFJlYWN0Um91dGVyLk5hdmlnYXRpb24ucmVwbGFjZVdpdGguY2FsbCh0aGlzLCByb3V0ZU5hbWVPclBhdGgsIHBhcmFtcywgcXVlcnkpO1xuICAgIH1cbn0pO1xuXy5leHRlbmQoTmF2aWdhdGlvbi5jb250ZXh0VHlwZXMsIFJlYWN0Um91dGVyLlN0YXRlLmNvbnRleHRUeXBlcyk7XG5cbnZhciBTdGF0ZSA9IF8uZXh0ZW5kKHt9LCBSZWFjdFJvdXRlci5TdGF0ZSwge1xuICAgIGdldEluaXRpYWxTdGF0ZTogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLl9xdWVyeSA9IHRoaXMuY29udGV4dC5nZXRDdXJyZW50UXVlcnkoKTtcbiAgICAgICAgdGhpcy5fcXVlcnlXYXRjaGVzID0gW107XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH0sXG4gICAgb25RdWVyeUNoYW5nZTogZnVuY3Rpb24gKGtleSwgY2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5fcXVlcnlXYXRjaGVzLnB1c2goe1xuICAgICAgICAgICAga2V5OiBrZXksXG4gICAgICAgICAgICBjYWxsYmFjazogY2FsbGJhY2tcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBjb21wb25lbnRXaWxsUmVjZWl2ZVByb3BzOiBmdW5jdGlvbiAobmV4dFByb3BzLCBuZXh0U3RhdGUpIHtcbiAgICAgICAgdmFyIHEgPSB0aGlzLmNvbnRleHQuZ2V0Q3VycmVudFF1ZXJ5KCk7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fcXVlcnlXYXRjaGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgd2F0Y2ggPSB0aGlzLl9xdWVyeVdhdGNoZXNbaV07XG4gICAgICAgICAgICBpZiAodGhpcy5fcXVlcnlbd2F0Y2gua2V5XSAhPT0gcVt3YXRjaC5rZXldKSB7XG4gICAgICAgICAgICAgICAgd2F0Y2guY2FsbGJhY2sodGhpcy5fcXVlcnlbd2F0Y2gua2V5XSwgcVt3YXRjaC5rZXldLCB3YXRjaC5rZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3F1ZXJ5ID0gcTtcbiAgICB9XG59KTtcblxudmFyIFNwbGl0dGVyID0gUmVhY3QuY3JlYXRlQ2xhc3Moe2Rpc3BsYXlOYW1lOiBcIlNwbGl0dGVyXCIsXG4gICAgZ2V0RGVmYXVsdFByb3BzOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBheGlzOiBcInhcIlxuICAgICAgICB9O1xuICAgIH0sXG4gICAgZ2V0SW5pdGlhbFN0YXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBhcHBsaWVkOiBmYWxzZSxcbiAgICAgICAgICAgIHN0YXJ0WDogZmFsc2UsXG4gICAgICAgICAgICBzdGFydFk6IGZhbHNlXG4gICAgICAgIH07XG4gICAgfSxcbiAgICBvbk1vdXNlRG93bjogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBzdGFydFg6IGUucGFnZVgsXG4gICAgICAgICAgICBzdGFydFk6IGUucGFnZVlcbiAgICAgICAgfSk7XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwibW91c2Vtb3ZlXCIsIHRoaXMub25Nb3VzZU1vdmUpO1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm1vdXNldXBcIiwgdGhpcy5vbk1vdXNlVXApO1xuICAgICAgICAvLyBPY2Nhc2lvbmFsbHksIG9ubHkgYSBkcmFnRW5kIGV2ZW50IGlzIHRyaWdnZXJlZCwgYnV0IG5vIG1vdXNlVXAuXG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwiZHJhZ2VuZFwiLCB0aGlzLm9uRHJhZ0VuZCk7XG4gICAgfSxcbiAgICBvbkRyYWdFbmQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5nZXRET01Ob2RlKCkuc3R5bGUudHJhbnNmb3JtID0gXCJcIjtcbiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJkcmFnZW5kXCIsIHRoaXMub25EcmFnRW5kKTtcbiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJtb3VzZXVwXCIsIHRoaXMub25Nb3VzZVVwKTtcbiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJtb3VzZW1vdmVcIiwgdGhpcy5vbk1vdXNlTW92ZSk7XG4gICAgfSxcbiAgICBvbk1vdXNlVXA6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHRoaXMub25EcmFnRW5kKCk7XG5cbiAgICAgICAgdmFyIG5vZGUgPSB0aGlzLmdldERPTU5vZGUoKTtcbiAgICAgICAgdmFyIHByZXYgPSBub2RlLnByZXZpb3VzRWxlbWVudFNpYmxpbmc7XG4gICAgICAgIHZhciBuZXh0ID0gbm9kZS5uZXh0RWxlbWVudFNpYmxpbmc7XG5cbiAgICAgICAgdmFyIGRYID0gZS5wYWdlWCAtIHRoaXMuc3RhdGUuc3RhcnRYO1xuICAgICAgICB2YXIgZFkgPSBlLnBhZ2VZIC0gdGhpcy5zdGF0ZS5zdGFydFk7XG4gICAgICAgIHZhciBmbGV4QmFzaXM7XG4gICAgICAgIGlmICh0aGlzLnByb3BzLmF4aXMgPT09IFwieFwiKSB7XG4gICAgICAgICAgICBmbGV4QmFzaXMgPSBwcmV2Lm9mZnNldFdpZHRoICsgZFg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmbGV4QmFzaXMgPSBwcmV2Lm9mZnNldEhlaWdodCArIGRZO1xuICAgICAgICB9XG5cbiAgICAgICAgcHJldi5zdHlsZS5mbGV4ID0gXCIwIDAgXCIgKyBNYXRoLm1heCgwLCBmbGV4QmFzaXMpICsgXCJweFwiO1xuICAgICAgICBuZXh0LnN0eWxlLmZsZXggPSBcIjEgMSBhdXRvXCI7XG5cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBhcHBsaWVkOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLm9uUmVzaXplKCk7XG4gICAgfSxcbiAgICBvbk1vdXNlTW92ZTogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIGRYID0gMCwgZFkgPSAwO1xuICAgICAgICBpZiAodGhpcy5wcm9wcy5heGlzID09PSBcInhcIikge1xuICAgICAgICAgICAgZFggPSBlLnBhZ2VYIC0gdGhpcy5zdGF0ZS5zdGFydFg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkWSA9IGUucGFnZVkgLSB0aGlzLnN0YXRlLnN0YXJ0WTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmdldERPTU5vZGUoKS5zdHlsZS50cmFuc2Zvcm0gPSBcInRyYW5zbGF0ZShcIiArIGRYICsgXCJweCxcIiArIGRZICsgXCJweClcIjtcbiAgICB9LFxuICAgIG9uUmVzaXplOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIFRyaWdnZXIgYSBnbG9iYWwgcmVzaXplIGV2ZW50LiBUaGlzIG5vdGlmaWVzIGNvbXBvbmVudHMgdGhhdCBlbXBsb3kgdmlydHVhbCBzY3JvbGxpbmdcbiAgICAgICAgLy8gdGhhdCB0aGVpciB2aWV3cG9ydCBtYXkgaGF2ZSBjaGFuZ2VkLlxuICAgICAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB3aW5kb3cuZGlzcGF0Y2hFdmVudChuZXcgQ3VzdG9tRXZlbnQoXCJyZXNpemVcIikpO1xuICAgICAgICB9LCAxKTtcbiAgICB9LFxuICAgIHJlc2V0OiBmdW5jdGlvbiAod2lsbFVubW91bnQpIHtcbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlLmFwcGxpZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbm9kZSA9IHRoaXMuZ2V0RE9NTm9kZSgpO1xuICAgICAgICB2YXIgcHJldiA9IG5vZGUucHJldmlvdXNFbGVtZW50U2libGluZztcbiAgICAgICAgdmFyIG5leHQgPSBub2RlLm5leHRFbGVtZW50U2libGluZztcblxuICAgICAgICBwcmV2LnN0eWxlLmZsZXggPSBcIlwiO1xuICAgICAgICBuZXh0LnN0eWxlLmZsZXggPSBcIlwiO1xuXG4gICAgICAgIGlmICghd2lsbFVubW91bnQpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgIGFwcGxpZWQ6IGZhbHNlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9uUmVzaXplKCk7XG4gICAgfSxcbiAgICBjb21wb25lbnRXaWxsVW5tb3VudDogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJlc2V0KHRydWUpO1xuICAgIH0sXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjbGFzc05hbWUgPSBcInNwbGl0dGVyXCI7XG4gICAgICAgIGlmICh0aGlzLnByb3BzLmF4aXMgPT09IFwieFwiKSB7XG4gICAgICAgICAgICBjbGFzc05hbWUgKz0gXCIgc3BsaXR0ZXIteFwiO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2xhc3NOYW1lICs9IFwiIHNwbGl0dGVyLXlcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7Y2xhc3NOYW1lOiBjbGFzc05hbWV9LCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtvbk1vdXNlRG93bjogdGhpcy5vbk1vdXNlRG93biwgZHJhZ2dhYmxlOiBcInRydWVcIn0pXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxufSk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIFN0YXRlOiBTdGF0ZSxcbiAgICBOYXZpZ2F0aW9uOiBOYXZpZ2F0aW9uLFxuICAgIFN0aWNreUhlYWRNaXhpbjogU3RpY2t5SGVhZE1peGluLFxuICAgIEF1dG9TY3JvbGxNaXhpbjogQXV0b1Njcm9sbE1peGluLFxuICAgIFNwbGl0dGVyOiBTcGxpdHRlclxufSIsInZhciBSZWFjdCA9IHJlcXVpcmUoXCJyZWFjdFwiKTtcbnZhciBjb21tb24gPSByZXF1aXJlKFwiLi9jb21tb24uanNcIik7XG52YXIgVmlydHVhbFNjcm9sbE1peGluID0gcmVxdWlyZShcIi4vdmlydHVhbHNjcm9sbC5qc1wiKTtcbnZhciB2aWV3cyA9IHJlcXVpcmUoXCIuLi9zdG9yZS92aWV3LmpzXCIpO1xuXG52YXIgTG9nTWVzc2FnZSA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJMb2dNZXNzYWdlXCIsXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBlbnRyeSA9IHRoaXMucHJvcHMuZW50cnk7XG4gICAgICAgIHZhciBpbmRpY2F0b3I7XG4gICAgICAgIHN3aXRjaCAoZW50cnkubGV2ZWwpIHtcbiAgICAgICAgICAgIGNhc2UgXCJ3ZWJcIjpcbiAgICAgICAgICAgICAgICBpbmRpY2F0b3IgPSBSZWFjdC5jcmVhdGVFbGVtZW50KFwiaVwiLCB7Y2xhc3NOYW1lOiBcImZhIGZhLWZ3IGZhLWh0bWw1XCJ9KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJkZWJ1Z1wiOlxuICAgICAgICAgICAgICAgIGluZGljYXRvciA9IFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJpXCIsIHtjbGFzc05hbWU6IFwiZmEgZmEtZncgZmEtYnVnXCJ9KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgaW5kaWNhdG9yID0gUmVhY3QuY3JlYXRlRWxlbWVudChcImlcIiwge2NsYXNzTmFtZTogXCJmYSBmYS1mdyBmYS1pbmZvXCJ9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCBudWxsLCBcbiAgICAgICAgICAgICAgICBpbmRpY2F0b3IsIFwiIFwiLCBlbnRyeS5tZXNzYWdlXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfSxcbiAgICBzaG91bGRDb21wb25lbnRVcGRhdGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBsb2cgZW50cmllcyBhcmUgaW1tdXRhYmxlLlxuICAgIH1cbn0pO1xuXG52YXIgRXZlbnRMb2dDb250ZW50cyA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJFdmVudExvZ0NvbnRlbnRzXCIsXG4gICAgbWl4aW5zOiBbY29tbW9uLkF1dG9TY3JvbGxNaXhpbiwgVmlydHVhbFNjcm9sbE1peGluXSxcbiAgICBnZXRJbml0aWFsU3RhdGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGxvZzogW11cbiAgICAgICAgfTtcbiAgICB9LFxuICAgIGNvbXBvbmVudFdpbGxNb3VudDogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLm9wZW5WaWV3KHRoaXMucHJvcHMuZXZlbnRTdG9yZSk7XG4gICAgfSxcbiAgICBjb21wb25lbnRXaWxsVW5tb3VudDogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNsb3NlVmlldygpO1xuICAgIH0sXG4gICAgb3BlblZpZXc6IGZ1bmN0aW9uIChzdG9yZSkge1xuICAgICAgICB2YXIgdmlldyA9IG5ldyB2aWV3cy5TdG9yZVZpZXcoc3RvcmUsIGZ1bmN0aW9uIChlbnRyeSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJvcHMuZmlsdGVyW2VudHJ5LmxldmVsXTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICB2aWV3OiB2aWV3XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZpZXcuYWRkTGlzdGVuZXIoXCJhZGQgcmVjYWxjdWxhdGVcIiwgdGhpcy5vbkV2ZW50TG9nQ2hhbmdlKTtcbiAgICB9LFxuICAgIGNsb3NlVmlldzogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnN0YXRlLnZpZXcuY2xvc2UoKTtcbiAgICB9LFxuICAgIG9uRXZlbnRMb2dDaGFuZ2U6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBsb2c6IHRoaXMuc3RhdGUudmlldy5saXN0XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgY29tcG9uZW50V2lsbFJlY2VpdmVQcm9wczogZnVuY3Rpb24gKG5leHRQcm9wcykge1xuICAgICAgICBpZiAobmV4dFByb3BzLmZpbHRlciAhPT0gdGhpcy5wcm9wcy5maWx0ZXIpIHtcbiAgICAgICAgICAgIHRoaXMucHJvcHMuZmlsdGVyID0gbmV4dFByb3BzLmZpbHRlcjsgLy8gRGlydHk6IE1ha2Ugc3VyZSB0aGF0IHZpZXcgZmlsdGVyIHNlZXMgdGhlIHVwZGF0ZS5cbiAgICAgICAgICAgIHRoaXMuc3RhdGUudmlldy5yZWNhbGN1bGF0ZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChuZXh0UHJvcHMuZXZlbnRTdG9yZSAhPT0gdGhpcy5wcm9wcy5ldmVudFN0b3JlKSB7XG4gICAgICAgICAgICB0aGlzLmNsb3NlVmlldygpO1xuICAgICAgICAgICAgdGhpcy5vcGVuVmlldyhuZXh0UHJvcHMuZXZlbnRTdG9yZSk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGdldERlZmF1bHRQcm9wczogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcm93SGVpZ2h0OiA0NSxcbiAgICAgICAgICAgIHJvd0hlaWdodE1pbjogMTUsXG4gICAgICAgICAgICBwbGFjZWhvbGRlclRhZ05hbWU6IFwiZGl2XCJcbiAgICAgICAgfTtcbiAgICB9LFxuICAgIHJlbmRlclJvdzogZnVuY3Rpb24gKGVsZW0pIHtcbiAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoTG9nTWVzc2FnZSwge2tleTogZWxlbS5pZCwgZW50cnk6IGVsZW19KTtcbiAgICB9LFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcm93cyA9IHRoaXMucmVuZGVyUm93cyh0aGlzLnN0YXRlLmxvZyk7XG5cbiAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJwcmVcIiwge29uU2Nyb2xsOiB0aGlzLm9uU2Nyb2xsfSwgXG4gICAgICAgICAgICAgdGhpcy5nZXRQbGFjZWhvbGRlclRvcCh0aGlzLnN0YXRlLmxvZy5sZW5ndGgpLCBcbiAgICAgICAgICAgIHJvd3MsIFxuICAgICAgICAgICAgIHRoaXMuZ2V0UGxhY2Vob2xkZXJCb3R0b20odGhpcy5zdGF0ZS5sb2cubGVuZ3RoKSBcbiAgICAgICAgKTtcbiAgICB9XG59KTtcblxudmFyIFRvZ2dsZUZpbHRlciA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJUb2dnbGVGaWx0ZXJcIixcbiAgICB0b2dnbGU6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMucHJvcHMudG9nZ2xlTGV2ZWwodGhpcy5wcm9wcy5uYW1lKTtcbiAgICB9LFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY2xhc3NOYW1lID0gXCJsYWJlbCBcIjtcbiAgICAgICAgaWYgKHRoaXMucHJvcHMuYWN0aXZlKSB7XG4gICAgICAgICAgICBjbGFzc05hbWUgKz0gXCJsYWJlbC1wcmltYXJ5XCI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjbGFzc05hbWUgKz0gXCJsYWJlbC1kZWZhdWx0XCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJhXCIsIHtcbiAgICAgICAgICAgICAgICBocmVmOiBcIiNcIiwgXG4gICAgICAgICAgICAgICAgY2xhc3NOYW1lOiBjbGFzc05hbWUsIFxuICAgICAgICAgICAgICAgIG9uQ2xpY2s6IHRoaXMudG9nZ2xlfSwgXG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wcy5uYW1lXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxufSk7XG5cbnZhciBFdmVudExvZyA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJFdmVudExvZ1wiLFxuICAgIGdldEluaXRpYWxTdGF0ZTogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZmlsdGVyOiB7XG4gICAgICAgICAgICAgICAgXCJkZWJ1Z1wiOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBcImluZm9cIjogdHJ1ZSxcbiAgICAgICAgICAgICAgICBcIndlYlwiOiB0cnVlXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfSxcbiAgICBjbG9zZTogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZCA9IHt9O1xuICAgICAgICBkW1F1ZXJ5LlNIT1dfRVZFTlRMT0ddID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLnNldFF1ZXJ5KGQpO1xuICAgIH0sXG4gICAgdG9nZ2xlTGV2ZWw6IGZ1bmN0aW9uIChsZXZlbCkge1xuICAgICAgICB2YXIgZmlsdGVyID0gXy5leHRlbmQoe30sIHRoaXMuc3RhdGUuZmlsdGVyKTtcbiAgICAgICAgZmlsdGVyW2xldmVsXSA9ICFmaWx0ZXJbbGV2ZWxdO1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtmaWx0ZXI6IGZpbHRlcn0pO1xuICAgIH0sXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtjbGFzc05hbWU6IFwiZXZlbnRsb2dcIn0sIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgbnVsbCwgXG4gICAgICAgICAgICAgICAgICAgIFwiRXZlbnRsb2dcIiwgXG4gICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwge2NsYXNzTmFtZTogXCJwdWxsLXJpZ2h0XCJ9LCBcbiAgICAgICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoVG9nZ2xlRmlsdGVyLCB7bmFtZTogXCJkZWJ1Z1wiLCBhY3RpdmU6IHRoaXMuc3RhdGUuZmlsdGVyLmRlYnVnLCB0b2dnbGVMZXZlbDogdGhpcy50b2dnbGVMZXZlbH0pLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoVG9nZ2xlRmlsdGVyLCB7bmFtZTogXCJpbmZvXCIsIGFjdGl2ZTogdGhpcy5zdGF0ZS5maWx0ZXIuaW5mbywgdG9nZ2xlTGV2ZWw6IHRoaXMudG9nZ2xlTGV2ZWx9KSwgXG4gICAgICAgICAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFRvZ2dsZUZpbHRlciwge25hbWU6IFwid2ViXCIsIGFjdGl2ZTogdGhpcy5zdGF0ZS5maWx0ZXIud2ViLCB0b2dnbGVMZXZlbDogdGhpcy50b2dnbGVMZXZlbH0pLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJpXCIsIHtvbkNsaWNrOiB0aGlzLmNsb3NlLCBjbGFzc05hbWU6IFwiZmEgZmEtY2xvc2VcIn0pXG4gICAgICAgICAgICAgICAgICAgIClcblxuICAgICAgICAgICAgICAgICksIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoRXZlbnRMb2dDb250ZW50cywge2ZpbHRlcjogdGhpcy5zdGF0ZS5maWx0ZXIsIGV2ZW50U3RvcmU6IHRoaXMucHJvcHMuZXZlbnRTdG9yZX0pXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxufSk7XG5cbm1vZHVsZS5leHBvcnRzID0gRXZlbnRMb2c7IiwidmFyIFJlYWN0ID0gcmVxdWlyZShcInJlYWN0XCIpO1xudmFyIF8gPSByZXF1aXJlKFwibG9kYXNoXCIpO1xuXG52YXIgY29tbW9uID0gcmVxdWlyZShcIi4vY29tbW9uLmpzXCIpO1xudmFyIGFjdGlvbnMgPSByZXF1aXJlKFwiLi4vYWN0aW9ucy5qc1wiKTtcbnZhciBmbG93dXRpbHMgPSByZXF1aXJlKFwiLi4vZmxvdy91dGlscy5qc1wiKTtcbnZhciB0b3B1dGlscyA9IHJlcXVpcmUoXCIuLi91dGlscy5qc1wiKTtcblxudmFyIE5hdkFjdGlvbiA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJOYXZBY3Rpb25cIixcbiAgICBvbkNsaWNrOiBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHRoaXMucHJvcHMub25DbGljaygpO1xuICAgIH0sXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiYVwiLCB7dGl0bGU6IHRoaXMucHJvcHMudGl0bGUsIFxuICAgICAgICAgICAgICAgIGhyZWY6IFwiI1wiLCBcbiAgICAgICAgICAgICAgICBjbGFzc05hbWU6IFwibmF2LWFjdGlvblwiLCBcbiAgICAgICAgICAgICAgICBvbkNsaWNrOiB0aGlzLm9uQ2xpY2t9LCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiaVwiLCB7Y2xhc3NOYW1lOiBcImZhIGZhLWZ3IFwiICsgdGhpcy5wcm9wcy5pY29ufSlcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG59KTtcblxudmFyIEZsb3dEZXRhaWxOYXYgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiRmxvd0RldGFpbE5hdlwiLFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZmxvdyA9IHRoaXMucHJvcHMuZmxvdztcblxuICAgICAgICB2YXIgdGFicyA9IHRoaXMucHJvcHMudGFicy5tYXAoZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIHZhciBzdHIgPSBlLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgZS5zbGljZSgxKTtcbiAgICAgICAgICAgIHZhciBjbGFzc05hbWUgPSB0aGlzLnByb3BzLmFjdGl2ZSA9PT0gZSA/IFwiYWN0aXZlXCIgOiBcIlwiO1xuICAgICAgICAgICAgdmFyIG9uQ2xpY2sgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BzLnNlbGVjdFRhYihlKTtcbiAgICAgICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgfS5iaW5kKHRoaXMpO1xuICAgICAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJhXCIsIHtrZXk6IGUsIFxuICAgICAgICAgICAgICAgIGhyZWY6IFwiI1wiLCBcbiAgICAgICAgICAgICAgICBjbGFzc05hbWU6IGNsYXNzTmFtZSwgXG4gICAgICAgICAgICAgICAgb25DbGljazogb25DbGlja30sIHN0cik7XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG5cbiAgICAgICAgdmFyIGFjY2VwdEJ1dHRvbiA9IG51bGw7XG4gICAgICAgIGlmKGZsb3cuaW50ZXJjZXB0ZWQpe1xuICAgICAgICAgICAgYWNjZXB0QnV0dG9uID0gUmVhY3QuY3JlYXRlRWxlbWVudChOYXZBY3Rpb24sIHt0aXRsZTogXCJbYV1jY2VwdCBpbnRlcmNlcHRlZCBmbG93XCIsIGljb246IFwiZmEtcGxheVwiLCBvbkNsaWNrOiBhY3Rpb25zLkZsb3dBY3Rpb25zLmFjY2VwdC5iaW5kKG51bGwsIGZsb3cpfSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJldmVydEJ1dHRvbiA9IG51bGw7XG4gICAgICAgIGlmKGZsb3cubW9kaWZpZWQpe1xuICAgICAgICAgICAgcmV2ZXJ0QnV0dG9uID0gUmVhY3QuY3JlYXRlRWxlbWVudChOYXZBY3Rpb24sIHt0aXRsZTogXCJyZXZlcnQgY2hhbmdlcyB0byBmbG93IFtWXVwiLCBpY29uOiBcImZhLWhpc3RvcnlcIiwgb25DbGljazogYWN0aW9ucy5GbG93QWN0aW9ucy5yZXZlcnQuYmluZChudWxsLCBmbG93KX0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJuYXZcIiwge3JlZjogXCJoZWFkXCIsIGNsYXNzTmFtZTogXCJuYXYtdGFicyBuYXYtdGFicy1zbVwifSwgXG4gICAgICAgICAgICAgICAgdGFicywgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChOYXZBY3Rpb24sIHt0aXRsZTogXCJbZF1lbGV0ZSBmbG93XCIsIGljb246IFwiZmEtdHJhc2hcIiwgb25DbGljazogYWN0aW9ucy5GbG93QWN0aW9ucy5kZWxldGUuYmluZChudWxsLCBmbG93KX0pLCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KE5hdkFjdGlvbiwge3RpdGxlOiBcIltEXXVwbGljYXRlIGZsb3dcIiwgaWNvbjogXCJmYS1jb3B5XCIsIG9uQ2xpY2s6IGFjdGlvbnMuRmxvd0FjdGlvbnMuZHVwbGljYXRlLmJpbmQobnVsbCwgZmxvdyl9KSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChOYXZBY3Rpb24sIHtkaXNhYmxlZDogdHJ1ZSwgdGl0bGU6IFwiW3JdZXBsYXkgZmxvd1wiLCBpY29uOiBcImZhLXJlcGVhdFwiLCBvbkNsaWNrOiBhY3Rpb25zLkZsb3dBY3Rpb25zLnJlcGxheS5iaW5kKG51bGwsIGZsb3cpfSksIFxuICAgICAgICAgICAgICAgIGFjY2VwdEJ1dHRvbiwgXG4gICAgICAgICAgICAgICAgcmV2ZXJ0QnV0dG9uXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxufSk7XG5cbnZhciBIZWFkZXJzID0gUmVhY3QuY3JlYXRlQ2xhc3Moe2Rpc3BsYXlOYW1lOiBcIkhlYWRlcnNcIixcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJvd3MgPSB0aGlzLnByb3BzLm1lc3NhZ2UuaGVhZGVycy5tYXAoZnVuY3Rpb24gKGhlYWRlciwgaSkge1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidHJcIiwge2tleTogaX0sIFxuICAgICAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGRcIiwge2NsYXNzTmFtZTogXCJoZWFkZXItbmFtZVwifSwgaGVhZGVyWzBdICsgXCI6XCIpLCBcbiAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcInRkXCIsIHtjbGFzc05hbWU6IFwiaGVhZGVyLXZhbHVlXCJ9LCBoZWFkZXJbMV0pXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGFibGVcIiwge2NsYXNzTmFtZTogXCJoZWFkZXItdGFibGVcIn0sIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0Ym9keVwiLCBudWxsLCBcbiAgICAgICAgICAgICAgICAgICAgcm93c1xuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG59KTtcblxudmFyIEZsb3dEZXRhaWxSZXF1ZXN0ID0gUmVhY3QuY3JlYXRlQ2xhc3Moe2Rpc3BsYXlOYW1lOiBcIkZsb3dEZXRhaWxSZXF1ZXN0XCIsXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBmbG93ID0gdGhpcy5wcm9wcy5mbG93O1xuICAgICAgICB2YXIgZmlyc3RfbGluZSA9IFtcbiAgICAgICAgICAgIGZsb3cucmVxdWVzdC5tZXRob2QsXG4gICAgICAgICAgICBmbG93dXRpbHMuUmVxdWVzdFV0aWxzLnByZXR0eV91cmwoZmxvdy5yZXF1ZXN0KSxcbiAgICAgICAgICAgIFwiSFRUUC9cIiArIGZsb3cucmVxdWVzdC5odHRwdmVyc2lvbi5qb2luKFwiLlwiKVxuICAgICAgICBdLmpvaW4oXCIgXCIpO1xuICAgICAgICB2YXIgY29udGVudCA9IG51bGw7XG4gICAgICAgIGlmIChmbG93LnJlcXVlc3QuY29udGVudExlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGNvbnRlbnQgPSBcIlJlcXVlc3QgQ29udGVudCBTaXplOiBcIiArIHRvcHV0aWxzLmZvcm1hdFNpemUoZmxvdy5yZXF1ZXN0LmNvbnRlbnRMZW5ndGgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29udGVudCA9IFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwge2NsYXNzTmFtZTogXCJhbGVydCBhbGVydC1pbmZvXCJ9LCBcIk5vIENvbnRlbnRcIik7XG4gICAgICAgIH1cblxuICAgICAgICAvL1RPRE86IFN0eWxpbmdcblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcInNlY3Rpb25cIiwgbnVsbCwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7Y2xhc3NOYW1lOiBcImZpcnN0LWxpbmVcIn0sIGZpcnN0X2xpbmUgKSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChIZWFkZXJzLCB7bWVzc2FnZTogZmxvdy5yZXF1ZXN0fSksIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJoclwiLCBudWxsKSwgXG4gICAgICAgICAgICAgICAgY29udGVudFxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG52YXIgRmxvd0RldGFpbFJlc3BvbnNlID0gUmVhY3QuY3JlYXRlQ2xhc3Moe2Rpc3BsYXlOYW1lOiBcIkZsb3dEZXRhaWxSZXNwb25zZVwiLFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZmxvdyA9IHRoaXMucHJvcHMuZmxvdztcbiAgICAgICAgdmFyIGZpcnN0X2xpbmUgPSBbXG4gICAgICAgICAgICBcIkhUVFAvXCIgKyBmbG93LnJlc3BvbnNlLmh0dHB2ZXJzaW9uLmpvaW4oXCIuXCIpLFxuICAgICAgICAgICAgZmxvdy5yZXNwb25zZS5jb2RlLFxuICAgICAgICAgICAgZmxvdy5yZXNwb25zZS5tc2dcbiAgICAgICAgXS5qb2luKFwiIFwiKTtcbiAgICAgICAgdmFyIGNvbnRlbnQgPSBudWxsO1xuICAgICAgICBpZiAoZmxvdy5yZXNwb25zZS5jb250ZW50TGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY29udGVudCA9IFwiUmVzcG9uc2UgQ29udGVudCBTaXplOiBcIiArIHRvcHV0aWxzLmZvcm1hdFNpemUoZmxvdy5yZXNwb25zZS5jb250ZW50TGVuZ3RoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnRlbnQgPSBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtjbGFzc05hbWU6IFwiYWxlcnQgYWxlcnQtaW5mb1wifSwgXCJObyBDb250ZW50XCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy9UT0RPOiBTdHlsaW5nXG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJzZWN0aW9uXCIsIG51bGwsIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwge2NsYXNzTmFtZTogXCJmaXJzdC1saW5lXCJ9LCBmaXJzdF9saW5lICksIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoSGVhZGVycywge21lc3NhZ2U6IGZsb3cucmVzcG9uc2V9KSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImhyXCIsIG51bGwpLCBcbiAgICAgICAgICAgICAgICBjb250ZW50XG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxufSk7XG5cbnZhciBGbG93RGV0YWlsRXJyb3IgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiRmxvd0RldGFpbEVycm9yXCIsXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBmbG93ID0gdGhpcy5wcm9wcy5mbG93O1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcInNlY3Rpb25cIiwgbnVsbCwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7Y2xhc3NOYW1lOiBcImFsZXJ0IGFsZXJ0LXdhcm5pbmdcIn0sIFxuICAgICAgICAgICAgICAgIGZsb3cuZXJyb3IubXNnLCBcbiAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCBudWxsLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJzbWFsbFwiLCBudWxsLCAgdG9wdXRpbHMuZm9ybWF0VGltZVN0YW1wKGZsb3cuZXJyb3IudGltZXN0YW1wKSApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxufSk7XG5cbnZhciBUaW1lU3RhbXAgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiVGltZVN0YW1wXCIsXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG5cbiAgICAgICAgaWYgKCF0aGlzLnByb3BzLnQpIHtcbiAgICAgICAgICAgIC8vc2hvdWxkIGJlIHJldHVybiBudWxsLCBidXQgdGhhdCB0cmlnZ2VycyBhIFJlYWN0IGJ1Zy5cbiAgICAgICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFwidHJcIiwgbnVsbCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdHMgPSB0b3B1dGlscy5mb3JtYXRUaW1lU3RhbXAodGhpcy5wcm9wcy50KTtcblxuICAgICAgICB2YXIgZGVsdGE7XG4gICAgICAgIGlmICh0aGlzLnByb3BzLmRlbHRhVG8pIHtcbiAgICAgICAgICAgIGRlbHRhID0gdG9wdXRpbHMuZm9ybWF0VGltZURlbHRhKDEwMDAgKiAodGhpcy5wcm9wcy50IC0gdGhpcy5wcm9wcy5kZWx0YVRvKSk7XG4gICAgICAgICAgICBkZWx0YSA9IFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIsIHtjbGFzc05hbWU6IFwidGV4dC1tdXRlZFwifSwgXCIoXCIgKyBkZWx0YSArIFwiKVwiKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRlbHRhID0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFwidHJcIiwgbnVsbCwgXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGRcIiwgbnVsbCwgdGhpcy5wcm9wcy50aXRsZSArIFwiOlwiKSwgXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGRcIiwgbnVsbCwgdHMsIFwiIFwiLCBkZWx0YSlcbiAgICAgICAgKTtcbiAgICB9XG59KTtcblxudmFyIENvbm5lY3Rpb25JbmZvID0gUmVhY3QuY3JlYXRlQ2xhc3Moe2Rpc3BsYXlOYW1lOiBcIkNvbm5lY3Rpb25JbmZvXCIsXG5cbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNvbm4gPSB0aGlzLnByb3BzLmNvbm47XG4gICAgICAgIHZhciBhZGRyZXNzID0gY29ubi5hZGRyZXNzLmFkZHJlc3Muam9pbihcIjpcIik7XG5cbiAgICAgICAgdmFyIHNuaSA9IFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0clwiLCB7a2V5OiBcInNuaVwifSk7IC8vc2hvdWxkIGJlIG51bGwsIGJ1dCB0aGF0IHRyaWdnZXJzIGEgUmVhY3QgYnVnLlxuICAgICAgICBpZiAoY29ubi5zbmkpIHtcbiAgICAgICAgICAgIHNuaSA9IFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0clwiLCB7a2V5OiBcInNuaVwifSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcInRkXCIsIG51bGwsIFxuICAgICAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiYWJiclwiLCB7dGl0bGU6IFwiVExTIFNlcnZlciBOYW1lIEluZGljYXRpb25cIn0sIFwiVExTIFNOSTpcIilcbiAgICAgICAgICAgICAgICApLCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGRcIiwgbnVsbCwgY29ubi5zbmkpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGFibGVcIiwge2NsYXNzTmFtZTogXCJjb25uZWN0aW9uLXRhYmxlXCJ9LCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGJvZHlcIiwgbnVsbCwgXG4gICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0clwiLCB7a2V5OiBcImFkZHJlc3NcIn0sIFxuICAgICAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcInRkXCIsIG51bGwsIFwiQWRkcmVzczpcIiksIFxuICAgICAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcInRkXCIsIG51bGwsIGFkZHJlc3MpXG4gICAgICAgICAgICAgICAgICAgICksIFxuICAgICAgICAgICAgICAgICAgICBzbmlcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxufSk7XG5cbnZhciBDZXJ0aWZpY2F0ZUluZm8gPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiQ2VydGlmaWNhdGVJbmZvXCIsXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vVE9ETzogV2Ugc2hvdWxkIGZldGNoIGh1bWFuLXJlYWRhYmxlIGNlcnRpZmljYXRlIHJlcHJlc2VudGF0aW9uXG4gICAgICAgIC8vIGZyb20gdGhlIHNlcnZlclxuICAgICAgICB2YXIgZmxvdyA9IHRoaXMucHJvcHMuZmxvdztcbiAgICAgICAgdmFyIGNsaWVudF9jb25uID0gZmxvdy5jbGllbnRfY29ubjtcbiAgICAgICAgdmFyIHNlcnZlcl9jb25uID0gZmxvdy5zZXJ2ZXJfY29ubjtcblxuICAgICAgICB2YXIgcHJlU3R5bGUgPSB7bWF4SGVpZ2h0OiAxMDB9O1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCBudWxsLCBcbiAgICAgICAgICAgIGNsaWVudF9jb25uLmNlcnQgPyBSZWFjdC5jcmVhdGVFbGVtZW50KFwiaDRcIiwgbnVsbCwgXCJDbGllbnQgQ2VydGlmaWNhdGVcIikgOiBudWxsLCBcbiAgICAgICAgICAgIGNsaWVudF9jb25uLmNlcnQgPyBSZWFjdC5jcmVhdGVFbGVtZW50KFwicHJlXCIsIHtzdHlsZTogcHJlU3R5bGV9LCBjbGllbnRfY29ubi5jZXJ0KSA6IG51bGwsIFxuXG4gICAgICAgICAgICBzZXJ2ZXJfY29ubi5jZXJ0ID8gUmVhY3QuY3JlYXRlRWxlbWVudChcImg0XCIsIG51bGwsIFwiU2VydmVyIENlcnRpZmljYXRlXCIpIDogbnVsbCwgXG4gICAgICAgICAgICBzZXJ2ZXJfY29ubi5jZXJ0ID8gUmVhY3QuY3JlYXRlRWxlbWVudChcInByZVwiLCB7c3R5bGU6IHByZVN0eWxlfSwgc2VydmVyX2Nvbm4uY2VydCkgOiBudWxsXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxufSk7XG5cbnZhciBUaW1pbmcgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiVGltaW5nXCIsXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBmbG93ID0gdGhpcy5wcm9wcy5mbG93O1xuICAgICAgICB2YXIgc2MgPSBmbG93LnNlcnZlcl9jb25uO1xuICAgICAgICB2YXIgY2MgPSBmbG93LmNsaWVudF9jb25uO1xuICAgICAgICB2YXIgcmVxID0gZmxvdy5yZXF1ZXN0O1xuICAgICAgICB2YXIgcmVzcCA9IGZsb3cucmVzcG9uc2U7XG5cbiAgICAgICAgdmFyIHRpbWVzdGFtcHMgPSBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdGl0bGU6IFwiU2VydmVyIGNvbm4uIGluaXRpYXRlZFwiLFxuICAgICAgICAgICAgICAgIHQ6IHNjLnRpbWVzdGFtcF9zdGFydCxcbiAgICAgICAgICAgICAgICBkZWx0YVRvOiByZXEudGltZXN0YW1wX3N0YXJ0XG4gICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgdGl0bGU6IFwiU2VydmVyIGNvbm4uIFRDUCBoYW5kc2hha2VcIixcbiAgICAgICAgICAgICAgICB0OiBzYy50aW1lc3RhbXBfdGNwX3NldHVwLFxuICAgICAgICAgICAgICAgIGRlbHRhVG86IHJlcS50aW1lc3RhbXBfc3RhcnRcbiAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICB0aXRsZTogXCJTZXJ2ZXIgY29ubi4gU1NMIGhhbmRzaGFrZVwiLFxuICAgICAgICAgICAgICAgIHQ6IHNjLnRpbWVzdGFtcF9zc2xfc2V0dXAsXG4gICAgICAgICAgICAgICAgZGVsdGFUbzogcmVxLnRpbWVzdGFtcF9zdGFydFxuICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgIHRpdGxlOiBcIkNsaWVudCBjb25uLiBlc3RhYmxpc2hlZFwiLFxuICAgICAgICAgICAgICAgIHQ6IGNjLnRpbWVzdGFtcF9zdGFydCxcbiAgICAgICAgICAgICAgICBkZWx0YVRvOiByZXEudGltZXN0YW1wX3N0YXJ0XG4gICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgdGl0bGU6IFwiQ2xpZW50IGNvbm4uIFNTTCBoYW5kc2hha2VcIixcbiAgICAgICAgICAgICAgICB0OiBjYy50aW1lc3RhbXBfc3NsX3NldHVwLFxuICAgICAgICAgICAgICAgIGRlbHRhVG86IHJlcS50aW1lc3RhbXBfc3RhcnRcbiAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICB0aXRsZTogXCJGaXJzdCByZXF1ZXN0IGJ5dGVcIixcbiAgICAgICAgICAgICAgICB0OiByZXEudGltZXN0YW1wX3N0YXJ0LFxuICAgICAgICAgICAgfSwge1xuICAgICAgICAgICAgICAgIHRpdGxlOiBcIlJlcXVlc3QgY29tcGxldGVcIixcbiAgICAgICAgICAgICAgICB0OiByZXEudGltZXN0YW1wX2VuZCxcbiAgICAgICAgICAgICAgICBkZWx0YVRvOiByZXEudGltZXN0YW1wX3N0YXJ0XG4gICAgICAgICAgICB9XG4gICAgICAgIF07XG5cbiAgICAgICAgaWYgKGZsb3cucmVzcG9uc2UpIHtcbiAgICAgICAgICAgIHRpbWVzdGFtcHMucHVzaChcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHRpdGxlOiBcIkZpcnN0IHJlc3BvbnNlIGJ5dGVcIixcbiAgICAgICAgICAgICAgICAgICAgdDogcmVzcC50aW1lc3RhbXBfc3RhcnQsXG4gICAgICAgICAgICAgICAgICAgIGRlbHRhVG86IHJlcS50aW1lc3RhbXBfc3RhcnRcbiAgICAgICAgICAgICAgICB9LCB7XG4gICAgICAgICAgICAgICAgICAgIHRpdGxlOiBcIlJlc3BvbnNlIGNvbXBsZXRlXCIsXG4gICAgICAgICAgICAgICAgICAgIHQ6IHJlc3AudGltZXN0YW1wX2VuZCxcbiAgICAgICAgICAgICAgICAgICAgZGVsdGFUbzogcmVxLnRpbWVzdGFtcF9zdGFydFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICAvL0FkZCB1bmlxdWUga2V5IGZvciBlYWNoIHJvdy5cbiAgICAgICAgdGltZXN0YW1wcy5mb3JFYWNoKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICBlLmtleSA9IGUudGl0bGU7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRpbWVzdGFtcHMgPSBfLnNvcnRCeSh0aW1lc3RhbXBzLCAndCcpO1xuXG4gICAgICAgIHZhciByb3dzID0gdGltZXN0YW1wcy5tYXAoZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFRpbWVTdGFtcCwgUmVhY3QuX19zcHJlYWQoe30sICBlKSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIG51bGwsIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJoNFwiLCBudWxsLCBcIlRpbWluZ1wiKSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcInRhYmxlXCIsIHtjbGFzc05hbWU6IFwidGltaW5nLXRhYmxlXCJ9LCBcbiAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcInRib2R5XCIsIG51bGwsIFxuICAgICAgICAgICAgICAgICAgICByb3dzXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxufSk7XG5cbnZhciBGbG93RGV0YWlsQ29ubmVjdGlvbkluZm8gPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiRmxvd0RldGFpbENvbm5lY3Rpb25JbmZvXCIsXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBmbG93ID0gdGhpcy5wcm9wcy5mbG93O1xuICAgICAgICB2YXIgY2xpZW50X2Nvbm4gPSBmbG93LmNsaWVudF9jb25uO1xuICAgICAgICB2YXIgc2VydmVyX2Nvbm4gPSBmbG93LnNlcnZlcl9jb25uO1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcInNlY3Rpb25cIiwgbnVsbCwgXG5cbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiaDRcIiwgbnVsbCwgXCJDbGllbnQgQ29ubmVjdGlvblwiKSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChDb25uZWN0aW9uSW5mbywge2Nvbm46IGNsaWVudF9jb25ufSksIFxuXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImg0XCIsIG51bGwsIFwiU2VydmVyIENvbm5lY3Rpb25cIiksIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoQ29ubmVjdGlvbkluZm8sIHtjb25uOiBzZXJ2ZXJfY29ubn0pLCBcblxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoQ2VydGlmaWNhdGVJbmZvLCB7ZmxvdzogZmxvd30pLCBcblxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoVGltaW5nLCB7ZmxvdzogZmxvd30pXG5cbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG59KTtcblxudmFyIGFsbFRhYnMgPSB7XG4gICAgcmVxdWVzdDogRmxvd0RldGFpbFJlcXVlc3QsXG4gICAgcmVzcG9uc2U6IEZsb3dEZXRhaWxSZXNwb25zZSxcbiAgICBlcnJvcjogRmxvd0RldGFpbEVycm9yLFxuICAgIGRldGFpbHM6IEZsb3dEZXRhaWxDb25uZWN0aW9uSW5mb1xufTtcblxudmFyIEZsb3dEZXRhaWwgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiRmxvd0RldGFpbFwiLFxuICAgIG1peGluczogW2NvbW1vbi5TdGlja3lIZWFkTWl4aW4sIGNvbW1vbi5OYXZpZ2F0aW9uLCBjb21tb24uU3RhdGVdLFxuICAgIGdldFRhYnM6IGZ1bmN0aW9uIChmbG93KSB7XG4gICAgICAgIHZhciB0YWJzID0gW107XG4gICAgICAgIFtcInJlcXVlc3RcIiwgXCJyZXNwb25zZVwiLCBcImVycm9yXCJdLmZvckVhY2goZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGlmIChmbG93W2VdKSB7XG4gICAgICAgICAgICAgICAgdGFicy5wdXNoKGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdGFicy5wdXNoKFwiZGV0YWlsc1wiKTtcbiAgICAgICAgcmV0dXJuIHRhYnM7XG4gICAgfSxcbiAgICBuZXh0VGFiOiBmdW5jdGlvbiAoaSkge1xuICAgICAgICB2YXIgdGFicyA9IHRoaXMuZ2V0VGFicyh0aGlzLnByb3BzLmZsb3cpO1xuICAgICAgICB2YXIgY3VycmVudEluZGV4ID0gdGFicy5pbmRleE9mKHRoaXMuZ2V0UGFyYW1zKCkuZGV0YWlsVGFiKTtcbiAgICAgICAgLy8gSlMgbW9kdWxvIG9wZXJhdG9yIGRvZXNuJ3QgY29ycmVjdCBuZWdhdGl2ZSBudW1iZXJzLCBtYWtlIHN1cmUgdGhhdCB3ZSBhcmUgcG9zaXRpdmUuXG4gICAgICAgIHZhciBuZXh0SW5kZXggPSAoY3VycmVudEluZGV4ICsgaSArIHRhYnMubGVuZ3RoKSAlIHRhYnMubGVuZ3RoO1xuICAgICAgICB0aGlzLnNlbGVjdFRhYih0YWJzW25leHRJbmRleF0pO1xuICAgIH0sXG4gICAgc2VsZWN0VGFiOiBmdW5jdGlvbiAocGFuZWwpIHtcbiAgICAgICAgdGhpcy5yZXBsYWNlV2l0aChcbiAgICAgICAgICAgIFwiZmxvd1wiLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGZsb3dJZDogdGhpcy5nZXRQYXJhbXMoKS5mbG93SWQsXG4gICAgICAgICAgICAgICAgZGV0YWlsVGFiOiBwYW5lbFxuICAgICAgICAgICAgfVxuICAgICAgICApO1xuICAgIH0sXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBmbG93ID0gdGhpcy5wcm9wcy5mbG93O1xuICAgICAgICB2YXIgdGFicyA9IHRoaXMuZ2V0VGFicyhmbG93KTtcbiAgICAgICAgdmFyIGFjdGl2ZSA9IHRoaXMuZ2V0UGFyYW1zKCkuZGV0YWlsVGFiO1xuXG4gICAgICAgIGlmICghXy5jb250YWlucyh0YWJzLCBhY3RpdmUpKSB7XG4gICAgICAgICAgICBpZiAoYWN0aXZlID09PSBcInJlc3BvbnNlXCIgJiYgZmxvdy5lcnJvcikge1xuICAgICAgICAgICAgICAgIGFjdGl2ZSA9IFwiZXJyb3JcIjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoYWN0aXZlID09PSBcImVycm9yXCIgJiYgZmxvdy5yZXNwb25zZSkge1xuICAgICAgICAgICAgICAgIGFjdGl2ZSA9IFwicmVzcG9uc2VcIjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYWN0aXZlID0gdGFic1swXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc2VsZWN0VGFiKGFjdGl2ZSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgVGFiID0gYWxsVGFic1thY3RpdmVdO1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7Y2xhc3NOYW1lOiBcImZsb3ctZGV0YWlsXCIsIG9uU2Nyb2xsOiB0aGlzLmFkanVzdEhlYWR9LCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KEZsb3dEZXRhaWxOYXYsIHtyZWY6IFwiaGVhZFwiLCBcbiAgICAgICAgICAgICAgICAgICAgZmxvdzogZmxvdywgXG4gICAgICAgICAgICAgICAgICAgIHRhYnM6IHRhYnMsIFxuICAgICAgICAgICAgICAgICAgICBhY3RpdmU6IGFjdGl2ZSwgXG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdFRhYjogdGhpcy5zZWxlY3RUYWJ9KSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChUYWIsIHtmbG93OiBmbG93fSlcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG59KTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgRmxvd0RldGFpbDogRmxvd0RldGFpbFxufTsiLCJ2YXIgUmVhY3QgPSByZXF1aXJlKFwicmVhY3RcIik7XG52YXIgZmxvd3V0aWxzID0gcmVxdWlyZShcIi4uL2Zsb3cvdXRpbHMuanNcIik7XG52YXIgdXRpbHMgPSByZXF1aXJlKFwiLi4vdXRpbHMuanNcIik7XG5cbnZhciBUTFNDb2x1bW4gPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiVExTQ29sdW1uXCIsXG4gICAgc3RhdGljczoge1xuICAgICAgICByZW5kZXJUaXRsZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0aFwiLCB7a2V5OiBcInRsc1wiLCBjbGFzc05hbWU6IFwiY29sLXRsc1wifSk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZmxvdyA9IHRoaXMucHJvcHMuZmxvdztcbiAgICAgICAgdmFyIHNzbCA9IChmbG93LnJlcXVlc3Quc2NoZW1lID09IFwiaHR0cHNcIik7XG4gICAgICAgIHZhciBjbGFzc2VzO1xuICAgICAgICBpZiAoc3NsKSB7XG4gICAgICAgICAgICBjbGFzc2VzID0gXCJjb2wtdGxzIGNvbC10bHMtaHR0cHNcIjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNsYXNzZXMgPSBcImNvbC10bHMgY29sLXRscy1odHRwXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0ZFwiLCB7Y2xhc3NOYW1lOiBjbGFzc2VzfSk7XG4gICAgfVxufSk7XG5cblxudmFyIEljb25Db2x1bW4gPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiSWNvbkNvbHVtblwiLFxuICAgIHN0YXRpY3M6IHtcbiAgICAgICAgcmVuZGVyVGl0bGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGhcIiwge2tleTogXCJpY29uXCIsIGNsYXNzTmFtZTogXCJjb2wtaWNvblwifSk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZmxvdyA9IHRoaXMucHJvcHMuZmxvdztcblxuICAgICAgICB2YXIgaWNvbjtcbiAgICAgICAgaWYgKGZsb3cucmVzcG9uc2UpIHtcbiAgICAgICAgICAgIHZhciBjb250ZW50VHlwZSA9IGZsb3d1dGlscy5SZXNwb25zZVV0aWxzLmdldENvbnRlbnRUeXBlKGZsb3cucmVzcG9uc2UpO1xuXG4gICAgICAgICAgICAvL1RPRE86IFdlIHNob3VsZCBhc3NpZ24gYSB0eXBlIHRvIHRoZSBmbG93IHNvbWV3aGVyZSBlbHNlLlxuICAgICAgICAgICAgaWYgKGZsb3cucmVzcG9uc2UuY29kZSA9PSAzMDQpIHtcbiAgICAgICAgICAgICAgICBpY29uID0gXCJyZXNvdXJjZS1pY29uLW5vdC1tb2RpZmllZFwiO1xuICAgICAgICAgICAgfSBlbHNlIGlmICgzMDAgPD0gZmxvdy5yZXNwb25zZS5jb2RlICYmIGZsb3cucmVzcG9uc2UuY29kZSA8IDQwMCkge1xuICAgICAgICAgICAgICAgIGljb24gPSBcInJlc291cmNlLWljb24tcmVkaXJlY3RcIjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY29udGVudFR5cGUgJiYgY29udGVudFR5cGUuaW5kZXhPZihcImltYWdlXCIpID49IDApIHtcbiAgICAgICAgICAgICAgICBpY29uID0gXCJyZXNvdXJjZS1pY29uLWltYWdlXCI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNvbnRlbnRUeXBlICYmIGNvbnRlbnRUeXBlLmluZGV4T2YoXCJqYXZhc2NyaXB0XCIpID49IDApIHtcbiAgICAgICAgICAgICAgICBpY29uID0gXCJyZXNvdXJjZS1pY29uLWpzXCI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNvbnRlbnRUeXBlICYmIGNvbnRlbnRUeXBlLmluZGV4T2YoXCJjc3NcIikgPj0gMCkge1xuICAgICAgICAgICAgICAgIGljb24gPSBcInJlc291cmNlLWljb24tY3NzXCI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNvbnRlbnRUeXBlICYmIGNvbnRlbnRUeXBlLmluZGV4T2YoXCJodG1sXCIpID49IDApIHtcbiAgICAgICAgICAgICAgICBpY29uID0gXCJyZXNvdXJjZS1pY29uLWRvY3VtZW50XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpY29uKSB7XG4gICAgICAgICAgICBpY29uID0gXCJyZXNvdXJjZS1pY29uLXBsYWluXCI7XG4gICAgICAgIH1cblxuXG4gICAgICAgIGljb24gKz0gXCIgcmVzb3VyY2UtaWNvblwiO1xuICAgICAgICByZXR1cm4gUmVhY3QuY3JlYXRlRWxlbWVudChcInRkXCIsIHtjbGFzc05hbWU6IFwiY29sLWljb25cIn0sIFxuICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7Y2xhc3NOYW1lOiBpY29ufSlcbiAgICAgICAgKTtcbiAgICB9XG59KTtcblxudmFyIFBhdGhDb2x1bW4gPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiUGF0aENvbHVtblwiLFxuICAgIHN0YXRpY3M6IHtcbiAgICAgICAgcmVuZGVyVGl0bGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGhcIiwge2tleTogXCJwYXRoXCIsIGNsYXNzTmFtZTogXCJjb2wtcGF0aFwifSwgXCJQYXRoXCIpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGZsb3cgPSB0aGlzLnByb3BzLmZsb3c7XG4gICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGRcIiwge2NsYXNzTmFtZTogXCJjb2wtcGF0aFwifSwgXG4gICAgICAgICAgICBmbG93LnJlcXVlc3QuaXNfcmVwbGF5ID8gUmVhY3QuY3JlYXRlRWxlbWVudChcImlcIiwge2NsYXNzTmFtZTogXCJmYSBmYS1mdyBmYS1yZXBlYXQgcHVsbC1yaWdodFwifSkgOiBudWxsLCBcbiAgICAgICAgICAgIGZsb3cuaW50ZXJjZXB0ZWQgPyBSZWFjdC5jcmVhdGVFbGVtZW50KFwiaVwiLCB7Y2xhc3NOYW1lOiBcImZhIGZhLWZ3IGZhLXBhdXNlIHB1bGwtcmlnaHRcIn0pIDogbnVsbCwgXG4gICAgICAgICAgICBmbG93LnJlcXVlc3Quc2NoZW1lICsgXCI6Ly9cIiArIGZsb3cucmVxdWVzdC5ob3N0ICsgZmxvdy5yZXF1ZXN0LnBhdGhcbiAgICAgICAgKTtcbiAgICB9XG59KTtcblxuXG52YXIgTWV0aG9kQ29sdW1uID0gUmVhY3QuY3JlYXRlQ2xhc3Moe2Rpc3BsYXlOYW1lOiBcIk1ldGhvZENvbHVtblwiLFxuICAgIHN0YXRpY3M6IHtcbiAgICAgICAgcmVuZGVyVGl0bGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGhcIiwge2tleTogXCJtZXRob2RcIiwgY2xhc3NOYW1lOiBcImNvbC1tZXRob2RcIn0sIFwiTWV0aG9kXCIpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGZsb3cgPSB0aGlzLnByb3BzLmZsb3c7XG4gICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGRcIiwge2NsYXNzTmFtZTogXCJjb2wtbWV0aG9kXCJ9LCBmbG93LnJlcXVlc3QubWV0aG9kKTtcbiAgICB9XG59KTtcblxuXG52YXIgU3RhdHVzQ29sdW1uID0gUmVhY3QuY3JlYXRlQ2xhc3Moe2Rpc3BsYXlOYW1lOiBcIlN0YXR1c0NvbHVtblwiLFxuICAgIHN0YXRpY3M6IHtcbiAgICAgICAgcmVuZGVyVGl0bGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGhcIiwge2tleTogXCJzdGF0dXNcIiwgY2xhc3NOYW1lOiBcImNvbC1zdGF0dXNcIn0sIFwiU3RhdHVzXCIpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGZsb3cgPSB0aGlzLnByb3BzLmZsb3c7XG4gICAgICAgIHZhciBzdGF0dXM7XG4gICAgICAgIGlmIChmbG93LnJlc3BvbnNlKSB7XG4gICAgICAgICAgICBzdGF0dXMgPSBmbG93LnJlc3BvbnNlLmNvZGU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdGF0dXMgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGRcIiwge2NsYXNzTmFtZTogXCJjb2wtc3RhdHVzXCJ9LCBzdGF0dXMpO1xuICAgIH1cbn0pO1xuXG5cbnZhciBTaXplQ29sdW1uID0gUmVhY3QuY3JlYXRlQ2xhc3Moe2Rpc3BsYXlOYW1lOiBcIlNpemVDb2x1bW5cIixcbiAgICBzdGF0aWNzOiB7XG4gICAgICAgIHJlbmRlclRpdGxlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gUmVhY3QuY3JlYXRlRWxlbWVudChcInRoXCIsIHtrZXk6IFwic2l6ZVwiLCBjbGFzc05hbWU6IFwiY29sLXNpemVcIn0sIFwiU2l6ZVwiKTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBmbG93ID0gdGhpcy5wcm9wcy5mbG93O1xuXG4gICAgICAgIHZhciB0b3RhbCA9IGZsb3cucmVxdWVzdC5jb250ZW50TGVuZ3RoO1xuICAgICAgICBpZiAoZmxvdy5yZXNwb25zZSkge1xuICAgICAgICAgICAgdG90YWwgKz0gZmxvdy5yZXNwb25zZS5jb250ZW50TGVuZ3RoIHx8IDA7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHNpemUgPSB1dGlscy5mb3JtYXRTaXplKHRvdGFsKTtcbiAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0ZFwiLCB7Y2xhc3NOYW1lOiBcImNvbC1zaXplXCJ9LCBzaXplKTtcbiAgICB9XG59KTtcblxuXG52YXIgVGltZUNvbHVtbiA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJUaW1lQ29sdW1uXCIsXG4gICAgc3RhdGljczoge1xuICAgICAgICByZW5kZXJUaXRsZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0aFwiLCB7a2V5OiBcInRpbWVcIiwgY2xhc3NOYW1lOiBcImNvbC10aW1lXCJ9LCBcIlRpbWVcIik7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZmxvdyA9IHRoaXMucHJvcHMuZmxvdztcbiAgICAgICAgdmFyIHRpbWU7XG4gICAgICAgIGlmIChmbG93LnJlc3BvbnNlKSB7XG4gICAgICAgICAgICB0aW1lID0gdXRpbHMuZm9ybWF0VGltZURlbHRhKDEwMDAgKiAoZmxvdy5yZXNwb25zZS50aW1lc3RhbXBfZW5kIC0gZmxvdy5yZXF1ZXN0LnRpbWVzdGFtcF9zdGFydCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGltZSA9IFwiLi4uXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0ZFwiLCB7Y2xhc3NOYW1lOiBcImNvbC10aW1lXCJ9LCB0aW1lKTtcbiAgICB9XG59KTtcblxuXG52YXIgYWxsX2NvbHVtbnMgPSBbXG4gICAgVExTQ29sdW1uLFxuICAgIEljb25Db2x1bW4sXG4gICAgUGF0aENvbHVtbixcbiAgICBNZXRob2RDb2x1bW4sXG4gICAgU3RhdHVzQ29sdW1uLFxuICAgIFNpemVDb2x1bW4sXG4gICAgVGltZUNvbHVtbl07XG5cblxubW9kdWxlLmV4cG9ydHMgPSBhbGxfY29sdW1ucztcblxuXG4iLCJ2YXIgUmVhY3QgPSByZXF1aXJlKFwicmVhY3RcIik7XG52YXIgY29tbW9uID0gcmVxdWlyZShcIi4vY29tbW9uLmpzXCIpO1xudmFyIFZpcnR1YWxTY3JvbGxNaXhpbiA9IHJlcXVpcmUoXCIuL3ZpcnR1YWxzY3JvbGwuanNcIik7XG52YXIgZmxvd3RhYmxlX2NvbHVtbnMgPSByZXF1aXJlKFwiLi9mbG93dGFibGUtY29sdW1ucy5qc1wiKTtcblxudmFyIEZsb3dSb3cgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiRmxvd1Jvd1wiLFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZmxvdyA9IHRoaXMucHJvcHMuZmxvdztcbiAgICAgICAgdmFyIGNvbHVtbnMgPSB0aGlzLnByb3BzLmNvbHVtbnMubWFwKGZ1bmN0aW9uIChDb2x1bW4pIHtcbiAgICAgICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KENvbHVtbiwge2tleTogQ29sdW1uLmRpc3BsYXlOYW1lLCBmbG93OiBmbG93fSk7XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG4gICAgICAgIHZhciBjbGFzc05hbWUgPSBcIlwiO1xuICAgICAgICBpZiAodGhpcy5wcm9wcy5zZWxlY3RlZCkge1xuICAgICAgICAgICAgY2xhc3NOYW1lICs9IFwiIHNlbGVjdGVkXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMucHJvcHMuaGlnaGxpZ2h0ZWQpIHtcbiAgICAgICAgICAgIGNsYXNzTmFtZSArPSBcIiBoaWdobGlnaHRlZFwiO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmbG93LmludGVyY2VwdGVkKSB7XG4gICAgICAgICAgICBjbGFzc05hbWUgKz0gXCIgaW50ZXJjZXB0ZWRcIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZmxvdy5yZXF1ZXN0KSB7XG4gICAgICAgICAgICBjbGFzc05hbWUgKz0gXCIgaGFzLXJlcXVlc3RcIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZmxvdy5yZXNwb25zZSkge1xuICAgICAgICAgICAgY2xhc3NOYW1lICs9IFwiIGhhcy1yZXNwb25zZVwiO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0clwiLCB7Y2xhc3NOYW1lOiBjbGFzc05hbWUsIG9uQ2xpY2s6IHRoaXMucHJvcHMuc2VsZWN0Rmxvdy5iaW5kKG51bGwsIGZsb3cpfSwgXG4gICAgICAgICAgICAgICAgY29sdW1uc1xuICAgICAgICAgICAgKSk7XG4gICAgfSxcbiAgICBzaG91bGRDb21wb25lbnRVcGRhdGU6IGZ1bmN0aW9uIChuZXh0UHJvcHMpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIC8vIEZ1cnRoZXIgb3B0aW1pemF0aW9uIGNvdWxkIGJlIGRvbmUgaGVyZVxuICAgICAgICAvLyBieSBjYWxsaW5nIGZvcmNlVXBkYXRlIG9uIGZsb3cgdXBkYXRlcywgc2VsZWN0aW9uIGNoYW5nZXMgYW5kIGNvbHVtbiBjaGFuZ2VzLlxuICAgICAgICAvL3JldHVybiAoXG4gICAgICAgIC8vKHRoaXMucHJvcHMuY29sdW1ucy5sZW5ndGggIT09IG5leHRQcm9wcy5jb2x1bW5zLmxlbmd0aCkgfHxcbiAgICAgICAgLy8odGhpcy5wcm9wcy5zZWxlY3RlZCAhPT0gbmV4dFByb3BzLnNlbGVjdGVkKVxuICAgICAgICAvLyk7XG4gICAgfVxufSk7XG5cbnZhciBGbG93VGFibGVIZWFkID0gUmVhY3QuY3JlYXRlQ2xhc3Moe2Rpc3BsYXlOYW1lOiBcIkZsb3dUYWJsZUhlYWRcIixcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNvbHVtbnMgPSB0aGlzLnByb3BzLmNvbHVtbnMubWFwKGZ1bmN0aW9uIChjb2x1bW4pIHtcbiAgICAgICAgICAgIHJldHVybiBjb2x1bW4ucmVuZGVyVGl0bGUoKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0aGVhZFwiLCBudWxsLCBcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0clwiLCBudWxsLCBjb2x1bW5zKVxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG5cbnZhciBST1dfSEVJR0hUID0gMzI7XG5cbnZhciBGbG93VGFibGUgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiRmxvd1RhYmxlXCIsXG4gICAgbWl4aW5zOiBbY29tbW9uLlN0aWNreUhlYWRNaXhpbiwgY29tbW9uLkF1dG9TY3JvbGxNaXhpbiwgVmlydHVhbFNjcm9sbE1peGluXSxcbiAgICBnZXRJbml0aWFsU3RhdGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGNvbHVtbnM6IGZsb3d0YWJsZV9jb2x1bW5zXG4gICAgICAgIH07XG4gICAgfSxcbiAgICBjb21wb25lbnRXaWxsTW91bnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMucHJvcHMudmlldykge1xuICAgICAgICAgICAgdGhpcy5wcm9wcy52aWV3LmFkZExpc3RlbmVyKFwiYWRkIHVwZGF0ZSByZW1vdmUgcmVjYWxjdWxhdGVcIiwgdGhpcy5vbkNoYW5nZSk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGNvbXBvbmVudFdpbGxSZWNlaXZlUHJvcHM6IGZ1bmN0aW9uIChuZXh0UHJvcHMpIHtcbiAgICAgICAgaWYgKG5leHRQcm9wcy52aWV3ICE9PSB0aGlzLnByb3BzLnZpZXcpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnByb3BzLnZpZXcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BzLnZpZXcucmVtb3ZlTGlzdGVuZXIoXCJhZGQgdXBkYXRlIHJlbW92ZSByZWNhbGN1bGF0ZVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5leHRQcm9wcy52aWV3LmFkZExpc3RlbmVyKFwiYWRkIHVwZGF0ZSByZW1vdmUgcmVjYWxjdWxhdGVcIiwgdGhpcy5vbkNoYW5nZSk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGdldERlZmF1bHRQcm9wczogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcm93SGVpZ2h0OiBST1dfSEVJR0hUXG4gICAgICAgIH07XG4gICAgfSxcbiAgICBvblNjcm9sbEZsb3dUYWJsZTogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmFkanVzdEhlYWQoKTtcbiAgICAgICAgdGhpcy5vblNjcm9sbCgpO1xuICAgIH0sXG4gICAgb25DaGFuZ2U6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5mb3JjZVVwZGF0ZSgpO1xuICAgIH0sXG4gICAgc2Nyb2xsSW50b1ZpZXc6IGZ1bmN0aW9uIChmbG93KSB7XG4gICAgICAgIHRoaXMuc2Nyb2xsUm93SW50b1ZpZXcoXG4gICAgICAgICAgICB0aGlzLnByb3BzLnZpZXcuaW5kZXgoZmxvdyksXG4gICAgICAgICAgICB0aGlzLnJlZnMuYm9keS5nZXRET01Ob2RlKCkub2Zmc2V0VG9wXG4gICAgICAgICk7XG4gICAgfSxcbiAgICByZW5kZXJSb3c6IGZ1bmN0aW9uIChmbG93KSB7XG4gICAgICAgIHZhciBzZWxlY3RlZCA9IChmbG93ID09PSB0aGlzLnByb3BzLnNlbGVjdGVkKTtcbiAgICAgICAgdmFyIGhpZ2hsaWdodGVkID1cbiAgICAgICAgICAgIChcbiAgICAgICAgICAgIHRoaXMucHJvcHMudmlldy5faGlnaGxpZ2h0ICYmXG4gICAgICAgICAgICB0aGlzLnByb3BzLnZpZXcuX2hpZ2hsaWdodFtmbG93LmlkXVxuICAgICAgICAgICAgKTtcblxuICAgICAgICByZXR1cm4gUmVhY3QuY3JlYXRlRWxlbWVudChGbG93Um93LCB7a2V5OiBmbG93LmlkLCBcbiAgICAgICAgICAgIHJlZjogZmxvdy5pZCwgXG4gICAgICAgICAgICBmbG93OiBmbG93LCBcbiAgICAgICAgICAgIGNvbHVtbnM6IHRoaXMuc3RhdGUuY29sdW1ucywgXG4gICAgICAgICAgICBzZWxlY3RlZDogc2VsZWN0ZWQsIFxuICAgICAgICAgICAgaGlnaGxpZ2h0ZWQ6IGhpZ2hsaWdodGVkLCBcbiAgICAgICAgICAgIHNlbGVjdEZsb3c6IHRoaXMucHJvcHMuc2VsZWN0Rmxvd31cbiAgICAgICAgKTtcbiAgICB9LFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICAvL2NvbnNvbGUubG9nKFwicmVuZGVyIGZsb3d0YWJsZVwiLCB0aGlzLnN0YXRlLnN0YXJ0LCB0aGlzLnN0YXRlLnN0b3AsIHRoaXMucHJvcHMuc2VsZWN0ZWQpO1xuICAgICAgICB2YXIgZmxvd3MgPSB0aGlzLnByb3BzLnZpZXcgPyB0aGlzLnByb3BzLnZpZXcubGlzdCA6IFtdO1xuXG4gICAgICAgIHZhciByb3dzID0gdGhpcy5yZW5kZXJSb3dzKGZsb3dzKTtcblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7Y2xhc3NOYW1lOiBcImZsb3ctdGFibGVcIiwgb25TY3JvbGw6IHRoaXMub25TY3JvbGxGbG93VGFibGV9LCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGFibGVcIiwgbnVsbCwgXG4gICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoRmxvd1RhYmxlSGVhZCwge3JlZjogXCJoZWFkXCIsIFxuICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uczogdGhpcy5zdGF0ZS5jb2x1bW5zfSksIFxuICAgICAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGJvZHlcIiwge3JlZjogXCJib2R5XCJ9LCBcbiAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmdldFBsYWNlaG9sZGVyVG9wKGZsb3dzLmxlbmd0aCksIFxuICAgICAgICAgICAgICAgICAgICAgICAgcm93cywgXG4gICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5nZXRQbGFjZWhvbGRlckJvdHRvbShmbG93cy5sZW5ndGgpIFxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEZsb3dUYWJsZTtcbiIsInZhciBSZWFjdCA9IHJlcXVpcmUoXCJyZWFjdFwiKTtcblxudmFyIEZvb3RlciA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJGb290ZXJcIixcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG1vZGUgPSB0aGlzLnByb3BzLnNldHRpbmdzLm1vZGU7XG4gICAgICAgIHZhciBpbnRlcmNlcHQgPSB0aGlzLnByb3BzLnNldHRpbmdzLmludGVyY2VwdDtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJmb290ZXJcIiwgbnVsbCwgXG4gICAgICAgICAgICAgICAgbW9kZSAhPSBcInJlZ3VsYXJcIiA/IFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIsIHtjbGFzc05hbWU6IFwibGFiZWwgbGFiZWwtc3VjY2Vzc1wifSwgbW9kZSwgXCIgbW9kZVwiKSA6IG51bGwsIFxuICAgICAgICAgICAgICAgIFwiwqBcIiwgXG4gICAgICAgICAgICAgICAgaW50ZXJjZXB0ID8gUmVhY3QuY3JlYXRlRWxlbWVudChcInNwYW5cIiwge2NsYXNzTmFtZTogXCJsYWJlbCBsYWJlbC1zdWNjZXNzXCJ9LCBcIkludGVyY2VwdDogXCIsIGludGVyY2VwdCkgOiBudWxsXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxufSk7XG5cbm1vZHVsZS5leHBvcnRzID0gRm9vdGVyOyIsInZhciBSZWFjdCA9IHJlcXVpcmUoXCJyZWFjdFwiKTtcbnZhciAkID0gcmVxdWlyZShcImpxdWVyeVwiKTtcblxudmFyIEZpbHQgPSByZXF1aXJlKFwiLi4vZmlsdC9maWx0LmpzXCIpO1xudmFyIHV0aWxzID0gcmVxdWlyZShcIi4uL3V0aWxzLmpzXCIpO1xuXG52YXIgY29tbW9uID0gcmVxdWlyZShcIi4vY29tbW9uLmpzXCIpO1xuXG52YXIgRmlsdGVyRG9jcyA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJGaWx0ZXJEb2NzXCIsXG4gICAgc3RhdGljczoge1xuICAgICAgICB4aHI6IGZhbHNlLFxuICAgICAgICBkb2M6IGZhbHNlXG4gICAgfSxcbiAgICBjb21wb25lbnRXaWxsTW91bnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCFGaWx0ZXJEb2NzLmRvYykge1xuICAgICAgICAgICAgRmlsdGVyRG9jcy54aHIgPSAkLmdldEpTT04oXCIvZmlsdGVyLWhlbHBcIikuZG9uZShmdW5jdGlvbiAoZG9jKSB7XG4gICAgICAgICAgICAgICAgRmlsdGVyRG9jcy5kb2MgPSBkb2M7XG4gICAgICAgICAgICAgICAgRmlsdGVyRG9jcy54aHIgPSBmYWxzZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChGaWx0ZXJEb2NzLnhocikge1xuICAgICAgICAgICAgRmlsdGVyRG9jcy54aHIuZG9uZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5mb3JjZVVwZGF0ZSgpO1xuICAgICAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghRmlsdGVyRG9jcy5kb2MpIHtcbiAgICAgICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFwiaVwiLCB7Y2xhc3NOYW1lOiBcImZhIGZhLXNwaW5uZXIgZmEtc3BpblwifSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgY29tbWFuZHMgPSBGaWx0ZXJEb2NzLmRvYy5jb21tYW5kcy5tYXAoZnVuY3Rpb24gKGMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gUmVhY3QuY3JlYXRlRWxlbWVudChcInRyXCIsIG51bGwsIFxuICAgICAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGRcIiwgbnVsbCwgY1swXS5yZXBsYWNlKFwiIFwiLCAnXFx1MDBhMCcpKSwgXG4gICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0ZFwiLCBudWxsLCBjWzFdKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGNvbW1hbmRzLnB1c2goUmVhY3QuY3JlYXRlRWxlbWVudChcInRyXCIsIG51bGwsIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0ZFwiLCB7Y29sU3BhbjogXCIyXCJ9LCBcbiAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImFcIiwge2hyZWY6IFwiaHR0cHM6Ly9taXRtcHJveHkub3JnL2RvYy9mZWF0dXJlcy9maWx0ZXJzLmh0bWxcIiwgXG4gICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQ6IFwiX2JsYW5rXCJ9LCBcbiAgICAgICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJpXCIsIHtjbGFzc05hbWU6IFwiZmEgZmEtZXh0ZXJuYWwtbGlua1wifSksIFxuICAgICAgICAgICAgICAgICAgICBcIsKgIG1pdG1wcm94eSBkb2NzXCIpXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSk7XG4gICAgICAgICAgICByZXR1cm4gUmVhY3QuY3JlYXRlRWxlbWVudChcInRhYmxlXCIsIHtjbGFzc05hbWU6IFwidGFibGUgdGFibGUtY29uZGVuc2VkXCJ9LCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidGJvZHlcIiwgbnVsbCwgY29tbWFuZHMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxufSk7XG52YXIgRmlsdGVySW5wdXQgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiRmlsdGVySW5wdXRcIixcbiAgICBnZXRJbml0aWFsU3RhdGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gQ29uc2lkZXIgYm90aCBmb2N1cyBhbmQgbW91c2VvdmVyIGZvciBzaG93aW5nL2hpZGluZyB0aGUgdG9vbHRpcCxcbiAgICAgICAgLy8gYmVjYXVzZSBvbkJsdXIgb2YgdGhlIGlucHV0IGlzIHRyaWdnZXJlZCBiZWZvcmUgdGhlIGNsaWNrIG9uIHRoZSB0b29sdGlwXG4gICAgICAgIC8vIGZpbmFsaXplZCwgaGlkaW5nIHRoZSB0b29sdGlwIGp1c3QgYXMgdGhlIHVzZXIgY2xpY2tzIG9uIGl0LlxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdmFsdWU6IHRoaXMucHJvcHMudmFsdWUsXG4gICAgICAgICAgICBmb2N1czogZmFsc2UsXG4gICAgICAgICAgICBtb3VzZWZvY3VzOiBmYWxzZVxuICAgICAgICB9O1xuICAgIH0sXG4gICAgY29tcG9uZW50V2lsbFJlY2VpdmVQcm9wczogZnVuY3Rpb24gKG5leHRQcm9wcykge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHt2YWx1ZTogbmV4dFByb3BzLnZhbHVlfSk7XG4gICAgfSxcbiAgICBvbkNoYW5nZTogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIG5leHRWYWx1ZSA9IGUudGFyZ2V0LnZhbHVlO1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIHZhbHVlOiBuZXh0VmFsdWVcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIE9ubHkgcHJvcGFnYXRlIHZhbGlkIGZpbHRlcnMgdXB3YXJkcy5cbiAgICAgICAgaWYgKHRoaXMuaXNWYWxpZChuZXh0VmFsdWUpKSB7XG4gICAgICAgICAgICB0aGlzLnByb3BzLm9uQ2hhbmdlKG5leHRWYWx1ZSk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGlzVmFsaWQ6IGZ1bmN0aW9uIChmaWx0KSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBGaWx0LnBhcnNlKGZpbHQgfHwgdGhpcy5zdGF0ZS52YWx1ZSk7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBnZXREZXNjOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBkZXNjO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgZGVzYyA9IEZpbHQucGFyc2UodGhpcy5zdGF0ZS52YWx1ZSkuZGVzYztcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgZGVzYyA9IFwiXCIgKyBlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChkZXNjICE9PSBcInRydWVcIikge1xuICAgICAgICAgICAgcmV0dXJuIGRlc2M7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoRmlsdGVyRG9jcywgbnVsbClcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG9uRm9jdXM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7Zm9jdXM6IHRydWV9KTtcbiAgICB9LFxuICAgIG9uQmx1cjogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtmb2N1czogZmFsc2V9KTtcbiAgICB9LFxuICAgIG9uTW91c2VFbnRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHttb3VzZWZvY3VzOiB0cnVlfSk7XG4gICAgfSxcbiAgICBvbk1vdXNlTGVhdmU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7bW91c2Vmb2N1czogZmFsc2V9KTtcbiAgICB9LFxuICAgIG9uS2V5RG93bjogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgaWYgKGUua2V5Q29kZSA9PT0gdXRpbHMuS2V5LkVTQyB8fCBlLmtleUNvZGUgPT09IHV0aWxzLktleS5FTlRFUikge1xuICAgICAgICAgICAgdGhpcy5ibHVyKCk7XG4gICAgICAgICAgICAvLyBJZiBjbG9zZWQgdXNpbmcgRVNDL0VOVEVSLCBoaWRlIHRoZSB0b29sdGlwLlxuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7bW91c2Vmb2N1czogZmFsc2V9KTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgYmx1cjogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJlZnMuaW5wdXQuZ2V0RE9NTm9kZSgpLmJsdXIoKTtcbiAgICB9LFxuICAgIGZvY3VzOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucmVmcy5pbnB1dC5nZXRET01Ob2RlKCkuc2VsZWN0KCk7XG4gICAgfSxcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGlzVmFsaWQgPSB0aGlzLmlzVmFsaWQoKTtcbiAgICAgICAgdmFyIGljb24gPSBcImZhIGZhLWZ3IGZhLVwiICsgdGhpcy5wcm9wcy50eXBlO1xuICAgICAgICB2YXIgZ3JvdXBDbGFzc05hbWUgPSBcImZpbHRlci1pbnB1dCBpbnB1dC1ncm91cFwiICsgKGlzVmFsaWQgPyBcIlwiIDogXCIgaGFzLWVycm9yXCIpO1xuXG4gICAgICAgIHZhciBwb3BvdmVyO1xuICAgICAgICBpZiAodGhpcy5zdGF0ZS5mb2N1cyB8fCB0aGlzLnN0YXRlLm1vdXNlZm9jdXMpIHtcbiAgICAgICAgICAgIHBvcG92ZXIgPSAoXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7Y2xhc3NOYW1lOiBcInBvcG92ZXIgYm90dG9tXCIsIG9uTW91c2VFbnRlcjogdGhpcy5vbk1vdXNlRW50ZXIsIG9uTW91c2VMZWF2ZTogdGhpcy5vbk1vdXNlTGVhdmV9LCBcbiAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7Y2xhc3NOYW1lOiBcImFycm93XCJ9KSwgXG4gICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwge2NsYXNzTmFtZTogXCJwb3BvdmVyLWNvbnRlbnRcIn0sIFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmdldERlc2MoKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtjbGFzc05hbWU6IGdyb3VwQ2xhc3NOYW1lfSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcInNwYW5cIiwge2NsYXNzTmFtZTogXCJpbnB1dC1ncm91cC1hZGRvblwifSwgXG4gICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJpXCIsIHtjbGFzc05hbWU6IGljb24sIHN0eWxlOiB7Y29sb3I6IHRoaXMucHJvcHMuY29sb3J9fSlcbiAgICAgICAgICAgICAgICApLCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiaW5wdXRcIiwge3R5cGU6IFwidGV4dFwiLCBwbGFjZWhvbGRlcjogdGhpcy5wcm9wcy5wbGFjZWhvbGRlciwgY2xhc3NOYW1lOiBcImZvcm0tY29udHJvbFwiLCBcbiAgICAgICAgICAgICAgICAgICAgcmVmOiBcImlucHV0XCIsIFxuICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZTogdGhpcy5vbkNoYW5nZSwgXG4gICAgICAgICAgICAgICAgICAgIG9uRm9jdXM6IHRoaXMub25Gb2N1cywgXG4gICAgICAgICAgICAgICAgICAgIG9uQmx1cjogdGhpcy5vbkJsdXIsIFxuICAgICAgICAgICAgICAgICAgICBvbktleURvd246IHRoaXMub25LZXlEb3duLCBcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMuc3RhdGUudmFsdWV9KSwgXG4gICAgICAgICAgICAgICAgcG9wb3ZlclxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG52YXIgTWFpbk1lbnUgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiTWFpbk1lbnVcIixcbiAgICBtaXhpbnM6IFtjb21tb24uTmF2aWdhdGlvbiwgY29tbW9uLlN0YXRlXSxcbiAgICBzdGF0aWNzOiB7XG4gICAgICAgIHRpdGxlOiBcIlN0YXJ0XCIsXG4gICAgICAgIHJvdXRlOiBcImZsb3dzXCJcbiAgICB9LFxuICAgIG9uRmlsdGVyQ2hhbmdlOiBmdW5jdGlvbiAodmFsKSB7XG4gICAgICAgIHZhciBkID0ge307XG4gICAgICAgIGRbUXVlcnkuRklMVEVSXSA9IHZhbDtcbiAgICAgICAgdGhpcy5zZXRRdWVyeShkKTtcbiAgICB9LFxuICAgIG9uSGlnaGxpZ2h0Q2hhbmdlOiBmdW5jdGlvbiAodmFsKSB7XG4gICAgICAgIHZhciBkID0ge307XG4gICAgICAgIGRbUXVlcnkuSElHSExJR0hUXSA9IHZhbDtcbiAgICAgICAgdGhpcy5zZXRRdWVyeShkKTtcbiAgICB9LFxuICAgIG9uSW50ZXJjZXB0Q2hhbmdlOiBmdW5jdGlvbiAodmFsKSB7XG4gICAgICAgIFNldHRpbmdzQWN0aW9ucy51cGRhdGUoe2ludGVyY2VwdDogdmFsfSk7XG4gICAgfSxcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGZpbHRlciA9IHRoaXMuZ2V0UXVlcnkoKVtRdWVyeS5GSUxURVJdIHx8IFwiXCI7XG4gICAgICAgIHZhciBoaWdobGlnaHQgPSB0aGlzLmdldFF1ZXJ5KClbUXVlcnkuSElHSExJR0hUXSB8fCBcIlwiO1xuICAgICAgICB2YXIgaW50ZXJjZXB0ID0gdGhpcy5wcm9wcy5zZXR0aW5ncy5pbnRlcmNlcHQgfHwgXCJcIjtcblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCBudWxsLCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHtjbGFzc05hbWU6IFwibWVudS1yb3dcIn0sIFxuICAgICAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KEZpbHRlcklucHV0LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcjogXCJGaWx0ZXJcIiwgXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcImZpbHRlclwiLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yOiBcImJsYWNrXCIsIFxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IGZpbHRlciwgXG4gICAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZTogdGhpcy5vbkZpbHRlckNoYW5nZX0pLCBcbiAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChGaWx0ZXJJbnB1dCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IFwiSGlnaGxpZ2h0XCIsIFxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJ0YWdcIiwgXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2xvcjogXCJoc2woNDgsIDEwMCUsIDUwJSlcIiwgXG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogaGlnaGxpZ2h0LCBcbiAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlOiB0aGlzLm9uSGlnaGxpZ2h0Q2hhbmdlfSksIFxuICAgICAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KEZpbHRlcklucHV0LCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcjogXCJJbnRlcmNlcHRcIiwgXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcInBhdXNlXCIsIFxuICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I6IFwiaHNsKDIwOCwgNTYlLCA1MyUpXCIsIFxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IGludGVyY2VwdCwgXG4gICAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZTogdGhpcy5vbkludGVyY2VwdENoYW5nZX0pXG4gICAgICAgICAgICAgICAgKSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7Y2xhc3NOYW1lOiBcImNsZWFyZml4XCJ9KVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG5cbnZhciBWaWV3TWVudSA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJWaWV3TWVudVwiLFxuICAgIHN0YXRpY3M6IHtcbiAgICAgICAgdGl0bGU6IFwiVmlld1wiLFxuICAgICAgICByb3V0ZTogXCJmbG93c1wiXG4gICAgfSxcbiAgICBtaXhpbnM6IFtjb21tb24uTmF2aWdhdGlvbiwgY29tbW9uLlN0YXRlXSxcbiAgICB0b2dnbGVFdmVudExvZzogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZCA9IHt9O1xuXG4gICAgICAgIGlmICh0aGlzLmdldFF1ZXJ5KClbUXVlcnkuU0hPV19FVkVOVExPR10pIHtcbiAgICAgICAgICAgIGRbUXVlcnkuU0hPV19FVkVOVExPR10gPSB1bmRlZmluZWQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkW1F1ZXJ5LlNIT1dfRVZFTlRMT0ddID0gXCJ0XCI7IC8vIGFueSBub24tZmFsc2UgdmFsdWUgd2lsbCBkbyBpdCwga2VlcCBpdCBzaG9ydFxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zZXRRdWVyeShkKTtcbiAgICB9LFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc2hvd0V2ZW50TG9nID0gdGhpcy5nZXRRdWVyeSgpW1F1ZXJ5LlNIT1dfRVZFTlRMT0ddO1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCBudWxsLCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiYnV0dG9uXCIsIHtcbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lOiBcImJ0biBcIiArIChzaG93RXZlbnRMb2cgPyBcImJ0bi1wcmltYXJ5XCIgOiBcImJ0bi1kZWZhdWx0XCIpLCBcbiAgICAgICAgICAgICAgICAgICAgb25DbGljazogdGhpcy50b2dnbGVFdmVudExvZ30sIFxuICAgICAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiaVwiLCB7Y2xhc3NOYW1lOiBcImZhIGZhLWRhdGFiYXNlXCJ9KSwgXG4gICAgICAgICAgICAgICAgXCLCoFNob3cgRXZlbnRsb2dcIlxuICAgICAgICAgICAgICAgICksIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIsIG51bGwsIFwiIFwiKVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG5cbnZhciBSZXBvcnRzTWVudSA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJSZXBvcnRzTWVudVwiLFxuICAgIHN0YXRpY3M6IHtcbiAgICAgICAgdGl0bGU6IFwiVmlzdWFsaXphdGlvblwiLFxuICAgICAgICByb3V0ZTogXCJyZXBvcnRzXCJcbiAgICB9LFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCBudWxsLCBcIlJlcG9ydHMgTWVudVwiKTtcbiAgICB9XG59KTtcblxudmFyIEZpbGVNZW51ID0gUmVhY3QuY3JlYXRlQ2xhc3Moe2Rpc3BsYXlOYW1lOiBcIkZpbGVNZW51XCIsXG4gICAgZ2V0SW5pdGlhbFN0YXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzaG93RmlsZU1lbnU6IGZhbHNlXG4gICAgICAgIH07XG4gICAgfSxcbiAgICBoYW5kbGVGaWxlQ2xpY2s6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlLnNob3dGaWxlTWVudSkge1xuICAgICAgICAgICAgdmFyIGNsb3NlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe3Nob3dGaWxlTWVudTogZmFsc2V9KTtcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgY2xvc2UpO1xuICAgICAgICAgICAgfS5iaW5kKHRoaXMpO1xuICAgICAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGNsb3NlKTtcblxuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgICAgc2hvd0ZpbGVNZW51OiB0cnVlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgaGFuZGxlTmV3Q2xpY2s6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgaWYgKGNvbmZpcm0oXCJEZWxldGUgYWxsIGZsb3dzP1wiKSkge1xuICAgICAgICAgICAgRmxvd0FjdGlvbnMuY2xlYXIoKTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgaGFuZGxlT3BlbkNsaWNrOiBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJ1bmltcGxlbWVudGVkOiBoYW5kbGVPcGVuQ2xpY2tcIik7XG4gICAgfSxcbiAgICBoYW5kbGVTYXZlQ2xpY2s6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgY29uc29sZS5lcnJvcihcInVuaW1wbGVtZW50ZWQ6IGhhbmRsZVNhdmVDbGlja1wiKTtcbiAgICB9LFxuICAgIGhhbmRsZVNodXRkb3duQ2xpY2s6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgY29uc29sZS5lcnJvcihcInVuaW1wbGVtZW50ZWQ6IGhhbmRsZVNodXRkb3duQ2xpY2tcIik7XG4gICAgfSxcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGZpbGVNZW51Q2xhc3MgPSBcImRyb3Bkb3duIHB1bGwtbGVmdFwiICsgKHRoaXMuc3RhdGUuc2hvd0ZpbGVNZW51ID8gXCIgb3BlblwiIDogXCJcIik7XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwge2NsYXNzTmFtZTogZmlsZU1lbnVDbGFzc30sIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJhXCIsIHtocmVmOiBcIiNcIiwgY2xhc3NOYW1lOiBcInNwZWNpYWxcIiwgb25DbGljazogdGhpcy5oYW5kbGVGaWxlQ2xpY2t9LCBcIiBtaXRtcHJveHkgXCIpLCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwidWxcIiwge2NsYXNzTmFtZTogXCJkcm9wZG93bi1tZW51XCIsIHJvbGU6IFwibWVudVwifSwgXG4gICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJsaVwiLCBudWxsLCBcbiAgICAgICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJhXCIsIHtocmVmOiBcIiNcIiwgb25DbGljazogdGhpcy5oYW5kbGVOZXdDbGlja30sIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJpXCIsIHtjbGFzc05hbWU6IFwiZmEgZmEtZncgZmEtZmlsZVwifSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiTmV3XCJcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKSwgXG4gICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJsaVwiLCB7cm9sZTogXCJwcmVzZW50YXRpb25cIiwgY2xhc3NOYW1lOiBcImRpdmlkZXJcIn0pLCBcbiAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImxpXCIsIG51bGwsIFxuICAgICAgICAgICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImFcIiwge2hyZWY6IFwiaHR0cDovL21pdG0uaXQvXCIsIHRhcmdldDogXCJfYmxhbmtcIn0sIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJpXCIsIHtjbGFzc05hbWU6IFwiZmEgZmEtZncgZmEtZXh0ZXJuYWwtbGlua1wifSksIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiSW5zdGFsbCBDZXJ0aWZpY2F0ZXMuLi5cIlxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAgICAgPGxpPlxuICAgICAgICAgICAgICAgICA8YSBocmVmPVwiI1wiIG9uQ2xpY2s9e3RoaXMuaGFuZGxlT3BlbkNsaWNrfT5cbiAgICAgICAgICAgICAgICAgPGkgY2xhc3NOYW1lPVwiZmEgZmEtZncgZmEtZm9sZGVyLW9wZW5cIj48L2k+XG4gICAgICAgICAgICAgICAgIE9wZW5cbiAgICAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgICAgICA8L2xpPlxuICAgICAgICAgICAgICAgICA8bGk+XG4gICAgICAgICAgICAgICAgIDxhIGhyZWY9XCIjXCIgb25DbGljaz17dGhpcy5oYW5kbGVTYXZlQ2xpY2t9PlxuICAgICAgICAgICAgICAgICA8aSBjbGFzc05hbWU9XCJmYSBmYS1mdyBmYS1zYXZlXCI+PC9pPlxuICAgICAgICAgICAgICAgICBTYXZlXG4gICAgICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICAgICAgPC9saT5cbiAgICAgICAgICAgICAgICAgPGxpIHJvbGU9XCJwcmVzZW50YXRpb25cIiBjbGFzc05hbWU9XCJkaXZpZGVyXCI+PC9saT5cbiAgICAgICAgICAgICAgICAgPGxpPlxuICAgICAgICAgICAgICAgICA8YSBocmVmPVwiI1wiIG9uQ2xpY2s9e3RoaXMuaGFuZGxlU2h1dGRvd25DbGlja30+XG4gICAgICAgICAgICAgICAgIDxpIGNsYXNzTmFtZT1cImZhIGZhLWZ3IGZhLXBsdWdcIj48L2k+XG4gICAgICAgICAgICAgICAgIFNodXRkb3duXG4gICAgICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICAgICAgPC9saT5cbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxufSk7XG5cblxudmFyIGhlYWRlcl9lbnRyaWVzID0gW01haW5NZW51LCBWaWV3TWVudSAvKiwgUmVwb3J0c01lbnUgKi9dO1xuXG5cbnZhciBIZWFkZXIgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiSGVhZGVyXCIsXG4gICAgbWl4aW5zOiBbY29tbW9uLk5hdmlnYXRpb25dLFxuICAgIGdldEluaXRpYWxTdGF0ZTogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgYWN0aXZlOiBoZWFkZXJfZW50cmllc1swXVxuICAgICAgICB9O1xuICAgIH0sXG4gICAgaGFuZGxlQ2xpY2s6IGZ1bmN0aW9uIChhY3RpdmUsIGUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB0aGlzLnJlcGxhY2VXaXRoKGFjdGl2ZS5yb3V0ZSk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe2FjdGl2ZTogYWN0aXZlfSk7XG4gICAgfSxcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGhlYWRlciA9IGhlYWRlcl9lbnRyaWVzLm1hcChmdW5jdGlvbiAoZW50cnksIGkpIHtcbiAgICAgICAgICAgIHZhciBjbGFzc2VzID0gUmVhY3QuYWRkb25zLmNsYXNzU2V0KHtcbiAgICAgICAgICAgICAgICBhY3RpdmU6IGVudHJ5ID09IHRoaXMuc3RhdGUuYWN0aXZlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImFcIiwge2tleTogaSwgXG4gICAgICAgICAgICAgICAgICAgIGhyZWY6IFwiI1wiLCBcbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lOiBjbGFzc2VzLCBcbiAgICAgICAgICAgICAgICAgICAgb25DbGljazogdGhpcy5oYW5kbGVDbGljay5iaW5kKHRoaXMsIGVudHJ5KVxuICAgICAgICAgICAgICAgIH0sIFxuICAgICAgICAgICAgICAgICAgICAgZW50cnkudGl0bGVcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiaGVhZGVyXCIsIG51bGwsIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJuYXZcIiwge2NsYXNzTmFtZTogXCJuYXYtdGFicyBuYXYtdGFicy1sZ1wifSwgXG4gICAgICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoRmlsZU1lbnUsIG51bGwpLCBcbiAgICAgICAgICAgICAgICAgICAgaGVhZGVyXG4gICAgICAgICAgICAgICAgKSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7Y2xhc3NOYW1lOiBcIm1lbnVcIn0sIFxuICAgICAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KHRoaXMuc3RhdGUuYWN0aXZlLCB7c2V0dGluZ3M6IHRoaXMucHJvcHMuc2V0dGluZ3N9KVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG59KTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBIZWFkZXI6IEhlYWRlclxufSIsInZhciBSZWFjdCA9IHJlcXVpcmUoXCJyZWFjdFwiKTtcblxudmFyIGNvbW1vbiA9IHJlcXVpcmUoXCIuL2NvbW1vbi5qc1wiKTtcbnZhciB0b3B1dGlscyA9IHJlcXVpcmUoXCIuLi91dGlscy5qc1wiKTtcbnZhciB2aWV3cyA9IHJlcXVpcmUoXCIuLi9zdG9yZS92aWV3LmpzXCIpO1xudmFyIEZpbHQgPSByZXF1aXJlKFwiLi4vZmlsdC9maWx0LmpzXCIpO1xuRmxvd1RhYmxlID0gcmVxdWlyZShcIi4vZmxvd3RhYmxlLmpzXCIpO1xudmFyIGZsb3dkZXRhaWwgPSByZXF1aXJlKFwiLi9mbG93ZGV0YWlsLmpzXCIpO1xuXG5cbnZhciBNYWluVmlldyA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtkaXNwbGF5TmFtZTogXCJNYWluVmlld1wiLFxuICAgIG1peGluczogW2NvbW1vbi5OYXZpZ2F0aW9uLCBjb21tb24uU3RhdGVdLFxuICAgIGdldEluaXRpYWxTdGF0ZTogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLm9uUXVlcnlDaGFuZ2UoUXVlcnkuRklMVEVSLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLnN0YXRlLnZpZXcucmVjYWxjdWxhdGUodGhpcy5nZXRWaWV3RmlsdCgpLCB0aGlzLmdldFZpZXdTb3J0KCkpO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLm9uUXVlcnlDaGFuZ2UoUXVlcnkuSElHSExJR0hULCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLnN0YXRlLnZpZXcucmVjYWxjdWxhdGUodGhpcy5nZXRWaWV3RmlsdCgpLCB0aGlzLmdldFZpZXdTb3J0KCkpO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZmxvd3M6IFtdXG4gICAgICAgIH07XG4gICAgfSxcbiAgICBnZXRWaWV3RmlsdDogZnVuY3Rpb24gKCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgdmFyIGZpbHQgPSBGaWx0LnBhcnNlKHRoaXMuZ2V0UXVlcnkoKVtRdWVyeS5GSUxURVJdIHx8IFwiXCIpO1xuICAgICAgICAgICAgdmFyIGhpZ2hsaWdodFN0ciA9IHRoaXMuZ2V0UXVlcnkoKVtRdWVyeS5ISUdITElHSFRdO1xuICAgICAgICAgICAgdmFyIGhpZ2hsaWdodCA9IGhpZ2hsaWdodFN0ciA/IEZpbHQucGFyc2UoaGlnaGxpZ2h0U3RyKSA6IGZhbHNlO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3Igd2hlbiBwcm9jZXNzaW5nIGZpbHRlcjogXCIgKyBlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBmaWx0ZXJfYW5kX2hpZ2hsaWdodChmbG93KSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuX2hpZ2hsaWdodCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2hpZ2hsaWdodCA9IHt9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5faGlnaGxpZ2h0W2Zsb3cuaWRdID0gaGlnaGxpZ2h0ICYmIGhpZ2hsaWdodChmbG93KTtcbiAgICAgICAgICAgIHJldHVybiBmaWx0KGZsb3cpO1xuICAgICAgICB9O1xuICAgIH0sXG4gICAgZ2V0Vmlld1NvcnQ6IGZ1bmN0aW9uICgpIHtcbiAgICB9LFxuICAgIGNvbXBvbmVudFdpbGxSZWNlaXZlUHJvcHM6IGZ1bmN0aW9uIChuZXh0UHJvcHMpIHtcbiAgICAgICAgaWYgKG5leHRQcm9wcy5mbG93U3RvcmUgIT09IHRoaXMucHJvcHMuZmxvd1N0b3JlKSB7XG4gICAgICAgICAgICB0aGlzLmNsb3NlVmlldygpO1xuICAgICAgICAgICAgdGhpcy5vcGVuVmlldyhuZXh0UHJvcHMuZmxvd1N0b3JlKTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgb3BlblZpZXc6IGZ1bmN0aW9uIChzdG9yZSkge1xuICAgICAgICB2YXIgdmlldyA9IG5ldyB2aWV3cy5TdG9yZVZpZXcoc3RvcmUsIHRoaXMuZ2V0Vmlld0ZpbHQoKSwgdGhpcy5nZXRWaWV3U29ydCgpKTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICB2aWV3OiB2aWV3XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZpZXcuYWRkTGlzdGVuZXIoXCJyZWNhbGN1bGF0ZVwiLCB0aGlzLm9uUmVjYWxjdWxhdGUpO1xuICAgICAgICB2aWV3LmFkZExpc3RlbmVyKFwiYWRkIHVwZGF0ZSByZW1vdmVcIiwgdGhpcy5vblVwZGF0ZSk7XG4gICAgICAgIHZpZXcuYWRkTGlzdGVuZXIoXCJyZW1vdmVcIiwgdGhpcy5vblJlbW92ZSk7XG4gICAgfSxcbiAgICBvblJlY2FsY3VsYXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZm9yY2VVcGRhdGUoKTtcbiAgICAgICAgdmFyIHNlbGVjdGVkID0gdGhpcy5nZXRTZWxlY3RlZCgpO1xuICAgICAgICBpZiAoc2VsZWN0ZWQpIHtcbiAgICAgICAgICAgIHRoaXMucmVmcy5mbG93VGFibGUuc2Nyb2xsSW50b1ZpZXcoc2VsZWN0ZWQpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBvblVwZGF0ZTogZnVuY3Rpb24gKGZsb3cpIHtcbiAgICAgICAgaWYgKGZsb3cuaWQgPT09IHRoaXMuZ2V0UGFyYW1zKCkuZmxvd0lkKSB7XG4gICAgICAgICAgICB0aGlzLmZvcmNlVXBkYXRlKCk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG9uUmVtb3ZlOiBmdW5jdGlvbiAoZmxvd19pZCwgaW5kZXgpIHtcbiAgICAgICAgaWYgKGZsb3dfaWQgPT09IHRoaXMuZ2V0UGFyYW1zKCkuZmxvd0lkKSB7XG4gICAgICAgICAgICB2YXIgZmxvd190b19zZWxlY3QgPSB0aGlzLnN0YXRlLnZpZXcubGlzdFtNYXRoLm1pbihpbmRleCwgdGhpcy5zdGF0ZS52aWV3Lmxpc3QubGVuZ3RoIC0xKV07XG4gICAgICAgICAgICB0aGlzLnNlbGVjdEZsb3coZmxvd190b19zZWxlY3QpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBjbG9zZVZpZXc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5zdGF0ZS52aWV3LmNsb3NlKCk7XG4gICAgfSxcbiAgICBjb21wb25lbnRXaWxsTW91bnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5vcGVuVmlldyh0aGlzLnByb3BzLmZsb3dTdG9yZSk7XG4gICAgfSxcbiAgICBjb21wb25lbnRXaWxsVW5tb3VudDogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNsb3NlVmlldygpO1xuICAgIH0sXG4gICAgc2VsZWN0RmxvdzogZnVuY3Rpb24gKGZsb3cpIHtcbiAgICAgICAgaWYgKGZsb3cpIHtcbiAgICAgICAgICAgIHRoaXMucmVwbGFjZVdpdGgoXG4gICAgICAgICAgICAgICAgXCJmbG93XCIsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBmbG93SWQ6IGZsb3cuaWQsXG4gICAgICAgICAgICAgICAgICAgIGRldGFpbFRhYjogdGhpcy5nZXRQYXJhbXMoKS5kZXRhaWxUYWIgfHwgXCJyZXF1ZXN0XCJcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdGhpcy5yZWZzLmZsb3dUYWJsZS5zY3JvbGxJbnRvVmlldyhmbG93KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucmVwbGFjZVdpdGgoXCJmbG93c1wiLCB7fSk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHNlbGVjdEZsb3dSZWxhdGl2ZTogZnVuY3Rpb24gKHNoaWZ0KSB7XG4gICAgICAgIHZhciBmbG93cyA9IHRoaXMuc3RhdGUudmlldy5saXN0O1xuICAgICAgICB2YXIgaW5kZXg7XG4gICAgICAgIGlmICghdGhpcy5nZXRQYXJhbXMoKS5mbG93SWQpIHtcbiAgICAgICAgICAgIGlmIChzaGlmdCA+IDApIHtcbiAgICAgICAgICAgICAgICBpbmRleCA9IGZsb3dzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGluZGV4ID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciBjdXJyRmxvd0lkID0gdGhpcy5nZXRQYXJhbXMoKS5mbG93SWQ7XG4gICAgICAgICAgICB2YXIgaSA9IGZsb3dzLmxlbmd0aDtcbiAgICAgICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgICAgICBpZiAoZmxvd3NbaV0uaWQgPT09IGN1cnJGbG93SWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggPSBpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpbmRleCA9IE1hdGgubWluKFxuICAgICAgICAgICAgICAgIE1hdGgubWF4KDAsIGluZGV4ICsgc2hpZnQpLFxuICAgICAgICAgICAgICAgIGZsb3dzLmxlbmd0aCAtIDEpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2VsZWN0RmxvdyhmbG93c1tpbmRleF0pO1xuICAgIH0sXG4gICAgb25LZXlEb3duOiBmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIgZmxvdyA9IHRoaXMuZ2V0U2VsZWN0ZWQoKTtcbiAgICAgICAgaWYgKGUuY3RybEtleSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHN3aXRjaCAoZS5rZXlDb2RlKSB7XG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5LOlxuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuVVA6XG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RGbG93UmVsYXRpdmUoLTEpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuSjpcbiAgICAgICAgICAgIGNhc2UgdG9wdXRpbHMuS2V5LkRPV046XG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RGbG93UmVsYXRpdmUoKzEpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuU1BBQ0U6XG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5QQUdFX0RPV046XG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RGbG93UmVsYXRpdmUoKzEwKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgdG9wdXRpbHMuS2V5LlBBR0VfVVA6XG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RGbG93UmVsYXRpdmUoLTEwKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgdG9wdXRpbHMuS2V5LkVORDpcbiAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdEZsb3dSZWxhdGl2ZSgrMWUxMCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5IT01FOlxuICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0Rmxvd1JlbGF0aXZlKC0xZTEwKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgdG9wdXRpbHMuS2V5LkVTQzpcbiAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdEZsb3cobnVsbCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5IOlxuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuTEVGVDpcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5yZWZzLmZsb3dEZXRhaWxzKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVmcy5mbG93RGV0YWlscy5uZXh0VGFiKC0xKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5MOlxuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuVEFCOlxuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuUklHSFQ6XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucmVmcy5mbG93RGV0YWlscykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlZnMuZmxvd0RldGFpbHMubmV4dFRhYigrMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuQzpcbiAgICAgICAgICAgICAgICBpZiAoZS5zaGlmdEtleSkge1xuICAgICAgICAgICAgICAgICAgICBGbG93QWN0aW9ucy5jbGVhcigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgdG9wdXRpbHMuS2V5LkQ6XG4gICAgICAgICAgICAgICAgaWYgKGZsb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGUuc2hpZnRLZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIEZsb3dBY3Rpb25zLmR1cGxpY2F0ZShmbG93KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIEZsb3dBY3Rpb25zLmRlbGV0ZShmbG93KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgdG9wdXRpbHMuS2V5LkE6XG4gICAgICAgICAgICAgICAgaWYgKGUuc2hpZnRLZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgRmxvd0FjdGlvbnMuYWNjZXB0X2FsbCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZmxvdyAmJiBmbG93LmludGVyY2VwdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIEZsb3dBY3Rpb25zLmFjY2VwdChmbG93KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5SOlxuICAgICAgICAgICAgICAgIGlmICghZS5zaGlmdEtleSAmJiBmbG93KSB7XG4gICAgICAgICAgICAgICAgICAgIEZsb3dBY3Rpb25zLnJlcGxheShmbG93KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5WOlxuICAgICAgICAgICAgICAgIGlmKGUuc2hpZnRLZXkgJiYgZmxvdyAmJiBmbG93Lm1vZGlmaWVkKSB7XG4gICAgICAgICAgICAgICAgICAgIEZsb3dBY3Rpb25zLnJldmVydChmbG93KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoXCJrZXlkb3duXCIsIGUua2V5Q29kZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB9LFxuICAgIGdldFNlbGVjdGVkOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnByb3BzLmZsb3dTdG9yZS5nZXQodGhpcy5nZXRQYXJhbXMoKS5mbG93SWQpO1xuICAgIH0sXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBzZWxlY3RlZCA9IHRoaXMuZ2V0U2VsZWN0ZWQoKTtcblxuICAgICAgICB2YXIgZGV0YWlscztcbiAgICAgICAgaWYgKHNlbGVjdGVkKSB7XG4gICAgICAgICAgICBkZXRhaWxzID0gW1xuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoY29tbW9uLlNwbGl0dGVyLCB7a2V5OiBcInNwbGl0dGVyXCJ9KSxcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KGZsb3dkZXRhaWwuRmxvd0RldGFpbCwge2tleTogXCJmbG93RGV0YWlsc1wiLCByZWY6IFwiZmxvd0RldGFpbHNcIiwgZmxvdzogc2VsZWN0ZWR9KVxuICAgICAgICAgICAgXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRldGFpbHMgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwge2NsYXNzTmFtZTogXCJtYWluLXZpZXdcIiwgb25LZXlEb3duOiB0aGlzLm9uS2V5RG93biwgdGFiSW5kZXg6IFwiMFwifSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChGbG93VGFibGUsIHtyZWY6IFwiZmxvd1RhYmxlXCIsIFxuICAgICAgICAgICAgICAgICAgICB2aWV3OiB0aGlzLnN0YXRlLnZpZXcsIFxuICAgICAgICAgICAgICAgICAgICBzZWxlY3RGbG93OiB0aGlzLnNlbGVjdEZsb3csIFxuICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZDogc2VsZWN0ZWR9KSwgXG4gICAgICAgICAgICAgICAgZGV0YWlsc1xuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cbn0pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IE1haW5WaWV3O1xuIiwidmFyIFJlYWN0ID0gcmVxdWlyZShcInJlYWN0XCIpO1xudmFyIFJlYWN0Um91dGVyID0gcmVxdWlyZShcInJlYWN0LXJvdXRlclwiKTtcbnZhciBfID0gcmVxdWlyZShcImxvZGFzaFwiKTtcblxudmFyIGNvbW1vbiA9IHJlcXVpcmUoXCIuL2NvbW1vbi5qc1wiKTtcbnZhciBNYWluVmlldyA9IHJlcXVpcmUoXCIuL21haW52aWV3LmpzXCIpO1xudmFyIEZvb3RlciA9IHJlcXVpcmUoXCIuL2Zvb3Rlci5qc1wiKTtcbnZhciBoZWFkZXIgPSByZXF1aXJlKFwiLi9oZWFkZXIuanNcIik7XG52YXIgRXZlbnRMb2cgPSByZXF1aXJlKFwiLi9ldmVudGxvZy5qc1wiKTtcbnZhciBzdG9yZSA9IHJlcXVpcmUoXCIuLi9zdG9yZS9zdG9yZS5qc1wiKTtcblxuXG4vL1RPRE86IE1vdmUgb3V0IG9mIGhlcmUsIGp1c3QgYSBzdHViLlxudmFyIFJlcG9ydHMgPSBSZWFjdC5jcmVhdGVDbGFzcyh7ZGlzcGxheU5hbWU6IFwiUmVwb3J0c1wiLFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCBudWxsLCBcIlJlcG9ydEVkaXRvclwiKTtcbiAgICB9XG59KTtcblxuXG52YXIgUHJveHlBcHBNYWluID0gUmVhY3QuY3JlYXRlQ2xhc3Moe2Rpc3BsYXlOYW1lOiBcIlByb3h5QXBwTWFpblwiLFxuICAgIG1peGluczogW2NvbW1vbi5TdGF0ZV0sXG4gICAgZ2V0SW5pdGlhbFN0YXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBldmVudFN0b3JlID0gbmV3IHN0b3JlLkV2ZW50TG9nU3RvcmUoKTtcbiAgICAgICAgdmFyIGZsb3dTdG9yZSA9IG5ldyBzdG9yZS5GbG93U3RvcmUoKTtcbiAgICAgICAgdmFyIHNldHRpbmdzID0gbmV3IHN0b3JlLlNldHRpbmdzU3RvcmUoKTtcblxuICAgICAgICAvLyBEZWZhdWx0IFNldHRpbmdzIGJlZm9yZSBmZXRjaFxuICAgICAgICBfLmV4dGVuZChzZXR0aW5ncy5kaWN0LHtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzZXR0aW5nczogc2V0dGluZ3MsXG4gICAgICAgICAgICBmbG93U3RvcmU6IGZsb3dTdG9yZSxcbiAgICAgICAgICAgIGV2ZW50U3RvcmU6IGV2ZW50U3RvcmVcbiAgICAgICAgfTtcbiAgICB9LFxuICAgIGNvbXBvbmVudERpZE1vdW50OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc3RhdGUuc2V0dGluZ3MuYWRkTGlzdGVuZXIoXCJyZWNhbGN1bGF0ZVwiLCB0aGlzLm9uU2V0dGluZ3NDaGFuZ2UpO1xuICAgICAgICB3aW5kb3cuYXBwID0gdGhpcztcbiAgICB9LFxuICAgIGNvbXBvbmVudFdpbGxVbm1vdW50OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuc3RhdGUuc2V0dGluZ3MucmVtb3ZlTGlzdGVuZXIoXCJyZWNhbGN1bGF0ZVwiLCB0aGlzLm9uU2V0dGluZ3NDaGFuZ2UpO1xuICAgIH0sXG4gICAgb25TZXR0aW5nc0NoYW5nZTogZnVuY3Rpb24oKXtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBzZXR0aW5nczogdGhpcy5zdGF0ZS5zZXR0aW5nc1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuXG4gICAgICAgIHZhciBldmVudGxvZztcbiAgICAgICAgaWYgKHRoaXMuZ2V0UXVlcnkoKVtRdWVyeS5TSE9XX0VWRU5UTE9HXSkge1xuICAgICAgICAgICAgZXZlbnRsb2cgPSBbXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChjb21tb24uU3BsaXR0ZXIsIHtrZXk6IFwic3BsaXR0ZXJcIiwgYXhpczogXCJ5XCJ9KSxcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KEV2ZW50TG9nLCB7a2V5OiBcImV2ZW50bG9nXCIsIGV2ZW50U3RvcmU6IHRoaXMuc3RhdGUuZXZlbnRTdG9yZX0pXG4gICAgICAgICAgICBdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZXZlbnRsb2cgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwge2lkOiBcImNvbnRhaW5lclwifSwgXG4gICAgICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChoZWFkZXIuSGVhZGVyLCB7c2V0dGluZ3M6IHRoaXMuc3RhdGUuc2V0dGluZ3MuZGljdH0pLCBcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFJvdXRlSGFuZGxlciwge3NldHRpbmdzOiB0aGlzLnN0YXRlLnNldHRpbmdzLmRpY3QsIGZsb3dTdG9yZTogdGhpcy5zdGF0ZS5mbG93U3RvcmV9KSwgXG4gICAgICAgICAgICAgICAgZXZlbnRsb2csIFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoRm9vdGVyLCB7c2V0dGluZ3M6IHRoaXMuc3RhdGUuc2V0dGluZ3MuZGljdH0pXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxufSk7XG5cblxudmFyIFJvdXRlID0gUmVhY3RSb3V0ZXIuUm91dGU7XG52YXIgUm91dGVIYW5kbGVyID0gUmVhY3RSb3V0ZXIuUm91dGVIYW5kbGVyO1xudmFyIFJlZGlyZWN0ID0gUmVhY3RSb3V0ZXIuUmVkaXJlY3Q7XG52YXIgRGVmYXVsdFJvdXRlID0gUmVhY3RSb3V0ZXIuRGVmYXVsdFJvdXRlO1xudmFyIE5vdEZvdW5kUm91dGUgPSBSZWFjdFJvdXRlci5Ob3RGb3VuZFJvdXRlO1xuXG5cbnZhciByb3V0ZXMgPSAoXG4gICAgUmVhY3QuY3JlYXRlRWxlbWVudChSb3V0ZSwge3BhdGg6IFwiL1wiLCBoYW5kbGVyOiBQcm94eUFwcE1haW59LCBcbiAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChSb3V0ZSwge25hbWU6IFwiZmxvd3NcIiwgcGF0aDogXCJmbG93c1wiLCBoYW5kbGVyOiBNYWluVmlld30pLCBcbiAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChSb3V0ZSwge25hbWU6IFwiZmxvd1wiLCBwYXRoOiBcImZsb3dzLzpmbG93SWQvOmRldGFpbFRhYlwiLCBoYW5kbGVyOiBNYWluVmlld30pLCBcbiAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChSb3V0ZSwge25hbWU6IFwicmVwb3J0c1wiLCBoYW5kbGVyOiBSZXBvcnRzfSksIFxuICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFJlZGlyZWN0LCB7cGF0aDogXCIvXCIsIHRvOiBcImZsb3dzXCJ9KVxuICAgIClcbik7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIHJvdXRlczogcm91dGVzXG59O1xuXG4iLCJ2YXIgUmVhY3QgPSByZXF1aXJlKFwicmVhY3RcIik7XG5cbnZhciBWaXJ0dWFsU2Nyb2xsTWl4aW4gPSB7XG4gICAgZ2V0SW5pdGlhbFN0YXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzdGFydDogMCxcbiAgICAgICAgICAgIHN0b3A6IDBcbiAgICAgICAgfTtcbiAgICB9LFxuICAgIGNvbXBvbmVudFdpbGxNb3VudDogZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMucHJvcHMucm93SGVpZ2h0KSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJWaXJ0dWFsU2Nyb2xsTWl4aW46IE5vIHJvd0hlaWdodCBzcGVjaWZpZWRcIiwgdGhpcyk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGdldFBsYWNlaG9sZGVyVG9wOiBmdW5jdGlvbiAodG90YWwpIHtcbiAgICAgICAgdmFyIFRhZyA9IHRoaXMucHJvcHMucGxhY2Vob2xkZXJUYWdOYW1lIHx8IFwidHJcIjtcbiAgICAgICAgLy8gV2hlbiBhIGxhcmdlIHRydW5rIG9mIGVsZW1lbnRzIGlzIHJlbW92ZWQgZnJvbSB0aGUgYnV0dG9uLCBzdGFydCBtYXkgYmUgZmFyIG9mZiB0aGUgdmlld3BvcnQuXG4gICAgICAgIC8vIFRvIG1ha2UgdGhpcyBpc3N1ZSBsZXNzIHNldmVyZSwgbGltaXQgdGhlIHRvcCBwbGFjZWhvbGRlciB0byB0aGUgdG90YWwgbnVtYmVyIG9mIHJvd3MuXG4gICAgICAgIHZhciBzdHlsZSA9IHtcbiAgICAgICAgICAgIGhlaWdodDogTWF0aC5taW4odGhpcy5zdGF0ZS5zdGFydCwgdG90YWwpICogdGhpcy5wcm9wcy5yb3dIZWlnaHRcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIHNwYWNlciA9IFJlYWN0LmNyZWF0ZUVsZW1lbnQoVGFnLCB7a2V5OiBcInBsYWNlaG9sZGVyLXRvcFwiLCBzdHlsZTogc3R5bGV9KTtcblxuICAgICAgICBpZiAodGhpcy5zdGF0ZS5zdGFydCAlIDIgPT09IDEpIHtcbiAgICAgICAgICAgIC8vIGZpeCBldmVuL29kZCByb3dzXG4gICAgICAgICAgICByZXR1cm4gW3NwYWNlciwgUmVhY3QuY3JlYXRlRWxlbWVudChUYWcsIHtrZXk6IFwicGxhY2Vob2xkZXItdG9wLTJcIn0pXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBzcGFjZXI7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGdldFBsYWNlaG9sZGVyQm90dG9tOiBmdW5jdGlvbiAodG90YWwpIHtcbiAgICAgICAgdmFyIFRhZyA9IHRoaXMucHJvcHMucGxhY2Vob2xkZXJUYWdOYW1lIHx8IFwidHJcIjtcbiAgICAgICAgdmFyIHN0eWxlID0ge1xuICAgICAgICAgICAgaGVpZ2h0OiBNYXRoLm1heCgwLCB0b3RhbCAtIHRoaXMuc3RhdGUuc3RvcCkgKiB0aGlzLnByb3BzLnJvd0hlaWdodFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gUmVhY3QuY3JlYXRlRWxlbWVudChUYWcsIHtrZXk6IFwicGxhY2Vob2xkZXItYm90dG9tXCIsIHN0eWxlOiBzdHlsZX0pO1xuICAgIH0sXG4gICAgY29tcG9uZW50RGlkTW91bnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5vblNjcm9sbCgpO1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5vblNjcm9sbCk7XG4gICAgfSxcbiAgICBjb21wb25lbnRXaWxsVW5tb3VudDogZnVuY3Rpb24oKXtcbiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIHRoaXMub25TY3JvbGwpO1xuICAgIH0sXG4gICAgb25TY3JvbGw6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHZpZXdwb3J0ID0gdGhpcy5nZXRET01Ob2RlKCk7XG4gICAgICAgIHZhciB0b3AgPSB2aWV3cG9ydC5zY3JvbGxUb3A7XG4gICAgICAgIHZhciBoZWlnaHQgPSB2aWV3cG9ydC5vZmZzZXRIZWlnaHQ7XG4gICAgICAgIHZhciBzdGFydCA9IE1hdGguZmxvb3IodG9wIC8gdGhpcy5wcm9wcy5yb3dIZWlnaHQpO1xuICAgICAgICB2YXIgc3RvcCA9IHN0YXJ0ICsgTWF0aC5jZWlsKGhlaWdodCAvICh0aGlzLnByb3BzLnJvd0hlaWdodE1pbiB8fCB0aGlzLnByb3BzLnJvd0hlaWdodCkpO1xuXG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgc3RhcnQ6IHN0YXJ0LFxuICAgICAgICAgICAgc3RvcDogc3RvcFxuICAgICAgICB9KTtcbiAgICB9LFxuICAgIHJlbmRlclJvd3M6IGZ1bmN0aW9uIChlbGVtcykge1xuICAgICAgICB2YXIgcm93cyA9IFtdO1xuICAgICAgICB2YXIgbWF4ID0gTWF0aC5taW4oZWxlbXMubGVuZ3RoLCB0aGlzLnN0YXRlLnN0b3ApO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSB0aGlzLnN0YXRlLnN0YXJ0OyBpIDwgbWF4OyBpKyspIHtcbiAgICAgICAgICAgIHZhciBlbGVtID0gZWxlbXNbaV07XG4gICAgICAgICAgICByb3dzLnB1c2godGhpcy5yZW5kZXJSb3coZWxlbSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByb3dzO1xuICAgIH0sXG4gICAgc2Nyb2xsUm93SW50b1ZpZXc6IGZ1bmN0aW9uIChpbmRleCwgaGVhZF9oZWlnaHQpIHtcblxuICAgICAgICB2YXIgcm93X3RvcCA9IChpbmRleCAqIHRoaXMucHJvcHMucm93SGVpZ2h0KSArIGhlYWRfaGVpZ2h0O1xuICAgICAgICB2YXIgcm93X2JvdHRvbSA9IHJvd190b3AgKyB0aGlzLnByb3BzLnJvd0hlaWdodDtcblxuICAgICAgICB2YXIgdmlld3BvcnQgPSB0aGlzLmdldERPTU5vZGUoKTtcbiAgICAgICAgdmFyIHZpZXdwb3J0X3RvcCA9IHZpZXdwb3J0LnNjcm9sbFRvcDtcbiAgICAgICAgdmFyIHZpZXdwb3J0X2JvdHRvbSA9IHZpZXdwb3J0X3RvcCArIHZpZXdwb3J0Lm9mZnNldEhlaWdodDtcblxuICAgICAgICAvLyBBY2NvdW50IGZvciBwaW5uZWQgdGhlYWRcbiAgICAgICAgaWYgKHJvd190b3AgLSBoZWFkX2hlaWdodCA8IHZpZXdwb3J0X3RvcCkge1xuICAgICAgICAgICAgdmlld3BvcnQuc2Nyb2xsVG9wID0gcm93X3RvcCAtIGhlYWRfaGVpZ2h0O1xuICAgICAgICB9IGVsc2UgaWYgKHJvd19ib3R0b20gPiB2aWV3cG9ydF9ib3R0b20pIHtcbiAgICAgICAgICAgIHZpZXdwb3J0LnNjcm9sbFRvcCA9IHJvd19ib3R0b20gLSB2aWV3cG9ydC5vZmZzZXRIZWlnaHQ7XG4gICAgICAgIH1cbiAgICB9LFxufTtcblxubW9kdWxlLmV4cG9ydHMgID0gVmlydHVhbFNjcm9sbE1peGluOyIsIlxudmFyIGFjdGlvbnMgPSByZXF1aXJlKFwiLi9hY3Rpb25zLmpzXCIpO1xuXG5mdW5jdGlvbiBDb25uZWN0aW9uKHVybCkge1xuICAgIGlmICh1cmxbMF0gPT09IFwiL1wiKSB7XG4gICAgICAgIHVybCA9IGxvY2F0aW9uLm9yaWdpbi5yZXBsYWNlKFwiaHR0cFwiLCBcIndzXCIpICsgdXJsO1xuICAgIH1cblxuICAgIHZhciB3cyA9IG5ldyBXZWJTb2NrZXQodXJsKTtcbiAgICB3cy5vbm9wZW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGFjdGlvbnMuQ29ubmVjdGlvbkFjdGlvbnMub3BlbigpO1xuICAgIH07XG4gICAgd3Mub25tZXNzYWdlID0gZnVuY3Rpb24gKG1lc3NhZ2UpIHtcbiAgICAgICAgdmFyIG0gPSBKU09OLnBhcnNlKG1lc3NhZ2UuZGF0YSk7XG4gICAgICAgIEFwcERpc3BhdGNoZXIuZGlzcGF0Y2hTZXJ2ZXJBY3Rpb24obSk7XG4gICAgfTtcbiAgICB3cy5vbmVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBhY3Rpb25zLkNvbm5lY3Rpb25BY3Rpb25zLmVycm9yKCk7XG4gICAgICAgIEV2ZW50TG9nQWN0aW9ucy5hZGRfZXZlbnQoXCJXZWJTb2NrZXQgY29ubmVjdGlvbiBlcnJvci5cIik7XG4gICAgfTtcbiAgICB3cy5vbmNsb3NlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBhY3Rpb25zLkNvbm5lY3Rpb25BY3Rpb25zLmNsb3NlKCk7XG4gICAgICAgIEV2ZW50TG9nQWN0aW9ucy5hZGRfZXZlbnQoXCJXZWJTb2NrZXQgY29ubmVjdGlvbiBjbG9zZWQuXCIpO1xuICAgIH07XG4gICAgcmV0dXJuIHdzO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IENvbm5lY3Rpb247IiwiXG52YXIgZmx1eCA9IHJlcXVpcmUoXCJmbHV4XCIpO1xuXG5jb25zdCBQYXlsb2FkU291cmNlcyA9IHtcbiAgICBWSUVXOiBcInZpZXdcIixcbiAgICBTRVJWRVI6IFwic2VydmVyXCJcbn07XG5cblxuQXBwRGlzcGF0Y2hlciA9IG5ldyBmbHV4LkRpc3BhdGNoZXIoKTtcbkFwcERpc3BhdGNoZXIuZGlzcGF0Y2hWaWV3QWN0aW9uID0gZnVuY3Rpb24gKGFjdGlvbikge1xuICAgIGFjdGlvbi5zb3VyY2UgPSBQYXlsb2FkU291cmNlcy5WSUVXO1xuICAgIHRoaXMuZGlzcGF0Y2goYWN0aW9uKTtcbn07XG5BcHBEaXNwYXRjaGVyLmRpc3BhdGNoU2VydmVyQWN0aW9uID0gZnVuY3Rpb24gKGFjdGlvbikge1xuICAgIGFjdGlvbi5zb3VyY2UgPSBQYXlsb2FkU291cmNlcy5TRVJWRVI7XG4gICAgdGhpcy5kaXNwYXRjaChhY3Rpb24pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgQXBwRGlzcGF0Y2hlcjogQXBwRGlzcGF0Y2hlclxufTsiLCJtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbigpIHtcbiAgLypcbiAgICogR2VuZXJhdGVkIGJ5IFBFRy5qcyAwLjguMC5cbiAgICpcbiAgICogaHR0cDovL3BlZ2pzLm1hamRhLmN6L1xuICAgKi9cblxuICBmdW5jdGlvbiBwZWckc3ViY2xhc3MoY2hpbGQsIHBhcmVudCkge1xuICAgIGZ1bmN0aW9uIGN0b3IoKSB7IHRoaXMuY29uc3RydWN0b3IgPSBjaGlsZDsgfVxuICAgIGN0b3IucHJvdG90eXBlID0gcGFyZW50LnByb3RvdHlwZTtcbiAgICBjaGlsZC5wcm90b3R5cGUgPSBuZXcgY3RvcigpO1xuICB9XG5cbiAgZnVuY3Rpb24gU3ludGF4RXJyb3IobWVzc2FnZSwgZXhwZWN0ZWQsIGZvdW5kLCBvZmZzZXQsIGxpbmUsIGNvbHVtbikge1xuICAgIHRoaXMubWVzc2FnZSAgPSBtZXNzYWdlO1xuICAgIHRoaXMuZXhwZWN0ZWQgPSBleHBlY3RlZDtcbiAgICB0aGlzLmZvdW5kICAgID0gZm91bmQ7XG4gICAgdGhpcy5vZmZzZXQgICA9IG9mZnNldDtcbiAgICB0aGlzLmxpbmUgICAgID0gbGluZTtcbiAgICB0aGlzLmNvbHVtbiAgID0gY29sdW1uO1xuXG4gICAgdGhpcy5uYW1lICAgICA9IFwiU3ludGF4RXJyb3JcIjtcbiAgfVxuXG4gIHBlZyRzdWJjbGFzcyhTeW50YXhFcnJvciwgRXJyb3IpO1xuXG4gIGZ1bmN0aW9uIHBhcnNlKGlucHV0KSB7XG4gICAgdmFyIG9wdGlvbnMgPSBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHt9LFxuXG4gICAgICAgIHBlZyRGQUlMRUQgPSB7fSxcblxuICAgICAgICBwZWckc3RhcnRSdWxlRnVuY3Rpb25zID0geyBzdGFydDogcGVnJHBhcnNlc3RhcnQgfSxcbiAgICAgICAgcGVnJHN0YXJ0UnVsZUZ1bmN0aW9uICA9IHBlZyRwYXJzZXN0YXJ0LFxuXG4gICAgICAgIHBlZyRjMCA9IHsgdHlwZTogXCJvdGhlclwiLCBkZXNjcmlwdGlvbjogXCJmaWx0ZXIgZXhwcmVzc2lvblwiIH0sXG4gICAgICAgIHBlZyRjMSA9IHBlZyRGQUlMRUQsXG4gICAgICAgIHBlZyRjMiA9IGZ1bmN0aW9uKG9yRXhwcikgeyByZXR1cm4gb3JFeHByOyB9LFxuICAgICAgICBwZWckYzMgPSBbXSxcbiAgICAgICAgcGVnJGM0ID0gZnVuY3Rpb24oKSB7cmV0dXJuIHRydWVGaWx0ZXI7IH0sXG4gICAgICAgIHBlZyRjNSA9IHsgdHlwZTogXCJvdGhlclwiLCBkZXNjcmlwdGlvbjogXCJ3aGl0ZXNwYWNlXCIgfSxcbiAgICAgICAgcGVnJGM2ID0gL15bIFxcdFxcblxccl0vLFxuICAgICAgICBwZWckYzcgPSB7IHR5cGU6IFwiY2xhc3NcIiwgdmFsdWU6IFwiWyBcXFxcdFxcXFxuXFxcXHJdXCIsIGRlc2NyaXB0aW9uOiBcIlsgXFxcXHRcXFxcblxcXFxyXVwiIH0sXG4gICAgICAgIHBlZyRjOCA9IHsgdHlwZTogXCJvdGhlclwiLCBkZXNjcmlwdGlvbjogXCJjb250cm9sIGNoYXJhY3RlclwiIH0sXG4gICAgICAgIHBlZyRjOSA9IC9eW3wmISgpflwiXS8sXG4gICAgICAgIHBlZyRjMTAgPSB7IHR5cGU6IFwiY2xhc3NcIiwgdmFsdWU6IFwiW3wmISgpflxcXCJdXCIsIGRlc2NyaXB0aW9uOiBcIlt8JiEoKX5cXFwiXVwiIH0sXG4gICAgICAgIHBlZyRjMTEgPSB7IHR5cGU6IFwib3RoZXJcIiwgZGVzY3JpcHRpb246IFwib3B0aW9uYWwgd2hpdGVzcGFjZVwiIH0sXG4gICAgICAgIHBlZyRjMTIgPSBcInxcIixcbiAgICAgICAgcGVnJGMxMyA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcInxcIiwgZGVzY3JpcHRpb246IFwiXFxcInxcXFwiXCIgfSxcbiAgICAgICAgcGVnJGMxNCA9IGZ1bmN0aW9uKGZpcnN0LCBzZWNvbmQpIHsgcmV0dXJuIG9yKGZpcnN0LCBzZWNvbmQpOyB9LFxuICAgICAgICBwZWckYzE1ID0gXCImXCIsXG4gICAgICAgIHBlZyRjMTYgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCImXCIsIGRlc2NyaXB0aW9uOiBcIlxcXCImXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjMTcgPSBmdW5jdGlvbihmaXJzdCwgc2Vjb25kKSB7IHJldHVybiBhbmQoZmlyc3QsIHNlY29uZCk7IH0sXG4gICAgICAgIHBlZyRjMTggPSBcIiFcIixcbiAgICAgICAgcGVnJGMxOSA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcIiFcIiwgZGVzY3JpcHRpb246IFwiXFxcIiFcXFwiXCIgfSxcbiAgICAgICAgcGVnJGMyMCA9IGZ1bmN0aW9uKGV4cHIpIHsgcmV0dXJuIG5vdChleHByKTsgfSxcbiAgICAgICAgcGVnJGMyMSA9IFwiKFwiLFxuICAgICAgICBwZWckYzIyID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwiKFwiLCBkZXNjcmlwdGlvbjogXCJcXFwiKFxcXCJcIiB9LFxuICAgICAgICBwZWckYzIzID0gXCIpXCIsXG4gICAgICAgIHBlZyRjMjQgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCIpXCIsIGRlc2NyaXB0aW9uOiBcIlxcXCIpXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjMjUgPSBmdW5jdGlvbihleHByKSB7IHJldHVybiBiaW5kaW5nKGV4cHIpOyB9LFxuICAgICAgICBwZWckYzI2ID0gXCJ+YVwiLFxuICAgICAgICBwZWckYzI3ID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwifmFcIiwgZGVzY3JpcHRpb246IFwiXFxcIn5hXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjMjggPSBmdW5jdGlvbigpIHsgcmV0dXJuIGFzc2V0RmlsdGVyOyB9LFxuICAgICAgICBwZWckYzI5ID0gXCJ+ZVwiLFxuICAgICAgICBwZWckYzMwID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwifmVcIiwgZGVzY3JpcHRpb246IFwiXFxcIn5lXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjMzEgPSBmdW5jdGlvbigpIHsgcmV0dXJuIGVycm9yRmlsdGVyOyB9LFxuICAgICAgICBwZWckYzMyID0gXCJ+cVwiLFxuICAgICAgICBwZWckYzMzID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwifnFcIiwgZGVzY3JpcHRpb246IFwiXFxcIn5xXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjMzQgPSBmdW5jdGlvbigpIHsgcmV0dXJuIG5vUmVzcG9uc2VGaWx0ZXI7IH0sXG4gICAgICAgIHBlZyRjMzUgPSBcIn5zXCIsXG4gICAgICAgIHBlZyRjMzYgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJ+c1wiLCBkZXNjcmlwdGlvbjogXCJcXFwifnNcXFwiXCIgfSxcbiAgICAgICAgcGVnJGMzNyA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gcmVzcG9uc2VGaWx0ZXI7IH0sXG4gICAgICAgIHBlZyRjMzggPSBcInRydWVcIixcbiAgICAgICAgcGVnJGMzOSA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcInRydWVcIiwgZGVzY3JpcHRpb246IFwiXFxcInRydWVcXFwiXCIgfSxcbiAgICAgICAgcGVnJGM0MCA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdHJ1ZUZpbHRlcjsgfSxcbiAgICAgICAgcGVnJGM0MSA9IFwiZmFsc2VcIixcbiAgICAgICAgcGVnJGM0MiA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcImZhbHNlXCIsIGRlc2NyaXB0aW9uOiBcIlxcXCJmYWxzZVxcXCJcIiB9LFxuICAgICAgICBwZWckYzQzID0gZnVuY3Rpb24oKSB7IHJldHVybiBmYWxzZUZpbHRlcjsgfSxcbiAgICAgICAgcGVnJGM0NCA9IFwifmNcIixcbiAgICAgICAgcGVnJGM0NSA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcIn5jXCIsIGRlc2NyaXB0aW9uOiBcIlxcXCJ+Y1xcXCJcIiB9LFxuICAgICAgICBwZWckYzQ2ID0gZnVuY3Rpb24ocykgeyByZXR1cm4gcmVzcG9uc2VDb2RlKHMpOyB9LFxuICAgICAgICBwZWckYzQ3ID0gXCJ+ZFwiLFxuICAgICAgICBwZWckYzQ4ID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwifmRcIiwgZGVzY3JpcHRpb246IFwiXFxcIn5kXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjNDkgPSBmdW5jdGlvbihzKSB7IHJldHVybiBkb21haW4ocyk7IH0sXG4gICAgICAgIHBlZyRjNTAgPSBcIn5oXCIsXG4gICAgICAgIHBlZyRjNTEgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJ+aFwiLCBkZXNjcmlwdGlvbjogXCJcXFwifmhcXFwiXCIgfSxcbiAgICAgICAgcGVnJGM1MiA9IGZ1bmN0aW9uKHMpIHsgcmV0dXJuIGhlYWRlcihzKTsgfSxcbiAgICAgICAgcGVnJGM1MyA9IFwifmhxXCIsXG4gICAgICAgIHBlZyRjNTQgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJ+aHFcIiwgZGVzY3JpcHRpb246IFwiXFxcIn5ocVxcXCJcIiB9LFxuICAgICAgICBwZWckYzU1ID0gZnVuY3Rpb24ocykgeyByZXR1cm4gcmVxdWVzdEhlYWRlcihzKTsgfSxcbiAgICAgICAgcGVnJGM1NiA9IFwifmhzXCIsXG4gICAgICAgIHBlZyRjNTcgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJ+aHNcIiwgZGVzY3JpcHRpb246IFwiXFxcIn5oc1xcXCJcIiB9LFxuICAgICAgICBwZWckYzU4ID0gZnVuY3Rpb24ocykgeyByZXR1cm4gcmVzcG9uc2VIZWFkZXIocyk7IH0sXG4gICAgICAgIHBlZyRjNTkgPSBcIn5tXCIsXG4gICAgICAgIHBlZyRjNjAgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJ+bVwiLCBkZXNjcmlwdGlvbjogXCJcXFwifm1cXFwiXCIgfSxcbiAgICAgICAgcGVnJGM2MSA9IGZ1bmN0aW9uKHMpIHsgcmV0dXJuIG1ldGhvZChzKTsgfSxcbiAgICAgICAgcGVnJGM2MiA9IFwifnRcIixcbiAgICAgICAgcGVnJGM2MyA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcIn50XCIsIGRlc2NyaXB0aW9uOiBcIlxcXCJ+dFxcXCJcIiB9LFxuICAgICAgICBwZWckYzY0ID0gZnVuY3Rpb24ocykgeyByZXR1cm4gY29udGVudFR5cGUocyk7IH0sXG4gICAgICAgIHBlZyRjNjUgPSBcIn50cVwiLFxuICAgICAgICBwZWckYzY2ID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwifnRxXCIsIGRlc2NyaXB0aW9uOiBcIlxcXCJ+dHFcXFwiXCIgfSxcbiAgICAgICAgcGVnJGM2NyA9IGZ1bmN0aW9uKHMpIHsgcmV0dXJuIHJlcXVlc3RDb250ZW50VHlwZShzKTsgfSxcbiAgICAgICAgcGVnJGM2OCA9IFwifnRzXCIsXG4gICAgICAgIHBlZyRjNjkgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJ+dHNcIiwgZGVzY3JpcHRpb246IFwiXFxcIn50c1xcXCJcIiB9LFxuICAgICAgICBwZWckYzcwID0gZnVuY3Rpb24ocykgeyByZXR1cm4gcmVzcG9uc2VDb250ZW50VHlwZShzKTsgfSxcbiAgICAgICAgcGVnJGM3MSA9IFwifnVcIixcbiAgICAgICAgcGVnJGM3MiA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcIn51XCIsIGRlc2NyaXB0aW9uOiBcIlxcXCJ+dVxcXCJcIiB9LFxuICAgICAgICBwZWckYzczID0gZnVuY3Rpb24ocykgeyByZXR1cm4gdXJsKHMpOyB9LFxuICAgICAgICBwZWckYzc0ID0geyB0eXBlOiBcIm90aGVyXCIsIGRlc2NyaXB0aW9uOiBcImludGVnZXJcIiB9LFxuICAgICAgICBwZWckYzc1ID0gbnVsbCxcbiAgICAgICAgcGVnJGM3NiA9IC9eWydcIl0vLFxuICAgICAgICBwZWckYzc3ID0geyB0eXBlOiBcImNsYXNzXCIsIHZhbHVlOiBcIlsnXFxcIl1cIiwgZGVzY3JpcHRpb246IFwiWydcXFwiXVwiIH0sXG4gICAgICAgIHBlZyRjNzggPSAvXlswLTldLyxcbiAgICAgICAgcGVnJGM3OSA9IHsgdHlwZTogXCJjbGFzc1wiLCB2YWx1ZTogXCJbMC05XVwiLCBkZXNjcmlwdGlvbjogXCJbMC05XVwiIH0sXG4gICAgICAgIHBlZyRjODAgPSBmdW5jdGlvbihkaWdpdHMpIHsgcmV0dXJuIHBhcnNlSW50KGRpZ2l0cy5qb2luKFwiXCIpLCAxMCk7IH0sXG4gICAgICAgIHBlZyRjODEgPSB7IHR5cGU6IFwib3RoZXJcIiwgZGVzY3JpcHRpb246IFwic3RyaW5nXCIgfSxcbiAgICAgICAgcGVnJGM4MiA9IFwiXFxcIlwiLFxuICAgICAgICBwZWckYzgzID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwiXFxcIlwiLCBkZXNjcmlwdGlvbjogXCJcXFwiXFxcXFxcXCJcXFwiXCIgfSxcbiAgICAgICAgcGVnJGM4NCA9IGZ1bmN0aW9uKGNoYXJzKSB7IHJldHVybiBjaGFycy5qb2luKFwiXCIpOyB9LFxuICAgICAgICBwZWckYzg1ID0gXCInXCIsXG4gICAgICAgIHBlZyRjODYgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCInXCIsIGRlc2NyaXB0aW9uOiBcIlxcXCInXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjODcgPSB2b2lkIDAsXG4gICAgICAgIHBlZyRjODggPSAvXltcIlxcXFxdLyxcbiAgICAgICAgcGVnJGM4OSA9IHsgdHlwZTogXCJjbGFzc1wiLCB2YWx1ZTogXCJbXFxcIlxcXFxcXFxcXVwiLCBkZXNjcmlwdGlvbjogXCJbXFxcIlxcXFxcXFxcXVwiIH0sXG4gICAgICAgIHBlZyRjOTAgPSB7IHR5cGU6IFwiYW55XCIsIGRlc2NyaXB0aW9uOiBcImFueSBjaGFyYWN0ZXJcIiB9LFxuICAgICAgICBwZWckYzkxID0gZnVuY3Rpb24oY2hhcikgeyByZXR1cm4gY2hhcjsgfSxcbiAgICAgICAgcGVnJGM5MiA9IFwiXFxcXFwiLFxuICAgICAgICBwZWckYzkzID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwiXFxcXFwiLCBkZXNjcmlwdGlvbjogXCJcXFwiXFxcXFxcXFxcXFwiXCIgfSxcbiAgICAgICAgcGVnJGM5NCA9IC9eWydcXFxcXS8sXG4gICAgICAgIHBlZyRjOTUgPSB7IHR5cGU6IFwiY2xhc3NcIiwgdmFsdWU6IFwiWydcXFxcXFxcXF1cIiwgZGVzY3JpcHRpb246IFwiWydcXFxcXFxcXF1cIiB9LFxuICAgICAgICBwZWckYzk2ID0gL15bJ1wiXFxcXF0vLFxuICAgICAgICBwZWckYzk3ID0geyB0eXBlOiBcImNsYXNzXCIsIHZhbHVlOiBcIlsnXFxcIlxcXFxcXFxcXVwiLCBkZXNjcmlwdGlvbjogXCJbJ1xcXCJcXFxcXFxcXF1cIiB9LFxuICAgICAgICBwZWckYzk4ID0gXCJuXCIsXG4gICAgICAgIHBlZyRjOTkgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJuXCIsIGRlc2NyaXB0aW9uOiBcIlxcXCJuXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjMTAwID0gZnVuY3Rpb24oKSB7IHJldHVybiBcIlxcblwiOyB9LFxuICAgICAgICBwZWckYzEwMSA9IFwiclwiLFxuICAgICAgICBwZWckYzEwMiA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcInJcIiwgZGVzY3JpcHRpb246IFwiXFxcInJcXFwiXCIgfSxcbiAgICAgICAgcGVnJGMxMDMgPSBmdW5jdGlvbigpIHsgcmV0dXJuIFwiXFxyXCI7IH0sXG4gICAgICAgIHBlZyRjMTA0ID0gXCJ0XCIsXG4gICAgICAgIHBlZyRjMTA1ID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwidFwiLCBkZXNjcmlwdGlvbjogXCJcXFwidFxcXCJcIiB9LFxuICAgICAgICBwZWckYzEwNiA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gXCJcXHRcIjsgfSxcblxuICAgICAgICBwZWckY3VyclBvcyAgICAgICAgICA9IDAsXG4gICAgICAgIHBlZyRyZXBvcnRlZFBvcyAgICAgID0gMCxcbiAgICAgICAgcGVnJGNhY2hlZFBvcyAgICAgICAgPSAwLFxuICAgICAgICBwZWckY2FjaGVkUG9zRGV0YWlscyA9IHsgbGluZTogMSwgY29sdW1uOiAxLCBzZWVuQ1I6IGZhbHNlIH0sXG4gICAgICAgIHBlZyRtYXhGYWlsUG9zICAgICAgID0gMCxcbiAgICAgICAgcGVnJG1heEZhaWxFeHBlY3RlZCAgPSBbXSxcbiAgICAgICAgcGVnJHNpbGVudEZhaWxzICAgICAgPSAwLFxuXG4gICAgICAgIHBlZyRyZXN1bHQ7XG5cbiAgICBpZiAoXCJzdGFydFJ1bGVcIiBpbiBvcHRpb25zKSB7XG4gICAgICBpZiAoIShvcHRpb25zLnN0YXJ0UnVsZSBpbiBwZWckc3RhcnRSdWxlRnVuY3Rpb25zKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW4ndCBzdGFydCBwYXJzaW5nIGZyb20gcnVsZSBcXFwiXCIgKyBvcHRpb25zLnN0YXJ0UnVsZSArIFwiXFxcIi5cIik7XG4gICAgICB9XG5cbiAgICAgIHBlZyRzdGFydFJ1bGVGdW5jdGlvbiA9IHBlZyRzdGFydFJ1bGVGdW5jdGlvbnNbb3B0aW9ucy5zdGFydFJ1bGVdO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRleHQoKSB7XG4gICAgICByZXR1cm4gaW5wdXQuc3Vic3RyaW5nKHBlZyRyZXBvcnRlZFBvcywgcGVnJGN1cnJQb3MpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG9mZnNldCgpIHtcbiAgICAgIHJldHVybiBwZWckcmVwb3J0ZWRQb3M7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGluZSgpIHtcbiAgICAgIHJldHVybiBwZWckY29tcHV0ZVBvc0RldGFpbHMocGVnJHJlcG9ydGVkUG9zKS5saW5lO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvbHVtbigpIHtcbiAgICAgIHJldHVybiBwZWckY29tcHV0ZVBvc0RldGFpbHMocGVnJHJlcG9ydGVkUG9zKS5jb2x1bW47XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZXhwZWN0ZWQoZGVzY3JpcHRpb24pIHtcbiAgICAgIHRocm93IHBlZyRidWlsZEV4Y2VwdGlvbihcbiAgICAgICAgbnVsbCxcbiAgICAgICAgW3sgdHlwZTogXCJvdGhlclwiLCBkZXNjcmlwdGlvbjogZGVzY3JpcHRpb24gfV0sXG4gICAgICAgIHBlZyRyZXBvcnRlZFBvc1xuICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBlcnJvcihtZXNzYWdlKSB7XG4gICAgICB0aHJvdyBwZWckYnVpbGRFeGNlcHRpb24obWVzc2FnZSwgbnVsbCwgcGVnJHJlcG9ydGVkUG9zKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckY29tcHV0ZVBvc0RldGFpbHMocG9zKSB7XG4gICAgICBmdW5jdGlvbiBhZHZhbmNlKGRldGFpbHMsIHN0YXJ0UG9zLCBlbmRQb3MpIHtcbiAgICAgICAgdmFyIHAsIGNoO1xuXG4gICAgICAgIGZvciAocCA9IHN0YXJ0UG9zOyBwIDwgZW5kUG9zOyBwKyspIHtcbiAgICAgICAgICBjaCA9IGlucHV0LmNoYXJBdChwKTtcbiAgICAgICAgICBpZiAoY2ggPT09IFwiXFxuXCIpIHtcbiAgICAgICAgICAgIGlmICghZGV0YWlscy5zZWVuQ1IpIHsgZGV0YWlscy5saW5lKys7IH1cbiAgICAgICAgICAgIGRldGFpbHMuY29sdW1uID0gMTtcbiAgICAgICAgICAgIGRldGFpbHMuc2VlbkNSID0gZmFsc2U7XG4gICAgICAgICAgfSBlbHNlIGlmIChjaCA9PT0gXCJcXHJcIiB8fCBjaCA9PT0gXCJcXHUyMDI4XCIgfHwgY2ggPT09IFwiXFx1MjAyOVwiKSB7XG4gICAgICAgICAgICBkZXRhaWxzLmxpbmUrKztcbiAgICAgICAgICAgIGRldGFpbHMuY29sdW1uID0gMTtcbiAgICAgICAgICAgIGRldGFpbHMuc2VlbkNSID0gdHJ1ZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGV0YWlscy5jb2x1bW4rKztcbiAgICAgICAgICAgIGRldGFpbHMuc2VlbkNSID0gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChwZWckY2FjaGVkUG9zICE9PSBwb3MpIHtcbiAgICAgICAgaWYgKHBlZyRjYWNoZWRQb3MgPiBwb3MpIHtcbiAgICAgICAgICBwZWckY2FjaGVkUG9zID0gMDtcbiAgICAgICAgICBwZWckY2FjaGVkUG9zRGV0YWlscyA9IHsgbGluZTogMSwgY29sdW1uOiAxLCBzZWVuQ1I6IGZhbHNlIH07XG4gICAgICAgIH1cbiAgICAgICAgYWR2YW5jZShwZWckY2FjaGVkUG9zRGV0YWlscywgcGVnJGNhY2hlZFBvcywgcG9zKTtcbiAgICAgICAgcGVnJGNhY2hlZFBvcyA9IHBvcztcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHBlZyRjYWNoZWRQb3NEZXRhaWxzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBlZyRmYWlsKGV4cGVjdGVkKSB7XG4gICAgICBpZiAocGVnJGN1cnJQb3MgPCBwZWckbWF4RmFpbFBvcykgeyByZXR1cm47IH1cblxuICAgICAgaWYgKHBlZyRjdXJyUG9zID4gcGVnJG1heEZhaWxQb3MpIHtcbiAgICAgICAgcGVnJG1heEZhaWxQb3MgPSBwZWckY3VyclBvcztcbiAgICAgICAgcGVnJG1heEZhaWxFeHBlY3RlZCA9IFtdO1xuICAgICAgfVxuXG4gICAgICBwZWckbWF4RmFpbEV4cGVjdGVkLnB1c2goZXhwZWN0ZWQpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBlZyRidWlsZEV4Y2VwdGlvbihtZXNzYWdlLCBleHBlY3RlZCwgcG9zKSB7XG4gICAgICBmdW5jdGlvbiBjbGVhbnVwRXhwZWN0ZWQoZXhwZWN0ZWQpIHtcbiAgICAgICAgdmFyIGkgPSAxO1xuXG4gICAgICAgIGV4cGVjdGVkLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICAgIGlmIChhLmRlc2NyaXB0aW9uIDwgYi5kZXNjcmlwdGlvbikge1xuICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICAgIH0gZWxzZSBpZiAoYS5kZXNjcmlwdGlvbiA+IGIuZGVzY3JpcHRpb24pIHtcbiAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHdoaWxlIChpIDwgZXhwZWN0ZWQubGVuZ3RoKSB7XG4gICAgICAgICAgaWYgKGV4cGVjdGVkW2kgLSAxXSA9PT0gZXhwZWN0ZWRbaV0pIHtcbiAgICAgICAgICAgIGV4cGVjdGVkLnNwbGljZShpLCAxKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaSsrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBidWlsZE1lc3NhZ2UoZXhwZWN0ZWQsIGZvdW5kKSB7XG4gICAgICAgIGZ1bmN0aW9uIHN0cmluZ0VzY2FwZShzKSB7XG4gICAgICAgICAgZnVuY3Rpb24gaGV4KGNoKSB7IHJldHVybiBjaC5jaGFyQ29kZUF0KDApLnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpOyB9XG5cbiAgICAgICAgICByZXR1cm4gc1xuICAgICAgICAgICAgLnJlcGxhY2UoL1xcXFwvZywgICAnXFxcXFxcXFwnKVxuICAgICAgICAgICAgLnJlcGxhY2UoL1wiL2csICAgICdcXFxcXCInKVxuICAgICAgICAgICAgLnJlcGxhY2UoL1xceDA4L2csICdcXFxcYicpXG4gICAgICAgICAgICAucmVwbGFjZSgvXFx0L2csICAgJ1xcXFx0JylcbiAgICAgICAgICAgIC5yZXBsYWNlKC9cXG4vZywgICAnXFxcXG4nKVxuICAgICAgICAgICAgLnJlcGxhY2UoL1xcZi9nLCAgICdcXFxcZicpXG4gICAgICAgICAgICAucmVwbGFjZSgvXFxyL2csICAgJ1xcXFxyJylcbiAgICAgICAgICAgIC5yZXBsYWNlKC9bXFx4MDAtXFx4MDdcXHgwQlxceDBFXFx4MEZdL2csIGZ1bmN0aW9uKGNoKSB7IHJldHVybiAnXFxcXHgwJyArIGhleChjaCk7IH0pXG4gICAgICAgICAgICAucmVwbGFjZSgvW1xceDEwLVxceDFGXFx4ODAtXFx4RkZdL2csICAgIGZ1bmN0aW9uKGNoKSB7IHJldHVybiAnXFxcXHgnICArIGhleChjaCk7IH0pXG4gICAgICAgICAgICAucmVwbGFjZSgvW1xcdTAxODAtXFx1MEZGRl0vZywgICAgICAgICBmdW5jdGlvbihjaCkgeyByZXR1cm4gJ1xcXFx1MCcgKyBoZXgoY2gpOyB9KVxuICAgICAgICAgICAgLnJlcGxhY2UoL1tcXHUxMDgwLVxcdUZGRkZdL2csICAgICAgICAgZnVuY3Rpb24oY2gpIHsgcmV0dXJuICdcXFxcdScgICsgaGV4KGNoKTsgfSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZXhwZWN0ZWREZXNjcyA9IG5ldyBBcnJheShleHBlY3RlZC5sZW5ndGgpLFxuICAgICAgICAgICAgZXhwZWN0ZWREZXNjLCBmb3VuZERlc2MsIGk7XG5cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGV4cGVjdGVkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgZXhwZWN0ZWREZXNjc1tpXSA9IGV4cGVjdGVkW2ldLmRlc2NyaXB0aW9uO1xuICAgICAgICB9XG5cbiAgICAgICAgZXhwZWN0ZWREZXNjID0gZXhwZWN0ZWQubGVuZ3RoID4gMVxuICAgICAgICAgID8gZXhwZWN0ZWREZXNjcy5zbGljZSgwLCAtMSkuam9pbihcIiwgXCIpXG4gICAgICAgICAgICAgICsgXCIgb3IgXCJcbiAgICAgICAgICAgICAgKyBleHBlY3RlZERlc2NzW2V4cGVjdGVkLmxlbmd0aCAtIDFdXG4gICAgICAgICAgOiBleHBlY3RlZERlc2NzWzBdO1xuXG4gICAgICAgIGZvdW5kRGVzYyA9IGZvdW5kID8gXCJcXFwiXCIgKyBzdHJpbmdFc2NhcGUoZm91bmQpICsgXCJcXFwiXCIgOiBcImVuZCBvZiBpbnB1dFwiO1xuXG4gICAgICAgIHJldHVybiBcIkV4cGVjdGVkIFwiICsgZXhwZWN0ZWREZXNjICsgXCIgYnV0IFwiICsgZm91bmREZXNjICsgXCIgZm91bmQuXCI7XG4gICAgICB9XG5cbiAgICAgIHZhciBwb3NEZXRhaWxzID0gcGVnJGNvbXB1dGVQb3NEZXRhaWxzKHBvcyksXG4gICAgICAgICAgZm91bmQgICAgICA9IHBvcyA8IGlucHV0Lmxlbmd0aCA/IGlucHV0LmNoYXJBdChwb3MpIDogbnVsbDtcblxuICAgICAgaWYgKGV4cGVjdGVkICE9PSBudWxsKSB7XG4gICAgICAgIGNsZWFudXBFeHBlY3RlZChleHBlY3RlZCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBuZXcgU3ludGF4RXJyb3IoXG4gICAgICAgIG1lc3NhZ2UgIT09IG51bGwgPyBtZXNzYWdlIDogYnVpbGRNZXNzYWdlKGV4cGVjdGVkLCBmb3VuZCksXG4gICAgICAgIGV4cGVjdGVkLFxuICAgICAgICBmb3VuZCxcbiAgICAgICAgcG9zLFxuICAgICAgICBwb3NEZXRhaWxzLmxpbmUsXG4gICAgICAgIHBvc0RldGFpbHMuY29sdW1uXG4gICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBlZyRwYXJzZXN0YXJ0KCkge1xuICAgICAgdmFyIHMwLCBzMSwgczIsIHMzO1xuXG4gICAgICBwZWckc2lsZW50RmFpbHMrKztcbiAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICBzMSA9IHBlZyRwYXJzZV9fKCk7XG4gICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczIgPSBwZWckcGFyc2VPckV4cHIoKTtcbiAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgczMgPSBwZWckcGFyc2VfXygpO1xuICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICBzMSA9IHBlZyRjMihzMik7XG4gICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgfVxuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgIHMxID0gW107XG4gICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgIHMxID0gcGVnJGM0KCk7XG4gICAgICAgIH1cbiAgICAgICAgczAgPSBzMTtcbiAgICAgIH1cbiAgICAgIHBlZyRzaWxlbnRGYWlscy0tO1xuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzApOyB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckcGFyc2V3cygpIHtcbiAgICAgIHZhciBzMCwgczE7XG5cbiAgICAgIHBlZyRzaWxlbnRGYWlscysrO1xuICAgICAgaWYgKHBlZyRjNi50ZXN0KGlucHV0LmNoYXJBdChwZWckY3VyclBvcykpKSB7XG4gICAgICAgIHMwID0gaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKTtcbiAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHMwID0gcGVnJEZBSUxFRDtcbiAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzcpOyB9XG4gICAgICB9XG4gICAgICBwZWckc2lsZW50RmFpbHMtLTtcbiAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM1KTsgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlY2MoKSB7XG4gICAgICB2YXIgczAsIHMxO1xuXG4gICAgICBwZWckc2lsZW50RmFpbHMrKztcbiAgICAgIGlmIChwZWckYzkudGVzdChpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpKSkge1xuICAgICAgICBzMCA9IGlucHV0LmNoYXJBdChwZWckY3VyclBvcyk7XG4gICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzMCA9IHBlZyRGQUlMRUQ7XG4gICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGMxMCk7IH1cbiAgICAgIH1cbiAgICAgIHBlZyRzaWxlbnRGYWlscy0tO1xuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzgpOyB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckcGFyc2VfXygpIHtcbiAgICAgIHZhciBzMCwgczE7XG5cbiAgICAgIHBlZyRzaWxlbnRGYWlscysrO1xuICAgICAgczAgPSBbXTtcbiAgICAgIHMxID0gcGVnJHBhcnNld3MoKTtcbiAgICAgIHdoaWxlIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMC5wdXNoKHMxKTtcbiAgICAgICAgczEgPSBwZWckcGFyc2V3cygpO1xuICAgICAgfVxuICAgICAgcGVnJHNpbGVudEZhaWxzLS07XG4gICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjMTEpOyB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckcGFyc2VPckV4cHIoKSB7XG4gICAgICB2YXIgczAsIHMxLCBzMiwgczMsIHM0LCBzNTtcblxuICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgIHMxID0gcGVnJHBhcnNlQW5kRXhwcigpO1xuICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMyID0gcGVnJHBhcnNlX18oKTtcbiAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgaWYgKGlucHV0LmNoYXJDb2RlQXQocGVnJGN1cnJQb3MpID09PSAxMjQpIHtcbiAgICAgICAgICAgIHMzID0gcGVnJGMxMjtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHMzID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGMxMyk7IH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICBzNCA9IHBlZyRwYXJzZV9fKCk7XG4gICAgICAgICAgICBpZiAoczQgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgczUgPSBwZWckcGFyc2VPckV4cHIoKTtcbiAgICAgICAgICAgICAgaWYgKHM1ICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICAgICAgczEgPSBwZWckYzE0KHMxLCBzNSk7XG4gICAgICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgIH1cbiAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMCA9IHBlZyRwYXJzZUFuZEV4cHIoKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHMwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBlZyRwYXJzZUFuZEV4cHIoKSB7XG4gICAgICB2YXIgczAsIHMxLCBzMiwgczMsIHM0LCBzNTtcblxuICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgIHMxID0gcGVnJHBhcnNlTm90RXhwcigpO1xuICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMyID0gcGVnJHBhcnNlX18oKTtcbiAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgaWYgKGlucHV0LmNoYXJDb2RlQXQocGVnJGN1cnJQb3MpID09PSAzOCkge1xuICAgICAgICAgICAgczMgPSBwZWckYzE1O1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgczMgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzE2KTsgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHM0ID0gcGVnJHBhcnNlX18oKTtcbiAgICAgICAgICAgIGlmIChzNCAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICBzNSA9IHBlZyRwYXJzZUFuZEV4cHIoKTtcbiAgICAgICAgICAgICAgaWYgKHM1ICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICAgICAgczEgPSBwZWckYzE3KHMxLCBzNSk7XG4gICAgICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgIH1cbiAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgICBzMSA9IHBlZyRwYXJzZU5vdEV4cHIoKTtcbiAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgczIgPSBbXTtcbiAgICAgICAgICBzMyA9IHBlZyRwYXJzZXdzKCk7XG4gICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICB3aGlsZSAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgczIucHVzaChzMyk7XG4gICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgczIgPSBwZWckYzE7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzMiAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgczMgPSBwZWckcGFyc2VBbmRFeHByKCk7XG4gICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICAgIHMxID0gcGVnJGMxNyhzMSwgczMpO1xuICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBzMCA9IHBlZyRwYXJzZU5vdEV4cHIoKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlTm90RXhwcigpIHtcbiAgICAgIHZhciBzMCwgczEsIHMyLCBzMztcblxuICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgIGlmIChpbnB1dC5jaGFyQ29kZUF0KHBlZyRjdXJyUG9zKSA9PT0gMzMpIHtcbiAgICAgICAgczEgPSBwZWckYzE4O1xuICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjMTkpOyB9XG4gICAgICB9XG4gICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczIgPSBwZWckcGFyc2VfXygpO1xuICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBzMyA9IHBlZyRwYXJzZU5vdEV4cHIoKTtcbiAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgczEgPSBwZWckYzIwKHMzKTtcbiAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICB9XG4gICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczAgPSBwZWckcGFyc2VCaW5kaW5nRXhwcigpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlQmluZGluZ0V4cHIoKSB7XG4gICAgICB2YXIgczAsIHMxLCBzMiwgczMsIHM0LCBzNTtcblxuICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgIGlmIChpbnB1dC5jaGFyQ29kZUF0KHBlZyRjdXJyUG9zKSA9PT0gNDApIHtcbiAgICAgICAgczEgPSBwZWckYzIxO1xuICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjMjIpOyB9XG4gICAgICB9XG4gICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczIgPSBwZWckcGFyc2VfXygpO1xuICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBzMyA9IHBlZyRwYXJzZU9yRXhwcigpO1xuICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgczQgPSBwZWckcGFyc2VfXygpO1xuICAgICAgICAgICAgaWYgKHM0ICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgIGlmIChpbnB1dC5jaGFyQ29kZUF0KHBlZyRjdXJyUG9zKSA9PT0gNDEpIHtcbiAgICAgICAgICAgICAgICBzNSA9IHBlZyRjMjM7XG4gICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzNSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzI0KTsgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChzNSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgICAgIHMxID0gcGVnJGMyNShzMyk7XG4gICAgICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgIH1cbiAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMCA9IHBlZyRwYXJzZUV4cHIoKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHMwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBlZyRwYXJzZUV4cHIoKSB7XG4gICAgICB2YXIgczA7XG5cbiAgICAgIHMwID0gcGVnJHBhcnNlTnVsbGFyeUV4cHIoKTtcbiAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMCA9IHBlZyRwYXJzZVVuYXJ5RXhwcigpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlTnVsbGFyeUV4cHIoKSB7XG4gICAgICB2YXIgczAsIHMxO1xuXG4gICAgICBzMCA9IHBlZyRwYXJzZUJvb2xlYW5MaXRlcmFsKCk7XG4gICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgaWYgKGlucHV0LnN1YnN0cihwZWckY3VyclBvcywgMikgPT09IHBlZyRjMjYpIHtcbiAgICAgICAgICBzMSA9IHBlZyRjMjY7XG4gICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzI3KTsgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgIHMxID0gcGVnJGMyOCgpO1xuICAgICAgICB9XG4gICAgICAgIHMwID0gczE7XG4gICAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgICAgaWYgKGlucHV0LnN1YnN0cihwZWckY3VyclBvcywgMikgPT09IHBlZyRjMjkpIHtcbiAgICAgICAgICAgIHMxID0gcGVnJGMyOTtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zICs9IDI7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGMzMCk7IH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgIHMxID0gcGVnJGMzMSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICAgIGlmIChpbnB1dC5zdWJzdHIocGVnJGN1cnJQb3MsIDIpID09PSBwZWckYzMyKSB7XG4gICAgICAgICAgICAgIHMxID0gcGVnJGMzMjtcbiAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzMzKTsgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgICBzMSA9IHBlZyRjMzQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICAgICAgaWYgKGlucHV0LnN1YnN0cihwZWckY3VyclBvcywgMikgPT09IHBlZyRjMzUpIHtcbiAgICAgICAgICAgICAgICBzMSA9IHBlZyRjMzU7XG4gICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMjtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzM2KTsgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgICAgIHMxID0gcGVnJGMzNygpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckcGFyc2VCb29sZWFuTGl0ZXJhbCgpIHtcbiAgICAgIHZhciBzMCwgczE7XG5cbiAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICBpZiAoaW5wdXQuc3Vic3RyKHBlZyRjdXJyUG9zLCA0KSA9PT0gcGVnJGMzOCkge1xuICAgICAgICBzMSA9IHBlZyRjMzg7XG4gICAgICAgIHBlZyRjdXJyUG9zICs9IDQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGMzOSk7IH1cbiAgICAgIH1cbiAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgczEgPSBwZWckYzQwKCk7XG4gICAgICB9XG4gICAgICBzMCA9IHMxO1xuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgIGlmIChpbnB1dC5zdWJzdHIocGVnJGN1cnJQb3MsIDUpID09PSBwZWckYzQxKSB7XG4gICAgICAgICAgczEgPSBwZWckYzQxO1xuICAgICAgICAgIHBlZyRjdXJyUG9zICs9IDU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM0Mik7IH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICBzMSA9IHBlZyRjNDMoKTtcbiAgICAgICAgfVxuICAgICAgICBzMCA9IHMxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlVW5hcnlFeHByKCkge1xuICAgICAgdmFyIHMwLCBzMSwgczIsIHMzO1xuXG4gICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgaWYgKGlucHV0LnN1YnN0cihwZWckY3VyclBvcywgMikgPT09IHBlZyRjNDQpIHtcbiAgICAgICAgczEgPSBwZWckYzQ0O1xuICAgICAgICBwZWckY3VyclBvcyArPSAyO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjNDUpOyB9XG4gICAgICB9XG4gICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczIgPSBbXTtcbiAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICB3aGlsZSAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHMyLnB1c2goczMpO1xuICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzMiA9IHBlZyRjMTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBzMyA9IHBlZyRwYXJzZUludGVnZXJMaXRlcmFsKCk7XG4gICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgIHMxID0gcGVnJGM0NihzMyk7XG4gICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgfVxuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgIGlmIChpbnB1dC5zdWJzdHIocGVnJGN1cnJQb3MsIDIpID09PSBwZWckYzQ3KSB7XG4gICAgICAgICAgczEgPSBwZWckYzQ3O1xuICAgICAgICAgIHBlZyRjdXJyUG9zICs9IDI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM0OCk7IH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBzMiA9IFtdO1xuICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHdoaWxlIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICBzMi5wdXNoKHMzKTtcbiAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzMiA9IHBlZyRjMTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICBzMyA9IHBlZyRwYXJzZVN0cmluZ0xpdGVyYWwoKTtcbiAgICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgczEgPSBwZWckYzQ5KHMzKTtcbiAgICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICBpZiAoaW5wdXQuc3Vic3RyKHBlZyRjdXJyUG9zLCAyKSA9PT0gcGVnJGM1MCkge1xuICAgICAgICAgICAgczEgPSBwZWckYzUwO1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMjtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzUxKTsgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHMyID0gW107XG4gICAgICAgICAgICBzMyA9IHBlZyRwYXJzZXdzKCk7XG4gICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgd2hpbGUgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgczIucHVzaChzMyk7XG4gICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBzMiA9IHBlZyRjMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzMiAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZVN0cmluZ0xpdGVyYWwoKTtcbiAgICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICAgICAgczEgPSBwZWckYzUyKHMzKTtcbiAgICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICAgIGlmIChpbnB1dC5zdWJzdHIocGVnJGN1cnJQb3MsIDMpID09PSBwZWckYzUzKSB7XG4gICAgICAgICAgICAgIHMxID0gcGVnJGM1MztcbiAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzU0KTsgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgIHMyID0gW107XG4gICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgd2hpbGUgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICBzMi5wdXNoKHMzKTtcbiAgICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgczIgPSBwZWckYzE7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2VTdHJpbmdMaXRlcmFsKCk7XG4gICAgICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgIHMxID0gcGVnJGM1NShzMyk7XG4gICAgICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgICAgICAgIGlmIChpbnB1dC5zdWJzdHIocGVnJGN1cnJQb3MsIDMpID09PSBwZWckYzU2KSB7XG4gICAgICAgICAgICAgICAgczEgPSBwZWckYzU2O1xuICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zICs9IDM7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM1Nyk7IH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICBzMiA9IFtdO1xuICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgIHdoaWxlIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgICBzMi5wdXNoKHMzKTtcbiAgICAgICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICBzMiA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZVN0cmluZ0xpdGVyYWwoKTtcbiAgICAgICAgICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckYzU4KHMzKTtcbiAgICAgICAgICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICAgICAgICBpZiAoaW5wdXQuc3Vic3RyKHBlZyRjdXJyUG9zLCAyKSA9PT0gcGVnJGM1OSkge1xuICAgICAgICAgICAgICAgICAgczEgPSBwZWckYzU5O1xuICAgICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzYwKTsgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgIHMyID0gW107XG4gICAgICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZXdzKCk7XG4gICAgICAgICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgczIucHVzaChzMyk7XG4gICAgICAgICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzMiA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIGlmIChzMiAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZVN0cmluZ0xpdGVyYWwoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckYzYxKHMzKTtcbiAgICAgICAgICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICAgICAgICAgIGlmIChpbnB1dC5zdWJzdHIocGVnJGN1cnJQb3MsIDIpID09PSBwZWckYzYyKSB7XG4gICAgICAgICAgICAgICAgICAgIHMxID0gcGVnJGM2MjtcbiAgICAgICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMjtcbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzYzKTsgfVxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgIHMyID0gW107XG4gICAgICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzMi5wdXNoKHMzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgczIgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2VTdHJpbmdMaXRlcmFsKCk7XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHMxID0gcGVnJGM2NChzMyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbnB1dC5zdWJzdHIocGVnJGN1cnJQb3MsIDMpID09PSBwZWckYzY1KSB7XG4gICAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckYzY1O1xuICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zICs9IDM7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM2Nik7IH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICBzMiA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBzMi5wdXNoKHMzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzMiA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZVN0cmluZ0xpdGVyYWwoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckYzY3KHMzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5wdXQuc3Vic3RyKHBlZyRjdXJyUG9zLCAzKSA9PT0gcGVnJGM2OCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckYzY4O1xuICAgICAgICAgICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMztcbiAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzY5KTsgfVxuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHMyID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZXdzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgczIucHVzaChzMyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBzMiA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzMiAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZVN0cmluZ0xpdGVyYWwoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckYzcwKHMzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbnB1dC5zdWJzdHIocGVnJGN1cnJQb3MsIDIpID09PSBwZWckYzcxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMxID0gcGVnJGM3MTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzcyKTsgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMyID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzMi5wdXNoKHMzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgczIgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2VTdHJpbmdMaXRlcmFsKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHMxID0gcGVnJGM3MyhzMyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMxID0gcGVnJHBhcnNlU3RyaW5nTGl0ZXJhbCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzMSA9IHBlZyRjNzMoczEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckcGFyc2VJbnRlZ2VyTGl0ZXJhbCgpIHtcbiAgICAgIHZhciBzMCwgczEsIHMyLCBzMztcblxuICAgICAgcGVnJHNpbGVudEZhaWxzKys7XG4gICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgaWYgKHBlZyRjNzYudGVzdChpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpKSkge1xuICAgICAgICBzMSA9IGlucHV0LmNoYXJBdChwZWckY3VyclBvcyk7XG4gICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM3Nyk7IH1cbiAgICAgIH1cbiAgICAgIGlmIChzMSA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMSA9IHBlZyRjNzU7XG4gICAgICB9XG4gICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczIgPSBbXTtcbiAgICAgICAgaWYgKHBlZyRjNzgudGVzdChpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpKSkge1xuICAgICAgICAgIHMzID0gaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKTtcbiAgICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHMzID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjNzkpOyB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgd2hpbGUgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICBzMi5wdXNoKHMzKTtcbiAgICAgICAgICAgIGlmIChwZWckYzc4LnRlc3QoaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKSkpIHtcbiAgICAgICAgICAgICAgczMgPSBpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpO1xuICAgICAgICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgczMgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjNzkpOyB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHMyID0gcGVnJGMxO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzMiAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIGlmIChwZWckYzc2LnRlc3QoaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKSkpIHtcbiAgICAgICAgICAgIHMzID0gaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKTtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHMzID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM3Nyk7IH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHMzID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICBzMyA9IHBlZyRjNzU7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICBzMSA9IHBlZyRjODAoczIpO1xuICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgIH1cbiAgICAgIHBlZyRzaWxlbnRGYWlscy0tO1xuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzc0KTsgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlU3RyaW5nTGl0ZXJhbCgpIHtcbiAgICAgIHZhciBzMCwgczEsIHMyLCBzMztcblxuICAgICAgcGVnJHNpbGVudEZhaWxzKys7XG4gICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgaWYgKGlucHV0LmNoYXJDb2RlQXQocGVnJGN1cnJQb3MpID09PSAzNCkge1xuICAgICAgICBzMSA9IHBlZyRjODI7XG4gICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM4Myk7IH1cbiAgICAgIH1cbiAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMiA9IFtdO1xuICAgICAgICBzMyA9IHBlZyRwYXJzZURvdWJsZVN0cmluZ0NoYXIoKTtcbiAgICAgICAgd2hpbGUgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgczIucHVzaChzMyk7XG4gICAgICAgICAgczMgPSBwZWckcGFyc2VEb3VibGVTdHJpbmdDaGFyKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgaWYgKGlucHV0LmNoYXJDb2RlQXQocGVnJGN1cnJQb3MpID09PSAzNCkge1xuICAgICAgICAgICAgczMgPSBwZWckYzgyO1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgczMgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzgzKTsgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgczEgPSBwZWckYzg0KHMyKTtcbiAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICB9XG4gICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgaWYgKGlucHV0LmNoYXJDb2RlQXQocGVnJGN1cnJQb3MpID09PSAzOSkge1xuICAgICAgICAgIHMxID0gcGVnJGM4NTtcbiAgICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjODYpOyB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgczIgPSBbXTtcbiAgICAgICAgICBzMyA9IHBlZyRwYXJzZVNpbmdsZVN0cmluZ0NoYXIoKTtcbiAgICAgICAgICB3aGlsZSAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHMyLnB1c2goczMpO1xuICAgICAgICAgICAgczMgPSBwZWckcGFyc2VTaW5nbGVTdHJpbmdDaGFyKCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzMiAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgaWYgKGlucHV0LmNoYXJDb2RlQXQocGVnJGN1cnJQb3MpID09PSAzOSkge1xuICAgICAgICAgICAgICBzMyA9IHBlZyRjODU7XG4gICAgICAgICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBzMyA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM4Nik7IH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgczEgPSBwZWckYzg0KHMyKTtcbiAgICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICBzMSA9IHBlZyRjdXJyUG9zO1xuICAgICAgICAgIHBlZyRzaWxlbnRGYWlscysrO1xuICAgICAgICAgIHMyID0gcGVnJHBhcnNlY2MoKTtcbiAgICAgICAgICBwZWckc2lsZW50RmFpbHMtLTtcbiAgICAgICAgICBpZiAoczIgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHMxID0gcGVnJGM4NztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMTtcbiAgICAgICAgICAgIHMxID0gcGVnJGMxO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHMyID0gW107XG4gICAgICAgICAgICBzMyA9IHBlZyRwYXJzZVVucXVvdGVkU3RyaW5nQ2hhcigpO1xuICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgIHdoaWxlIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgIHMyLnB1c2goczMpO1xuICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNlVW5xdW90ZWRTdHJpbmdDaGFyKCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHMyID0gcGVnJGMxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgICBzMSA9IHBlZyRjODQoczIpO1xuICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHBlZyRzaWxlbnRGYWlscy0tO1xuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzgxKTsgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlRG91YmxlU3RyaW5nQ2hhcigpIHtcbiAgICAgIHZhciBzMCwgczEsIHMyO1xuXG4gICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgczEgPSBwZWckY3VyclBvcztcbiAgICAgIHBlZyRzaWxlbnRGYWlscysrO1xuICAgICAgaWYgKHBlZyRjODgudGVzdChpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpKSkge1xuICAgICAgICBzMiA9IGlucHV0LmNoYXJBdChwZWckY3VyclBvcyk7XG4gICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzMiA9IHBlZyRGQUlMRUQ7XG4gICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM4OSk7IH1cbiAgICAgIH1cbiAgICAgIHBlZyRzaWxlbnRGYWlscy0tO1xuICAgICAgaWYgKHMyID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMxID0gcGVnJGM4NztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlZyRjdXJyUG9zID0gczE7XG4gICAgICAgIHMxID0gcGVnJGMxO1xuICAgICAgfVxuICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIGlmIChpbnB1dC5sZW5ndGggPiBwZWckY3VyclBvcykge1xuICAgICAgICAgIHMyID0gaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKTtcbiAgICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHMyID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjOTApOyB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgczEgPSBwZWckYzkxKHMyKTtcbiAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgfVxuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgIGlmIChpbnB1dC5jaGFyQ29kZUF0KHBlZyRjdXJyUG9zKSA9PT0gOTIpIHtcbiAgICAgICAgICBzMSA9IHBlZyRjOTI7XG4gICAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzkzKTsgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHMyID0gcGVnJHBhcnNlRXNjYXBlU2VxdWVuY2UoKTtcbiAgICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgczEgPSBwZWckYzkxKHMyKTtcbiAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlU2luZ2xlU3RyaW5nQ2hhcigpIHtcbiAgICAgIHZhciBzMCwgczEsIHMyO1xuXG4gICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgczEgPSBwZWckY3VyclBvcztcbiAgICAgIHBlZyRzaWxlbnRGYWlscysrO1xuICAgICAgaWYgKHBlZyRjOTQudGVzdChpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpKSkge1xuICAgICAgICBzMiA9IGlucHV0LmNoYXJBdChwZWckY3VyclBvcyk7XG4gICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzMiA9IHBlZyRGQUlMRUQ7XG4gICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM5NSk7IH1cbiAgICAgIH1cbiAgICAgIHBlZyRzaWxlbnRGYWlscy0tO1xuICAgICAgaWYgKHMyID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMxID0gcGVnJGM4NztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlZyRjdXJyUG9zID0gczE7XG4gICAgICAgIHMxID0gcGVnJGMxO1xuICAgICAgfVxuICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIGlmIChpbnB1dC5sZW5ndGggPiBwZWckY3VyclBvcykge1xuICAgICAgICAgIHMyID0gaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKTtcbiAgICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHMyID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjOTApOyB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgczEgPSBwZWckYzkxKHMyKTtcbiAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgfVxuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgIGlmIChpbnB1dC5jaGFyQ29kZUF0KHBlZyRjdXJyUG9zKSA9PT0gOTIpIHtcbiAgICAgICAgICBzMSA9IHBlZyRjOTI7XG4gICAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzkzKTsgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHMyID0gcGVnJHBhcnNlRXNjYXBlU2VxdWVuY2UoKTtcbiAgICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgczEgPSBwZWckYzkxKHMyKTtcbiAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlVW5xdW90ZWRTdHJpbmdDaGFyKCkge1xuICAgICAgdmFyIHMwLCBzMSwgczI7XG5cbiAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICBzMSA9IHBlZyRjdXJyUG9zO1xuICAgICAgcGVnJHNpbGVudEZhaWxzKys7XG4gICAgICBzMiA9IHBlZyRwYXJzZXdzKCk7XG4gICAgICBwZWckc2lsZW50RmFpbHMtLTtcbiAgICAgIGlmIChzMiA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMSA9IHBlZyRjODc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwZWckY3VyclBvcyA9IHMxO1xuICAgICAgICBzMSA9IHBlZyRjMTtcbiAgICAgIH1cbiAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBpZiAoaW5wdXQubGVuZ3RoID4gcGVnJGN1cnJQb3MpIHtcbiAgICAgICAgICBzMiA9IGlucHV0LmNoYXJBdChwZWckY3VyclBvcyk7XG4gICAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzMiA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzkwKTsgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChzMiAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgIHMxID0gcGVnJGM5MShzMik7XG4gICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHMwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBlZyRwYXJzZUVzY2FwZVNlcXVlbmNlKCkge1xuICAgICAgdmFyIHMwLCBzMTtcblxuICAgICAgaWYgKHBlZyRjOTYudGVzdChpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpKSkge1xuICAgICAgICBzMCA9IGlucHV0LmNoYXJBdChwZWckY3VyclBvcyk7XG4gICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzMCA9IHBlZyRGQUlMRUQ7XG4gICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM5Nyk7IH1cbiAgICAgIH1cbiAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgICBpZiAoaW5wdXQuY2hhckNvZGVBdChwZWckY3VyclBvcykgPT09IDExMCkge1xuICAgICAgICAgIHMxID0gcGVnJGM5ODtcbiAgICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjOTkpOyB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgczEgPSBwZWckYzEwMCgpO1xuICAgICAgICB9XG4gICAgICAgIHMwID0gczE7XG4gICAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgICAgaWYgKGlucHV0LmNoYXJDb2RlQXQocGVnJGN1cnJQb3MpID09PSAxMTQpIHtcbiAgICAgICAgICAgIHMxID0gcGVnJGMxMDE7XG4gICAgICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjMTAyKTsgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgczEgPSBwZWckYzEwMygpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICAgIGlmIChpbnB1dC5jaGFyQ29kZUF0KHBlZyRjdXJyUG9zKSA9PT0gMTE2KSB7XG4gICAgICAgICAgICAgIHMxID0gcGVnJGMxMDQ7XG4gICAgICAgICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGMxMDUpOyB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICAgIHMxID0gcGVnJGMxMDYoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cblxuICAgIHZhciBmbG93dXRpbHMgPSByZXF1aXJlKFwiLi4vZmxvdy91dGlscy5qc1wiKTtcblxuICAgIGZ1bmN0aW9uIG9yKGZpcnN0LCBzZWNvbmQpIHtcbiAgICAgICAgLy8gQWRkIGV4cGxpY2l0IGZ1bmN0aW9uIG5hbWVzIHRvIGVhc2UgZGVidWdnaW5nLlxuICAgICAgICBmdW5jdGlvbiBvckZpbHRlcigpIHtcbiAgICAgICAgICAgIHJldHVybiBmaXJzdC5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHNlY29uZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgICAgIG9yRmlsdGVyLmRlc2MgPSBmaXJzdC5kZXNjICsgXCIgb3IgXCIgKyBzZWNvbmQuZGVzYztcbiAgICAgICAgcmV0dXJuIG9yRmlsdGVyO1xuICAgIH1cbiAgICBmdW5jdGlvbiBhbmQoZmlyc3QsIHNlY29uZCkge1xuICAgICAgICBmdW5jdGlvbiBhbmRGaWx0ZXIoKSB7XG4gICAgICAgICAgICByZXR1cm4gZmlyc3QuYXBwbHkodGhpcywgYXJndW1lbnRzKSAmJiBzZWNvbmQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfVxuICAgICAgICBhbmRGaWx0ZXIuZGVzYyA9IGZpcnN0LmRlc2MgKyBcIiBhbmQgXCIgKyBzZWNvbmQuZGVzYztcbiAgICAgICAgcmV0dXJuIGFuZEZpbHRlcjtcbiAgICB9XG4gICAgZnVuY3Rpb24gbm90KGV4cHIpIHtcbiAgICAgICAgZnVuY3Rpb24gbm90RmlsdGVyKCkge1xuICAgICAgICAgICAgcmV0dXJuICFleHByLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH1cbiAgICAgICAgbm90RmlsdGVyLmRlc2MgPSBcIm5vdCBcIiArIGV4cHIuZGVzYztcbiAgICAgICAgcmV0dXJuIG5vdEZpbHRlcjtcbiAgICB9XG4gICAgZnVuY3Rpb24gYmluZGluZyhleHByKSB7XG4gICAgICAgIGZ1bmN0aW9uIGJpbmRpbmdGaWx0ZXIoKSB7XG4gICAgICAgICAgICByZXR1cm4gZXhwci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgICAgIGJpbmRpbmdGaWx0ZXIuZGVzYyA9IFwiKFwiICsgZXhwci5kZXNjICsgXCIpXCI7XG4gICAgICAgIHJldHVybiBiaW5kaW5nRmlsdGVyO1xuICAgIH1cbiAgICBmdW5jdGlvbiB0cnVlRmlsdGVyKGZsb3cpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHRydWVGaWx0ZXIuZGVzYyA9IFwidHJ1ZVwiO1xuICAgIGZ1bmN0aW9uIGZhbHNlRmlsdGVyKGZsb3cpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBmYWxzZUZpbHRlci5kZXNjID0gXCJmYWxzZVwiO1xuXG4gICAgdmFyIEFTU0VUX1RZUEVTID0gW1xuICAgICAgICBuZXcgUmVnRXhwKFwidGV4dC9qYXZhc2NyaXB0XCIpLFxuICAgICAgICBuZXcgUmVnRXhwKFwiYXBwbGljYXRpb24veC1qYXZhc2NyaXB0XCIpLFxuICAgICAgICBuZXcgUmVnRXhwKFwiYXBwbGljYXRpb24vamF2YXNjcmlwdFwiKSxcbiAgICAgICAgbmV3IFJlZ0V4cChcInRleHQvY3NzXCIpLFxuICAgICAgICBuZXcgUmVnRXhwKFwiaW1hZ2UvLipcIiksXG4gICAgICAgIG5ldyBSZWdFeHAoXCJhcHBsaWNhdGlvbi94LXNob2Nrd2F2ZS1mbGFzaFwiKVxuICAgIF07XG4gICAgZnVuY3Rpb24gYXNzZXRGaWx0ZXIoZmxvdykge1xuICAgICAgICBpZiAoZmxvdy5yZXNwb25zZSkge1xuICAgICAgICAgICAgdmFyIGN0ID0gZmxvd3V0aWxzLlJlc3BvbnNlVXRpbHMuZ2V0Q29udGVudFR5cGUoZmxvdy5yZXNwb25zZSk7XG4gICAgICAgICAgICB2YXIgaSA9IEFTU0VUX1RZUEVTLmxlbmd0aDtcbiAgICAgICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgICAgICBpZiAoQVNTRVRfVFlQRVNbaV0udGVzdChjdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgYXNzZXRGaWx0ZXIuZGVzYyA9IFwiaXMgYXNzZXRcIjtcbiAgICBmdW5jdGlvbiByZXNwb25zZUNvZGUoY29kZSl7XG4gICAgICAgIGZ1bmN0aW9uIHJlc3BvbnNlQ29kZUZpbHRlcihmbG93KXtcbiAgICAgICAgICAgIHJldHVybiBmbG93LnJlc3BvbnNlICYmIGZsb3cucmVzcG9uc2UuY29kZSA9PT0gY29kZTtcbiAgICAgICAgfVxuICAgICAgICByZXNwb25zZUNvZGVGaWx0ZXIuZGVzYyA9IFwicmVzcC4gY29kZSBpcyBcIiArIGNvZGU7XG4gICAgICAgIHJldHVybiByZXNwb25zZUNvZGVGaWx0ZXI7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGRvbWFpbihyZWdleCl7XG4gICAgICAgIHJlZ2V4ID0gbmV3IFJlZ0V4cChyZWdleCwgXCJpXCIpO1xuICAgICAgICBmdW5jdGlvbiBkb21haW5GaWx0ZXIoZmxvdyl7XG4gICAgICAgICAgICByZXR1cm4gZmxvdy5yZXF1ZXN0ICYmIHJlZ2V4LnRlc3QoZmxvdy5yZXF1ZXN0Lmhvc3QpO1xuICAgICAgICB9XG4gICAgICAgIGRvbWFpbkZpbHRlci5kZXNjID0gXCJkb21haW4gbWF0Y2hlcyBcIiArIHJlZ2V4O1xuICAgICAgICByZXR1cm4gZG9tYWluRmlsdGVyO1xuICAgIH1cbiAgICBmdW5jdGlvbiBlcnJvckZpbHRlcihmbG93KXtcbiAgICAgICAgcmV0dXJuICEhZmxvdy5lcnJvcjtcbiAgICB9XG4gICAgZXJyb3JGaWx0ZXIuZGVzYyA9IFwiaGFzIGVycm9yXCI7XG4gICAgZnVuY3Rpb24gaGVhZGVyKHJlZ2V4KXtcbiAgICAgICAgcmVnZXggPSBuZXcgUmVnRXhwKHJlZ2V4LCBcImlcIik7XG4gICAgICAgIGZ1bmN0aW9uIGhlYWRlckZpbHRlcihmbG93KXtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgKGZsb3cucmVxdWVzdCAmJiBmbG93dXRpbHMuUmVxdWVzdFV0aWxzLm1hdGNoX2hlYWRlcihmbG93LnJlcXVlc3QsIHJlZ2V4KSlcbiAgICAgICAgICAgICAgICB8fFxuICAgICAgICAgICAgICAgIChmbG93LnJlc3BvbnNlICYmIGZsb3d1dGlscy5SZXNwb25zZVV0aWxzLm1hdGNoX2hlYWRlcihmbG93LnJlc3BvbnNlLCByZWdleCkpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGhlYWRlckZpbHRlci5kZXNjID0gXCJoZWFkZXIgbWF0Y2hlcyBcIiArIHJlZ2V4O1xuICAgICAgICByZXR1cm4gaGVhZGVyRmlsdGVyO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZXF1ZXN0SGVhZGVyKHJlZ2V4KXtcbiAgICAgICAgcmVnZXggPSBuZXcgUmVnRXhwKHJlZ2V4LCBcImlcIik7XG4gICAgICAgIGZ1bmN0aW9uIHJlcXVlc3RIZWFkZXJGaWx0ZXIoZmxvdyl7XG4gICAgICAgICAgICByZXR1cm4gKGZsb3cucmVxdWVzdCAmJiBmbG93dXRpbHMuUmVxdWVzdFV0aWxzLm1hdGNoX2hlYWRlcihmbG93LnJlcXVlc3QsIHJlZ2V4KSk7XG4gICAgICAgIH1cbiAgICAgICAgcmVxdWVzdEhlYWRlckZpbHRlci5kZXNjID0gXCJyZXEuIGhlYWRlciBtYXRjaGVzIFwiICsgcmVnZXg7XG4gICAgICAgIHJldHVybiByZXF1ZXN0SGVhZGVyRmlsdGVyO1xuICAgIH1cbiAgICBmdW5jdGlvbiByZXNwb25zZUhlYWRlcihyZWdleCl7XG4gICAgICAgIHJlZ2V4ID0gbmV3IFJlZ0V4cChyZWdleCwgXCJpXCIpO1xuICAgICAgICBmdW5jdGlvbiByZXNwb25zZUhlYWRlckZpbHRlcihmbG93KXtcbiAgICAgICAgICAgIHJldHVybiAoZmxvdy5yZXNwb25zZSAmJiBmbG93dXRpbHMuUmVzcG9uc2VVdGlscy5tYXRjaF9oZWFkZXIoZmxvdy5yZXNwb25zZSwgcmVnZXgpKTtcbiAgICAgICAgfVxuICAgICAgICByZXNwb25zZUhlYWRlckZpbHRlci5kZXNjID0gXCJyZXNwLiBoZWFkZXIgbWF0Y2hlcyBcIiArIHJlZ2V4O1xuICAgICAgICByZXR1cm4gcmVzcG9uc2VIZWFkZXJGaWx0ZXI7XG4gICAgfVxuICAgIGZ1bmN0aW9uIG1ldGhvZChyZWdleCl7XG4gICAgICAgIHJlZ2V4ID0gbmV3IFJlZ0V4cChyZWdleCwgXCJpXCIpO1xuICAgICAgICBmdW5jdGlvbiBtZXRob2RGaWx0ZXIoZmxvdyl7XG4gICAgICAgICAgICByZXR1cm4gZmxvdy5yZXF1ZXN0ICYmIHJlZ2V4LnRlc3QoZmxvdy5yZXF1ZXN0Lm1ldGhvZCk7XG4gICAgICAgIH1cbiAgICAgICAgbWV0aG9kRmlsdGVyLmRlc2MgPSBcIm1ldGhvZCBtYXRjaGVzIFwiICsgcmVnZXg7XG4gICAgICAgIHJldHVybiBtZXRob2RGaWx0ZXI7XG4gICAgfVxuICAgIGZ1bmN0aW9uIG5vUmVzcG9uc2VGaWx0ZXIoZmxvdyl7XG4gICAgICAgIHJldHVybiBmbG93LnJlcXVlc3QgJiYgIWZsb3cucmVzcG9uc2U7XG4gICAgfVxuICAgIG5vUmVzcG9uc2VGaWx0ZXIuZGVzYyA9IFwiaGFzIG5vIHJlc3BvbnNlXCI7XG4gICAgZnVuY3Rpb24gcmVzcG9uc2VGaWx0ZXIoZmxvdyl7XG4gICAgICAgIHJldHVybiAhIWZsb3cucmVzcG9uc2U7XG4gICAgfVxuICAgIHJlc3BvbnNlRmlsdGVyLmRlc2MgPSBcImhhcyByZXNwb25zZVwiO1xuXG4gICAgZnVuY3Rpb24gY29udGVudFR5cGUocmVnZXgpe1xuICAgICAgICByZWdleCA9IG5ldyBSZWdFeHAocmVnZXgsIFwiaVwiKTtcbiAgICAgICAgZnVuY3Rpb24gY29udGVudFR5cGVGaWx0ZXIoZmxvdyl7XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIChmbG93LnJlcXVlc3QgJiYgcmVnZXgudGVzdChmbG93dXRpbHMuUmVxdWVzdFV0aWxzLmdldENvbnRlbnRUeXBlKGZsb3cucmVxdWVzdCkpKVxuICAgICAgICAgICAgICAgIHx8XG4gICAgICAgICAgICAgICAgKGZsb3cucmVzcG9uc2UgJiYgcmVnZXgudGVzdChmbG93dXRpbHMuUmVzcG9uc2VVdGlscy5nZXRDb250ZW50VHlwZShmbG93LnJlc3BvbnNlKSkpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGNvbnRlbnRUeXBlRmlsdGVyLmRlc2MgPSBcImNvbnRlbnQgdHlwZSBtYXRjaGVzIFwiICsgcmVnZXg7XG4gICAgICAgIHJldHVybiBjb250ZW50VHlwZUZpbHRlcjtcbiAgICB9XG4gICAgZnVuY3Rpb24gcmVxdWVzdENvbnRlbnRUeXBlKHJlZ2V4KXtcbiAgICAgICAgcmVnZXggPSBuZXcgUmVnRXhwKHJlZ2V4LCBcImlcIik7XG4gICAgICAgIGZ1bmN0aW9uIHJlcXVlc3RDb250ZW50VHlwZUZpbHRlcihmbG93KXtcbiAgICAgICAgICAgIHJldHVybiBmbG93LnJlcXVlc3QgJiYgcmVnZXgudGVzdChmbG93dXRpbHMuUmVxdWVzdFV0aWxzLmdldENvbnRlbnRUeXBlKGZsb3cucmVxdWVzdCkpO1xuICAgICAgICB9XG4gICAgICAgIHJlcXVlc3RDb250ZW50VHlwZUZpbHRlci5kZXNjID0gXCJyZXEuIGNvbnRlbnQgdHlwZSBtYXRjaGVzIFwiICsgcmVnZXg7XG4gICAgICAgIHJldHVybiByZXF1ZXN0Q29udGVudFR5cGVGaWx0ZXI7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlc3BvbnNlQ29udGVudFR5cGUocmVnZXgpe1xuICAgICAgICByZWdleCA9IG5ldyBSZWdFeHAocmVnZXgsIFwiaVwiKTtcbiAgICAgICAgZnVuY3Rpb24gcmVzcG9uc2VDb250ZW50VHlwZUZpbHRlcihmbG93KXtcbiAgICAgICAgICAgIHJldHVybiBmbG93LnJlc3BvbnNlICYmIHJlZ2V4LnRlc3QoZmxvd3V0aWxzLlJlc3BvbnNlVXRpbHMuZ2V0Q29udGVudFR5cGUoZmxvdy5yZXNwb25zZSkpO1xuICAgICAgICB9XG4gICAgICAgIHJlc3BvbnNlQ29udGVudFR5cGVGaWx0ZXIuZGVzYyA9IFwicmVzcC4gY29udGVudCB0eXBlIG1hdGNoZXMgXCIgKyByZWdleDtcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlQ29udGVudFR5cGVGaWx0ZXI7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHVybChyZWdleCl7XG4gICAgICAgIHJlZ2V4ID0gbmV3IFJlZ0V4cChyZWdleCwgXCJpXCIpO1xuICAgICAgICBmdW5jdGlvbiB1cmxGaWx0ZXIoZmxvdyl7XG4gICAgICAgICAgICByZXR1cm4gZmxvdy5yZXF1ZXN0ICYmIHJlZ2V4LnRlc3QoZmxvd3V0aWxzLlJlcXVlc3RVdGlscy5wcmV0dHlfdXJsKGZsb3cucmVxdWVzdCkpO1xuICAgICAgICB9XG4gICAgICAgIHVybEZpbHRlci5kZXNjID0gXCJ1cmwgbWF0Y2hlcyBcIiArIHJlZ2V4O1xuICAgICAgICByZXR1cm4gdXJsRmlsdGVyO1xuICAgIH1cblxuXG4gICAgcGVnJHJlc3VsdCA9IHBlZyRzdGFydFJ1bGVGdW5jdGlvbigpO1xuXG4gICAgaWYgKHBlZyRyZXN1bHQgIT09IHBlZyRGQUlMRUQgJiYgcGVnJGN1cnJQb3MgPT09IGlucHV0Lmxlbmd0aCkge1xuICAgICAgcmV0dXJuIHBlZyRyZXN1bHQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChwZWckcmVzdWx0ICE9PSBwZWckRkFJTEVEICYmIHBlZyRjdXJyUG9zIDwgaW5wdXQubGVuZ3RoKSB7XG4gICAgICAgIHBlZyRmYWlsKHsgdHlwZTogXCJlbmRcIiwgZGVzY3JpcHRpb246IFwiZW5kIG9mIGlucHV0XCIgfSk7XG4gICAgICB9XG5cbiAgICAgIHRocm93IHBlZyRidWlsZEV4Y2VwdGlvbihudWxsLCBwZWckbWF4RmFpbEV4cGVjdGVkLCBwZWckbWF4RmFpbFBvcyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBTeW50YXhFcnJvcjogU3ludGF4RXJyb3IsXG4gICAgcGFyc2U6ICAgICAgIHBhcnNlXG4gIH07XG59KSgpOyIsInZhciBfID0gcmVxdWlyZShcImxvZGFzaFwiKTtcblxudmFyIF9NZXNzYWdlVXRpbHMgPSB7XG4gICAgZ2V0Q29udGVudFR5cGU6IGZ1bmN0aW9uIChtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldF9maXJzdF9oZWFkZXIobWVzc2FnZSwgL15Db250ZW50LVR5cGUkL2kpO1xuICAgIH0sXG4gICAgZ2V0X2ZpcnN0X2hlYWRlcjogZnVuY3Rpb24gKG1lc3NhZ2UsIHJlZ2V4KSB7XG4gICAgICAgIC8vRklYTUU6IENhY2hlIEludmFsaWRhdGlvbi5cbiAgICAgICAgaWYgKCFtZXNzYWdlLl9oZWFkZXJMb29rdXBzKVxuICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG1lc3NhZ2UsIFwiX2hlYWRlckxvb2t1cHNcIiwge1xuICAgICAgICAgICAgICAgIHZhbHVlOiB7fSxcbiAgICAgICAgICAgICAgICBjb25maWd1cmFibGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHdyaXRhYmxlOiBmYWxzZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIGlmICghKHJlZ2V4IGluIG1lc3NhZ2UuX2hlYWRlckxvb2t1cHMpKSB7XG4gICAgICAgICAgICB2YXIgaGVhZGVyO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLmhlYWRlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoISFtZXNzYWdlLmhlYWRlcnNbaV1bMF0ubWF0Y2gocmVnZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGhlYWRlciA9IG1lc3NhZ2UuaGVhZGVyc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbWVzc2FnZS5faGVhZGVyTG9va3Vwc1tyZWdleF0gPSBoZWFkZXIgPyBoZWFkZXJbMV0gOiB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1lc3NhZ2UuX2hlYWRlckxvb2t1cHNbcmVnZXhdO1xuICAgIH0sXG4gICAgbWF0Y2hfaGVhZGVyOiBmdW5jdGlvbiAobWVzc2FnZSwgcmVnZXgpIHtcbiAgICAgICAgdmFyIGhlYWRlcnMgPSBtZXNzYWdlLmhlYWRlcnM7XG4gICAgICAgIHZhciBpID0gaGVhZGVycy5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIGlmIChyZWdleC50ZXN0KGhlYWRlcnNbaV0uam9pbihcIiBcIikpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhlYWRlcnNbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbn07XG5cbnZhciBkZWZhdWx0UG9ydHMgPSB7XG4gICAgXCJodHRwXCI6IDgwLFxuICAgIFwiaHR0cHNcIjogNDQzXG59O1xuXG52YXIgUmVxdWVzdFV0aWxzID0gXy5leHRlbmQoX01lc3NhZ2VVdGlscywge1xuICAgIHByZXR0eV9ob3N0OiBmdW5jdGlvbiAocmVxdWVzdCkge1xuICAgICAgICAvL0ZJWE1FOiBBZGQgaG9zdGhlYWRlclxuICAgICAgICByZXR1cm4gcmVxdWVzdC5ob3N0O1xuICAgIH0sXG4gICAgcHJldHR5X3VybDogZnVuY3Rpb24gKHJlcXVlc3QpIHtcbiAgICAgICAgdmFyIHBvcnQgPSBcIlwiO1xuICAgICAgICBpZiAoZGVmYXVsdFBvcnRzW3JlcXVlc3Quc2NoZW1lXSAhPT0gcmVxdWVzdC5wb3J0KSB7XG4gICAgICAgICAgICBwb3J0ID0gXCI6XCIgKyByZXF1ZXN0LnBvcnQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcXVlc3Quc2NoZW1lICsgXCI6Ly9cIiArIHRoaXMucHJldHR5X2hvc3QocmVxdWVzdCkgKyBwb3J0ICsgcmVxdWVzdC5wYXRoO1xuICAgIH1cbn0pO1xuXG52YXIgUmVzcG9uc2VVdGlscyA9IF8uZXh0ZW5kKF9NZXNzYWdlVXRpbHMsIHt9KTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBSZXNwb25zZVV0aWxzOiBSZXNwb25zZVV0aWxzLFxuICAgIFJlcXVlc3RVdGlsczogUmVxdWVzdFV0aWxzXG5cbn0iLCJcbnZhciBfID0gcmVxdWlyZShcImxvZGFzaFwiKTtcbnZhciAkID0gcmVxdWlyZShcImpxdWVyeVwiKTtcbnZhciBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXI7XG5cbnZhciB1dGlscyA9IHJlcXVpcmUoXCIuLi91dGlscy5qc1wiKTtcbnZhciBhY3Rpb25zID0gcmVxdWlyZShcIi4uL2FjdGlvbnMuanNcIik7XG52YXIgZGlzcGF0Y2hlciA9IHJlcXVpcmUoXCIuLi9kaXNwYXRjaGVyLmpzXCIpO1xuXG5cbmZ1bmN0aW9uIExpc3RTdG9yZSgpIHtcbiAgICBFdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcbiAgICB0aGlzLnJlc2V0KCk7XG59XG5fLmV4dGVuZChMaXN0U3RvcmUucHJvdG90eXBlLCBFdmVudEVtaXR0ZXIucHJvdG90eXBlLCB7XG4gICAgYWRkOiBmdW5jdGlvbiAoZWxlbSkge1xuICAgICAgICBpZiAoZWxlbS5pZCBpbiB0aGlzLl9wb3NfbWFwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcG9zX21hcFtlbGVtLmlkXSA9IHRoaXMubGlzdC5sZW5ndGg7XG4gICAgICAgIHRoaXMubGlzdC5wdXNoKGVsZW0pO1xuICAgICAgICB0aGlzLmVtaXQoXCJhZGRcIiwgZWxlbSk7XG4gICAgfSxcbiAgICB1cGRhdGU6IGZ1bmN0aW9uIChlbGVtKSB7XG4gICAgICAgIGlmICghKGVsZW0uaWQgaW4gdGhpcy5fcG9zX21hcCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxpc3RbdGhpcy5fcG9zX21hcFtlbGVtLmlkXV0gPSBlbGVtO1xuICAgICAgICB0aGlzLmVtaXQoXCJ1cGRhdGVcIiwgZWxlbSk7XG4gICAgfSxcbiAgICByZW1vdmU6IGZ1bmN0aW9uIChlbGVtX2lkKSB7XG4gICAgICAgIGlmICghKGVsZW1faWQgaW4gdGhpcy5fcG9zX21hcCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxpc3Quc3BsaWNlKHRoaXMuX3Bvc19tYXBbZWxlbV9pZF0sIDEpO1xuICAgICAgICB0aGlzLl9idWlsZF9tYXAoKTtcbiAgICAgICAgdGhpcy5lbWl0KFwicmVtb3ZlXCIsIGVsZW1faWQpO1xuICAgIH0sXG4gICAgcmVzZXQ6IGZ1bmN0aW9uIChlbGVtcykge1xuICAgICAgICB0aGlzLmxpc3QgPSBlbGVtcyB8fCBbXTtcbiAgICAgICAgdGhpcy5fYnVpbGRfbWFwKCk7XG4gICAgICAgIHRoaXMuZW1pdChcInJlY2FsY3VsYXRlXCIpO1xuICAgIH0sXG4gICAgX2J1aWxkX21hcDogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLl9wb3NfbWFwID0ge307XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5saXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgZWxlbSA9IHRoaXMubGlzdFtpXTtcbiAgICAgICAgICAgIHRoaXMuX3Bvc19tYXBbZWxlbS5pZF0gPSBpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBnZXQ6IGZ1bmN0aW9uIChlbGVtX2lkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RbdGhpcy5fcG9zX21hcFtlbGVtX2lkXV07XG4gICAgfSxcbiAgICBpbmRleDogZnVuY3Rpb24gKGVsZW1faWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3Bvc19tYXBbZWxlbV9pZF07XG4gICAgfVxufSk7XG5cblxuZnVuY3Rpb24gRGljdFN0b3JlKCkge1xuICAgIEV2ZW50RW1pdHRlci5jYWxsKHRoaXMpO1xuICAgIHRoaXMucmVzZXQoKTtcbn1cbl8uZXh0ZW5kKERpY3RTdG9yZS5wcm90b3R5cGUsIEV2ZW50RW1pdHRlci5wcm90b3R5cGUsIHtcbiAgICB1cGRhdGU6IGZ1bmN0aW9uIChkaWN0KSB7XG4gICAgICAgIF8ubWVyZ2UodGhpcy5kaWN0LCBkaWN0KTtcbiAgICAgICAgdGhpcy5lbWl0KFwicmVjYWxjdWxhdGVcIik7XG4gICAgfSxcbiAgICByZXNldDogZnVuY3Rpb24gKGRpY3QpIHtcbiAgICAgICAgdGhpcy5kaWN0ID0gZGljdCB8fCB7fTtcbiAgICAgICAgdGhpcy5lbWl0KFwicmVjYWxjdWxhdGVcIik7XG4gICAgfVxufSk7XG5cbmZ1bmN0aW9uIExpdmVTdG9yZU1peGluKHR5cGUpIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuXG4gICAgdGhpcy5fdXBkYXRlc19iZWZvcmVfZmV0Y2ggPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fZmV0Y2h4aHIgPSBmYWxzZTtcblxuICAgIHRoaXMuaGFuZGxlID0gdGhpcy5oYW5kbGUuYmluZCh0aGlzKTtcbiAgICBkaXNwYXRjaGVyLkFwcERpc3BhdGNoZXIucmVnaXN0ZXIodGhpcy5oYW5kbGUpO1xuXG4gICAgLy8gQXZvaWQgZG91YmxlLWZldGNoIG9uIHN0YXJ0dXAuXG4gICAgaWYgKCEod2luZG93LndzICYmIHdpbmRvdy53cy5yZWFkeVN0YXRlID09PSBXZWJTb2NrZXQuQ09OTkVDVElORykpIHtcbiAgICAgICAgdGhpcy5mZXRjaCgpO1xuICAgIH1cbn1cbl8uZXh0ZW5kKExpdmVTdG9yZU1peGluLnByb3RvdHlwZSwge1xuICAgIGhhbmRsZTogZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIGlmIChldmVudC50eXBlID09PSBhY3Rpb25zLkFjdGlvblR5cGVzLkNPTk5FQ1RJT05fT1BFTikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmV0Y2goKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXZlbnQudHlwZSA9PT0gdGhpcy50eXBlKSB7XG4gICAgICAgICAgICBpZiAoZXZlbnQuY21kID09PSBhY3Rpb25zLlN0b3JlQ21kcy5SRVNFVCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZmV0Y2goZXZlbnQuZGF0YSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX3VwZGF0ZXNfYmVmb3JlX2ZldGNoKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJkZWZlciB1cGRhdGVcIiwgZXZlbnQpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZXNfYmVmb3JlX2ZldGNoLnB1c2goZXZlbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzW2V2ZW50LmNtZF0oZXZlbnQuZGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGNsb3NlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGRpc3BhdGNoZXIuQXBwRGlzcGF0Y2hlci51bnJlZ2lzdGVyKHRoaXMuaGFuZGxlKTtcbiAgICB9LFxuICAgIGZldGNoOiBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICBjb25zb2xlLmxvZyhcImZldGNoIFwiICsgdGhpcy50eXBlKTtcbiAgICAgICAgaWYgKHRoaXMuX2ZldGNoeGhyKSB7XG4gICAgICAgICAgICB0aGlzLl9mZXRjaHhoci5hYm9ydCgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3VwZGF0ZXNfYmVmb3JlX2ZldGNoID0gW107IC8vIChKUzogZW1wdHkgYXJyYXkgaXMgdHJ1ZSlcbiAgICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlX2ZldGNoKGRhdGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fZmV0Y2h4aHIgPSAkLmdldEpTT04oXCIvXCIgKyB0aGlzLnR5cGUpXG4gICAgICAgICAgICAgICAgLmRvbmUoZnVuY3Rpb24gKG1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVfZmV0Y2gobWVzc2FnZS5kYXRhKTtcbiAgICAgICAgICAgICAgICB9LmJpbmQodGhpcykpXG4gICAgICAgICAgICAgICAgLmZhaWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBFdmVudExvZ0FjdGlvbnMuYWRkX2V2ZW50KFwiQ291bGQgbm90IGZldGNoIFwiICsgdGhpcy50eXBlKTtcbiAgICAgICAgICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBoYW5kbGVfZmV0Y2g6IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgIHRoaXMuX2ZldGNoeGhyID0gZmFsc2U7XG4gICAgICAgIGNvbnNvbGUubG9nKHRoaXMudHlwZSArIFwiIGZldGNoZWQuXCIsIHRoaXMuX3VwZGF0ZXNfYmVmb3JlX2ZldGNoKTtcbiAgICAgICAgdGhpcy5yZXNldChkYXRhKTtcbiAgICAgICAgdmFyIHVwZGF0ZXMgPSB0aGlzLl91cGRhdGVzX2JlZm9yZV9mZXRjaDtcbiAgICAgICAgdGhpcy5fdXBkYXRlc19iZWZvcmVfZmV0Y2ggPSBmYWxzZTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB1cGRhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZSh1cGRhdGVzW2ldKTtcbiAgICAgICAgfVxuICAgIH0sXG59KTtcblxuZnVuY3Rpb24gTGl2ZUxpc3RTdG9yZSh0eXBlKSB7XG4gICAgTGlzdFN0b3JlLmNhbGwodGhpcyk7XG4gICAgTGl2ZVN0b3JlTWl4aW4uY2FsbCh0aGlzLCB0eXBlKTtcbn1cbl8uZXh0ZW5kKExpdmVMaXN0U3RvcmUucHJvdG90eXBlLCBMaXN0U3RvcmUucHJvdG90eXBlLCBMaXZlU3RvcmVNaXhpbi5wcm90b3R5cGUpO1xuXG5mdW5jdGlvbiBMaXZlRGljdFN0b3JlKHR5cGUpIHtcbiAgICBEaWN0U3RvcmUuY2FsbCh0aGlzKTtcbiAgICBMaXZlU3RvcmVNaXhpbi5jYWxsKHRoaXMsIHR5cGUpO1xufVxuXy5leHRlbmQoTGl2ZURpY3RTdG9yZS5wcm90b3R5cGUsIERpY3RTdG9yZS5wcm90b3R5cGUsIExpdmVTdG9yZU1peGluLnByb3RvdHlwZSk7XG5cblxuZnVuY3Rpb24gRmxvd1N0b3JlKCkge1xuICAgIHJldHVybiBuZXcgTGl2ZUxpc3RTdG9yZShhY3Rpb25zLkFjdGlvblR5cGVzLkZMT1dfU1RPUkUpO1xufVxuXG5mdW5jdGlvbiBTZXR0aW5nc1N0b3JlKCkge1xuICAgIHJldHVybiBuZXcgTGl2ZURpY3RTdG9yZShhY3Rpb25zLkFjdGlvblR5cGVzLlNFVFRJTkdTX1NUT1JFKTtcbn1cblxuZnVuY3Rpb24gRXZlbnRMb2dTdG9yZSgpIHtcbiAgICBMaXZlTGlzdFN0b3JlLmNhbGwodGhpcywgYWN0aW9ucy5BY3Rpb25UeXBlcy5FVkVOVF9TVE9SRSk7XG59XG5fLmV4dGVuZChFdmVudExvZ1N0b3JlLnByb3RvdHlwZSwgTGl2ZUxpc3RTdG9yZS5wcm90b3R5cGUsIHtcbiAgICBmZXRjaDogZnVuY3Rpb24oKXtcbiAgICAgICAgTGl2ZUxpc3RTdG9yZS5wcm90b3R5cGUuZmV0Y2guYXBwbHkodGhpcywgYXJndW1lbnRzKTtcblxuICAgICAgICAvLyBNYWtlIHN1cmUgdG8gZGlzcGxheSB1cGRhdGVzIGV2ZW4gaWYgZmV0Y2hpbmcgYWxsIGV2ZW50cyBmYWlsZWQuXG4gICAgICAgIC8vIFRoaXMgd2F5LCB3ZSBjYW4gc2VuZCBcImZldGNoIGZhaWxlZFwiIGxvZyBtZXNzYWdlcyB0byB0aGUgbG9nLlxuICAgICAgICBpZih0aGlzLl9mZXRjaHhocil7XG4gICAgICAgICAgICB0aGlzLl9mZXRjaHhoci5mYWlsKGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVfZmV0Y2gobnVsbCk7XG4gICAgICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgICAgICB9XG4gICAgfVxufSk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgRXZlbnRMb2dTdG9yZTogRXZlbnRMb2dTdG9yZSxcbiAgICBTZXR0aW5nc1N0b3JlOiBTZXR0aW5nc1N0b3JlLFxuICAgIEZsb3dTdG9yZTogRmxvd1N0b3JlXG59OyIsIlxudmFyIEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoJ2V2ZW50cycpLkV2ZW50RW1pdHRlcjtcbnZhciBfID0gcmVxdWlyZShcImxvZGFzaFwiKTtcblxuXG52YXIgdXRpbHMgPSByZXF1aXJlKFwiLi4vdXRpbHMuanNcIik7XG5cbmZ1bmN0aW9uIFNvcnRCeVN0b3JlT3JkZXIoZWxlbSkge1xuICAgIHJldHVybiB0aGlzLnN0b3JlLmluZGV4KGVsZW0uaWQpO1xufVxuXG52YXIgZGVmYXVsdF9zb3J0ID0gU29ydEJ5U3RvcmVPcmRlcjtcbnZhciBkZWZhdWx0X2ZpbHQgPSBmdW5jdGlvbihlbGVtKXtcbiAgICByZXR1cm4gdHJ1ZTtcbn07XG5cbmZ1bmN0aW9uIFN0b3JlVmlldyhzdG9yZSwgZmlsdCwgc29ydGZ1bikge1xuICAgIEV2ZW50RW1pdHRlci5jYWxsKHRoaXMpO1xuICAgIGZpbHQgPSBmaWx0IHx8IGRlZmF1bHRfZmlsdDtcbiAgICBzb3J0ZnVuID0gc29ydGZ1biB8fCBkZWZhdWx0X3NvcnQ7XG5cbiAgICB0aGlzLnN0b3JlID0gc3RvcmU7XG5cbiAgICB0aGlzLmFkZCA9IHRoaXMuYWRkLmJpbmQodGhpcyk7XG4gICAgdGhpcy51cGRhdGUgPSB0aGlzLnVwZGF0ZS5iaW5kKHRoaXMpO1xuICAgIHRoaXMucmVtb3ZlID0gdGhpcy5yZW1vdmUuYmluZCh0aGlzKTtcbiAgICB0aGlzLnJlY2FsY3VsYXRlID0gdGhpcy5yZWNhbGN1bGF0ZS5iaW5kKHRoaXMpO1xuICAgIHRoaXMuc3RvcmUuYWRkTGlzdGVuZXIoXCJhZGRcIiwgdGhpcy5hZGQpO1xuICAgIHRoaXMuc3RvcmUuYWRkTGlzdGVuZXIoXCJ1cGRhdGVcIiwgdGhpcy51cGRhdGUpO1xuICAgIHRoaXMuc3RvcmUuYWRkTGlzdGVuZXIoXCJyZW1vdmVcIiwgdGhpcy5yZW1vdmUpO1xuICAgIHRoaXMuc3RvcmUuYWRkTGlzdGVuZXIoXCJyZWNhbGN1bGF0ZVwiLCB0aGlzLnJlY2FsY3VsYXRlKTtcblxuICAgIHRoaXMucmVjYWxjdWxhdGUoZmlsdCwgc29ydGZ1bik7XG59XG5cbl8uZXh0ZW5kKFN0b3JlVmlldy5wcm90b3R5cGUsIEV2ZW50RW1pdHRlci5wcm90b3R5cGUsIHtcbiAgICBjbG9zZTogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnN0b3JlLnJlbW92ZUxpc3RlbmVyKFwiYWRkXCIsIHRoaXMuYWRkKTtcbiAgICAgICAgdGhpcy5zdG9yZS5yZW1vdmVMaXN0ZW5lcihcInVwZGF0ZVwiLCB0aGlzLnVwZGF0ZSk7XG4gICAgICAgIHRoaXMuc3RvcmUucmVtb3ZlTGlzdGVuZXIoXCJyZW1vdmVcIiwgdGhpcy5yZW1vdmUpO1xuICAgICAgICB0aGlzLnN0b3JlLnJlbW92ZUxpc3RlbmVyKFwicmVjYWxjdWxhdGVcIiwgdGhpcy5yZWNhbGN1bGF0ZSk7XG4gICAgICAgIH0sXG4gICAgICAgIHJlY2FsY3VsYXRlOiBmdW5jdGlvbiAoZmlsdCwgc29ydGZ1bikge1xuICAgICAgICBpZiAoZmlsdCkge1xuICAgICAgICAgICAgdGhpcy5maWx0ID0gZmlsdC5iaW5kKHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzb3J0ZnVuKSB7XG4gICAgICAgICAgICB0aGlzLnNvcnRmdW4gPSBzb3J0ZnVuLmJpbmQodGhpcyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmxpc3QgPSB0aGlzLnN0b3JlLmxpc3QuZmlsdGVyKHRoaXMuZmlsdCk7XG4gICAgICAgIHRoaXMubGlzdC5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zb3J0ZnVuKGEpIC0gdGhpcy5zb3J0ZnVuKGIpO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmVtaXQoXCJyZWNhbGN1bGF0ZVwiKTtcbiAgICB9LFxuICAgIGluZGV4OiBmdW5jdGlvbiAoZWxlbSkge1xuICAgICAgICByZXR1cm4gXy5zb3J0ZWRJbmRleCh0aGlzLmxpc3QsIGVsZW0sIHRoaXMuc29ydGZ1bik7XG4gICAgfSxcbiAgICBhZGQ6IGZ1bmN0aW9uIChlbGVtKSB7XG4gICAgICAgIGlmICh0aGlzLmZpbHQoZWxlbSkpIHtcbiAgICAgICAgICAgIHZhciBpZHggPSB0aGlzLmluZGV4KGVsZW0pO1xuICAgICAgICAgICAgaWYgKGlkeCA9PT0gdGhpcy5saXN0Lmxlbmd0aCkgeyAvL2hhcHBlbnMgb2Z0ZW4sIC5wdXNoIGlzIHdheSBmYXN0ZXIuXG4gICAgICAgICAgICAgICAgdGhpcy5saXN0LnB1c2goZWxlbSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMubGlzdC5zcGxpY2UoaWR4LCAwLCBlbGVtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZW1pdChcImFkZFwiLCBlbGVtLCBpZHgpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICB1cGRhdGU6IGZ1bmN0aW9uIChlbGVtKSB7XG4gICAgICAgIHZhciBpZHg7XG4gICAgICAgIHZhciBpID0gdGhpcy5saXN0Lmxlbmd0aDtcbiAgICAgICAgLy8gU2VhcmNoIGZyb20gdGhlIGJhY2ssIHdlIHVzdWFsbHkgdXBkYXRlIHRoZSBsYXRlc3QgZW50cmllcy5cbiAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgaWYgKHRoaXMubGlzdFtpXS5pZCA9PT0gZWxlbS5pZCkge1xuICAgICAgICAgICAgICAgIGlkeCA9IGk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaWR4ID09PSAtMSkgeyAvL25vdCBjb250YWluZWQgaW4gbGlzdFxuICAgICAgICAgICAgdGhpcy5hZGQoZWxlbSk7XG4gICAgICAgIH0gZWxzZSBpZiAoIXRoaXMuZmlsdChlbGVtKSkge1xuICAgICAgICAgICAgdGhpcy5yZW1vdmUoZWxlbS5pZCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zb3J0ZnVuKHRoaXMubGlzdFtpZHhdKSAhPT0gdGhpcy5zb3J0ZnVuKGVsZW0pKSB7IC8vc29ydHBvcyBoYXMgY2hhbmdlZFxuICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlKHRoaXMubGlzdFtpZHhdKTtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZChlbGVtKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5saXN0W2lkeF0gPSBlbGVtO1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdChcInVwZGF0ZVwiLCBlbGVtLCBpZHgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSxcbiAgICByZW1vdmU6IGZ1bmN0aW9uIChlbGVtX2lkKSB7XG4gICAgICAgIHZhciBpZHggPSB0aGlzLmxpc3QubGVuZ3RoO1xuICAgICAgICB3aGlsZSAoaWR4LS0pIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmxpc3RbaWR4XS5pZCA9PT0gZWxlbV9pZCkge1xuICAgICAgICAgICAgICAgIHRoaXMubGlzdC5zcGxpY2UoaWR4LCAxKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXQoXCJyZW1vdmVcIiwgZWxlbV9pZCwgaWR4KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn0pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBTdG9yZVZpZXc6IFN0b3JlVmlld1xufTsiLCJ2YXIgJCA9IHJlcXVpcmUoXCJqcXVlcnlcIik7XG5cblxudmFyIEtleSA9IHtcbiAgICBVUDogMzgsXG4gICAgRE9XTjogNDAsXG4gICAgUEFHRV9VUDogMzMsXG4gICAgUEFHRV9ET1dOOiAzNCxcbiAgICBIT01FOiAzNixcbiAgICBFTkQ6IDM1LFxuICAgIExFRlQ6IDM3LFxuICAgIFJJR0hUOiAzOSxcbiAgICBFTlRFUjogMTMsXG4gICAgRVNDOiAyNyxcbiAgICBUQUI6IDksXG4gICAgU1BBQ0U6IDMyLFxuICAgIEJBQ0tTUEFDRTogOCxcbn07XG4vLyBBZGQgQS1aXG5mb3IgKHZhciBpID0gNjU7IGkgPD0gOTA7IGkrKykge1xuICAgIEtleVtTdHJpbmcuZnJvbUNoYXJDb2RlKGkpXSA9IGk7XG59XG5cblxudmFyIGZvcm1hdFNpemUgPSBmdW5jdGlvbiAoYnl0ZXMpIHtcbiAgICBpZiAoYnl0ZXMgPT09IDApXG4gICAgICAgIHJldHVybiBcIjBcIjtcbiAgICB2YXIgcHJlZml4ID0gW1wiYlwiLCBcImtiXCIsIFwibWJcIiwgXCJnYlwiLCBcInRiXCJdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJlZml4Lmxlbmd0aDsgaSsrKXtcbiAgICAgICAgaWYgKE1hdGgucG93KDEwMjQsIGkgKyAxKSA+IGJ5dGVzKXtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuICAgIHZhciBwcmVjaXNpb247XG4gICAgaWYgKGJ5dGVzJU1hdGgucG93KDEwMjQsIGkpID09PSAwKVxuICAgICAgICBwcmVjaXNpb24gPSAwO1xuICAgIGVsc2VcbiAgICAgICAgcHJlY2lzaW9uID0gMTtcbiAgICByZXR1cm4gKGJ5dGVzL01hdGgucG93KDEwMjQsIGkpKS50b0ZpeGVkKHByZWNpc2lvbikgKyBwcmVmaXhbaV07XG59O1xuXG5cbnZhciBmb3JtYXRUaW1lRGVsdGEgPSBmdW5jdGlvbiAobWlsbGlzZWNvbmRzKSB7XG4gICAgdmFyIHRpbWUgPSBtaWxsaXNlY29uZHM7XG4gICAgdmFyIHByZWZpeCA9IFtcIm1zXCIsIFwic1wiLCBcIm1pblwiLCBcImhcIl07XG4gICAgdmFyIGRpdiA9IFsxMDAwLCA2MCwgNjBdO1xuICAgIHZhciBpID0gMDtcbiAgICB3aGlsZSAoTWF0aC5hYnModGltZSkgPj0gZGl2W2ldICYmIGkgPCBkaXYubGVuZ3RoKSB7XG4gICAgICAgIHRpbWUgPSB0aW1lIC8gZGl2W2ldO1xuICAgICAgICBpKys7XG4gICAgfVxuICAgIHJldHVybiBNYXRoLnJvdW5kKHRpbWUpICsgcHJlZml4W2ldO1xufTtcblxuXG52YXIgZm9ybWF0VGltZVN0YW1wID0gZnVuY3Rpb24gKHNlY29uZHMpIHtcbiAgICB2YXIgdHMgPSAobmV3IERhdGUoc2Vjb25kcyAqIDEwMDApKS50b0lTT1N0cmluZygpO1xuICAgIHJldHVybiB0cy5yZXBsYWNlKFwiVFwiLCBcIiBcIikucmVwbGFjZShcIlpcIiwgXCJcIik7XG59O1xuXG5cbmZ1bmN0aW9uIGdldENvb2tpZShuYW1lKSB7XG4gICAgdmFyIHIgPSBkb2N1bWVudC5jb29raWUubWF0Y2goXCJcXFxcYlwiICsgbmFtZSArIFwiPShbXjtdKilcXFxcYlwiKTtcbiAgICByZXR1cm4gciA/IHJbMV0gOiB1bmRlZmluZWQ7XG59XG52YXIgeHNyZiA9ICQucGFyYW0oe194c3JmOiBnZXRDb29raWUoXCJfeHNyZlwiKX0pO1xuXG4vL1Rvcm5hZG8gWFNSRiBQcm90ZWN0aW9uLlxuJC5hamF4UHJlZmlsdGVyKGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgaWYgKFtcInBvc3RcIiwgXCJwdXRcIiwgXCJkZWxldGVcIl0uaW5kZXhPZihvcHRpb25zLnR5cGUudG9Mb3dlckNhc2UoKSkgPj0gMCAmJiBvcHRpb25zLnVybFswXSA9PT0gXCIvXCIpIHtcbiAgICAgICAgaWYgKG9wdGlvbnMuZGF0YSkge1xuICAgICAgICAgICAgb3B0aW9ucy5kYXRhICs9IChcIiZcIiArIHhzcmYpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb3B0aW9ucy5kYXRhID0geHNyZjtcbiAgICAgICAgfVxuICAgIH1cbn0pO1xuLy8gTG9nIEFKQVggRXJyb3JzXG4kKGRvY3VtZW50KS5hamF4RXJyb3IoZnVuY3Rpb24gKGV2ZW50LCBqcVhIUiwgYWpheFNldHRpbmdzLCB0aHJvd25FcnJvcikge1xuICAgIHZhciBtZXNzYWdlID0ganFYSFIucmVzcG9uc2VUZXh0O1xuICAgIGNvbnNvbGUuZXJyb3IobWVzc2FnZSwgYXJndW1lbnRzKTtcbiAgICBFdmVudExvZ0FjdGlvbnMuYWRkX2V2ZW50KHRocm93bkVycm9yICsgXCI6IFwiICsgbWVzc2FnZSk7XG4gICAgd2luZG93LmFsZXJ0KG1lc3NhZ2UpO1xufSk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGZvcm1hdFNpemU6IGZvcm1hdFNpemUsXG4gICAgZm9ybWF0VGltZURlbHRhOiBmb3JtYXRUaW1lRGVsdGEsXG4gICAgZm9ybWF0VGltZVN0YW1wOiBmb3JtYXRUaW1lU3RhbXAsXG4gICAgS2V5OiBLZXlcbn07Il19 +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlc1xcYnJvd3NlcmlmeVxcbm9kZV9tb2R1bGVzXFxicm93c2VyLXBhY2tcXF9wcmVsdWRlLmpzIiwibm9kZV9tb2R1bGVzXFxicm93c2VyaWZ5XFxub2RlX21vZHVsZXNcXGV2ZW50c1xcZXZlbnRzLmpzIiwiQzpcXFVzZXJzXFx1c2VyXFxnaXRcXG1pdG1wcm94eVxcd2ViXFxzcmNcXGpzXFxhY3Rpb25zLmpzIiwiQzpcXFVzZXJzXFx1c2VyXFxnaXRcXG1pdG1wcm94eVxcd2ViXFxzcmNcXGpzXFxhcHAuanMiLCJDOlxcVXNlcnNcXHVzZXJcXGdpdFxcbWl0bXByb3h5XFx3ZWJcXHNyY1xcanNcXGNvbXBvbmVudHNcXGNvbW1vbi5qcyIsIkM6XFxVc2Vyc1xcdXNlclxcZ2l0XFxtaXRtcHJveHlcXHdlYlxcc3JjXFxqc1xcY29tcG9uZW50c1xcZXZlbnRsb2cuanMiLCJDOlxcVXNlcnNcXHVzZXJcXGdpdFxcbWl0bXByb3h5XFx3ZWJcXHNyY1xcanNcXGNvbXBvbmVudHNcXGZsb3dkZXRhaWwuanMiLCJDOlxcVXNlcnNcXHVzZXJcXGdpdFxcbWl0bXByb3h5XFx3ZWJcXHNyY1xcanNcXGNvbXBvbmVudHNcXGZsb3d0YWJsZS1jb2x1bW5zLmpzIiwiQzpcXFVzZXJzXFx1c2VyXFxnaXRcXG1pdG1wcm94eVxcd2ViXFxzcmNcXGpzXFxjb21wb25lbnRzXFxmbG93dGFibGUuanMiLCJDOlxcVXNlcnNcXHVzZXJcXGdpdFxcbWl0bXByb3h5XFx3ZWJcXHNyY1xcanNcXGNvbXBvbmVudHNcXGZvb3Rlci5qcyIsIkM6XFxVc2Vyc1xcdXNlclxcZ2l0XFxtaXRtcHJveHlcXHdlYlxcc3JjXFxqc1xcY29tcG9uZW50c1xcaGVhZGVyLmpzIiwiQzpcXFVzZXJzXFx1c2VyXFxnaXRcXG1pdG1wcm94eVxcd2ViXFxzcmNcXGpzXFxjb21wb25lbnRzXFxtYWludmlldy5qcyIsIkM6XFxVc2Vyc1xcdXNlclxcZ2l0XFxtaXRtcHJveHlcXHdlYlxcc3JjXFxqc1xcY29tcG9uZW50c1xccHJveHlhcHAuanMiLCJDOlxcVXNlcnNcXHVzZXJcXGdpdFxcbWl0bXByb3h5XFx3ZWJcXHNyY1xcanNcXGNvbXBvbmVudHNcXHZpcnR1YWxzY3JvbGwuanMiLCJDOlxcVXNlcnNcXHVzZXJcXGdpdFxcbWl0bXByb3h5XFx3ZWJcXHNyY1xcanNcXGNvbm5lY3Rpb24uanMiLCJDOlxcVXNlcnNcXHVzZXJcXGdpdFxcbWl0bXByb3h5XFx3ZWJcXHNyY1xcanNcXGRpc3BhdGNoZXIuanMiLCJDOlxcVXNlcnNcXHVzZXJcXGdpdFxcbWl0bXByb3h5XFx3ZWJcXHNyY1xcanNcXGZpbHRcXGZpbHQuanMiLCJDOlxcVXNlcnNcXHVzZXJcXGdpdFxcbWl0bXByb3h5XFx3ZWJcXHNyY1xcanNcXGZsb3dcXHV0aWxzLmpzIiwiQzpcXFVzZXJzXFx1c2VyXFxnaXRcXG1pdG1wcm94eVxcd2ViXFxzcmNcXGpzXFxzdG9yZVxcc3RvcmUuanMiLCJDOlxcVXNlcnNcXHVzZXJcXGdpdFxcbWl0bXByb3h5XFx3ZWJcXHNyY1xcanNcXHN0b3JlXFx2aWV3LmpzIiwiQzpcXFVzZXJzXFx1c2VyXFxnaXRcXG1pdG1wcm94eVxcd2ViXFxzcmNcXGpzXFx1dGlscy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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QUFJLENBQUMsS0FBSyxFQUFFLENBQUM7Q0FDaEI7QUFDRCxDQUFDLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxTQUFTLEVBQUUsWUFBWSxDQUFDLFNBQVMsRUFBRTtJQUNsRCxHQUFHLEVBQUUsVUFBVSxJQUFJLEVBQUU7UUFDakIsSUFBSSxJQUFJLENBQUMsRUFBRSxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDMUIsT0FBTztTQUNWO1FBQ0QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7UUFDMUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDckIsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7S0FDMUI7SUFDRCxNQUFNLEVBQUUsVUFBVSxJQUFJLEVBQUU7UUFDcEIsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFO1lBQzdCLE9BQU87U0FDVjtRQUNELElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUM7UUFDekMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7S0FDN0I7SUFDRCxNQUFNLEVBQUUsVUFBVSxPQUFPLEVBQUU7UUFDdkIsSUFBSSxFQUFFLE9BQU8sSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUU7WUFDN0IsT0FBTztTQUNWO1FBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUM1QyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDbEIsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUM7S0FDaEM7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QUFDLFFBQVEsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxVQUFVLEtBQUssRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLFdBQVcsRUFBRTtJQUNyRSxJQUFJLE9BQU8sR0FBRyxLQUFLLENBQUMsWUFBWSxDQUFDO0lBQ2pDLE9BQU8sQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQ2xDLGVBQWUsQ0FBQyxTQUFTLENBQUMsV0FBVyxHQUFHLElBQUksR0FBRyxPQUFPLENBQUMsQ0FBQztJQUN4RCxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQzFCLENBQUMsQ0FBQyxDQUFDOztBQUVILE1BQU0sQ0FBQyxPQUFPLEdBQUc7SUFDYixVQUFVLEVBQUUsVUFBVTtJQUN0QixlQUFlLEVBQUUsZUFBZTtJQUNoQyxlQUFlLEVBQUUsZUFBZTtJQUNoQyxHQUFHLEVBQUUsR0FBRztDQUNYIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG5mdW5jdGlvbiBFdmVudEVtaXR0ZXIoKSB7XG4gIHRoaXMuX2V2ZW50cyA9IHRoaXMuX2V2ZW50cyB8fCB7fTtcbiAgdGhpcy5fbWF4TGlzdGVuZXJzID0gdGhpcy5fbWF4TGlzdGVuZXJzIHx8IHVuZGVmaW5lZDtcbn1cbm1vZHVsZS5leHBvcnRzID0gRXZlbnRFbWl0dGVyO1xuXG4vLyBCYWNrd2FyZHMtY29tcGF0IHdpdGggbm9kZSAwLjEwLnhcbkV2ZW50RW1pdHRlci5FdmVudEVtaXR0ZXIgPSBFdmVudEVtaXR0ZXI7XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuX2V2ZW50cyA9IHVuZGVmaW5lZDtcbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuX21heExpc3RlbmVycyA9IHVuZGVmaW5lZDtcblxuLy8gQnkgZGVmYXVsdCBFdmVudEVtaXR0ZXJzIHdpbGwgcHJpbnQgYSB3YXJuaW5nIGlmIG1vcmUgdGhhbiAxMCBsaXN0ZW5lcnMgYXJlXG4vLyBhZGRlZCB0byBpdC4gVGhpcyBpcyBhIHVzZWZ1bCBkZWZhdWx0IHdoaWNoIGhlbHBzIGZpbmRpbmcgbWVtb3J5IGxlYWtzLlxuRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnMgPSAxMDtcblxuLy8gT2J2aW91c2x5IG5vdCBhbGwgRW1pdHRlcnMgc2hvdWxkIGJlIGxpbWl0ZWQgdG8gMTAuIFRoaXMgZnVuY3Rpb24gYWxsb3dzXG4vLyB0aGF0IHRvIGJlIGluY3JlYXNlZC4gU2V0IHRvIHplcm8gZm9yIHVubGltaXRlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuc2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24obikge1xuICBpZiAoIWlzTnVtYmVyKG4pIHx8IG4gPCAwIHx8IGlzTmFOKG4pKVxuICAgIHRocm93IFR5cGVFcnJvcignbiBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gIHRoaXMuX21heExpc3RlbmVycyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5lbWl0ID0gZnVuY3Rpb24odHlwZSkge1xuICB2YXIgZXIsIGhhbmRsZXIsIGxlbiwgYXJncywgaSwgbGlzdGVuZXJzO1xuXG4gIGlmICghdGhpcy5fZXZlbnRzKVxuICAgIHRoaXMuX2V2ZW50cyA9IHt9O1xuXG4gIC8vIElmIHRoZXJlIGlzIG5vICdlcnJvcicgZXZlbnQgbGlzdGVuZXIgdGhlbiB0aHJvdy5cbiAgaWYgKHR5cGUgPT09ICdlcnJvcicpIHtcbiAgICBpZiAoIXRoaXMuX2V2ZW50cy5lcnJvciB8fFxuICAgICAgICAoaXNPYmplY3QodGhpcy5fZXZlbnRzLmVycm9yKSAmJiAhdGhpcy5fZXZlbnRzLmVycm9yLmxlbmd0aCkpIHtcbiAgICAgIGVyID0gYXJndW1lbnRzWzFdO1xuICAgICAgaWYgKGVyIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gICAgICB9XG4gICAgICB0aHJvdyBUeXBlRXJyb3IoJ1VuY2F1Z2h0LCB1bnNwZWNpZmllZCBcImVycm9yXCIgZXZlbnQuJyk7XG4gICAgfVxuICB9XG5cbiAgaGFuZGxlciA9IHRoaXMuX2V2ZW50c1t0eXBlXTtcblxuICBpZiAoaXNVbmRlZmluZWQoaGFuZGxlcikpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIGlmIChpc0Z1bmN0aW9uKGhhbmRsZXIpKSB7XG4gICAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICAvLyBmYXN0IGNhc2VzXG4gICAgICBjYXNlIDE6XG4gICAgICAgIGhhbmRsZXIuY2FsbCh0aGlzKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDI6XG4gICAgICAgIGhhbmRsZXIuY2FsbCh0aGlzLCBhcmd1bWVudHNbMV0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMzpcbiAgICAgICAgaGFuZGxlci5jYWxsKHRoaXMsIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICAvLyBzbG93ZXJcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgICAgIGFyZ3MgPSBuZXcgQXJyYXkobGVuIC0gMSk7XG4gICAgICAgIGZvciAoaSA9IDE7IGkgPCBsZW47IGkrKylcbiAgICAgICAgICBhcmdzW2kgLSAxXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgaGFuZGxlci5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoaXNPYmplY3QoaGFuZGxlcikpIHtcbiAgICBsZW4gPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgIGFyZ3MgPSBuZXcgQXJyYXkobGVuIC0gMSk7XG4gICAgZm9yIChpID0gMTsgaSA8IGxlbjsgaSsrKVxuICAgICAgYXJnc1tpIC0gMV0gPSBhcmd1bWVudHNbaV07XG5cbiAgICBsaXN0ZW5lcnMgPSBoYW5kbGVyLnNsaWNlKCk7XG4gICAgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspXG4gICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkodGhpcywgYXJncyk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuYWRkTGlzdGVuZXIgPSBmdW5jdGlvbih0eXBlLCBsaXN0ZW5lcikge1xuICB2YXIgbTtcblxuICBpZiAoIWlzRnVuY3Rpb24obGlzdGVuZXIpKVxuICAgIHRocm93IFR5cGVFcnJvcignbGlzdGVuZXIgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgaWYgKCF0aGlzLl9ldmVudHMpXG4gICAgdGhpcy5fZXZlbnRzID0ge307XG5cbiAgLy8gVG8gYXZvaWQgcmVjdXJzaW9uIGluIHRoZSBjYXNlIHRoYXQgdHlwZSA9PT0gXCJuZXdMaXN0ZW5lclwiISBCZWZvcmVcbiAgLy8gYWRkaW5nIGl0IHRvIHRoZSBsaXN0ZW5lcnMsIGZpcnN0IGVtaXQgXCJuZXdMaXN0ZW5lclwiLlxuICBpZiAodGhpcy5fZXZlbnRzLm5ld0xpc3RlbmVyKVxuICAgIHRoaXMuZW1pdCgnbmV3TGlzdGVuZXInLCB0eXBlLFxuICAgICAgICAgICAgICBpc0Z1bmN0aW9uKGxpc3RlbmVyLmxpc3RlbmVyKSA/XG4gICAgICAgICAgICAgIGxpc3RlbmVyLmxpc3RlbmVyIDogbGlzdGVuZXIpO1xuXG4gIGlmICghdGhpcy5fZXZlbnRzW3R5cGVdKVxuICAgIC8vIE9wdGltaXplIHRoZSBjYXNlIG9mIG9uZSBsaXN0ZW5lci4gRG9uJ3QgbmVlZCB0aGUgZXh0cmEgYXJyYXkgb2JqZWN0LlxuICAgIHRoaXMuX2V2ZW50c1t0eXBlXSA9IGxpc3RlbmVyO1xuICBlbHNlIGlmIChpc09iamVjdCh0aGlzLl9ldmVudHNbdHlwZV0pKVxuICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgZ290IGFuIGFycmF5LCBqdXN0IGFwcGVuZC5cbiAgICB0aGlzLl9ldmVudHNbdHlwZV0ucHVzaChsaXN0ZW5lcik7XG4gIGVsc2VcbiAgICAvLyBBZGRpbmcgdGhlIHNlY29uZCBlbGVtZW50LCBuZWVkIHRvIGNoYW5nZSB0byBhcnJheS5cbiAgICB0aGlzLl9ldmVudHNbdHlwZV0gPSBbdGhpcy5fZXZlbnRzW3R5cGVdLCBsaXN0ZW5lcl07XG5cbiAgLy8gQ2hlY2sgZm9yIGxpc3RlbmVyIGxlYWtcbiAgaWYgKGlzT2JqZWN0KHRoaXMuX2V2ZW50c1t0eXBlXSkgJiYgIXRoaXMuX2V2ZW50c1t0eXBlXS53YXJuZWQpIHtcbiAgICB2YXIgbTtcbiAgICBpZiAoIWlzVW5kZWZpbmVkKHRoaXMuX21heExpc3RlbmVycykpIHtcbiAgICAgIG0gPSB0aGlzLl9tYXhMaXN0ZW5lcnM7XG4gICAgfSBlbHNlIHtcbiAgICAgIG0gPSBFdmVudEVtaXR0ZXIuZGVmYXVsdE1heExpc3RlbmVycztcbiAgICB9XG5cbiAgICBpZiAobSAmJiBtID4gMCAmJiB0aGlzLl9ldmVudHNbdHlwZV0ubGVuZ3RoID4gbSkge1xuICAgICAgdGhpcy5fZXZlbnRzW3R5cGVdLndhcm5lZCA9IHRydWU7XG4gICAgICBjb25zb2xlLmVycm9yKCcobm9kZSkgd2FybmluZzogcG9zc2libGUgRXZlbnRFbWl0dGVyIG1lbW9yeSAnICtcbiAgICAgICAgICAgICAgICAgICAgJ2xlYWsgZGV0ZWN0ZWQuICVkIGxpc3RlbmVycyBhZGRlZC4gJyArXG4gICAgICAgICAgICAgICAgICAgICdVc2UgZW1pdHRlci5zZXRNYXhMaXN0ZW5lcnMoKSB0byBpbmNyZWFzZSBsaW1pdC4nLFxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9ldmVudHNbdHlwZV0ubGVuZ3RoKTtcbiAgICAgIGlmICh0eXBlb2YgY29uc29sZS50cmFjZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAvLyBub3Qgc3VwcG9ydGVkIGluIElFIDEwXG4gICAgICAgIGNvbnNvbGUudHJhY2UoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub24gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbih0eXBlLCBsaXN0ZW5lcikge1xuICBpZiAoIWlzRnVuY3Rpb24obGlzdGVuZXIpKVxuICAgIHRocm93IFR5cGVFcnJvcignbGlzdGVuZXIgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgdmFyIGZpcmVkID0gZmFsc2U7XG5cbiAgZnVuY3Rpb24gZygpIHtcbiAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGcpO1xuXG4gICAgaWYgKCFmaXJlZCkge1xuICAgICAgZmlyZWQgPSB0cnVlO1xuICAgICAgbGlzdGVuZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBnLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gIHRoaXMub24odHlwZSwgZyk7XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vLyBlbWl0cyBhICdyZW1vdmVMaXN0ZW5lcicgZXZlbnQgaWZmIHRoZSBsaXN0ZW5lciB3YXMgcmVtb3ZlZFxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lciA9IGZ1bmN0aW9uKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBsaXN0LCBwb3NpdGlvbiwgbGVuZ3RoLCBpO1xuXG4gIGlmICghaXNGdW5jdGlvbihsaXN0ZW5lcikpXG4gICAgdGhyb3cgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcblxuICBpZiAoIXRoaXMuX2V2ZW50cyB8fCAhdGhpcy5fZXZlbnRzW3R5cGVdKVxuICAgIHJldHVybiB0aGlzO1xuXG4gIGxpc3QgPSB0aGlzLl9ldmVudHNbdHlwZV07XG4gIGxlbmd0aCA9IGxpc3QubGVuZ3RoO1xuICBwb3NpdGlvbiA9IC0xO1xuXG4gIGlmIChsaXN0ID09PSBsaXN0ZW5lciB8fFxuICAgICAgKGlzRnVuY3Rpb24obGlzdC5saXN0ZW5lcikgJiYgbGlzdC5saXN0ZW5lciA9PT0gbGlzdGVuZXIpKSB7XG4gICAgZGVsZXRlIHRoaXMuX2V2ZW50c1t0eXBlXTtcbiAgICBpZiAodGhpcy5fZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgdGhpcy5lbWl0KCdyZW1vdmVMaXN0ZW5lcicsIHR5cGUsIGxpc3RlbmVyKTtcblxuICB9IGVsc2UgaWYgKGlzT2JqZWN0KGxpc3QpKSB7XG4gICAgZm9yIChpID0gbGVuZ3RoOyBpLS0gPiAwOykge1xuICAgICAgaWYgKGxpc3RbaV0gPT09IGxpc3RlbmVyIHx8XG4gICAgICAgICAgKGxpc3RbaV0ubGlzdGVuZXIgJiYgbGlzdFtpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpKSB7XG4gICAgICAgIHBvc2l0aW9uID0gaTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHBvc2l0aW9uIDwgMClcbiAgICAgIHJldHVybiB0aGlzO1xuXG4gICAgaWYgKGxpc3QubGVuZ3RoID09PSAxKSB7XG4gICAgICBsaXN0Lmxlbmd0aCA9IDA7XG4gICAgICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuICAgIH0gZWxzZSB7XG4gICAgICBsaXN0LnNwbGljZShwb3NpdGlvbiwgMSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX2V2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBsaXN0ZW5lcik7XG4gIH1cblxuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucmVtb3ZlQWxsTGlzdGVuZXJzID0gZnVuY3Rpb24odHlwZSkge1xuICB2YXIga2V5LCBsaXN0ZW5lcnM7XG5cbiAgaWYgKCF0aGlzLl9ldmVudHMpXG4gICAgcmV0dXJuIHRoaXM7XG5cbiAgLy8gbm90IGxpc3RlbmluZyBmb3IgcmVtb3ZlTGlzdGVuZXIsIG5vIG5lZWQgdG8gZW1pdFxuICBpZiAoIXRoaXMuX2V2ZW50cy5yZW1vdmVMaXN0ZW5lcikge1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKVxuICAgICAgdGhpcy5fZXZlbnRzID0ge307XG4gICAgZWxzZSBpZiAodGhpcy5fZXZlbnRzW3R5cGVdKVxuICAgICAgZGVsZXRlIHRoaXMuX2V2ZW50c1t0eXBlXTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8vIGVtaXQgcmVtb3ZlTGlzdGVuZXIgZm9yIGFsbCBsaXN0ZW5lcnMgb24gYWxsIGV2ZW50c1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgIGZvciAoa2V5IGluIHRoaXMuX2V2ZW50cykge1xuICAgICAgaWYgKGtleSA9PT0gJ3JlbW92ZUxpc3RlbmVyJykgY29udGludWU7XG4gICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhrZXkpO1xuICAgIH1cbiAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycygncmVtb3ZlTGlzdGVuZXInKTtcbiAgICB0aGlzLl9ldmVudHMgPSB7fTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIGxpc3RlbmVycyA9IHRoaXMuX2V2ZW50c1t0eXBlXTtcblxuICBpZiAoaXNGdW5jdGlvbihsaXN0ZW5lcnMpKSB7XG4gICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnMpO1xuICB9IGVsc2Uge1xuICAgIC8vIExJRk8gb3JkZXJcbiAgICB3aGlsZSAobGlzdGVuZXJzLmxlbmd0aClcbiAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXJzW2xpc3RlbmVycy5sZW5ndGggLSAxXSk7XG4gIH1cbiAgZGVsZXRlIHRoaXMuX2V2ZW50c1t0eXBlXTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJzID0gZnVuY3Rpb24odHlwZSkge1xuICB2YXIgcmV0O1xuICBpZiAoIXRoaXMuX2V2ZW50cyB8fCAhdGhpcy5fZXZlbnRzW3R5cGVdKVxuICAgIHJldCA9IFtdO1xuICBlbHNlIGlmIChpc0Z1bmN0aW9uKHRoaXMuX2V2ZW50c1t0eXBlXSkpXG4gICAgcmV0ID0gW3RoaXMuX2V2ZW50c1t0eXBlXV07XG4gIGVsc2VcbiAgICByZXQgPSB0aGlzLl9ldmVudHNbdHlwZV0uc2xpY2UoKTtcbiAgcmV0dXJuIHJldDtcbn07XG5cbkV2ZW50RW1pdHRlci5saXN0ZW5lckNvdW50ID0gZnVuY3Rpb24oZW1pdHRlciwgdHlwZSkge1xuICB2YXIgcmV0O1xuICBpZiAoIWVtaXR0ZXIuX2V2ZW50cyB8fCAhZW1pdHRlci5fZXZlbnRzW3R5cGVdKVxuICAgIHJldCA9IDA7XG4gIGVsc2UgaWYgKGlzRnVuY3Rpb24oZW1pdHRlci5fZXZlbnRzW3R5cGVdKSlcbiAgICByZXQgPSAxO1xuICBlbHNlXG4gICAgcmV0ID0gZW1pdHRlci5fZXZlbnRzW3R5cGVdLmxlbmd0aDtcbiAgcmV0dXJuIHJldDtcbn07XG5cbmZ1bmN0aW9uIGlzRnVuY3Rpb24oYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnZnVuY3Rpb24nO1xufVxuXG5mdW5jdGlvbiBpc051bWJlcihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc09iamVjdChhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdvYmplY3QnICYmIGFyZyAhPT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNVbmRlZmluZWQoYXJnKSB7XG4gIHJldHVybiBhcmcgPT09IHZvaWQgMDtcbn1cbiIsInZhciAkID0gcmVxdWlyZShcImpxdWVyeVwiKTtcclxuXHJcbnZhciBBY3Rpb25UeXBlcyA9IHtcclxuICAgIC8vIENvbm5lY3Rpb25cclxuICAgIENPTk5FQ1RJT05fT1BFTjogXCJjb25uZWN0aW9uX29wZW5cIixcclxuICAgIENPTk5FQ1RJT05fQ0xPU0U6IFwiY29ubmVjdGlvbl9jbG9zZVwiLFxyXG4gICAgQ09OTkVDVElPTl9FUlJPUjogXCJjb25uZWN0aW9uX2Vycm9yXCIsXHJcblxyXG4gICAgLy8gU3RvcmVzXHJcbiAgICBTRVRUSU5HU19TVE9SRTogXCJzZXR0aW5nc1wiLFxyXG4gICAgRVZFTlRfU1RPUkU6IFwiZXZlbnRzXCIsXHJcbiAgICBGTE9XX1NUT1JFOiBcImZsb3dzXCIsXHJcbn07XHJcblxyXG52YXIgU3RvcmVDbWRzID0ge1xyXG4gICAgQUREOiBcImFkZFwiLFxyXG4gICAgVVBEQVRFOiBcInVwZGF0ZVwiLFxyXG4gICAgUkVNT1ZFOiBcInJlbW92ZVwiLFxyXG4gICAgUkVTRVQ6IFwicmVzZXRcIlxyXG59O1xyXG5cclxudmFyIENvbm5lY3Rpb25BY3Rpb25zID0ge1xyXG4gICAgb3BlbjogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIEFwcERpc3BhdGNoZXIuZGlzcGF0Y2hWaWV3QWN0aW9uKHtcclxuICAgICAgICAgICAgdHlwZTogQWN0aW9uVHlwZXMuQ09OTkVDVElPTl9PUEVOXHJcbiAgICAgICAgfSk7XHJcbiAgICB9LFxyXG4gICAgY2xvc2U6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICBBcHBEaXNwYXRjaGVyLmRpc3BhdGNoVmlld0FjdGlvbih7XHJcbiAgICAgICAgICAgIHR5cGU6IEFjdGlvblR5cGVzLkNPTk5FQ1RJT05fQ0xPU0VcclxuICAgICAgICB9KTtcclxuICAgIH0sXHJcbiAgICBlcnJvcjogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIEFwcERpc3BhdGNoZXIuZGlzcGF0Y2hWaWV3QWN0aW9uKHtcclxuICAgICAgICAgICAgdHlwZTogQWN0aW9uVHlwZXMuQ09OTkVDVElPTl9FUlJPUlxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG59O1xyXG5cclxudmFyIFNldHRpbmdzQWN0aW9ucyA9IHtcclxuICAgIHVwZGF0ZTogZnVuY3Rpb24gKHNldHRpbmdzKSB7XHJcblxyXG4gICAgICAgICQuYWpheCh7XHJcbiAgICAgICAgICAgIHR5cGU6IFwiUFVUXCIsXHJcbiAgICAgICAgICAgIHVybDogXCIvc2V0dGluZ3NcIixcclxuICAgICAgICAgICAgZGF0YTogc2V0dGluZ3NcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgLypcclxuICAgICAgICAvL0ZhY2Vib29rIEZsdXg6IFdlIGRvIGFuIG9wdGltaXN0aWMgdXBkYXRlIG9uIHRoZSBjbGllbnQgYWxyZWFkeS5cclxuICAgICAgICBBcHBEaXNwYXRjaGVyLmRpc3BhdGNoVmlld0FjdGlvbih7XHJcbiAgICAgICAgICAgIHR5cGU6IEFjdGlvblR5cGVzLlNFVFRJTkdTX1NUT1JFLFxyXG4gICAgICAgICAgICBjbWQ6IFN0b3JlQ21kcy5VUERBVEUsXHJcbiAgICAgICAgICAgIGRhdGE6IHNldHRpbmdzXHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgKi9cclxuICAgIH1cclxufTtcclxuXHJcbnZhciBFdmVudExvZ0FjdGlvbnNfZXZlbnRfaWQgPSAwO1xyXG52YXIgRXZlbnRMb2dBY3Rpb25zID0ge1xyXG4gICAgYWRkX2V2ZW50OiBmdW5jdGlvbiAobWVzc2FnZSkge1xyXG4gICAgICAgIEFwcERpc3BhdGNoZXIuZGlzcGF0Y2hWaWV3QWN0aW9uKHtcclxuICAgICAgICAgICAgdHlwZTogQWN0aW9uVHlwZXMuRVZFTlRfU1RPUkUsXHJcbiAgICAgICAgICAgIGNtZDogU3RvcmVDbWRzLkFERCxcclxuICAgICAgICAgICAgZGF0YToge1xyXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogbWVzc2FnZSxcclxuICAgICAgICAgICAgICAgIGxldmVsOiBcIndlYlwiLFxyXG4gICAgICAgICAgICAgICAgaWQ6IFwidmlld0FjdGlvbi1cIiArIEV2ZW50TG9nQWN0aW9uc19ldmVudF9pZCsrXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgIH1cclxufTtcclxuXHJcbnZhciBGbG93QWN0aW9ucyA9IHtcclxuICAgIGFjY2VwdDogZnVuY3Rpb24gKGZsb3cpIHtcclxuICAgICAgICAkLnBvc3QoXCIvZmxvd3MvXCIgKyBmbG93LmlkICsgXCIvYWNjZXB0XCIpO1xyXG4gICAgfSxcclxuICAgIGFjY2VwdF9hbGw6IGZ1bmN0aW9uKCl7XHJcbiAgICAgICAgJC5wb3N0KFwiL2Zsb3dzL2FjY2VwdFwiKTtcclxuICAgIH0sXHJcbiAgICBcImRlbGV0ZVwiOiBmdW5jdGlvbihmbG93KXtcclxuICAgICAgICAkLmFqYXgoe1xyXG4gICAgICAgICAgICB0eXBlOlwiREVMRVRFXCIsXHJcbiAgICAgICAgICAgIHVybDogXCIvZmxvd3MvXCIgKyBmbG93LmlkXHJcbiAgICAgICAgfSk7XHJcbiAgICB9LFxyXG4gICAgZHVwbGljYXRlOiBmdW5jdGlvbihmbG93KXtcclxuICAgICAgICAkLnBvc3QoXCIvZmxvd3MvXCIgKyBmbG93LmlkICsgXCIvZHVwbGljYXRlXCIpO1xyXG4gICAgfSxcclxuICAgIHJlcGxheTogZnVuY3Rpb24oZmxvdyl7XHJcbiAgICAgICAgJC5wb3N0KFwiL2Zsb3dzL1wiICsgZmxvdy5pZCArIFwiL3JlcGxheVwiKTtcclxuICAgIH0sXHJcbiAgICByZXZlcnQ6IGZ1bmN0aW9uKGZsb3cpe1xyXG4gICAgICAgICQucG9zdChcIi9mbG93cy9cIiArIGZsb3cuaWQgKyBcIi9yZXZlcnRcIik7XHJcbiAgICB9LFxyXG4gICAgdXBkYXRlOiBmdW5jdGlvbiAoZmxvdykge1xyXG4gICAgICAgIEFwcERpc3BhdGNoZXIuZGlzcGF0Y2hWaWV3QWN0aW9uKHtcclxuICAgICAgICAgICAgdHlwZTogQWN0aW9uVHlwZXMuRkxPV19TVE9SRSxcclxuICAgICAgICAgICAgY21kOiBTdG9yZUNtZHMuVVBEQVRFLFxyXG4gICAgICAgICAgICBkYXRhOiBmbG93XHJcbiAgICAgICAgfSk7XHJcbiAgICB9LFxyXG4gICAgY2xlYXI6IGZ1bmN0aW9uKCl7XHJcbiAgICAgICAgJC5wb3N0KFwiL2NsZWFyXCIpO1xyXG4gICAgfVxyXG59O1xyXG5cclxuUXVlcnkgPSB7XHJcbiAgICBGSUxURVI6IFwiZlwiLFxyXG4gICAgSElHSExJR0hUOiBcImhcIixcclxuICAgIFNIT1dfRVZFTlRMT0c6IFwiZVwiXHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IHtcclxuICAgIEFjdGlvblR5cGVzOiBBY3Rpb25UeXBlcyxcclxuICAgIENvbm5lY3Rpb25BY3Rpb25zOiBDb25uZWN0aW9uQWN0aW9ucyxcclxuICAgIEZsb3dBY3Rpb25zOiBGbG93QWN0aW9ucyxcclxuICAgIFN0b3JlQ21kczogU3RvcmVDbWRzXHJcbn07IiwiXHJcbnZhciBSZWFjdCA9IHJlcXVpcmUoXCJyZWFjdFwiKTtcclxudmFyIFJlYWN0Um91dGVyID0gcmVxdWlyZShcInJlYWN0LXJvdXRlclwiKTtcclxudmFyICQgPSByZXF1aXJlKFwianF1ZXJ5XCIpO1xyXG5cclxudmFyIENvbm5lY3Rpb24gPSByZXF1aXJlKFwiLi9jb25uZWN0aW9uXCIpO1xyXG52YXIgcHJveHlhcHAgPSByZXF1aXJlKFwiLi9jb21wb25lbnRzL3Byb3h5YXBwLmpzXCIpO1xyXG5cclxuJChmdW5jdGlvbiAoKSB7XHJcbiAgICB3aW5kb3cud3MgPSBuZXcgQ29ubmVjdGlvbihcIi91cGRhdGVzXCIpO1xyXG5cclxuICAgIFJlYWN0Um91dGVyLnJ1bihwcm94eWFwcC5yb3V0ZXMsIGZ1bmN0aW9uIChIYW5kbGVyKSB7XHJcbiAgICAgICAgUmVhY3QucmVuZGVyKDxIYW5kbGVyLz4sIGRvY3VtZW50LmJvZHkpO1xyXG4gICAgfSk7XHJcbn0pO1xyXG5cclxuIiwidmFyIFJlYWN0ID0gcmVxdWlyZShcInJlYWN0XCIpO1xyXG52YXIgUmVhY3RSb3V0ZXIgPSByZXF1aXJlKFwicmVhY3Qtcm91dGVyXCIpO1xyXG52YXIgXyA9IHJlcXVpcmUoXCJsb2Rhc2hcIik7XHJcblxyXG4vLyBodHRwOi8vYmxvZy52amV1eC5jb20vMjAxMy9qYXZhc2NyaXB0L3Njcm9sbC1wb3NpdGlvbi13aXRoLXJlYWN0Lmh0bWwgKGFsc28gY29udGFpbnMgaW52ZXJzZSBleGFtcGxlKVxyXG52YXIgQXV0b1Njcm9sbE1peGluID0ge1xyXG4gICAgY29tcG9uZW50V2lsbFVwZGF0ZTogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHZhciBub2RlID0gdGhpcy5nZXRET01Ob2RlKCk7XHJcbiAgICAgICAgdGhpcy5fc2hvdWxkU2Nyb2xsQm90dG9tID0gKFxyXG4gICAgICAgICAgICBub2RlLnNjcm9sbFRvcCAhPT0gMCAmJlxyXG4gICAgICAgICAgICBub2RlLnNjcm9sbFRvcCArIG5vZGUuY2xpZW50SGVpZ2h0ID09PSBub2RlLnNjcm9sbEhlaWdodFxyXG4gICAgICAgICk7XHJcbiAgICB9LFxyXG4gICAgY29tcG9uZW50RGlkVXBkYXRlOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuX3Nob3VsZFNjcm9sbEJvdHRvbSkge1xyXG4gICAgICAgICAgICB2YXIgbm9kZSA9IHRoaXMuZ2V0RE9NTm9kZSgpO1xyXG4gICAgICAgICAgICBub2RlLnNjcm9sbFRvcCA9IG5vZGUuc2Nyb2xsSGVpZ2h0O1xyXG4gICAgICAgIH1cclxuICAgIH0sXHJcbn07XHJcblxyXG5cclxudmFyIFN0aWNreUhlYWRNaXhpbiA9IHtcclxuICAgIGFkanVzdEhlYWQ6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAvLyBBYnVzaW5nIENTUyB0cmFuc2Zvcm1zIHRvIHNldCB0aGUgZWxlbWVudFxyXG4gICAgICAgIC8vIHJlZmVyZW5jZWQgYXMgaGVhZCBpbnRvIHNvbWUga2luZCBvZiBwb3NpdGlvbjpzdGlja3kuXHJcbiAgICAgICAgdmFyIGhlYWQgPSB0aGlzLnJlZnMuaGVhZC5nZXRET01Ob2RlKCk7XHJcbiAgICAgICAgaGVhZC5zdHlsZS50cmFuc2Zvcm0gPSBcInRyYW5zbGF0ZSgwLFwiICsgdGhpcy5nZXRET01Ob2RlKCkuc2Nyb2xsVG9wICsgXCJweClcIjtcclxuICAgIH1cclxufTtcclxuXHJcblxyXG52YXIgTmF2aWdhdGlvbiA9IF8uZXh0ZW5kKHt9LCBSZWFjdFJvdXRlci5OYXZpZ2F0aW9uLCB7XHJcbiAgICBzZXRRdWVyeTogZnVuY3Rpb24gKGRpY3QpIHtcclxuICAgICAgICB2YXIgcSA9IHRoaXMuY29udGV4dC5nZXRDdXJyZW50UXVlcnkoKTtcclxuICAgICAgICBmb3IodmFyIGkgaW4gZGljdCl7XHJcbiAgICAgICAgICAgIGlmKGRpY3QuaGFzT3duUHJvcGVydHkoaSkpe1xyXG4gICAgICAgICAgICAgICAgcVtpXSA9IGRpY3RbaV0gfHwgdW5kZWZpbmVkOyAvL2ZhbHNleSB2YWx1ZXMgc2hhbGwgYmUgcmVtb3ZlZC5cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBxLl8gPSBcIl9cIjsgLy8gd29ya2Fyb3VuZCBmb3IgaHR0cHM6Ly9naXRodWIuY29tL3JhY2t0L3JlYWN0LXJvdXRlci9wdWxsLzU5OVxyXG4gICAgICAgIHRoaXMucmVwbGFjZVdpdGgodGhpcy5jb250ZXh0LmdldEN1cnJlbnRQYXRoKCksIHRoaXMuY29udGV4dC5nZXRDdXJyZW50UGFyYW1zKCksIHEpO1xyXG4gICAgfSxcclxuICAgIHJlcGxhY2VXaXRoOiBmdW5jdGlvbihyb3V0ZU5hbWVPclBhdGgsIHBhcmFtcywgcXVlcnkpIHtcclxuICAgICAgICBpZihyb3V0ZU5hbWVPclBhdGggPT09IHVuZGVmaW5lZCl7XHJcbiAgICAgICAgICAgIHJvdXRlTmFtZU9yUGF0aCA9IHRoaXMuY29udGV4dC5nZXRDdXJyZW50UGF0aCgpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZihwYXJhbXMgPT09IHVuZGVmaW5lZCl7XHJcbiAgICAgICAgICAgIHBhcmFtcyA9IHRoaXMuY29udGV4dC5nZXRDdXJyZW50UGFyYW1zKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmKHF1ZXJ5ID09PSB1bmRlZmluZWQpe1xyXG4gICAgICAgICAgICBxdWVyeSA9IHRoaXMuY29udGV4dC5nZXRDdXJyZW50UXVlcnkoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgUmVhY3RSb3V0ZXIuTmF2aWdhdGlvbi5yZXBsYWNlV2l0aC5jYWxsKHRoaXMsIHJvdXRlTmFtZU9yUGF0aCwgcGFyYW1zLCBxdWVyeSk7XHJcbiAgICB9XHJcbn0pO1xyXG5fLmV4dGVuZChOYXZpZ2F0aW9uLmNvbnRleHRUeXBlcywgUmVhY3RSb3V0ZXIuU3RhdGUuY29udGV4dFR5cGVzKTtcclxuXHJcbnZhciBTdGF0ZSA9IF8uZXh0ZW5kKHt9LCBSZWFjdFJvdXRlci5TdGF0ZSwge1xyXG4gICAgZ2V0SW5pdGlhbFN0YXRlOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdGhpcy5fcXVlcnkgPSB0aGlzLmNvbnRleHQuZ2V0Q3VycmVudFF1ZXJ5KCk7XHJcbiAgICAgICAgdGhpcy5fcXVlcnlXYXRjaGVzID0gW107XHJcbiAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9LFxyXG4gICAgb25RdWVyeUNoYW5nZTogZnVuY3Rpb24gKGtleSwgY2FsbGJhY2spIHtcclxuICAgICAgICB0aGlzLl9xdWVyeVdhdGNoZXMucHVzaCh7XHJcbiAgICAgICAgICAgIGtleToga2V5LFxyXG4gICAgICAgICAgICBjYWxsYmFjazogY2FsbGJhY2tcclxuICAgICAgICB9KTtcclxuICAgIH0sXHJcbiAgICBjb21wb25lbnRXaWxsUmVjZWl2ZVByb3BzOiBmdW5jdGlvbiAobmV4dFByb3BzLCBuZXh0U3RhdGUpIHtcclxuICAgICAgICB2YXIgcSA9IHRoaXMuY29udGV4dC5nZXRDdXJyZW50UXVlcnkoKTtcclxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX3F1ZXJ5V2F0Y2hlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICB2YXIgd2F0Y2ggPSB0aGlzLl9xdWVyeVdhdGNoZXNbaV07XHJcbiAgICAgICAgICAgIGlmICh0aGlzLl9xdWVyeVt3YXRjaC5rZXldICE9PSBxW3dhdGNoLmtleV0pIHtcclxuICAgICAgICAgICAgICAgIHdhdGNoLmNhbGxiYWNrKHRoaXMuX3F1ZXJ5W3dhdGNoLmtleV0sIHFbd2F0Y2gua2V5XSwgd2F0Y2gua2V5KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLl9xdWVyeSA9IHE7XHJcbiAgICB9XHJcbn0pO1xyXG5cclxudmFyIFNwbGl0dGVyID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xyXG4gICAgZ2V0RGVmYXVsdFByb3BzOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgYXhpczogXCJ4XCJcclxuICAgICAgICB9O1xyXG4gICAgfSxcclxuICAgIGdldEluaXRpYWxTdGF0ZTogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIGFwcGxpZWQ6IGZhbHNlLFxyXG4gICAgICAgICAgICBzdGFydFg6IGZhbHNlLFxyXG4gICAgICAgICAgICBzdGFydFk6IGZhbHNlXHJcbiAgICAgICAgfTtcclxuICAgIH0sXHJcbiAgICBvbk1vdXNlRG93bjogZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICB0aGlzLnNldFN0YXRlKHtcclxuICAgICAgICAgICAgc3RhcnRYOiBlLnBhZ2VYLFxyXG4gICAgICAgICAgICBzdGFydFk6IGUucGFnZVlcclxuICAgICAgICB9KTtcclxuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm1vdXNlbW92ZVwiLCB0aGlzLm9uTW91c2VNb3ZlKTtcclxuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm1vdXNldXBcIiwgdGhpcy5vbk1vdXNlVXApO1xyXG4gICAgICAgIC8vIE9jY2FzaW9uYWxseSwgb25seSBhIGRyYWdFbmQgZXZlbnQgaXMgdHJpZ2dlcmVkLCBidXQgbm8gbW91c2VVcC5cclxuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcImRyYWdlbmRcIiwgdGhpcy5vbkRyYWdFbmQpO1xyXG4gICAgfSxcclxuICAgIG9uRHJhZ0VuZDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHRoaXMuZ2V0RE9NTm9kZSgpLnN0eWxlLnRyYW5zZm9ybSA9IFwiXCI7XHJcbiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJkcmFnZW5kXCIsIHRoaXMub25EcmFnRW5kKTtcclxuICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihcIm1vdXNldXBcIiwgdGhpcy5vbk1vdXNlVXApO1xyXG4gICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKFwibW91c2Vtb3ZlXCIsIHRoaXMub25Nb3VzZU1vdmUpO1xyXG4gICAgfSxcclxuICAgIG9uTW91c2VVcDogZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICB0aGlzLm9uRHJhZ0VuZCgpO1xyXG5cclxuICAgICAgICB2YXIgbm9kZSA9IHRoaXMuZ2V0RE9NTm9kZSgpO1xyXG4gICAgICAgIHZhciBwcmV2ID0gbm9kZS5wcmV2aW91c0VsZW1lbnRTaWJsaW5nO1xyXG4gICAgICAgIHZhciBuZXh0ID0gbm9kZS5uZXh0RWxlbWVudFNpYmxpbmc7XHJcblxyXG4gICAgICAgIHZhciBkWCA9IGUucGFnZVggLSB0aGlzLnN0YXRlLnN0YXJ0WDtcclxuICAgICAgICB2YXIgZFkgPSBlLnBhZ2VZIC0gdGhpcy5zdGF0ZS5zdGFydFk7XHJcbiAgICAgICAgdmFyIGZsZXhCYXNpcztcclxuICAgICAgICBpZiAodGhpcy5wcm9wcy5heGlzID09PSBcInhcIikge1xyXG4gICAgICAgICAgICBmbGV4QmFzaXMgPSBwcmV2Lm9mZnNldFdpZHRoICsgZFg7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgZmxleEJhc2lzID0gcHJldi5vZmZzZXRIZWlnaHQgKyBkWTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHByZXYuc3R5bGUuZmxleCA9IFwiMCAwIFwiICsgTWF0aC5tYXgoMCwgZmxleEJhc2lzKSArIFwicHhcIjtcclxuICAgICAgICBuZXh0LnN0eWxlLmZsZXggPSBcIjEgMSBhdXRvXCI7XHJcblxyXG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xyXG4gICAgICAgICAgICBhcHBsaWVkOiB0cnVlXHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgdGhpcy5vblJlc2l6ZSgpO1xyXG4gICAgfSxcclxuICAgIG9uTW91c2VNb3ZlOiBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgIHZhciBkWCA9IDAsIGRZID0gMDtcclxuICAgICAgICBpZiAodGhpcy5wcm9wcy5heGlzID09PSBcInhcIikge1xyXG4gICAgICAgICAgICBkWCA9IGUucGFnZVggLSB0aGlzLnN0YXRlLnN0YXJ0WDtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBkWSA9IGUucGFnZVkgLSB0aGlzLnN0YXRlLnN0YXJ0WTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5nZXRET01Ob2RlKCkuc3R5bGUudHJhbnNmb3JtID0gXCJ0cmFuc2xhdGUoXCIgKyBkWCArIFwicHgsXCIgKyBkWSArIFwicHgpXCI7XHJcbiAgICB9LFxyXG4gICAgb25SZXNpemU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAvLyBUcmlnZ2VyIGEgZ2xvYmFsIHJlc2l6ZSBldmVudC4gVGhpcyBub3RpZmllcyBjb21wb25lbnRzIHRoYXQgZW1wbG95IHZpcnR1YWwgc2Nyb2xsaW5nXHJcbiAgICAgICAgLy8gdGhhdCB0aGVpciB2aWV3cG9ydCBtYXkgaGF2ZSBjaGFuZ2VkLlxyXG4gICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgd2luZG93LmRpc3BhdGNoRXZlbnQobmV3IEN1c3RvbUV2ZW50KFwicmVzaXplXCIpKTtcclxuICAgICAgICB9LCAxKTtcclxuICAgIH0sXHJcbiAgICByZXNldDogZnVuY3Rpb24gKHdpbGxVbm1vdW50KSB7XHJcbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlLmFwcGxpZWQpIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgbm9kZSA9IHRoaXMuZ2V0RE9NTm9kZSgpO1xyXG4gICAgICAgIHZhciBwcmV2ID0gbm9kZS5wcmV2aW91c0VsZW1lbnRTaWJsaW5nO1xyXG4gICAgICAgIHZhciBuZXh0ID0gbm9kZS5uZXh0RWxlbWVudFNpYmxpbmc7XHJcblxyXG4gICAgICAgIHByZXYuc3R5bGUuZmxleCA9IFwiXCI7XHJcbiAgICAgICAgbmV4dC5zdHlsZS5mbGV4ID0gXCJcIjtcclxuXHJcbiAgICAgICAgaWYgKCF3aWxsVW5tb3VudCkge1xyXG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcclxuICAgICAgICAgICAgICAgIGFwcGxpZWQ6IGZhbHNlXHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLm9uUmVzaXplKCk7XHJcbiAgICB9LFxyXG4gICAgY29tcG9uZW50V2lsbFVubW91bnQ6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB0aGlzLnJlc2V0KHRydWUpO1xyXG4gICAgfSxcclxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHZhciBjbGFzc05hbWUgPSBcInNwbGl0dGVyXCI7XHJcbiAgICAgICAgaWYgKHRoaXMucHJvcHMuYXhpcyA9PT0gXCJ4XCIpIHtcclxuICAgICAgICAgICAgY2xhc3NOYW1lICs9IFwiIHNwbGl0dGVyLXhcIjtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBjbGFzc05hbWUgKz0gXCIgc3BsaXR0ZXIteVwiO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gKFxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT17Y2xhc3NOYW1lfT5cclxuICAgICAgICAgICAgICAgIDxkaXYgb25Nb3VzZURvd249e3RoaXMub25Nb3VzZURvd259IGRyYWdnYWJsZT1cInRydWVcIj48L2Rpdj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgKTtcclxuICAgIH1cclxufSk7XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IHtcclxuICAgIFN0YXRlOiBTdGF0ZSxcclxuICAgIE5hdmlnYXRpb246IE5hdmlnYXRpb24sXHJcbiAgICBTdGlja3lIZWFkTWl4aW46IFN0aWNreUhlYWRNaXhpbixcclxuICAgIEF1dG9TY3JvbGxNaXhpbjogQXV0b1Njcm9sbE1peGluLFxyXG4gICAgU3BsaXR0ZXI6IFNwbGl0dGVyXHJcbn0iLCJ2YXIgUmVhY3QgPSByZXF1aXJlKFwicmVhY3RcIik7XHJcbnZhciBjb21tb24gPSByZXF1aXJlKFwiLi9jb21tb24uanNcIik7XHJcbnZhciBWaXJ0dWFsU2Nyb2xsTWl4aW4gPSByZXF1aXJlKFwiLi92aXJ0dWFsc2Nyb2xsLmpzXCIpO1xyXG52YXIgdmlld3MgPSByZXF1aXJlKFwiLi4vc3RvcmUvdmlldy5qc1wiKTtcclxuXHJcbnZhciBMb2dNZXNzYWdlID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xyXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdmFyIGVudHJ5ID0gdGhpcy5wcm9wcy5lbnRyeTtcclxuICAgICAgICB2YXIgaW5kaWNhdG9yO1xyXG4gICAgICAgIHN3aXRjaCAoZW50cnkubGV2ZWwpIHtcclxuICAgICAgICAgICAgY2FzZSBcIndlYlwiOlxyXG4gICAgICAgICAgICAgICAgaW5kaWNhdG9yID0gPGkgY2xhc3NOYW1lPVwiZmEgZmEtZncgZmEtaHRtbDVcIj48L2k+O1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIGNhc2UgXCJkZWJ1Z1wiOlxyXG4gICAgICAgICAgICAgICAgaW5kaWNhdG9yID0gPGkgY2xhc3NOYW1lPVwiZmEgZmEtZncgZmEtYnVnXCI+PC9pPjtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgaW5kaWNhdG9yID0gPGkgY2xhc3NOYW1lPVwiZmEgZmEtZncgZmEtaW5mb1wiPjwvaT47XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiAoXHJcbiAgICAgICAgICAgIDxkaXY+XHJcbiAgICAgICAgICAgICAgICB7IGluZGljYXRvciB9IHtlbnRyeS5tZXNzYWdlfVxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICApO1xyXG4gICAgfSxcclxuICAgIHNob3VsZENvbXBvbmVudFVwZGF0ZTogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHJldHVybiBmYWxzZTsgLy8gbG9nIGVudHJpZXMgYXJlIGltbXV0YWJsZS5cclxuICAgIH1cclxufSk7XHJcblxyXG52YXIgRXZlbnRMb2dDb250ZW50cyA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcclxuICAgIG1peGluczogW2NvbW1vbi5BdXRvU2Nyb2xsTWl4aW4sIFZpcnR1YWxTY3JvbGxNaXhpbl0sXHJcbiAgICBnZXRJbml0aWFsU3RhdGU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICBsb2c6IFtdXHJcbiAgICAgICAgfTtcclxuICAgIH0sXHJcbiAgICBjb21wb25lbnRXaWxsTW91bnQ6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB0aGlzLm9wZW5WaWV3KHRoaXMucHJvcHMuZXZlbnRTdG9yZSk7XHJcbiAgICB9LFxyXG4gICAgY29tcG9uZW50V2lsbFVubW91bnQ6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB0aGlzLmNsb3NlVmlldygpO1xyXG4gICAgfSxcclxuICAgIG9wZW5WaWV3OiBmdW5jdGlvbiAoc3RvcmUpIHtcclxuICAgICAgICB2YXIgdmlldyA9IG5ldyB2aWV3cy5TdG9yZVZpZXcoc3RvcmUsIGZ1bmN0aW9uIChlbnRyeSkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wcm9wcy5maWx0ZXJbZW50cnkubGV2ZWxdO1xyXG4gICAgICAgIH0uYmluZCh0aGlzKSk7XHJcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XHJcbiAgICAgICAgICAgIHZpZXc6IHZpZXdcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgdmlldy5hZGRMaXN0ZW5lcihcImFkZCByZWNhbGN1bGF0ZVwiLCB0aGlzLm9uRXZlbnRMb2dDaGFuZ2UpO1xyXG4gICAgfSxcclxuICAgIGNsb3NlVmlldzogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHRoaXMuc3RhdGUudmlldy5jbG9zZSgpO1xyXG4gICAgfSxcclxuICAgIG9uRXZlbnRMb2dDaGFuZ2U6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB0aGlzLnNldFN0YXRlKHtcclxuICAgICAgICAgICAgbG9nOiB0aGlzLnN0YXRlLnZpZXcubGlzdFxyXG4gICAgICAgIH0pO1xyXG4gICAgfSxcclxuICAgIGNvbXBvbmVudFdpbGxSZWNlaXZlUHJvcHM6IGZ1bmN0aW9uIChuZXh0UHJvcHMpIHtcclxuICAgICAgICBpZiAobmV4dFByb3BzLmZpbHRlciAhPT0gdGhpcy5wcm9wcy5maWx0ZXIpIHtcclxuICAgICAgICAgICAgdGhpcy5wcm9wcy5maWx0ZXIgPSBuZXh0UHJvcHMuZmlsdGVyOyAvLyBEaXJ0eTogTWFrZSBzdXJlIHRoYXQgdmlldyBmaWx0ZXIgc2VlcyB0aGUgdXBkYXRlLlxyXG4gICAgICAgICAgICB0aGlzLnN0YXRlLnZpZXcucmVjYWxjdWxhdGUoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKG5leHRQcm9wcy5ldmVudFN0b3JlICE9PSB0aGlzLnByb3BzLmV2ZW50U3RvcmUpIHtcclxuICAgICAgICAgICAgdGhpcy5jbG9zZVZpZXcoKTtcclxuICAgICAgICAgICAgdGhpcy5vcGVuVmlldyhuZXh0UHJvcHMuZXZlbnRTdG9yZSk7XHJcbiAgICAgICAgfVxyXG4gICAgfSxcclxuICAgIGdldERlZmF1bHRQcm9wczogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIHJvd0hlaWdodDogNDUsXHJcbiAgICAgICAgICAgIHJvd0hlaWdodE1pbjogMTUsXHJcbiAgICAgICAgICAgIHBsYWNlaG9sZGVyVGFnTmFtZTogXCJkaXZcIlxyXG4gICAgICAgIH07XHJcbiAgICB9LFxyXG4gICAgcmVuZGVyUm93OiBmdW5jdGlvbiAoZWxlbSkge1xyXG4gICAgICAgIHJldHVybiA8TG9nTWVzc2FnZSBrZXk9e2VsZW0uaWR9IGVudHJ5PXtlbGVtfS8+O1xyXG4gICAgfSxcclxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHZhciByb3dzID0gdGhpcy5yZW5kZXJSb3dzKHRoaXMuc3RhdGUubG9nKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIDxwcmUgb25TY3JvbGw9e3RoaXMub25TY3JvbGx9PlxyXG4gICAgICAgICAgICB7IHRoaXMuZ2V0UGxhY2Vob2xkZXJUb3AodGhpcy5zdGF0ZS5sb2cubGVuZ3RoKSB9XHJcbiAgICAgICAgICAgIHtyb3dzfVxyXG4gICAgICAgICAgICB7IHRoaXMuZ2V0UGxhY2Vob2xkZXJCb3R0b20odGhpcy5zdGF0ZS5sb2cubGVuZ3RoKSB9XHJcbiAgICAgICAgPC9wcmU+O1xyXG4gICAgfVxyXG59KTtcclxuXHJcbnZhciBUb2dnbGVGaWx0ZXIgPSBSZWFjdC5jcmVhdGVDbGFzcyh7XHJcbiAgICB0b2dnbGU6IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgIHJldHVybiB0aGlzLnByb3BzLnRvZ2dsZUxldmVsKHRoaXMucHJvcHMubmFtZSk7XHJcbiAgICB9LFxyXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdmFyIGNsYXNzTmFtZSA9IFwibGFiZWwgXCI7XHJcbiAgICAgICAgaWYgKHRoaXMucHJvcHMuYWN0aXZlKSB7XHJcbiAgICAgICAgICAgIGNsYXNzTmFtZSArPSBcImxhYmVsLXByaW1hcnlcIjtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBjbGFzc05hbWUgKz0gXCJsYWJlbC1kZWZhdWx0XCI7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiAoXHJcbiAgICAgICAgICAgIDxhXHJcbiAgICAgICAgICAgICAgICBocmVmPVwiI1wiXHJcbiAgICAgICAgICAgICAgICBjbGFzc05hbWU9e2NsYXNzTmFtZX1cclxuICAgICAgICAgICAgICAgIG9uQ2xpY2s9e3RoaXMudG9nZ2xlfT5cclxuICAgICAgICAgICAgICAgIHt0aGlzLnByb3BzLm5hbWV9XHJcbiAgICAgICAgICAgIDwvYT5cclxuICAgICAgICApO1xyXG4gICAgfVxyXG59KTtcclxuXHJcbnZhciBFdmVudExvZyA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcclxuICAgIGdldEluaXRpYWxTdGF0ZTogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIGZpbHRlcjoge1xyXG4gICAgICAgICAgICAgICAgXCJkZWJ1Z1wiOiBmYWxzZSxcclxuICAgICAgICAgICAgICAgIFwiaW5mb1wiOiB0cnVlLFxyXG4gICAgICAgICAgICAgICAgXCJ3ZWJcIjogdHJ1ZVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfTtcclxuICAgIH0sXHJcbiAgICBjbG9zZTogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHZhciBkID0ge307XHJcbiAgICAgICAgZFtRdWVyeS5TSE9XX0VWRU5UTE9HXSA9IHVuZGVmaW5lZDtcclxuICAgICAgICB0aGlzLnNldFF1ZXJ5KGQpO1xyXG4gICAgfSxcclxuICAgIHRvZ2dsZUxldmVsOiBmdW5jdGlvbiAobGV2ZWwpIHtcclxuICAgICAgICB2YXIgZmlsdGVyID0gXy5leHRlbmQoe30sIHRoaXMuc3RhdGUuZmlsdGVyKTtcclxuICAgICAgICBmaWx0ZXJbbGV2ZWxdID0gIWZpbHRlcltsZXZlbF07XHJcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7ZmlsdGVyOiBmaWx0ZXJ9KTtcclxuICAgIH0sXHJcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4gKFxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImV2ZW50bG9nXCI+XHJcbiAgICAgICAgICAgICAgICA8ZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIEV2ZW50bG9nXHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJwdWxsLXJpZ2h0XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxUb2dnbGVGaWx0ZXIgbmFtZT1cImRlYnVnXCIgYWN0aXZlPXt0aGlzLnN0YXRlLmZpbHRlci5kZWJ1Z30gdG9nZ2xlTGV2ZWw9e3RoaXMudG9nZ2xlTGV2ZWx9Lz5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPFRvZ2dsZUZpbHRlciBuYW1lPVwiaW5mb1wiIGFjdGl2ZT17dGhpcy5zdGF0ZS5maWx0ZXIuaW5mb30gdG9nZ2xlTGV2ZWw9e3RoaXMudG9nZ2xlTGV2ZWx9Lz5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPFRvZ2dsZUZpbHRlciBuYW1lPVwid2ViXCIgYWN0aXZlPXt0aGlzLnN0YXRlLmZpbHRlci53ZWJ9IHRvZ2dsZUxldmVsPXt0aGlzLnRvZ2dsZUxldmVsfS8+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxpIG9uQ2xpY2s9e3RoaXMuY2xvc2V9IGNsYXNzTmFtZT1cImZhIGZhLWNsb3NlXCI+PC9pPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPEV2ZW50TG9nQ29udGVudHMgZmlsdGVyPXt0aGlzLnN0YXRlLmZpbHRlcn0gZXZlbnRTdG9yZT17dGhpcy5wcm9wcy5ldmVudFN0b3JlfS8+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcbn0pO1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBFdmVudExvZzsiLCJ2YXIgUmVhY3QgPSByZXF1aXJlKFwicmVhY3RcIik7XHJcbnZhciBfID0gcmVxdWlyZShcImxvZGFzaFwiKTtcclxuXHJcbnZhciBjb21tb24gPSByZXF1aXJlKFwiLi9jb21tb24uanNcIik7XHJcbnZhciBhY3Rpb25zID0gcmVxdWlyZShcIi4uL2FjdGlvbnMuanNcIik7XHJcbnZhciBmbG93dXRpbHMgPSByZXF1aXJlKFwiLi4vZmxvdy91dGlscy5qc1wiKTtcclxudmFyIHRvcHV0aWxzID0gcmVxdWlyZShcIi4uL3V0aWxzLmpzXCIpO1xyXG5cclxudmFyIE5hdkFjdGlvbiA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcclxuICAgIG9uQ2xpY2s6IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgIHRoaXMucHJvcHMub25DbGljaygpO1xyXG4gICAgfSxcclxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHJldHVybiAoXHJcbiAgICAgICAgICAgIDxhIHRpdGxlPXt0aGlzLnByb3BzLnRpdGxlfVxyXG4gICAgICAgICAgICAgICAgaHJlZj1cIiNcIlxyXG4gICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibmF2LWFjdGlvblwiXHJcbiAgICAgICAgICAgICAgICBvbkNsaWNrPXt0aGlzLm9uQ2xpY2t9PlxyXG4gICAgICAgICAgICAgICAgPGkgY2xhc3NOYW1lPXtcImZhIGZhLWZ3IFwiICsgdGhpcy5wcm9wcy5pY29ufT48L2k+XHJcbiAgICAgICAgICAgIDwvYT5cclxuICAgICAgICApO1xyXG4gICAgfVxyXG59KTtcclxuXHJcbnZhciBGbG93RGV0YWlsTmF2ID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xyXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdmFyIGZsb3cgPSB0aGlzLnByb3BzLmZsb3c7XHJcblxyXG4gICAgICAgIHZhciB0YWJzID0gdGhpcy5wcm9wcy50YWJzLm1hcChmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICB2YXIgc3RyID0gZS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIGUuc2xpY2UoMSk7XHJcbiAgICAgICAgICAgIHZhciBjbGFzc05hbWUgPSB0aGlzLnByb3BzLmFjdGl2ZSA9PT0gZSA/IFwiYWN0aXZlXCIgOiBcIlwiO1xyXG4gICAgICAgICAgICB2YXIgb25DbGljayA9IGZ1bmN0aW9uIChldmVudCkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wcy5zZWxlY3RUYWIoZSk7XHJcbiAgICAgICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgICAgICB9LmJpbmQodGhpcyk7XHJcbiAgICAgICAgICAgIHJldHVybiA8YSBrZXk9e2V9XHJcbiAgICAgICAgICAgICAgICBocmVmPVwiI1wiXHJcbiAgICAgICAgICAgICAgICBjbGFzc05hbWU9e2NsYXNzTmFtZX1cclxuICAgICAgICAgICAgICAgIG9uQ2xpY2s9e29uQ2xpY2t9PntzdHJ9PC9hPjtcclxuICAgICAgICB9LmJpbmQodGhpcykpO1xyXG5cclxuICAgICAgICB2YXIgYWNjZXB0QnV0dG9uID0gbnVsbDtcclxuICAgICAgICBpZihmbG93LmludGVyY2VwdGVkKXtcclxuICAgICAgICAgICAgYWNjZXB0QnV0dG9uID0gPE5hdkFjdGlvbiB0aXRsZT1cIlthXWNjZXB0IGludGVyY2VwdGVkIGZsb3dcIiBpY29uPVwiZmEtcGxheVwiIG9uQ2xpY2s9e2FjdGlvbnMuRmxvd0FjdGlvbnMuYWNjZXB0LmJpbmQobnVsbCwgZmxvdyl9IC8+O1xyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgcmV2ZXJ0QnV0dG9uID0gbnVsbDtcclxuICAgICAgICBpZihmbG93Lm1vZGlmaWVkKXtcclxuICAgICAgICAgICAgcmV2ZXJ0QnV0dG9uID0gPE5hdkFjdGlvbiB0aXRsZT1cInJldmVydCBjaGFuZ2VzIHRvIGZsb3cgW1ZdXCIgaWNvbj1cImZhLWhpc3RvcnlcIiBvbkNsaWNrPXthY3Rpb25zLkZsb3dBY3Rpb25zLnJldmVydC5iaW5kKG51bGwsIGZsb3cpfSAvPjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiAoXHJcbiAgICAgICAgICAgIDxuYXYgcmVmPVwiaGVhZFwiIGNsYXNzTmFtZT1cIm5hdi10YWJzIG5hdi10YWJzLXNtXCI+XHJcbiAgICAgICAgICAgICAgICB7dGFic31cclxuICAgICAgICAgICAgICAgIDxOYXZBY3Rpb24gdGl0bGU9XCJbZF1lbGV0ZSBmbG93XCIgaWNvbj1cImZhLXRyYXNoXCIgb25DbGljaz17YWN0aW9ucy5GbG93QWN0aW9ucy5kZWxldGUuYmluZChudWxsLCBmbG93KX0gLz5cclxuICAgICAgICAgICAgICAgIDxOYXZBY3Rpb24gdGl0bGU9XCJbRF11cGxpY2F0ZSBmbG93XCIgaWNvbj1cImZhLWNvcHlcIiBvbkNsaWNrPXthY3Rpb25zLkZsb3dBY3Rpb25zLmR1cGxpY2F0ZS5iaW5kKG51bGwsIGZsb3cpfSAvPlxyXG4gICAgICAgICAgICAgICAgPE5hdkFjdGlvbiBkaXNhYmxlZCB0aXRsZT1cIltyXWVwbGF5IGZsb3dcIiBpY29uPVwiZmEtcmVwZWF0XCIgb25DbGljaz17YWN0aW9ucy5GbG93QWN0aW9ucy5yZXBsYXkuYmluZChudWxsLCBmbG93KX0gLz5cclxuICAgICAgICAgICAgICAgIHthY2NlcHRCdXR0b259XHJcbiAgICAgICAgICAgICAgICB7cmV2ZXJ0QnV0dG9ufVxyXG4gICAgICAgICAgICA8L25hdj5cclxuICAgICAgICApO1xyXG4gICAgfVxyXG59KTtcclxuXHJcbnZhciBIZWFkZXJzID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xyXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdmFyIHJvd3MgPSB0aGlzLnByb3BzLm1lc3NhZ2UuaGVhZGVycy5tYXAoZnVuY3Rpb24gKGhlYWRlciwgaSkge1xyXG4gICAgICAgICAgICByZXR1cm4gKFxyXG4gICAgICAgICAgICAgICAgPHRyIGtleT17aX0+XHJcbiAgICAgICAgICAgICAgICAgICAgPHRkIGNsYXNzTmFtZT1cImhlYWRlci1uYW1lXCI+e2hlYWRlclswXSArIFwiOlwifTwvdGQ+XHJcbiAgICAgICAgICAgICAgICAgICAgPHRkIGNsYXNzTmFtZT1cImhlYWRlci12YWx1ZVwiPntoZWFkZXJbMV19PC90ZD5cclxuICAgICAgICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgPHRhYmxlIGNsYXNzTmFtZT1cImhlYWRlci10YWJsZVwiPlxyXG4gICAgICAgICAgICAgICAgPHRib2R5PlxyXG4gICAgICAgICAgICAgICAgICAgIHtyb3dzfVxyXG4gICAgICAgICAgICAgICAgPC90Ym9keT5cclxuICAgICAgICAgICAgPC90YWJsZT5cclxuICAgICAgICApO1xyXG4gICAgfVxyXG59KTtcclxuXHJcbnZhciBGbG93RGV0YWlsUmVxdWVzdCA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcclxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHZhciBmbG93ID0gdGhpcy5wcm9wcy5mbG93O1xyXG4gICAgICAgIHZhciBmaXJzdF9saW5lID0gW1xyXG4gICAgICAgICAgICBmbG93LnJlcXVlc3QubWV0aG9kLFxyXG4gICAgICAgICAgICBmbG93dXRpbHMuUmVxdWVzdFV0aWxzLnByZXR0eV91cmwoZmxvdy5yZXF1ZXN0KSxcclxuICAgICAgICAgICAgXCJIVFRQL1wiICsgZmxvdy5yZXF1ZXN0Lmh0dHB2ZXJzaW9uLmpvaW4oXCIuXCIpXHJcbiAgICAgICAgXS5qb2luKFwiIFwiKTtcclxuICAgICAgICB2YXIgY29udGVudCA9IG51bGw7XHJcbiAgICAgICAgaWYgKGZsb3cucmVxdWVzdC5jb250ZW50TGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICBjb250ZW50ID0gXCJSZXF1ZXN0IENvbnRlbnQgU2l6ZTogXCIgKyB0b3B1dGlscy5mb3JtYXRTaXplKGZsb3cucmVxdWVzdC5jb250ZW50TGVuZ3RoKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBjb250ZW50ID0gPGRpdiBjbGFzc05hbWU9XCJhbGVydCBhbGVydC1pbmZvXCI+Tm8gQ29udGVudDwvZGl2PjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vVE9ETzogU3R5bGluZ1xyXG5cclxuICAgICAgICByZXR1cm4gKFxyXG4gICAgICAgICAgICA8c2VjdGlvbj5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiZmlyc3QtbGluZVwiPnsgZmlyc3RfbGluZSB9PC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8SGVhZGVycyBtZXNzYWdlPXtmbG93LnJlcXVlc3R9Lz5cclxuICAgICAgICAgICAgICAgIDxoci8+XHJcbiAgICAgICAgICAgICAgICB7Y29udGVudH1cclxuICAgICAgICAgICAgPC9zZWN0aW9uPlxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcbn0pO1xyXG5cclxudmFyIEZsb3dEZXRhaWxSZXNwb25zZSA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcclxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHZhciBmbG93ID0gdGhpcy5wcm9wcy5mbG93O1xyXG4gICAgICAgIHZhciBmaXJzdF9saW5lID0gW1xyXG4gICAgICAgICAgICBcIkhUVFAvXCIgKyBmbG93LnJlc3BvbnNlLmh0dHB2ZXJzaW9uLmpvaW4oXCIuXCIpLFxyXG4gICAgICAgICAgICBmbG93LnJlc3BvbnNlLmNvZGUsXHJcbiAgICAgICAgICAgIGZsb3cucmVzcG9uc2UubXNnXHJcbiAgICAgICAgXS5qb2luKFwiIFwiKTtcclxuICAgICAgICB2YXIgY29udGVudCA9IG51bGw7XHJcbiAgICAgICAgaWYgKGZsb3cucmVzcG9uc2UuY29udGVudExlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgY29udGVudCA9IFwiUmVzcG9uc2UgQ29udGVudCBTaXplOiBcIiArIHRvcHV0aWxzLmZvcm1hdFNpemUoZmxvdy5yZXNwb25zZS5jb250ZW50TGVuZ3RoKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBjb250ZW50ID0gPGRpdiBjbGFzc05hbWU9XCJhbGVydCBhbGVydC1pbmZvXCI+Tm8gQ29udGVudDwvZGl2PjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vVE9ETzogU3R5bGluZ1xyXG5cclxuICAgICAgICByZXR1cm4gKFxyXG4gICAgICAgICAgICA8c2VjdGlvbj5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiZmlyc3QtbGluZVwiPnsgZmlyc3RfbGluZSB9PC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8SGVhZGVycyBtZXNzYWdlPXtmbG93LnJlc3BvbnNlfS8+XHJcbiAgICAgICAgICAgICAgICA8aHIvPlxyXG4gICAgICAgICAgICAgICAge2NvbnRlbnR9XHJcbiAgICAgICAgICAgIDwvc2VjdGlvbj5cclxuICAgICAgICApO1xyXG4gICAgfVxyXG59KTtcclxuXHJcbnZhciBGbG93RGV0YWlsRXJyb3IgPSBSZWFjdC5jcmVhdGVDbGFzcyh7XHJcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB2YXIgZmxvdyA9IHRoaXMucHJvcHMuZmxvdztcclxuICAgICAgICByZXR1cm4gKFxyXG4gICAgICAgICAgICA8c2VjdGlvbj5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiYWxlcnQgYWxlcnQtd2FybmluZ1wiPlxyXG4gICAgICAgICAgICAgICAge2Zsb3cuZXJyb3IubXNnfVxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxzbWFsbD57IHRvcHV0aWxzLmZvcm1hdFRpbWVTdGFtcChmbG93LmVycm9yLnRpbWVzdGFtcCkgfTwvc21hbGw+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPC9zZWN0aW9uPlxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcbn0pO1xyXG5cclxudmFyIFRpbWVTdGFtcCA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcclxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xyXG5cclxuICAgICAgICBpZiAoIXRoaXMucHJvcHMudCkge1xyXG4gICAgICAgICAgICAvL3Nob3VsZCBiZSByZXR1cm4gbnVsbCwgYnV0IHRoYXQgdHJpZ2dlcnMgYSBSZWFjdCBidWcuXHJcbiAgICAgICAgICAgIHJldHVybiA8dHI+PC90cj47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB2YXIgdHMgPSB0b3B1dGlscy5mb3JtYXRUaW1lU3RhbXAodGhpcy5wcm9wcy50KTtcclxuXHJcbiAgICAgICAgdmFyIGRlbHRhO1xyXG4gICAgICAgIGlmICh0aGlzLnByb3BzLmRlbHRhVG8pIHtcclxuICAgICAgICAgICAgZGVsdGEgPSB0b3B1dGlscy5mb3JtYXRUaW1lRGVsdGEoMTAwMCAqICh0aGlzLnByb3BzLnQgLSB0aGlzLnByb3BzLmRlbHRhVG8pKTtcclxuICAgICAgICAgICAgZGVsdGEgPSA8c3BhbiBjbGFzc05hbWU9XCJ0ZXh0LW11dGVkXCI+e1wiKFwiICsgZGVsdGEgKyBcIilcIn08L3NwYW4+O1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGRlbHRhID0gbnVsbDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiA8dHI+XHJcbiAgICAgICAgICAgIDx0ZD57dGhpcy5wcm9wcy50aXRsZSArIFwiOlwifTwvdGQ+XHJcbiAgICAgICAgICAgIDx0ZD57dHN9IHtkZWx0YX08L3RkPlxyXG4gICAgICAgIDwvdHI+O1xyXG4gICAgfVxyXG59KTtcclxuXHJcbnZhciBDb25uZWN0aW9uSW5mbyA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcclxuXHJcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB2YXIgY29ubiA9IHRoaXMucHJvcHMuY29ubjtcclxuICAgICAgICB2YXIgYWRkcmVzcyA9IGNvbm4uYWRkcmVzcy5hZGRyZXNzLmpvaW4oXCI6XCIpO1xyXG5cclxuICAgICAgICB2YXIgc25pID0gPHRyIGtleT1cInNuaVwiPjwvdHI+OyAvL3Nob3VsZCBiZSBudWxsLCBidXQgdGhhdCB0cmlnZ2VycyBhIFJlYWN0IGJ1Zy5cclxuICAgICAgICBpZiAoY29ubi5zbmkpIHtcclxuICAgICAgICAgICAgc25pID0gPHRyIGtleT1cInNuaVwiPlxyXG4gICAgICAgICAgICAgICAgPHRkPlxyXG4gICAgICAgICAgICAgICAgICAgIDxhYmJyIHRpdGxlPVwiVExTIFNlcnZlciBOYW1lIEluZGljYXRpb25cIj5UTFMgU05JOjwvYWJicj5cclxuICAgICAgICAgICAgICAgIDwvdGQ+XHJcbiAgICAgICAgICAgICAgICA8dGQ+e2Nvbm4uc25pfTwvdGQ+XHJcbiAgICAgICAgICAgIDwvdHI+O1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gKFxyXG4gICAgICAgICAgICA8dGFibGUgY2xhc3NOYW1lPVwiY29ubmVjdGlvbi10YWJsZVwiPlxyXG4gICAgICAgICAgICAgICAgPHRib2R5PlxyXG4gICAgICAgICAgICAgICAgICAgIDx0ciBrZXk9XCJhZGRyZXNzXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD5BZGRyZXNzOjwvdGQ+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD57YWRkcmVzc308L3RkPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgICAgICAgICAgICAge3NuaX1cclxuICAgICAgICAgICAgICAgIDwvdGJvZHk+XHJcbiAgICAgICAgICAgIDwvdGFibGU+XHJcbiAgICAgICAgKTtcclxuICAgIH1cclxufSk7XHJcblxyXG52YXIgQ2VydGlmaWNhdGVJbmZvID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xyXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgLy9UT0RPOiBXZSBzaG91bGQgZmV0Y2ggaHVtYW4tcmVhZGFibGUgY2VydGlmaWNhdGUgcmVwcmVzZW50YXRpb25cclxuICAgICAgICAvLyBmcm9tIHRoZSBzZXJ2ZXJcclxuICAgICAgICB2YXIgZmxvdyA9IHRoaXMucHJvcHMuZmxvdztcclxuICAgICAgICB2YXIgY2xpZW50X2Nvbm4gPSBmbG93LmNsaWVudF9jb25uO1xyXG4gICAgICAgIHZhciBzZXJ2ZXJfY29ubiA9IGZsb3cuc2VydmVyX2Nvbm47XHJcblxyXG4gICAgICAgIHZhciBwcmVTdHlsZSA9IHttYXhIZWlnaHQ6IDEwMH07XHJcbiAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgPGRpdj5cclxuICAgICAgICAgICAge2NsaWVudF9jb25uLmNlcnQgPyA8aDQ+Q2xpZW50IENlcnRpZmljYXRlPC9oND4gOiBudWxsfVxyXG4gICAgICAgICAgICB7Y2xpZW50X2Nvbm4uY2VydCA/IDxwcmUgc3R5bGU9e3ByZVN0eWxlfT57Y2xpZW50X2Nvbm4uY2VydH08L3ByZT4gOiBudWxsfVxyXG5cclxuICAgICAgICAgICAge3NlcnZlcl9jb25uLmNlcnQgPyA8aDQ+U2VydmVyIENlcnRpZmljYXRlPC9oND4gOiBudWxsfVxyXG4gICAgICAgICAgICB7c2VydmVyX2Nvbm4uY2VydCA/IDxwcmUgc3R5bGU9e3ByZVN0eWxlfT57c2VydmVyX2Nvbm4uY2VydH08L3ByZT4gOiBudWxsfVxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICApO1xyXG4gICAgfVxyXG59KTtcclxuXHJcbnZhciBUaW1pbmcgPSBSZWFjdC5jcmVhdGVDbGFzcyh7XHJcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB2YXIgZmxvdyA9IHRoaXMucHJvcHMuZmxvdztcclxuICAgICAgICB2YXIgc2MgPSBmbG93LnNlcnZlcl9jb25uO1xyXG4gICAgICAgIHZhciBjYyA9IGZsb3cuY2xpZW50X2Nvbm47XHJcbiAgICAgICAgdmFyIHJlcSA9IGZsb3cucmVxdWVzdDtcclxuICAgICAgICB2YXIgcmVzcCA9IGZsb3cucmVzcG9uc2U7XHJcblxyXG4gICAgICAgIHZhciB0aW1lc3RhbXBzID0gW1xyXG4gICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICB0aXRsZTogXCJTZXJ2ZXIgY29ubi4gaW5pdGlhdGVkXCIsXHJcbiAgICAgICAgICAgICAgICB0OiBzYy50aW1lc3RhbXBfc3RhcnQsXHJcbiAgICAgICAgICAgICAgICBkZWx0YVRvOiByZXEudGltZXN0YW1wX3N0YXJ0XHJcbiAgICAgICAgICAgIH0sIHtcclxuICAgICAgICAgICAgICAgIHRpdGxlOiBcIlNlcnZlciBjb25uLiBUQ1AgaGFuZHNoYWtlXCIsXHJcbiAgICAgICAgICAgICAgICB0OiBzYy50aW1lc3RhbXBfdGNwX3NldHVwLFxyXG4gICAgICAgICAgICAgICAgZGVsdGFUbzogcmVxLnRpbWVzdGFtcF9zdGFydFxyXG4gICAgICAgICAgICB9LCB7XHJcbiAgICAgICAgICAgICAgICB0aXRsZTogXCJTZXJ2ZXIgY29ubi4gU1NMIGhhbmRzaGFrZVwiLFxyXG4gICAgICAgICAgICAgICAgdDogc2MudGltZXN0YW1wX3NzbF9zZXR1cCxcclxuICAgICAgICAgICAgICAgIGRlbHRhVG86IHJlcS50aW1lc3RhbXBfc3RhcnRcclxuICAgICAgICAgICAgfSwge1xyXG4gICAgICAgICAgICAgICAgdGl0bGU6IFwiQ2xpZW50IGNvbm4uIGVzdGFibGlzaGVkXCIsXHJcbiAgICAgICAgICAgICAgICB0OiBjYy50aW1lc3RhbXBfc3RhcnQsXHJcbiAgICAgICAgICAgICAgICBkZWx0YVRvOiByZXEudGltZXN0YW1wX3N0YXJ0XHJcbiAgICAgICAgICAgIH0sIHtcclxuICAgICAgICAgICAgICAgIHRpdGxlOiBcIkNsaWVudCBjb25uLiBTU0wgaGFuZHNoYWtlXCIsXHJcbiAgICAgICAgICAgICAgICB0OiBjYy50aW1lc3RhbXBfc3NsX3NldHVwLFxyXG4gICAgICAgICAgICAgICAgZGVsdGFUbzogcmVxLnRpbWVzdGFtcF9zdGFydFxyXG4gICAgICAgICAgICB9LCB7XHJcbiAgICAgICAgICAgICAgICB0aXRsZTogXCJGaXJzdCByZXF1ZXN0IGJ5dGVcIixcclxuICAgICAgICAgICAgICAgIHQ6IHJlcS50aW1lc3RhbXBfc3RhcnQsXHJcbiAgICAgICAgICAgIH0sIHtcclxuICAgICAgICAgICAgICAgIHRpdGxlOiBcIlJlcXVlc3QgY29tcGxldGVcIixcclxuICAgICAgICAgICAgICAgIHQ6IHJlcS50aW1lc3RhbXBfZW5kLFxyXG4gICAgICAgICAgICAgICAgZGVsdGFUbzogcmVxLnRpbWVzdGFtcF9zdGFydFxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgXTtcclxuXHJcbiAgICAgICAgaWYgKGZsb3cucmVzcG9uc2UpIHtcclxuICAgICAgICAgICAgdGltZXN0YW1wcy5wdXNoKFxyXG4gICAgICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgICAgIHRpdGxlOiBcIkZpcnN0IHJlc3BvbnNlIGJ5dGVcIixcclxuICAgICAgICAgICAgICAgICAgICB0OiByZXNwLnRpbWVzdGFtcF9zdGFydCxcclxuICAgICAgICAgICAgICAgICAgICBkZWx0YVRvOiByZXEudGltZXN0YW1wX3N0YXJ0XHJcbiAgICAgICAgICAgICAgICB9LCB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGl0bGU6IFwiUmVzcG9uc2UgY29tcGxldGVcIixcclxuICAgICAgICAgICAgICAgICAgICB0OiByZXNwLnRpbWVzdGFtcF9lbmQsXHJcbiAgICAgICAgICAgICAgICAgICAgZGVsdGFUbzogcmVxLnRpbWVzdGFtcF9zdGFydFxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy9BZGQgdW5pcXVlIGtleSBmb3IgZWFjaCByb3cuXHJcbiAgICAgICAgdGltZXN0YW1wcy5mb3JFYWNoKGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgIGUua2V5ID0gZS50aXRsZTtcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgdGltZXN0YW1wcyA9IF8uc29ydEJ5KHRpbWVzdGFtcHMsICd0Jyk7XHJcblxyXG4gICAgICAgIHZhciByb3dzID0gdGltZXN0YW1wcy5tYXAoZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICAgICAgcmV0dXJuIDxUaW1lU3RhbXAgey4uLmV9Lz47XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHJldHVybiAoXHJcbiAgICAgICAgICAgIDxkaXY+XHJcbiAgICAgICAgICAgICAgICA8aDQ+VGltaW5nPC9oND5cclxuICAgICAgICAgICAgICAgIDx0YWJsZSBjbGFzc05hbWU9XCJ0aW1pbmctdGFibGVcIj5cclxuICAgICAgICAgICAgICAgICAgICA8dGJvZHk+XHJcbiAgICAgICAgICAgICAgICAgICAge3Jvd3N9XHJcbiAgICAgICAgICAgICAgICAgICAgPC90Ym9keT5cclxuICAgICAgICAgICAgICAgIDwvdGFibGU+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcbn0pO1xyXG5cclxudmFyIEZsb3dEZXRhaWxDb25uZWN0aW9uSW5mbyA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcclxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHZhciBmbG93ID0gdGhpcy5wcm9wcy5mbG93O1xyXG4gICAgICAgIHZhciBjbGllbnRfY29ubiA9IGZsb3cuY2xpZW50X2Nvbm47XHJcbiAgICAgICAgdmFyIHNlcnZlcl9jb25uID0gZmxvdy5zZXJ2ZXJfY29ubjtcclxuICAgICAgICByZXR1cm4gKFxyXG4gICAgICAgICAgICA8c2VjdGlvbj5cclxuXHJcbiAgICAgICAgICAgICAgICA8aDQ+Q2xpZW50IENvbm5lY3Rpb248L2g0PlxyXG4gICAgICAgICAgICAgICAgPENvbm5lY3Rpb25JbmZvIGNvbm49e2NsaWVudF9jb25ufS8+XHJcblxyXG4gICAgICAgICAgICAgICAgPGg0PlNlcnZlciBDb25uZWN0aW9uPC9oND5cclxuICAgICAgICAgICAgICAgIDxDb25uZWN0aW9uSW5mbyBjb25uPXtzZXJ2ZXJfY29ubn0vPlxyXG5cclxuICAgICAgICAgICAgICAgIDxDZXJ0aWZpY2F0ZUluZm8gZmxvdz17Zmxvd30vPlxyXG5cclxuICAgICAgICAgICAgICAgIDxUaW1pbmcgZmxvdz17Zmxvd30vPlxyXG5cclxuICAgICAgICAgICAgPC9zZWN0aW9uPlxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcbn0pO1xyXG5cclxudmFyIGFsbFRhYnMgPSB7XHJcbiAgICByZXF1ZXN0OiBGbG93RGV0YWlsUmVxdWVzdCxcclxuICAgIHJlc3BvbnNlOiBGbG93RGV0YWlsUmVzcG9uc2UsXHJcbiAgICBlcnJvcjogRmxvd0RldGFpbEVycm9yLFxyXG4gICAgZGV0YWlsczogRmxvd0RldGFpbENvbm5lY3Rpb25JbmZvXHJcbn07XHJcblxyXG52YXIgRmxvd0RldGFpbCA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcclxuICAgIG1peGluczogW2NvbW1vbi5TdGlja3lIZWFkTWl4aW4sIGNvbW1vbi5OYXZpZ2F0aW9uLCBjb21tb24uU3RhdGVdLFxyXG4gICAgZ2V0VGFiczogZnVuY3Rpb24gKGZsb3cpIHtcclxuICAgICAgICB2YXIgdGFicyA9IFtdO1xyXG4gICAgICAgIFtcInJlcXVlc3RcIiwgXCJyZXNwb25zZVwiLCBcImVycm9yXCJdLmZvckVhY2goZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICAgICAgaWYgKGZsb3dbZV0pIHtcclxuICAgICAgICAgICAgICAgIHRhYnMucHVzaChlKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHRhYnMucHVzaChcImRldGFpbHNcIik7XHJcbiAgICAgICAgcmV0dXJuIHRhYnM7XHJcbiAgICB9LFxyXG4gICAgbmV4dFRhYjogZnVuY3Rpb24gKGkpIHtcclxuICAgICAgICB2YXIgdGFicyA9IHRoaXMuZ2V0VGFicyh0aGlzLnByb3BzLmZsb3cpO1xyXG4gICAgICAgIHZhciBjdXJyZW50SW5kZXggPSB0YWJzLmluZGV4T2YodGhpcy5nZXRQYXJhbXMoKS5kZXRhaWxUYWIpO1xyXG4gICAgICAgIC8vIEpTIG1vZHVsbyBvcGVyYXRvciBkb2Vzbid0IGNvcnJlY3QgbmVnYXRpdmUgbnVtYmVycywgbWFrZSBzdXJlIHRoYXQgd2UgYXJlIHBvc2l0aXZlLlxyXG4gICAgICAgIHZhciBuZXh0SW5kZXggPSAoY3VycmVudEluZGV4ICsgaSArIHRhYnMubGVuZ3RoKSAlIHRhYnMubGVuZ3RoO1xyXG4gICAgICAgIHRoaXMuc2VsZWN0VGFiKHRhYnNbbmV4dEluZGV4XSk7XHJcbiAgICB9LFxyXG4gICAgc2VsZWN0VGFiOiBmdW5jdGlvbiAocGFuZWwpIHtcclxuICAgICAgICB0aGlzLnJlcGxhY2VXaXRoKFxyXG4gICAgICAgICAgICBcImZsb3dcIixcclxuICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgZmxvd0lkOiB0aGlzLmdldFBhcmFtcygpLmZsb3dJZCxcclxuICAgICAgICAgICAgICAgIGRldGFpbFRhYjogcGFuZWxcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICk7XHJcbiAgICB9LFxyXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdmFyIGZsb3cgPSB0aGlzLnByb3BzLmZsb3c7XHJcbiAgICAgICAgdmFyIHRhYnMgPSB0aGlzLmdldFRhYnMoZmxvdyk7XHJcbiAgICAgICAgdmFyIGFjdGl2ZSA9IHRoaXMuZ2V0UGFyYW1zKCkuZGV0YWlsVGFiO1xyXG5cclxuICAgICAgICBpZiAoIV8uY29udGFpbnModGFicywgYWN0aXZlKSkge1xyXG4gICAgICAgICAgICBpZiAoYWN0aXZlID09PSBcInJlc3BvbnNlXCIgJiYgZmxvdy5lcnJvcikge1xyXG4gICAgICAgICAgICAgICAgYWN0aXZlID0gXCJlcnJvclwiO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGFjdGl2ZSA9PT0gXCJlcnJvclwiICYmIGZsb3cucmVzcG9uc2UpIHtcclxuICAgICAgICAgICAgICAgIGFjdGl2ZSA9IFwicmVzcG9uc2VcIjtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGFjdGl2ZSA9IHRhYnNbMF07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdGhpcy5zZWxlY3RUYWIoYWN0aXZlKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHZhciBUYWIgPSBhbGxUYWJzW2FjdGl2ZV07XHJcbiAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJmbG93LWRldGFpbFwiIG9uU2Nyb2xsPXt0aGlzLmFkanVzdEhlYWR9PlxyXG4gICAgICAgICAgICAgICAgPEZsb3dEZXRhaWxOYXYgcmVmPVwiaGVhZFwiXHJcbiAgICAgICAgICAgICAgICAgICAgZmxvdz17Zmxvd31cclxuICAgICAgICAgICAgICAgICAgICB0YWJzPXt0YWJzfVxyXG4gICAgICAgICAgICAgICAgICAgIGFjdGl2ZT17YWN0aXZlfVxyXG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdFRhYj17dGhpcy5zZWxlY3RUYWJ9Lz5cclxuICAgICAgICAgICAgICAgIDxUYWIgZmxvdz17Zmxvd30vPlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICApO1xyXG4gICAgfVxyXG59KTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0ge1xyXG4gICAgRmxvd0RldGFpbDogRmxvd0RldGFpbFxyXG59OyIsInZhciBSZWFjdCA9IHJlcXVpcmUoXCJyZWFjdFwiKTtcclxudmFyIGZsb3d1dGlscyA9IHJlcXVpcmUoXCIuLi9mbG93L3V0aWxzLmpzXCIpO1xyXG52YXIgdXRpbHMgPSByZXF1aXJlKFwiLi4vdXRpbHMuanNcIik7XHJcblxyXG52YXIgVExTQ29sdW1uID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xyXG4gICAgc3RhdGljczoge1xyXG4gICAgICAgIHJlbmRlclRpdGxlOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiA8dGgga2V5PVwidGxzXCIgY2xhc3NOYW1lPVwiY29sLXRsc1wiPjwvdGg+O1xyXG4gICAgICAgIH1cclxuICAgIH0sXHJcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB2YXIgZmxvdyA9IHRoaXMucHJvcHMuZmxvdztcclxuICAgICAgICB2YXIgc3NsID0gKGZsb3cucmVxdWVzdC5zY2hlbWUgPT0gXCJodHRwc1wiKTtcclxuICAgICAgICB2YXIgY2xhc3NlcztcclxuICAgICAgICBpZiAoc3NsKSB7XHJcbiAgICAgICAgICAgIGNsYXNzZXMgPSBcImNvbC10bHMgY29sLXRscy1odHRwc1wiO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGNsYXNzZXMgPSBcImNvbC10bHMgY29sLXRscy1odHRwXCI7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiA8dGQgY2xhc3NOYW1lPXtjbGFzc2VzfT48L3RkPjtcclxuICAgIH1cclxufSk7XHJcblxyXG5cclxudmFyIEljb25Db2x1bW4gPSBSZWFjdC5jcmVhdGVDbGFzcyh7XHJcbiAgICBzdGF0aWNzOiB7XHJcbiAgICAgICAgcmVuZGVyVGl0bGU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIDx0aCBrZXk9XCJpY29uXCIgY2xhc3NOYW1lPVwiY29sLWljb25cIj48L3RoPjtcclxuICAgICAgICB9XHJcbiAgICB9LFxyXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdmFyIGZsb3cgPSB0aGlzLnByb3BzLmZsb3c7XHJcblxyXG4gICAgICAgIHZhciBpY29uO1xyXG4gICAgICAgIGlmIChmbG93LnJlc3BvbnNlKSB7XHJcbiAgICAgICAgICAgIHZhciBjb250ZW50VHlwZSA9IGZsb3d1dGlscy5SZXNwb25zZVV0aWxzLmdldENvbnRlbnRUeXBlKGZsb3cucmVzcG9uc2UpO1xyXG5cclxuICAgICAgICAgICAgLy9UT0RPOiBXZSBzaG91bGQgYXNzaWduIGEgdHlwZSB0byB0aGUgZmxvdyBzb21ld2hlcmUgZWxzZS5cclxuICAgICAgICAgICAgaWYgKGZsb3cucmVzcG9uc2UuY29kZSA9PSAzMDQpIHtcclxuICAgICAgICAgICAgICAgIGljb24gPSBcInJlc291cmNlLWljb24tbm90LW1vZGlmaWVkXCI7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoMzAwIDw9IGZsb3cucmVzcG9uc2UuY29kZSAmJiBmbG93LnJlc3BvbnNlLmNvZGUgPCA0MDApIHtcclxuICAgICAgICAgICAgICAgIGljb24gPSBcInJlc291cmNlLWljb24tcmVkaXJlY3RcIjtcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChjb250ZW50VHlwZSAmJiBjb250ZW50VHlwZS5pbmRleE9mKFwiaW1hZ2VcIikgPj0gMCkge1xyXG4gICAgICAgICAgICAgICAgaWNvbiA9IFwicmVzb3VyY2UtaWNvbi1pbWFnZVwiO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNvbnRlbnRUeXBlICYmIGNvbnRlbnRUeXBlLmluZGV4T2YoXCJqYXZhc2NyaXB0XCIpID49IDApIHtcclxuICAgICAgICAgICAgICAgIGljb24gPSBcInJlc291cmNlLWljb24tanNcIjtcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChjb250ZW50VHlwZSAmJiBjb250ZW50VHlwZS5pbmRleE9mKFwiY3NzXCIpID49IDApIHtcclxuICAgICAgICAgICAgICAgIGljb24gPSBcInJlc291cmNlLWljb24tY3NzXCI7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY29udGVudFR5cGUgJiYgY29udGVudFR5cGUuaW5kZXhPZihcImh0bWxcIikgPj0gMCkge1xyXG4gICAgICAgICAgICAgICAgaWNvbiA9IFwicmVzb3VyY2UtaWNvbi1kb2N1bWVudFwiO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmICghaWNvbikge1xyXG4gICAgICAgICAgICBpY29uID0gXCJyZXNvdXJjZS1pY29uLXBsYWluXCI7XHJcbiAgICAgICAgfVxyXG5cclxuXHJcbiAgICAgICAgaWNvbiArPSBcIiByZXNvdXJjZS1pY29uXCI7XHJcbiAgICAgICAgcmV0dXJuIDx0ZCBjbGFzc05hbWU9XCJjb2wtaWNvblwiPlxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT17aWNvbn0+PC9kaXY+XHJcbiAgICAgICAgPC90ZD47XHJcbiAgICB9XHJcbn0pO1xyXG5cclxudmFyIFBhdGhDb2x1bW4gPSBSZWFjdC5jcmVhdGVDbGFzcyh7XHJcbiAgICBzdGF0aWNzOiB7XHJcbiAgICAgICAgcmVuZGVyVGl0bGU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIDx0aCBrZXk9XCJwYXRoXCIgY2xhc3NOYW1lPVwiY29sLXBhdGhcIj5QYXRoPC90aD47XHJcbiAgICAgICAgfVxyXG4gICAgfSxcclxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHZhciBmbG93ID0gdGhpcy5wcm9wcy5mbG93O1xyXG4gICAgICAgIHJldHVybiA8dGQgY2xhc3NOYW1lPVwiY29sLXBhdGhcIj5cclxuICAgICAgICAgICAge2Zsb3cucmVxdWVzdC5pc19yZXBsYXkgPyA8aSBjbGFzc05hbWU9XCJmYSBmYS1mdyBmYS1yZXBlYXQgcHVsbC1yaWdodFwiPjwvaT4gOiBudWxsfVxyXG4gICAgICAgICAgICB7Zmxvdy5pbnRlcmNlcHRlZCA/IDxpIGNsYXNzTmFtZT1cImZhIGZhLWZ3IGZhLXBhdXNlIHB1bGwtcmlnaHRcIj48L2k+IDogbnVsbH1cclxuICAgICAgICAgICAge2Zsb3cucmVxdWVzdC5zY2hlbWUgKyBcIjovL1wiICsgZmxvdy5yZXF1ZXN0Lmhvc3QgKyBmbG93LnJlcXVlc3QucGF0aH1cclxuICAgICAgICA8L3RkPjtcclxuICAgIH1cclxufSk7XHJcblxyXG5cclxudmFyIE1ldGhvZENvbHVtbiA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcclxuICAgIHN0YXRpY3M6IHtcclxuICAgICAgICByZW5kZXJUaXRsZTogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gPHRoIGtleT1cIm1ldGhvZFwiIGNsYXNzTmFtZT1cImNvbC1tZXRob2RcIj5NZXRob2Q8L3RoPjtcclxuICAgICAgICB9XHJcbiAgICB9LFxyXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdmFyIGZsb3cgPSB0aGlzLnByb3BzLmZsb3c7XHJcbiAgICAgICAgcmV0dXJuIDx0ZCBjbGFzc05hbWU9XCJjb2wtbWV0aG9kXCI+e2Zsb3cucmVxdWVzdC5tZXRob2R9PC90ZD47XHJcbiAgICB9XHJcbn0pO1xyXG5cclxuXHJcbnZhciBTdGF0dXNDb2x1bW4gPSBSZWFjdC5jcmVhdGVDbGFzcyh7XHJcbiAgICBzdGF0aWNzOiB7XHJcbiAgICAgICAgcmVuZGVyVGl0bGU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgcmV0dXJuIDx0aCBrZXk9XCJzdGF0dXNcIiBjbGFzc05hbWU9XCJjb2wtc3RhdHVzXCI+U3RhdHVzPC90aD47XHJcbiAgICAgICAgfVxyXG4gICAgfSxcclxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHZhciBmbG93ID0gdGhpcy5wcm9wcy5mbG93O1xyXG4gICAgICAgIHZhciBzdGF0dXM7XHJcbiAgICAgICAgaWYgKGZsb3cucmVzcG9uc2UpIHtcclxuICAgICAgICAgICAgc3RhdHVzID0gZmxvdy5yZXNwb25zZS5jb2RlO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHN0YXR1cyA9IG51bGw7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiA8dGQgY2xhc3NOYW1lPVwiY29sLXN0YXR1c1wiPntzdGF0dXN9PC90ZD47XHJcbiAgICB9XHJcbn0pO1xyXG5cclxuXHJcbnZhciBTaXplQ29sdW1uID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xyXG4gICAgc3RhdGljczoge1xyXG4gICAgICAgIHJlbmRlclRpdGxlOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiA8dGgga2V5PVwic2l6ZVwiIGNsYXNzTmFtZT1cImNvbC1zaXplXCI+U2l6ZTwvdGg+O1xyXG4gICAgICAgIH1cclxuICAgIH0sXHJcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB2YXIgZmxvdyA9IHRoaXMucHJvcHMuZmxvdztcclxuXHJcbiAgICAgICAgdmFyIHRvdGFsID0gZmxvdy5yZXF1ZXN0LmNvbnRlbnRMZW5ndGg7XHJcbiAgICAgICAgaWYgKGZsb3cucmVzcG9uc2UpIHtcclxuICAgICAgICAgICAgdG90YWwgKz0gZmxvdy5yZXNwb25zZS5jb250ZW50TGVuZ3RoIHx8IDA7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHZhciBzaXplID0gdXRpbHMuZm9ybWF0U2l6ZSh0b3RhbCk7XHJcbiAgICAgICAgcmV0dXJuIDx0ZCBjbGFzc05hbWU9XCJjb2wtc2l6ZVwiPntzaXplfTwvdGQ+O1xyXG4gICAgfVxyXG59KTtcclxuXHJcblxyXG52YXIgVGltZUNvbHVtbiA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcclxuICAgIHN0YXRpY3M6IHtcclxuICAgICAgICByZW5kZXJUaXRsZTogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gPHRoIGtleT1cInRpbWVcIiBjbGFzc05hbWU9XCJjb2wtdGltZVwiPlRpbWU8L3RoPjtcclxuICAgICAgICB9XHJcbiAgICB9LFxyXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdmFyIGZsb3cgPSB0aGlzLnByb3BzLmZsb3c7XHJcbiAgICAgICAgdmFyIHRpbWU7XHJcbiAgICAgICAgaWYgKGZsb3cucmVzcG9uc2UpIHtcclxuICAgICAgICAgICAgdGltZSA9IHV0aWxzLmZvcm1hdFRpbWVEZWx0YSgxMDAwICogKGZsb3cucmVzcG9uc2UudGltZXN0YW1wX2VuZCAtIGZsb3cucmVxdWVzdC50aW1lc3RhbXBfc3RhcnQpKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aW1lID0gXCIuLi5cIjtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIDx0ZCBjbGFzc05hbWU9XCJjb2wtdGltZVwiPnt0aW1lfTwvdGQ+O1xyXG4gICAgfVxyXG59KTtcclxuXHJcblxyXG52YXIgYWxsX2NvbHVtbnMgPSBbXHJcbiAgICBUTFNDb2x1bW4sXHJcbiAgICBJY29uQ29sdW1uLFxyXG4gICAgUGF0aENvbHVtbixcclxuICAgIE1ldGhvZENvbHVtbixcclxuICAgIFN0YXR1c0NvbHVtbixcclxuICAgIFNpemVDb2x1bW4sXHJcbiAgICBUaW1lQ29sdW1uXTtcclxuXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGFsbF9jb2x1bW5zO1xyXG5cclxuXHJcbiIsInZhciBSZWFjdCA9IHJlcXVpcmUoXCJyZWFjdFwiKTtcclxudmFyIGNvbW1vbiA9IHJlcXVpcmUoXCIuL2NvbW1vbi5qc1wiKTtcclxudmFyIFZpcnR1YWxTY3JvbGxNaXhpbiA9IHJlcXVpcmUoXCIuL3ZpcnR1YWxzY3JvbGwuanNcIik7XHJcbnZhciBmbG93dGFibGVfY29sdW1ucyA9IHJlcXVpcmUoXCIuL2Zsb3d0YWJsZS1jb2x1bW5zLmpzXCIpO1xyXG5cclxudmFyIEZsb3dSb3cgPSBSZWFjdC5jcmVhdGVDbGFzcyh7XHJcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB2YXIgZmxvdyA9IHRoaXMucHJvcHMuZmxvdztcclxuICAgICAgICB2YXIgY29sdW1ucyA9IHRoaXMucHJvcHMuY29sdW1ucy5tYXAoZnVuY3Rpb24gKENvbHVtbikge1xyXG4gICAgICAgICAgICByZXR1cm4gPENvbHVtbiBrZXk9e0NvbHVtbi5kaXNwbGF5TmFtZX0gZmxvdz17Zmxvd30vPjtcclxuICAgICAgICB9LmJpbmQodGhpcykpO1xyXG4gICAgICAgIHZhciBjbGFzc05hbWUgPSBcIlwiO1xyXG4gICAgICAgIGlmICh0aGlzLnByb3BzLnNlbGVjdGVkKSB7XHJcbiAgICAgICAgICAgIGNsYXNzTmFtZSArPSBcIiBzZWxlY3RlZFwiO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAodGhpcy5wcm9wcy5oaWdobGlnaHRlZCkge1xyXG4gICAgICAgICAgICBjbGFzc05hbWUgKz0gXCIgaGlnaGxpZ2h0ZWRcIjtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGZsb3cuaW50ZXJjZXB0ZWQpIHtcclxuICAgICAgICAgICAgY2xhc3NOYW1lICs9IFwiIGludGVyY2VwdGVkXCI7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChmbG93LnJlcXVlc3QpIHtcclxuICAgICAgICAgICAgY2xhc3NOYW1lICs9IFwiIGhhcy1yZXF1ZXN0XCI7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChmbG93LnJlc3BvbnNlKSB7XHJcbiAgICAgICAgICAgIGNsYXNzTmFtZSArPSBcIiBoYXMtcmVzcG9uc2VcIjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiAoXHJcbiAgICAgICAgICAgIDx0ciBjbGFzc05hbWU9e2NsYXNzTmFtZX0gb25DbGljaz17dGhpcy5wcm9wcy5zZWxlY3RGbG93LmJpbmQobnVsbCwgZmxvdyl9PlxyXG4gICAgICAgICAgICAgICAge2NvbHVtbnN9XHJcbiAgICAgICAgICAgIDwvdHI+KTtcclxuICAgIH0sXHJcbiAgICBzaG91bGRDb21wb25lbnRVcGRhdGU6IGZ1bmN0aW9uIChuZXh0UHJvcHMpIHtcclxuICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICAvLyBGdXJ0aGVyIG9wdGltaXphdGlvbiBjb3VsZCBiZSBkb25lIGhlcmVcclxuICAgICAgICAvLyBieSBjYWxsaW5nIGZvcmNlVXBkYXRlIG9uIGZsb3cgdXBkYXRlcywgc2VsZWN0aW9uIGNoYW5nZXMgYW5kIGNvbHVtbiBjaGFuZ2VzLlxyXG4gICAgICAgIC8vcmV0dXJuIChcclxuICAgICAgICAvLyh0aGlzLnByb3BzLmNvbHVtbnMubGVuZ3RoICE9PSBuZXh0UHJvcHMuY29sdW1ucy5sZW5ndGgpIHx8XHJcbiAgICAgICAgLy8odGhpcy5wcm9wcy5zZWxlY3RlZCAhPT0gbmV4dFByb3BzLnNlbGVjdGVkKVxyXG4gICAgICAgIC8vKTtcclxuICAgIH1cclxufSk7XHJcblxyXG52YXIgRmxvd1RhYmxlSGVhZCA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcclxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHZhciBjb2x1bW5zID0gdGhpcy5wcm9wcy5jb2x1bW5zLm1hcChmdW5jdGlvbiAoY29sdW1uKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBjb2x1bW4ucmVuZGVyVGl0bGUoKTtcclxuICAgICAgICB9LmJpbmQodGhpcykpO1xyXG4gICAgICAgIHJldHVybiA8dGhlYWQ+XHJcbiAgICAgICAgICAgIDx0cj57Y29sdW1uc308L3RyPlxyXG4gICAgICAgIDwvdGhlYWQ+O1xyXG4gICAgfVxyXG59KTtcclxuXHJcblxyXG52YXIgUk9XX0hFSUdIVCA9IDMyO1xyXG5cclxudmFyIEZsb3dUYWJsZSA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcclxuICAgIG1peGluczogW2NvbW1vbi5TdGlja3lIZWFkTWl4aW4sIGNvbW1vbi5BdXRvU2Nyb2xsTWl4aW4sIFZpcnR1YWxTY3JvbGxNaXhpbl0sXHJcbiAgICBnZXRJbml0aWFsU3RhdGU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICBjb2x1bW5zOiBmbG93dGFibGVfY29sdW1uc1xyXG4gICAgICAgIH07XHJcbiAgICB9LFxyXG4gICAgY29tcG9uZW50V2lsbE1vdW50OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgaWYgKHRoaXMucHJvcHMudmlldykge1xyXG4gICAgICAgICAgICB0aGlzLnByb3BzLnZpZXcuYWRkTGlzdGVuZXIoXCJhZGQgdXBkYXRlIHJlbW92ZSByZWNhbGN1bGF0ZVwiLCB0aGlzLm9uQ2hhbmdlKTtcclxuICAgICAgICB9XHJcbiAgICB9LFxyXG4gICAgY29tcG9uZW50V2lsbFJlY2VpdmVQcm9wczogZnVuY3Rpb24gKG5leHRQcm9wcykge1xyXG4gICAgICAgIGlmIChuZXh0UHJvcHMudmlldyAhPT0gdGhpcy5wcm9wcy52aWV3KSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLnByb3BzLnZpZXcpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMucHJvcHMudmlldy5yZW1vdmVMaXN0ZW5lcihcImFkZCB1cGRhdGUgcmVtb3ZlIHJlY2FsY3VsYXRlXCIpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIG5leHRQcm9wcy52aWV3LmFkZExpc3RlbmVyKFwiYWRkIHVwZGF0ZSByZW1vdmUgcmVjYWxjdWxhdGVcIiwgdGhpcy5vbkNoYW5nZSk7XHJcbiAgICAgICAgfVxyXG4gICAgfSxcclxuICAgIGdldERlZmF1bHRQcm9wczogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIHJvd0hlaWdodDogUk9XX0hFSUdIVFxyXG4gICAgICAgIH07XHJcbiAgICB9LFxyXG4gICAgb25TY3JvbGxGbG93VGFibGU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB0aGlzLmFkanVzdEhlYWQoKTtcclxuICAgICAgICB0aGlzLm9uU2Nyb2xsKCk7XHJcbiAgICB9LFxyXG4gICAgb25DaGFuZ2U6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB0aGlzLmZvcmNlVXBkYXRlKCk7XHJcbiAgICB9LFxyXG4gICAgc2Nyb2xsSW50b1ZpZXc6IGZ1bmN0aW9uIChmbG93KSB7XHJcbiAgICAgICAgdGhpcy5zY3JvbGxSb3dJbnRvVmlldyhcclxuICAgICAgICAgICAgdGhpcy5wcm9wcy52aWV3LmluZGV4KGZsb3cpLFxyXG4gICAgICAgICAgICB0aGlzLnJlZnMuYm9keS5nZXRET01Ob2RlKCkub2Zmc2V0VG9wXHJcbiAgICAgICAgKTtcclxuICAgIH0sXHJcbiAgICByZW5kZXJSb3c6IGZ1bmN0aW9uIChmbG93KSB7XHJcbiAgICAgICAgdmFyIHNlbGVjdGVkID0gKGZsb3cgPT09IHRoaXMucHJvcHMuc2VsZWN0ZWQpO1xyXG4gICAgICAgIHZhciBoaWdobGlnaHRlZCA9XHJcbiAgICAgICAgICAgIChcclxuICAgICAgICAgICAgdGhpcy5wcm9wcy52aWV3Ll9oaWdobGlnaHQgJiZcclxuICAgICAgICAgICAgdGhpcy5wcm9wcy52aWV3Ll9oaWdobGlnaHRbZmxvdy5pZF1cclxuICAgICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIDxGbG93Um93IGtleT17Zmxvdy5pZH1cclxuICAgICAgICAgICAgcmVmPXtmbG93LmlkfVxyXG4gICAgICAgICAgICBmbG93PXtmbG93fVxyXG4gICAgICAgICAgICBjb2x1bW5zPXt0aGlzLnN0YXRlLmNvbHVtbnN9XHJcbiAgICAgICAgICAgIHNlbGVjdGVkPXtzZWxlY3RlZH1cclxuICAgICAgICAgICAgaGlnaGxpZ2h0ZWQ9e2hpZ2hsaWdodGVkfVxyXG4gICAgICAgICAgICBzZWxlY3RGbG93PXt0aGlzLnByb3BzLnNlbGVjdEZsb3d9XHJcbiAgICAgICAgLz47XHJcbiAgICB9LFxyXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgLy9jb25zb2xlLmxvZyhcInJlbmRlciBmbG93dGFibGVcIiwgdGhpcy5zdGF0ZS5zdGFydCwgdGhpcy5zdGF0ZS5zdG9wLCB0aGlzLnByb3BzLnNlbGVjdGVkKTtcclxuICAgICAgICB2YXIgZmxvd3MgPSB0aGlzLnByb3BzLnZpZXcgPyB0aGlzLnByb3BzLnZpZXcubGlzdCA6IFtdO1xyXG5cclxuICAgICAgICB2YXIgcm93cyA9IHRoaXMucmVuZGVyUm93cyhmbG93cyk7XHJcblxyXG4gICAgICAgIHJldHVybiAoXHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiZmxvdy10YWJsZVwiIG9uU2Nyb2xsPXt0aGlzLm9uU2Nyb2xsRmxvd1RhYmxlfT5cclxuICAgICAgICAgICAgICAgIDx0YWJsZT5cclxuICAgICAgICAgICAgICAgICAgICA8Rmxvd1RhYmxlSGVhZCByZWY9XCJoZWFkXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1ucz17dGhpcy5zdGF0ZS5jb2x1bW5zfS8+XHJcbiAgICAgICAgICAgICAgICAgICAgPHRib2R5IHJlZj1cImJvZHlcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgeyB0aGlzLmdldFBsYWNlaG9sZGVyVG9wKGZsb3dzLmxlbmd0aCkgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB7cm93c31cclxuICAgICAgICAgICAgICAgICAgICAgICAgeyB0aGlzLmdldFBsYWNlaG9sZGVyQm90dG9tKGZsb3dzLmxlbmd0aCkgfVxyXG4gICAgICAgICAgICAgICAgICAgIDwvdGJvZHk+XHJcbiAgICAgICAgICAgICAgICA8L3RhYmxlPlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICApO1xyXG4gICAgfVxyXG59KTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gRmxvd1RhYmxlO1xyXG4iLCJ2YXIgUmVhY3QgPSByZXF1aXJlKFwicmVhY3RcIik7XHJcblxyXG52YXIgRm9vdGVyID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xyXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdmFyIG1vZGUgPSB0aGlzLnByb3BzLnNldHRpbmdzLm1vZGU7XHJcbiAgICAgICAgdmFyIGludGVyY2VwdCA9IHRoaXMucHJvcHMuc2V0dGluZ3MuaW50ZXJjZXB0O1xyXG4gICAgICAgIHJldHVybiAoXHJcbiAgICAgICAgICAgIDxmb290ZXI+XHJcbiAgICAgICAgICAgICAgICB7bW9kZSAhPSBcInJlZ3VsYXJcIiA/IDxzcGFuIGNsYXNzTmFtZT1cImxhYmVsIGxhYmVsLXN1Y2Nlc3NcIj57bW9kZX0gbW9kZTwvc3Bhbj4gOiBudWxsfVxyXG4gICAgICAgICAgICAgICAgJm5ic3A7XHJcbiAgICAgICAgICAgICAgICB7aW50ZXJjZXB0ID8gPHNwYW4gY2xhc3NOYW1lPVwibGFiZWwgbGFiZWwtc3VjY2Vzc1wiPkludGVyY2VwdDoge2ludGVyY2VwdH08L3NwYW4+IDogbnVsbH1cclxuICAgICAgICAgICAgPC9mb290ZXI+XHJcbiAgICAgICAgKTtcclxuICAgIH1cclxufSk7XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IEZvb3RlcjsiLCJ2YXIgUmVhY3QgPSByZXF1aXJlKFwicmVhY3RcIik7XHJcbnZhciAkID0gcmVxdWlyZShcImpxdWVyeVwiKTtcclxuXHJcbnZhciBGaWx0ID0gcmVxdWlyZShcIi4uL2ZpbHQvZmlsdC5qc1wiKTtcclxudmFyIHV0aWxzID0gcmVxdWlyZShcIi4uL3V0aWxzLmpzXCIpO1xyXG5cclxudmFyIGNvbW1vbiA9IHJlcXVpcmUoXCIuL2NvbW1vbi5qc1wiKTtcclxuXHJcbnZhciBGaWx0ZXJEb2NzID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xyXG4gICAgc3RhdGljczoge1xyXG4gICAgICAgIHhocjogZmFsc2UsXHJcbiAgICAgICAgZG9jOiBmYWxzZVxyXG4gICAgfSxcclxuICAgIGNvbXBvbmVudFdpbGxNb3VudDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIGlmICghRmlsdGVyRG9jcy5kb2MpIHtcclxuICAgICAgICAgICAgRmlsdGVyRG9jcy54aHIgPSAkLmdldEpTT04oXCIvZmlsdGVyLWhlbHBcIikuZG9uZShmdW5jdGlvbiAoZG9jKSB7XHJcbiAgICAgICAgICAgICAgICBGaWx0ZXJEb2NzLmRvYyA9IGRvYztcclxuICAgICAgICAgICAgICAgIEZpbHRlckRvY3MueGhyID0gZmFsc2U7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoRmlsdGVyRG9jcy54aHIpIHtcclxuICAgICAgICAgICAgRmlsdGVyRG9jcy54aHIuZG9uZShmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmZvcmNlVXBkYXRlKCk7XHJcbiAgICAgICAgICAgIH0uYmluZCh0aGlzKSk7XHJcbiAgICAgICAgfVxyXG4gICAgfSxcclxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIGlmICghRmlsdGVyRG9jcy5kb2MpIHtcclxuICAgICAgICAgICAgcmV0dXJuIDxpIGNsYXNzTmFtZT1cImZhIGZhLXNwaW5uZXIgZmEtc3BpblwiPjwvaT47XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdmFyIGNvbW1hbmRzID0gRmlsdGVyRG9jcy5kb2MuY29tbWFuZHMubWFwKGZ1bmN0aW9uIChjKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gPHRyPlxyXG4gICAgICAgICAgICAgICAgICAgIDx0ZD57Y1swXS5yZXBsYWNlKFwiIFwiLCAnXFx1MDBhMCcpfTwvdGQ+XHJcbiAgICAgICAgICAgICAgICAgICAgPHRkPntjWzFdfTwvdGQ+XHJcbiAgICAgICAgICAgICAgICA8L3RyPjtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIGNvbW1hbmRzLnB1c2goPHRyPlxyXG4gICAgICAgICAgICAgICAgPHRkIGNvbFNwYW49XCIyXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGEgaHJlZj1cImh0dHBzOi8vbWl0bXByb3h5Lm9yZy9kb2MvZmVhdHVyZXMvZmlsdGVycy5odG1sXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0PVwiX2JsYW5rXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzTmFtZT1cImZhIGZhLWV4dGVybmFsLWxpbmtcIj48L2k+XHJcbiAgICAgICAgICAgICAgICAgICAgJm5ic3A7IG1pdG1wcm94eSBkb2NzPC9hPlxyXG4gICAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgPC90cj4pO1xyXG4gICAgICAgICAgICByZXR1cm4gPHRhYmxlIGNsYXNzTmFtZT1cInRhYmxlIHRhYmxlLWNvbmRlbnNlZFwiPlxyXG4gICAgICAgICAgICAgICAgPHRib2R5Pntjb21tYW5kc308L3Rib2R5PlxyXG4gICAgICAgICAgICA8L3RhYmxlPjtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn0pO1xyXG52YXIgRmlsdGVySW5wdXQgPSBSZWFjdC5jcmVhdGVDbGFzcyh7XHJcbiAgICBnZXRJbml0aWFsU3RhdGU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAvLyBDb25zaWRlciBib3RoIGZvY3VzIGFuZCBtb3VzZW92ZXIgZm9yIHNob3dpbmcvaGlkaW5nIHRoZSB0b29sdGlwLFxyXG4gICAgICAgIC8vIGJlY2F1c2Ugb25CbHVyIG9mIHRoZSBpbnB1dCBpcyB0cmlnZ2VyZWQgYmVmb3JlIHRoZSBjbGljayBvbiB0aGUgdG9vbHRpcFxyXG4gICAgICAgIC8vIGZpbmFsaXplZCwgaGlkaW5nIHRoZSB0b29sdGlwIGp1c3QgYXMgdGhlIHVzZXIgY2xpY2tzIG9uIGl0LlxyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIHZhbHVlOiB0aGlzLnByb3BzLnZhbHVlLFxyXG4gICAgICAgICAgICBmb2N1czogZmFsc2UsXHJcbiAgICAgICAgICAgIG1vdXNlZm9jdXM6IGZhbHNlXHJcbiAgICAgICAgfTtcclxuICAgIH0sXHJcbiAgICBjb21wb25lbnRXaWxsUmVjZWl2ZVByb3BzOiBmdW5jdGlvbiAobmV4dFByb3BzKSB7XHJcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7dmFsdWU6IG5leHRQcm9wcy52YWx1ZX0pO1xyXG4gICAgfSxcclxuICAgIG9uQ2hhbmdlOiBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgIHZhciBuZXh0VmFsdWUgPSBlLnRhcmdldC52YWx1ZTtcclxuICAgICAgICB0aGlzLnNldFN0YXRlKHtcclxuICAgICAgICAgICAgdmFsdWU6IG5leHRWYWx1ZVxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIC8vIE9ubHkgcHJvcGFnYXRlIHZhbGlkIGZpbHRlcnMgdXB3YXJkcy5cclxuICAgICAgICBpZiAodGhpcy5pc1ZhbGlkKG5leHRWYWx1ZSkpIHtcclxuICAgICAgICAgICAgdGhpcy5wcm9wcy5vbkNoYW5nZShuZXh0VmFsdWUpO1xyXG4gICAgICAgIH1cclxuICAgIH0sXHJcbiAgICBpc1ZhbGlkOiBmdW5jdGlvbiAoZmlsdCkge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIEZpbHQucGFyc2UoZmlsdCB8fCB0aGlzLnN0YXRlLnZhbHVlKTtcclxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgfSxcclxuICAgIGdldERlc2M6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB2YXIgZGVzYztcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBkZXNjID0gRmlsdC5wYXJzZSh0aGlzLnN0YXRlLnZhbHVlKS5kZXNjO1xyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgZGVzYyA9IFwiXCIgKyBlO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoZGVzYyAhPT0gXCJ0cnVlXCIpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGRlc2M7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgICAgIDxGaWx0ZXJEb2NzLz5cclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9XHJcbiAgICB9LFxyXG4gICAgb25Gb2N1czogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe2ZvY3VzOiB0cnVlfSk7XHJcbiAgICB9LFxyXG4gICAgb25CbHVyOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7Zm9jdXM6IGZhbHNlfSk7XHJcbiAgICB9LFxyXG4gICAgb25Nb3VzZUVudGVyOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7bW91c2Vmb2N1czogdHJ1ZX0pO1xyXG4gICAgfSxcclxuICAgIG9uTW91c2VMZWF2ZTogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe21vdXNlZm9jdXM6IGZhbHNlfSk7XHJcbiAgICB9LFxyXG4gICAgb25LZXlEb3duOiBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgIGlmIChlLmtleUNvZGUgPT09IHV0aWxzLktleS5FU0MgfHwgZS5rZXlDb2RlID09PSB1dGlscy5LZXkuRU5URVIpIHtcclxuICAgICAgICAgICAgdGhpcy5ibHVyKCk7XHJcbiAgICAgICAgICAgIC8vIElmIGNsb3NlZCB1c2luZyBFU0MvRU5URVIsIGhpZGUgdGhlIHRvb2x0aXAuXHJcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe21vdXNlZm9jdXM6IGZhbHNlfSk7XHJcbiAgICAgICAgfVxyXG4gICAgfSxcclxuICAgIGJsdXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB0aGlzLnJlZnMuaW5wdXQuZ2V0RE9NTm9kZSgpLmJsdXIoKTtcclxuICAgIH0sXHJcbiAgICBmb2N1czogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHRoaXMucmVmcy5pbnB1dC5nZXRET01Ob2RlKCkuc2VsZWN0KCk7XHJcbiAgICB9LFxyXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdmFyIGlzVmFsaWQgPSB0aGlzLmlzVmFsaWQoKTtcclxuICAgICAgICB2YXIgaWNvbiA9IFwiZmEgZmEtZncgZmEtXCIgKyB0aGlzLnByb3BzLnR5cGU7XHJcbiAgICAgICAgdmFyIGdyb3VwQ2xhc3NOYW1lID0gXCJmaWx0ZXItaW5wdXQgaW5wdXQtZ3JvdXBcIiArIChpc1ZhbGlkID8gXCJcIiA6IFwiIGhhcy1lcnJvclwiKTtcclxuXHJcbiAgICAgICAgdmFyIHBvcG92ZXI7XHJcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUuZm9jdXMgfHwgdGhpcy5zdGF0ZS5tb3VzZWZvY3VzKSB7XHJcbiAgICAgICAgICAgIHBvcG92ZXIgPSAoXHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cInBvcG92ZXIgYm90dG9tXCIgb25Nb3VzZUVudGVyPXt0aGlzLm9uTW91c2VFbnRlcn0gb25Nb3VzZUxlYXZlPXt0aGlzLm9uTW91c2VMZWF2ZX0+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJhcnJvd1wiPjwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwicG9wb3Zlci1jb250ZW50XCI+XHJcbiAgICAgICAgICAgICAgICAgICAge3RoaXMuZ2V0RGVzYygpfVxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gKFxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT17Z3JvdXBDbGFzc05hbWV9PlxyXG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3NOYW1lPVwiaW5wdXQtZ3JvdXAtYWRkb25cIj5cclxuICAgICAgICAgICAgICAgICAgICA8aSBjbGFzc05hbWU9e2ljb259IHN0eWxlPXt7Y29sb3I6IHRoaXMucHJvcHMuY29sb3J9fT48L2k+XHJcbiAgICAgICAgICAgICAgICA8L3NwYW4+XHJcbiAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cInRleHRcIiBwbGFjZWhvbGRlcj17dGhpcy5wcm9wcy5wbGFjZWhvbGRlcn0gY2xhc3NOYW1lPVwiZm9ybS1jb250cm9sXCJcclxuICAgICAgICAgICAgICAgICAgICByZWY9XCJpbnB1dFwiXHJcbiAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U9e3RoaXMub25DaGFuZ2V9XHJcbiAgICAgICAgICAgICAgICAgICAgb25Gb2N1cz17dGhpcy5vbkZvY3VzfVxyXG4gICAgICAgICAgICAgICAgICAgIG9uQmx1cj17dGhpcy5vbkJsdXJ9XHJcbiAgICAgICAgICAgICAgICAgICAgb25LZXlEb3duPXt0aGlzLm9uS2V5RG93bn1cclxuICAgICAgICAgICAgICAgICAgICB2YWx1ZT17dGhpcy5zdGF0ZS52YWx1ZX0vPlxyXG4gICAgICAgICAgICAgICAge3BvcG92ZXJ9XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcbn0pO1xyXG5cclxudmFyIE1haW5NZW51ID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xyXG4gICAgbWl4aW5zOiBbY29tbW9uLk5hdmlnYXRpb24sIGNvbW1vbi5TdGF0ZV0sXHJcbiAgICBzdGF0aWNzOiB7XHJcbiAgICAgICAgdGl0bGU6IFwiU3RhcnRcIixcclxuICAgICAgICByb3V0ZTogXCJmbG93c1wiXHJcbiAgICB9LFxyXG4gICAgb25GaWx0ZXJDaGFuZ2U6IGZ1bmN0aW9uICh2YWwpIHtcclxuICAgICAgICB2YXIgZCA9IHt9O1xyXG4gICAgICAgIGRbUXVlcnkuRklMVEVSXSA9IHZhbDtcclxuICAgICAgICB0aGlzLnNldFF1ZXJ5KGQpO1xyXG4gICAgfSxcclxuICAgIG9uSGlnaGxpZ2h0Q2hhbmdlOiBmdW5jdGlvbiAodmFsKSB7XHJcbiAgICAgICAgdmFyIGQgPSB7fTtcclxuICAgICAgICBkW1F1ZXJ5LkhJR0hMSUdIVF0gPSB2YWw7XHJcbiAgICAgICAgdGhpcy5zZXRRdWVyeShkKTtcclxuICAgIH0sXHJcbiAgICBvbkludGVyY2VwdENoYW5nZTogZnVuY3Rpb24gKHZhbCkge1xyXG4gICAgICAgIFNldHRpbmdzQWN0aW9ucy51cGRhdGUoe2ludGVyY2VwdDogdmFsfSk7XHJcbiAgICB9LFxyXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdmFyIGZpbHRlciA9IHRoaXMuZ2V0UXVlcnkoKVtRdWVyeS5GSUxURVJdIHx8IFwiXCI7XHJcbiAgICAgICAgdmFyIGhpZ2hsaWdodCA9IHRoaXMuZ2V0UXVlcnkoKVtRdWVyeS5ISUdITElHSFRdIHx8IFwiXCI7XHJcbiAgICAgICAgdmFyIGludGVyY2VwdCA9IHRoaXMucHJvcHMuc2V0dGluZ3MuaW50ZXJjZXB0IHx8IFwiXCI7XHJcblxyXG4gICAgICAgIHJldHVybiAoXHJcbiAgICAgICAgICAgIDxkaXY+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm1lbnUtcm93XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPEZpbHRlcklucHV0XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiRmlsdGVyXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImZpbHRlclwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yPVwiYmxhY2tcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZT17ZmlsdGVyfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZT17dGhpcy5vbkZpbHRlckNoYW5nZX0gLz5cclxuICAgICAgICAgICAgICAgICAgICA8RmlsdGVySW5wdXRcclxuICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJIaWdobGlnaHRcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwidGFnXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I9XCJoc2woNDgsIDEwMCUsIDUwJSlcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZT17aGlnaGxpZ2h0fVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZT17dGhpcy5vbkhpZ2hsaWdodENoYW5nZX0vPlxyXG4gICAgICAgICAgICAgICAgICAgIDxGaWx0ZXJJbnB1dFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIkludGVyY2VwdFwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJwYXVzZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yPVwiaHNsKDIwOCwgNTYlLCA1MyUpXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9e2ludGVyY2VwdH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U9e3RoaXMub25JbnRlcmNlcHRDaGFuZ2V9Lz5cclxuICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJjbGVhcmZpeFwiPjwvZGl2PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICApO1xyXG4gICAgfVxyXG59KTtcclxuXHJcblxyXG52YXIgVmlld01lbnUgPSBSZWFjdC5jcmVhdGVDbGFzcyh7XHJcbiAgICBzdGF0aWNzOiB7XHJcbiAgICAgICAgdGl0bGU6IFwiVmlld1wiLFxyXG4gICAgICAgIHJvdXRlOiBcImZsb3dzXCJcclxuICAgIH0sXHJcbiAgICBtaXhpbnM6IFtjb21tb24uTmF2aWdhdGlvbiwgY29tbW9uLlN0YXRlXSxcclxuICAgIHRvZ2dsZUV2ZW50TG9nOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdmFyIGQgPSB7fTtcclxuXHJcbiAgICAgICAgaWYgKHRoaXMuZ2V0UXVlcnkoKVtRdWVyeS5TSE9XX0VWRU5UTE9HXSkge1xyXG4gICAgICAgICAgICBkW1F1ZXJ5LlNIT1dfRVZFTlRMT0ddID0gdW5kZWZpbmVkO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGRbUXVlcnkuU0hPV19FVkVOVExPR10gPSBcInRcIjsgLy8gYW55IG5vbi1mYWxzZSB2YWx1ZSB3aWxsIGRvIGl0LCBrZWVwIGl0IHNob3J0XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLnNldFF1ZXJ5KGQpO1xyXG4gICAgfSxcclxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHZhciBzaG93RXZlbnRMb2cgPSB0aGlzLmdldFF1ZXJ5KClbUXVlcnkuU0hPV19FVkVOVExPR107XHJcbiAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgPGRpdj5cclxuICAgICAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU9e1wiYnRuIFwiICsgKHNob3dFdmVudExvZyA/IFwiYnRuLXByaW1hcnlcIiA6IFwiYnRuLWRlZmF1bHRcIil9XHJcbiAgICAgICAgICAgICAgICAgICAgb25DbGljaz17dGhpcy50b2dnbGVFdmVudExvZ30+XHJcbiAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3NOYW1lPVwiZmEgZmEtZGF0YWJhc2VcIj48L2k+XHJcbiAgICAgICAgICAgICAgICAmbmJzcDtTaG93IEV2ZW50bG9nXHJcbiAgICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgICAgIDxzcGFuPiA8L3NwYW4+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcbn0pO1xyXG5cclxuXHJcbnZhciBSZXBvcnRzTWVudSA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcclxuICAgIHN0YXRpY3M6IHtcclxuICAgICAgICB0aXRsZTogXCJWaXN1YWxpemF0aW9uXCIsXHJcbiAgICAgICAgcm91dGU6IFwicmVwb3J0c1wiXHJcbiAgICB9LFxyXG4gICAgcmVuZGVyOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgcmV0dXJuIDxkaXY+UmVwb3J0cyBNZW51PC9kaXY+O1xyXG4gICAgfVxyXG59KTtcclxuXHJcbnZhciBGaWxlTWVudSA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcclxuICAgIGdldEluaXRpYWxTdGF0ZTogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIHNob3dGaWxlTWVudTogZmFsc2VcclxuICAgICAgICB9O1xyXG4gICAgfSxcclxuICAgIGhhbmRsZUZpbGVDbGljazogZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlLnNob3dGaWxlTWVudSkge1xyXG4gICAgICAgICAgICB2YXIgY2xvc2UgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtzaG93RmlsZU1lbnU6IGZhbHNlfSk7XHJcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgY2xvc2UpO1xyXG4gICAgICAgICAgICB9LmJpbmQodGhpcyk7XHJcbiAgICAgICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBjbG9zZSk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcclxuICAgICAgICAgICAgICAgIHNob3dGaWxlTWVudTogdHJ1ZVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICB9LFxyXG4gICAgaGFuZGxlTmV3Q2xpY2s6IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgIGlmIChjb25maXJtKFwiRGVsZXRlIGFsbCBmbG93cz9cIikpIHtcclxuICAgICAgICAgICAgRmxvd0FjdGlvbnMuY2xlYXIoKTtcclxuICAgICAgICB9XHJcbiAgICB9LFxyXG4gICAgaGFuZGxlT3BlbkNsaWNrOiBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICBjb25zb2xlLmVycm9yKFwidW5pbXBsZW1lbnRlZDogaGFuZGxlT3BlbkNsaWNrXCIpO1xyXG4gICAgfSxcclxuICAgIGhhbmRsZVNhdmVDbGljazogZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgY29uc29sZS5lcnJvcihcInVuaW1wbGVtZW50ZWQ6IGhhbmRsZVNhdmVDbGlja1wiKTtcclxuICAgIH0sXHJcbiAgICBoYW5kbGVTaHV0ZG93bkNsaWNrOiBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICBjb25zb2xlLmVycm9yKFwidW5pbXBsZW1lbnRlZDogaGFuZGxlU2h1dGRvd25DbGlja1wiKTtcclxuICAgIH0sXHJcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB2YXIgZmlsZU1lbnVDbGFzcyA9IFwiZHJvcGRvd24gcHVsbC1sZWZ0XCIgKyAodGhpcy5zdGF0ZS5zaG93RmlsZU1lbnUgPyBcIiBvcGVuXCIgOiBcIlwiKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9e2ZpbGVNZW51Q2xhc3N9PlxyXG4gICAgICAgICAgICAgICAgPGEgaHJlZj1cIiNcIiBjbGFzc05hbWU9XCJzcGVjaWFsXCIgb25DbGljaz17dGhpcy5oYW5kbGVGaWxlQ2xpY2t9PiBtaXRtcHJveHkgPC9hPlxyXG4gICAgICAgICAgICAgICAgPHVsIGNsYXNzTmFtZT1cImRyb3Bkb3duLW1lbnVcIiByb2xlPVwibWVudVwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxsaT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPGEgaHJlZj1cIiNcIiBvbkNsaWNrPXt0aGlzLmhhbmRsZU5ld0NsaWNrfT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzTmFtZT1cImZhIGZhLWZ3IGZhLWZpbGVcIj48L2k+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBOZXdcclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9hPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvbGk+XHJcbiAgICAgICAgICAgICAgICAgICAgPGxpIHJvbGU9XCJwcmVzZW50YXRpb25cIiBjbGFzc05hbWU9XCJkaXZpZGVyXCI+PC9saT5cclxuICAgICAgICAgICAgICAgICAgICA8bGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxhIGhyZWY9XCJodHRwOi8vbWl0bS5pdC9cIiB0YXJnZXQ9XCJfYmxhbmtcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzTmFtZT1cImZhIGZhLWZ3IGZhLWV4dGVybmFsLWxpbmtcIj48L2k+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBJbnN0YWxsIENlcnRpZmljYXRlcy4uLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L2E+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9saT5cclxuICAgICAgICAgICAgICAgIHsvKlxyXG4gICAgICAgICAgICAgICAgIDxsaT5cclxuICAgICAgICAgICAgICAgICA8YSBocmVmPVwiI1wiIG9uQ2xpY2s9e3RoaXMuaGFuZGxlT3BlbkNsaWNrfT5cclxuICAgICAgICAgICAgICAgICA8aSBjbGFzc05hbWU9XCJmYSBmYS1mdyBmYS1mb2xkZXItb3BlblwiPjwvaT5cclxuICAgICAgICAgICAgICAgICBPcGVuXHJcbiAgICAgICAgICAgICAgICAgPC9hPlxyXG4gICAgICAgICAgICAgICAgIDwvbGk+XHJcbiAgICAgICAgICAgICAgICAgPGxpPlxyXG4gICAgICAgICAgICAgICAgIDxhIGhyZWY9XCIjXCIgb25DbGljaz17dGhpcy5oYW5kbGVTYXZlQ2xpY2t9PlxyXG4gICAgICAgICAgICAgICAgIDxpIGNsYXNzTmFtZT1cImZhIGZhLWZ3IGZhLXNhdmVcIj48L2k+XHJcbiAgICAgICAgICAgICAgICAgU2F2ZVxyXG4gICAgICAgICAgICAgICAgIDwvYT5cclxuICAgICAgICAgICAgICAgICA8L2xpPlxyXG4gICAgICAgICAgICAgICAgIDxsaSByb2xlPVwicHJlc2VudGF0aW9uXCIgY2xhc3NOYW1lPVwiZGl2aWRlclwiPjwvbGk+XHJcbiAgICAgICAgICAgICAgICAgPGxpPlxyXG4gICAgICAgICAgICAgICAgIDxhIGhyZWY9XCIjXCIgb25DbGljaz17dGhpcy5oYW5kbGVTaHV0ZG93bkNsaWNrfT5cclxuICAgICAgICAgICAgICAgICA8aSBjbGFzc05hbWU9XCJmYSBmYS1mdyBmYS1wbHVnXCI+PC9pPlxyXG4gICAgICAgICAgICAgICAgIFNodXRkb3duXHJcbiAgICAgICAgICAgICAgICAgPC9hPlxyXG4gICAgICAgICAgICAgICAgIDwvbGk+XHJcbiAgICAgICAgICAgICAgICAgKi99XHJcbiAgICAgICAgICAgICAgICA8L3VsPlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICApO1xyXG4gICAgfVxyXG59KTtcclxuXHJcblxyXG52YXIgaGVhZGVyX2VudHJpZXMgPSBbTWFpbk1lbnUsIFZpZXdNZW51IC8qLCBSZXBvcnRzTWVudSAqL107XHJcblxyXG5cclxudmFyIEhlYWRlciA9IFJlYWN0LmNyZWF0ZUNsYXNzKHtcclxuICAgIG1peGluczogW2NvbW1vbi5OYXZpZ2F0aW9uXSxcclxuICAgIGdldEluaXRpYWxTdGF0ZTogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIGFjdGl2ZTogaGVhZGVyX2VudHJpZXNbMF1cclxuICAgICAgICB9O1xyXG4gICAgfSxcclxuICAgIGhhbmRsZUNsaWNrOiBmdW5jdGlvbiAoYWN0aXZlLCBlKSB7XHJcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgIHRoaXMucmVwbGFjZVdpdGgoYWN0aXZlLnJvdXRlKTtcclxuICAgICAgICB0aGlzLnNldFN0YXRlKHthY3RpdmU6IGFjdGl2ZX0pO1xyXG4gICAgfSxcclxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHZhciBoZWFkZXIgPSBoZWFkZXJfZW50cmllcy5tYXAoZnVuY3Rpb24gKGVudHJ5LCBpKSB7XHJcbiAgICAgICAgICAgIHZhciBjbGFzc2VzID0gUmVhY3QuYWRkb25zLmNsYXNzU2V0KHtcclxuICAgICAgICAgICAgICAgIGFjdGl2ZTogZW50cnkgPT0gdGhpcy5zdGF0ZS5hY3RpdmVcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIHJldHVybiAoXHJcbiAgICAgICAgICAgICAgICA8YSBrZXk9e2l9XHJcbiAgICAgICAgICAgICAgICAgICAgaHJlZj1cIiNcIlxyXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT17Y2xhc3Nlc31cclxuICAgICAgICAgICAgICAgICAgICBvbkNsaWNrPXt0aGlzLmhhbmRsZUNsaWNrLmJpbmQodGhpcywgZW50cnkpfVxyXG4gICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgICAgIHsgZW50cnkudGl0bGV9XHJcbiAgICAgICAgICAgICAgICA8L2E+XHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgPGhlYWRlcj5cclxuICAgICAgICAgICAgICAgIDxuYXYgY2xhc3NOYW1lPVwibmF2LXRhYnMgbmF2LXRhYnMtbGdcIj5cclxuICAgICAgICAgICAgICAgICAgICA8RmlsZU1lbnUvPlxyXG4gICAgICAgICAgICAgICAgICAgIHtoZWFkZXJ9XHJcbiAgICAgICAgICAgICAgICA8L25hdj5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwibWVudVwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDx0aGlzLnN0YXRlLmFjdGl2ZSBzZXR0aW5ncz17dGhpcy5wcm9wcy5zZXR0aW5nc30vPlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDwvaGVhZGVyPlxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcbn0pO1xyXG5cclxuXHJcbm1vZHVsZS5leHBvcnRzID0ge1xyXG4gICAgSGVhZGVyOiBIZWFkZXJcclxufSIsInZhciBSZWFjdCA9IHJlcXVpcmUoXCJyZWFjdFwiKTtcclxuXHJcbnZhciBjb21tb24gPSByZXF1aXJlKFwiLi9jb21tb24uanNcIik7XHJcbnZhciB0b3B1dGlscyA9IHJlcXVpcmUoXCIuLi91dGlscy5qc1wiKTtcclxudmFyIHZpZXdzID0gcmVxdWlyZShcIi4uL3N0b3JlL3ZpZXcuanNcIik7XHJcbnZhciBGaWx0ID0gcmVxdWlyZShcIi4uL2ZpbHQvZmlsdC5qc1wiKTtcclxuRmxvd1RhYmxlID0gcmVxdWlyZShcIi4vZmxvd3RhYmxlLmpzXCIpO1xyXG52YXIgZmxvd2RldGFpbCA9IHJlcXVpcmUoXCIuL2Zsb3dkZXRhaWwuanNcIik7XHJcblxyXG5cclxudmFyIE1haW5WaWV3ID0gUmVhY3QuY3JlYXRlQ2xhc3Moe1xyXG4gICAgbWl4aW5zOiBbY29tbW9uLk5hdmlnYXRpb24sIGNvbW1vbi5TdGF0ZV0sXHJcbiAgICBnZXRJbml0aWFsU3RhdGU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB0aGlzLm9uUXVlcnlDaGFuZ2UoUXVlcnkuRklMVEVSLCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHRoaXMuc3RhdGUudmlldy5yZWNhbGN1bGF0ZSh0aGlzLmdldFZpZXdGaWx0KCksIHRoaXMuZ2V0Vmlld1NvcnQoKSk7XHJcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcclxuICAgICAgICB0aGlzLm9uUXVlcnlDaGFuZ2UoUXVlcnkuSElHSExJR0hULCBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIHRoaXMuc3RhdGUudmlldy5yZWNhbGN1bGF0ZSh0aGlzLmdldFZpZXdGaWx0KCksIHRoaXMuZ2V0Vmlld1NvcnQoKSk7XHJcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICBmbG93czogW11cclxuICAgICAgICB9O1xyXG4gICAgfSxcclxuICAgIGdldFZpZXdGaWx0OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgdmFyIGZpbHQgPSBGaWx0LnBhcnNlKHRoaXMuZ2V0UXVlcnkoKVtRdWVyeS5GSUxURVJdIHx8IFwiXCIpO1xyXG4gICAgICAgICAgICB2YXIgaGlnaGxpZ2h0U3RyID0gdGhpcy5nZXRRdWVyeSgpW1F1ZXJ5LkhJR0hMSUdIVF07XHJcbiAgICAgICAgICAgIHZhciBoaWdobGlnaHQgPSBoaWdobGlnaHRTdHIgPyBGaWx0LnBhcnNlKGhpZ2hsaWdodFN0cikgOiBmYWxzZTtcclxuICAgICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciB3aGVuIHByb2Nlc3NpbmcgZmlsdGVyOiBcIiArIGUpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIGZpbHRlcl9hbmRfaGlnaGxpZ2h0KGZsb3cpIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLl9oaWdobGlnaHQpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuX2hpZ2hsaWdodCA9IHt9O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHRoaXMuX2hpZ2hsaWdodFtmbG93LmlkXSA9IGhpZ2hsaWdodCAmJiBoaWdobGlnaHQoZmxvdyk7XHJcbiAgICAgICAgICAgIHJldHVybiBmaWx0KGZsb3cpO1xyXG4gICAgICAgIH07XHJcbiAgICB9LFxyXG4gICAgZ2V0Vmlld1NvcnQ6IGZ1bmN0aW9uICgpIHtcclxuICAgIH0sXHJcbiAgICBjb21wb25lbnRXaWxsUmVjZWl2ZVByb3BzOiBmdW5jdGlvbiAobmV4dFByb3BzKSB7XHJcbiAgICAgICAgaWYgKG5leHRQcm9wcy5mbG93U3RvcmUgIT09IHRoaXMucHJvcHMuZmxvd1N0b3JlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuY2xvc2VWaWV3KCk7XHJcbiAgICAgICAgICAgIHRoaXMub3BlblZpZXcobmV4dFByb3BzLmZsb3dTdG9yZSk7XHJcbiAgICAgICAgfVxyXG4gICAgfSxcclxuICAgIG9wZW5WaWV3OiBmdW5jdGlvbiAoc3RvcmUpIHtcclxuICAgICAgICB2YXIgdmlldyA9IG5ldyB2aWV3cy5TdG9yZVZpZXcoc3RvcmUsIHRoaXMuZ2V0Vmlld0ZpbHQoKSwgdGhpcy5nZXRWaWV3U29ydCgpKTtcclxuICAgICAgICB0aGlzLnNldFN0YXRlKHtcclxuICAgICAgICAgICAgdmlldzogdmlld1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICB2aWV3LmFkZExpc3RlbmVyKFwicmVjYWxjdWxhdGVcIiwgdGhpcy5vblJlY2FsY3VsYXRlKTtcclxuICAgICAgICB2aWV3LmFkZExpc3RlbmVyKFwiYWRkIHVwZGF0ZSByZW1vdmVcIiwgdGhpcy5vblVwZGF0ZSk7XHJcbiAgICAgICAgdmlldy5hZGRMaXN0ZW5lcihcInJlbW92ZVwiLCB0aGlzLm9uUmVtb3ZlKTtcclxuICAgIH0sXHJcbiAgICBvblJlY2FsY3VsYXRlOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdGhpcy5mb3JjZVVwZGF0ZSgpO1xyXG4gICAgICAgIHZhciBzZWxlY3RlZCA9IHRoaXMuZ2V0U2VsZWN0ZWQoKTtcclxuICAgICAgICBpZiAoc2VsZWN0ZWQpIHtcclxuICAgICAgICAgICAgdGhpcy5yZWZzLmZsb3dUYWJsZS5zY3JvbGxJbnRvVmlldyhzZWxlY3RlZCk7XHJcbiAgICAgICAgfVxyXG4gICAgfSxcclxuICAgIG9uVXBkYXRlOiBmdW5jdGlvbiAoZmxvdykge1xyXG4gICAgICAgIGlmIChmbG93LmlkID09PSB0aGlzLmdldFBhcmFtcygpLmZsb3dJZCkge1xyXG4gICAgICAgICAgICB0aGlzLmZvcmNlVXBkYXRlKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfSxcclxuICAgIG9uUmVtb3ZlOiBmdW5jdGlvbiAoZmxvd19pZCwgaW5kZXgpIHtcclxuICAgICAgICBpZiAoZmxvd19pZCA9PT0gdGhpcy5nZXRQYXJhbXMoKS5mbG93SWQpIHtcclxuICAgICAgICAgICAgdmFyIGZsb3dfdG9fc2VsZWN0ID0gdGhpcy5zdGF0ZS52aWV3Lmxpc3RbTWF0aC5taW4oaW5kZXgsIHRoaXMuc3RhdGUudmlldy5saXN0Lmxlbmd0aCAtMSldO1xyXG4gICAgICAgICAgICB0aGlzLnNlbGVjdEZsb3coZmxvd190b19zZWxlY3QpO1xyXG4gICAgICAgIH1cclxuICAgIH0sXHJcbiAgICBjbG9zZVZpZXc6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB0aGlzLnN0YXRlLnZpZXcuY2xvc2UoKTtcclxuICAgIH0sXHJcbiAgICBjb21wb25lbnRXaWxsTW91bnQ6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB0aGlzLm9wZW5WaWV3KHRoaXMucHJvcHMuZmxvd1N0b3JlKTtcclxuICAgIH0sXHJcbiAgICBjb21wb25lbnRXaWxsVW5tb3VudDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHRoaXMuY2xvc2VWaWV3KCk7XHJcbiAgICB9LFxyXG4gICAgc2VsZWN0RmxvdzogZnVuY3Rpb24gKGZsb3cpIHtcclxuICAgICAgICBpZiAoZmxvdykge1xyXG4gICAgICAgICAgICB0aGlzLnJlcGxhY2VXaXRoKFxyXG4gICAgICAgICAgICAgICAgXCJmbG93XCIsXHJcbiAgICAgICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICAgICAgZmxvd0lkOiBmbG93LmlkLFxyXG4gICAgICAgICAgICAgICAgICAgIGRldGFpbFRhYjogdGhpcy5nZXRQYXJhbXMoKS5kZXRhaWxUYWIgfHwgXCJyZXF1ZXN0XCJcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgdGhpcy5yZWZzLmZsb3dUYWJsZS5zY3JvbGxJbnRvVmlldyhmbG93KTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLnJlcGxhY2VXaXRoKFwiZmxvd3NcIiwge30pO1xyXG4gICAgICAgIH1cclxuICAgIH0sXHJcbiAgICBzZWxlY3RGbG93UmVsYXRpdmU6IGZ1bmN0aW9uIChzaGlmdCkge1xyXG4gICAgICAgIHZhciBmbG93cyA9IHRoaXMuc3RhdGUudmlldy5saXN0O1xyXG4gICAgICAgIHZhciBpbmRleDtcclxuICAgICAgICBpZiAoIXRoaXMuZ2V0UGFyYW1zKCkuZmxvd0lkKSB7XHJcbiAgICAgICAgICAgIGlmIChzaGlmdCA+IDApIHtcclxuICAgICAgICAgICAgICAgIGluZGV4ID0gZmxvd3MubGVuZ3RoIC0gMTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGluZGV4ID0gMDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHZhciBjdXJyRmxvd0lkID0gdGhpcy5nZXRQYXJhbXMoKS5mbG93SWQ7XHJcbiAgICAgICAgICAgIHZhciBpID0gZmxvd3MubGVuZ3RoO1xyXG4gICAgICAgICAgICB3aGlsZSAoaS0tKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoZmxvd3NbaV0uaWQgPT09IGN1cnJGbG93SWQpIHtcclxuICAgICAgICAgICAgICAgICAgICBpbmRleCA9IGk7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaW5kZXggPSBNYXRoLm1pbihcclxuICAgICAgICAgICAgICAgIE1hdGgubWF4KDAsIGluZGV4ICsgc2hpZnQpLFxyXG4gICAgICAgICAgICAgICAgZmxvd3MubGVuZ3RoIC0gMSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuc2VsZWN0RmxvdyhmbG93c1tpbmRleF0pO1xyXG4gICAgfSxcclxuICAgIG9uS2V5RG93bjogZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICB2YXIgZmxvdyA9IHRoaXMuZ2V0U2VsZWN0ZWQoKTtcclxuICAgICAgICBpZiAoZS5jdHJsS2V5KSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgc3dpdGNoIChlLmtleUNvZGUpIHtcclxuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuSzpcclxuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuVVA6XHJcbiAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdEZsb3dSZWxhdGl2ZSgtMSk7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuSjpcclxuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuRE9XTjpcclxuICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0Rmxvd1JlbGF0aXZlKCsxKTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5TUEFDRTpcclxuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuUEFHRV9ET1dOOlxyXG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RGbG93UmVsYXRpdmUoKzEwKTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5QQUdFX1VQOlxyXG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RGbG93UmVsYXRpdmUoLTEwKTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5FTkQ6XHJcbiAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdEZsb3dSZWxhdGl2ZSgrMWUxMCk7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuSE9NRTpcclxuICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0Rmxvd1JlbGF0aXZlKC0xZTEwKTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5FU0M6XHJcbiAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdEZsb3cobnVsbCk7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuSDpcclxuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuTEVGVDpcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnJlZnMuZmxvd0RldGFpbHMpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlZnMuZmxvd0RldGFpbHMubmV4dFRhYigtMSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuTDpcclxuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuVEFCOlxyXG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5SSUdIVDpcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnJlZnMuZmxvd0RldGFpbHMpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlZnMuZmxvd0RldGFpbHMubmV4dFRhYigrMSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuQzpcclxuICAgICAgICAgICAgICAgIGlmIChlLnNoaWZ0S2V5KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgRmxvd0FjdGlvbnMuY2xlYXIoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5EOlxyXG4gICAgICAgICAgICAgICAgaWYgKGZsb3cpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoZS5zaGlmdEtleSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBGbG93QWN0aW9ucy5kdXBsaWNhdGUoZmxvdyk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgRmxvd0FjdGlvbnMuZGVsZXRlKGZsb3cpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5BOlxyXG4gICAgICAgICAgICAgICAgaWYgKGUuc2hpZnRLZXkpIHtcclxuICAgICAgICAgICAgICAgICAgICBGbG93QWN0aW9ucy5hY2NlcHRfYWxsKCk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGZsb3cgJiYgZmxvdy5pbnRlcmNlcHRlZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIEZsb3dBY3Rpb25zLmFjY2VwdChmbG93KTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIHRvcHV0aWxzLktleS5SOlxyXG4gICAgICAgICAgICAgICAgaWYgKCFlLnNoaWZ0S2V5ICYmIGZsb3cpIHtcclxuICAgICAgICAgICAgICAgICAgICBGbG93QWN0aW9ucy5yZXBsYXkoZmxvdyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSB0b3B1dGlscy5LZXkuVjpcclxuICAgICAgICAgICAgICAgIGlmKGUuc2hpZnRLZXkgJiYgZmxvdyAmJiBmbG93Lm1vZGlmaWVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgRmxvd0FjdGlvbnMucmV2ZXJ0KGZsb3cpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKFwia2V5ZG93blwiLCBlLmtleUNvZGUpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICB9LFxyXG4gICAgZ2V0U2VsZWN0ZWQ6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5wcm9wcy5mbG93U3RvcmUuZ2V0KHRoaXMuZ2V0UGFyYW1zKCkuZmxvd0lkKTtcclxuICAgIH0sXHJcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB2YXIgc2VsZWN0ZWQgPSB0aGlzLmdldFNlbGVjdGVkKCk7XHJcblxyXG4gICAgICAgIHZhciBkZXRhaWxzO1xyXG4gICAgICAgIGlmIChzZWxlY3RlZCkge1xyXG4gICAgICAgICAgICBkZXRhaWxzID0gW1xyXG4gICAgICAgICAgICAgICAgPGNvbW1vbi5TcGxpdHRlciBrZXk9XCJzcGxpdHRlclwiLz4sXHJcbiAgICAgICAgICAgICAgICA8Zmxvd2RldGFpbC5GbG93RGV0YWlsIGtleT1cImZsb3dEZXRhaWxzXCIgcmVmPVwiZmxvd0RldGFpbHNcIiBmbG93PXtzZWxlY3RlZH0vPlxyXG4gICAgICAgICAgICBdO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGRldGFpbHMgPSBudWxsO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJtYWluLXZpZXdcIiBvbktleURvd249e3RoaXMub25LZXlEb3dufSB0YWJJbmRleD1cIjBcIj5cclxuICAgICAgICAgICAgICAgIDxGbG93VGFibGUgcmVmPVwiZmxvd1RhYmxlXCJcclxuICAgICAgICAgICAgICAgICAgICB2aWV3PXt0aGlzLnN0YXRlLnZpZXd9XHJcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0Rmxvdz17dGhpcy5zZWxlY3RGbG93fVxyXG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkPXtzZWxlY3RlZH0gLz5cclxuICAgICAgICAgICAgICAgIHtkZXRhaWxzfVxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICApO1xyXG4gICAgfVxyXG59KTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gTWFpblZpZXc7XHJcbiIsInZhciBSZWFjdCA9IHJlcXVpcmUoXCJyZWFjdFwiKTtcclxudmFyIFJlYWN0Um91dGVyID0gcmVxdWlyZShcInJlYWN0LXJvdXRlclwiKTtcclxudmFyIF8gPSByZXF1aXJlKFwibG9kYXNoXCIpO1xyXG5cclxudmFyIGNvbW1vbiA9IHJlcXVpcmUoXCIuL2NvbW1vbi5qc1wiKTtcclxudmFyIE1haW5WaWV3ID0gcmVxdWlyZShcIi4vbWFpbnZpZXcuanNcIik7XHJcbnZhciBGb290ZXIgPSByZXF1aXJlKFwiLi9mb290ZXIuanNcIik7XHJcbnZhciBoZWFkZXIgPSByZXF1aXJlKFwiLi9oZWFkZXIuanNcIik7XHJcbnZhciBFdmVudExvZyA9IHJlcXVpcmUoXCIuL2V2ZW50bG9nLmpzXCIpO1xyXG52YXIgc3RvcmUgPSByZXF1aXJlKFwiLi4vc3RvcmUvc3RvcmUuanNcIik7XHJcblxyXG5cclxuLy9UT0RPOiBNb3ZlIG91dCBvZiBoZXJlLCBqdXN0IGEgc3R1Yi5cclxudmFyIFJlcG9ydHMgPSBSZWFjdC5jcmVhdGVDbGFzcyh7XHJcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4gPGRpdj5SZXBvcnRFZGl0b3I8L2Rpdj47XHJcbiAgICB9XHJcbn0pO1xyXG5cclxuXHJcbnZhciBQcm94eUFwcE1haW4gPSBSZWFjdC5jcmVhdGVDbGFzcyh7XHJcbiAgICBtaXhpbnM6IFtjb21tb24uU3RhdGVdLFxyXG4gICAgZ2V0SW5pdGlhbFN0YXRlOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdmFyIGV2ZW50U3RvcmUgPSBuZXcgc3RvcmUuRXZlbnRMb2dTdG9yZSgpO1xyXG4gICAgICAgIHZhciBmbG93U3RvcmUgPSBuZXcgc3RvcmUuRmxvd1N0b3JlKCk7XHJcbiAgICAgICAgdmFyIHNldHRpbmdzID0gbmV3IHN0b3JlLlNldHRpbmdzU3RvcmUoKTtcclxuXHJcbiAgICAgICAgLy8gRGVmYXVsdCBTZXR0aW5ncyBiZWZvcmUgZmV0Y2hcclxuICAgICAgICBfLmV4dGVuZChzZXR0aW5ncy5kaWN0LHtcclxuICAgICAgICB9KTtcclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICBzZXR0aW5nczogc2V0dGluZ3MsXHJcbiAgICAgICAgICAgIGZsb3dTdG9yZTogZmxvd1N0b3JlLFxyXG4gICAgICAgICAgICBldmVudFN0b3JlOiBldmVudFN0b3JlXHJcbiAgICAgICAgfTtcclxuICAgIH0sXHJcbiAgICBjb21wb25lbnREaWRNb3VudDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHRoaXMuc3RhdGUuc2V0dGluZ3MuYWRkTGlzdGVuZXIoXCJyZWNhbGN1bGF0ZVwiLCB0aGlzLm9uU2V0dGluZ3NDaGFuZ2UpO1xyXG4gICAgICAgIHdpbmRvdy5hcHAgPSB0aGlzO1xyXG4gICAgfSxcclxuICAgIGNvbXBvbmVudFdpbGxVbm1vdW50OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdGhpcy5zdGF0ZS5zZXR0aW5ncy5yZW1vdmVMaXN0ZW5lcihcInJlY2FsY3VsYXRlXCIsIHRoaXMub25TZXR0aW5nc0NoYW5nZSk7XHJcbiAgICB9LFxyXG4gICAgb25TZXR0aW5nc0NoYW5nZTogZnVuY3Rpb24oKXtcclxuICAgICAgICB0aGlzLnNldFN0YXRlKHtcclxuICAgICAgICAgICAgc2V0dGluZ3M6IHRoaXMuc3RhdGUuc2V0dGluZ3NcclxuICAgICAgICB9KTtcclxuICAgIH0sXHJcbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcclxuXHJcbiAgICAgICAgdmFyIGV2ZW50bG9nO1xyXG4gICAgICAgIGlmICh0aGlzLmdldFF1ZXJ5KClbUXVlcnkuU0hPV19FVkVOVExPR10pIHtcclxuICAgICAgICAgICAgZXZlbnRsb2cgPSBbXHJcbiAgICAgICAgICAgICAgICA8Y29tbW9uLlNwbGl0dGVyIGtleT1cInNwbGl0dGVyXCIgYXhpcz1cInlcIi8+LFxyXG4gICAgICAgICAgICAgICAgPEV2ZW50TG9nIGtleT1cImV2ZW50bG9nXCIgZXZlbnRTdG9yZT17dGhpcy5zdGF0ZS5ldmVudFN0b3JlfS8+XHJcbiAgICAgICAgICAgIF07XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgZXZlbnRsb2cgPSBudWxsO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgPGRpdiBpZD1cImNvbnRhaW5lclwiPlxyXG4gICAgICAgICAgICAgICAgPGhlYWRlci5IZWFkZXIgc2V0dGluZ3M9e3RoaXMuc3RhdGUuc2V0dGluZ3MuZGljdH0vPlxyXG4gICAgICAgICAgICAgICAgPFJvdXRlSGFuZGxlciBzZXR0aW5ncz17dGhpcy5zdGF0ZS5zZXR0aW5ncy5kaWN0fSBmbG93U3RvcmU9e3RoaXMuc3RhdGUuZmxvd1N0b3JlfS8+XHJcbiAgICAgICAgICAgICAgICB7ZXZlbnRsb2d9XHJcbiAgICAgICAgICAgICAgICA8Rm9vdGVyIHNldHRpbmdzPXt0aGlzLnN0YXRlLnNldHRpbmdzLmRpY3R9Lz5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgKTtcclxuICAgIH1cclxufSk7XHJcblxyXG5cclxudmFyIFJvdXRlID0gUmVhY3RSb3V0ZXIuUm91dGU7XHJcbnZhciBSb3V0ZUhhbmRsZXIgPSBSZWFjdFJvdXRlci5Sb3V0ZUhhbmRsZXI7XHJcbnZhciBSZWRpcmVjdCA9IFJlYWN0Um91dGVyLlJlZGlyZWN0O1xyXG52YXIgRGVmYXVsdFJvdXRlID0gUmVhY3RSb3V0ZXIuRGVmYXVsdFJvdXRlO1xyXG52YXIgTm90Rm91bmRSb3V0ZSA9IFJlYWN0Um91dGVyLk5vdEZvdW5kUm91dGU7XHJcblxyXG5cclxudmFyIHJvdXRlcyA9IChcclxuICAgIDxSb3V0ZSBwYXRoPVwiL1wiIGhhbmRsZXI9e1Byb3h5QXBwTWFpbn0+XHJcbiAgICAgICAgPFJvdXRlIG5hbWU9XCJmbG93c1wiIHBhdGg9XCJmbG93c1wiIGhhbmRsZXI9e01haW5WaWV3fS8+XHJcbiAgICAgICAgPFJvdXRlIG5hbWU9XCJmbG93XCIgcGF0aD1cImZsb3dzLzpmbG93SWQvOmRldGFpbFRhYlwiIGhhbmRsZXI9e01haW5WaWV3fS8+XHJcbiAgICAgICAgPFJvdXRlIG5hbWU9XCJyZXBvcnRzXCIgaGFuZGxlcj17UmVwb3J0c30vPlxyXG4gICAgICAgIDxSZWRpcmVjdCBwYXRoPVwiL1wiIHRvPVwiZmxvd3NcIiAvPlxyXG4gICAgPC9Sb3V0ZT5cclxuKTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0ge1xyXG4gICAgcm91dGVzOiByb3V0ZXNcclxufTtcclxuXHJcbiIsInZhciBSZWFjdCA9IHJlcXVpcmUoXCJyZWFjdFwiKTtcclxuXHJcbnZhciBWaXJ0dWFsU2Nyb2xsTWl4aW4gPSB7XHJcbiAgICBnZXRJbml0aWFsU3RhdGU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICBzdGFydDogMCxcclxuICAgICAgICAgICAgc3RvcDogMFxyXG4gICAgICAgIH07XHJcbiAgICB9LFxyXG4gICAgY29tcG9uZW50V2lsbE1vdW50OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgaWYgKCF0aGlzLnByb3BzLnJvd0hlaWdodCkge1xyXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXCJWaXJ0dWFsU2Nyb2xsTWl4aW46IE5vIHJvd0hlaWdodCBzcGVjaWZpZWRcIiwgdGhpcyk7XHJcbiAgICAgICAgfVxyXG4gICAgfSxcclxuICAgIGdldFBsYWNlaG9sZGVyVG9wOiBmdW5jdGlvbiAodG90YWwpIHtcclxuICAgICAgICB2YXIgVGFnID0gdGhpcy5wcm9wcy5wbGFjZWhvbGRlclRhZ05hbWUgfHwgXCJ0clwiO1xyXG4gICAgICAgIC8vIFdoZW4gYSBsYXJnZSB0cnVuayBvZiBlbGVtZW50cyBpcyByZW1vdmVkIGZyb20gdGhlIGJ1dHRvbiwgc3RhcnQgbWF5IGJlIGZhciBvZmYgdGhlIHZpZXdwb3J0LlxyXG4gICAgICAgIC8vIFRvIG1ha2UgdGhpcyBpc3N1ZSBsZXNzIHNldmVyZSwgbGltaXQgdGhlIHRvcCBwbGFjZWhvbGRlciB0byB0aGUgdG90YWwgbnVtYmVyIG9mIHJvd3MuXHJcbiAgICAgICAgdmFyIHN0eWxlID0ge1xyXG4gICAgICAgICAgICBoZWlnaHQ6IE1hdGgubWluKHRoaXMuc3RhdGUuc3RhcnQsIHRvdGFsKSAqIHRoaXMucHJvcHMucm93SGVpZ2h0XHJcbiAgICAgICAgfTtcclxuICAgICAgICB2YXIgc3BhY2VyID0gPFRhZyBrZXk9XCJwbGFjZWhvbGRlci10b3BcIiBzdHlsZT17c3R5bGV9PjwvVGFnPjtcclxuXHJcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUuc3RhcnQgJSAyID09PSAxKSB7XHJcbiAgICAgICAgICAgIC8vIGZpeCBldmVuL29kZCByb3dzXHJcbiAgICAgICAgICAgIHJldHVybiBbc3BhY2VyLCA8VGFnIGtleT1cInBsYWNlaG9sZGVyLXRvcC0yXCI+PC9UYWc+XTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gc3BhY2VyO1xyXG4gICAgICAgIH1cclxuICAgIH0sXHJcbiAgICBnZXRQbGFjZWhvbGRlckJvdHRvbTogZnVuY3Rpb24gKHRvdGFsKSB7XHJcbiAgICAgICAgdmFyIFRhZyA9IHRoaXMucHJvcHMucGxhY2Vob2xkZXJUYWdOYW1lIHx8IFwidHJcIjtcclxuICAgICAgICB2YXIgc3R5bGUgPSB7XHJcbiAgICAgICAgICAgIGhlaWdodDogTWF0aC5tYXgoMCwgdG90YWwgLSB0aGlzLnN0YXRlLnN0b3ApICogdGhpcy5wcm9wcy5yb3dIZWlnaHRcclxuICAgICAgICB9O1xyXG4gICAgICAgIHJldHVybiA8VGFnIGtleT1cInBsYWNlaG9sZGVyLWJvdHRvbVwiIHN0eWxlPXtzdHlsZX0+PC9UYWc+O1xyXG4gICAgfSxcclxuICAgIGNvbXBvbmVudERpZE1vdW50OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdGhpcy5vblNjcm9sbCgpO1xyXG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdyZXNpemUnLCB0aGlzLm9uU2Nyb2xsKTtcclxuICAgIH0sXHJcbiAgICBjb21wb25lbnRXaWxsVW5tb3VudDogZnVuY3Rpb24oKXtcclxuICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5vblNjcm9sbCk7XHJcbiAgICB9LFxyXG4gICAgb25TY3JvbGw6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICB2YXIgdmlld3BvcnQgPSB0aGlzLmdldERPTU5vZGUoKTtcclxuICAgICAgICB2YXIgdG9wID0gdmlld3BvcnQuc2Nyb2xsVG9wO1xyXG4gICAgICAgIHZhciBoZWlnaHQgPSB2aWV3cG9ydC5vZmZzZXRIZWlnaHQ7XHJcbiAgICAgICAgdmFyIHN0YXJ0ID0gTWF0aC5mbG9vcih0b3AgLyB0aGlzLnByb3BzLnJvd0hlaWdodCk7XHJcbiAgICAgICAgdmFyIHN0b3AgPSBzdGFydCArIE1hdGguY2VpbChoZWlnaHQgLyAodGhpcy5wcm9wcy5yb3dIZWlnaHRNaW4gfHwgdGhpcy5wcm9wcy5yb3dIZWlnaHQpKTtcclxuXHJcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XHJcbiAgICAgICAgICAgIHN0YXJ0OiBzdGFydCxcclxuICAgICAgICAgICAgc3RvcDogc3RvcFxyXG4gICAgICAgIH0pO1xyXG4gICAgfSxcclxuICAgIHJlbmRlclJvd3M6IGZ1bmN0aW9uIChlbGVtcykge1xyXG4gICAgICAgIHZhciByb3dzID0gW107XHJcbiAgICAgICAgdmFyIG1heCA9IE1hdGgubWluKGVsZW1zLmxlbmd0aCwgdGhpcy5zdGF0ZS5zdG9wKTtcclxuXHJcbiAgICAgICAgZm9yICh2YXIgaSA9IHRoaXMuc3RhdGUuc3RhcnQ7IGkgPCBtYXg7IGkrKykge1xyXG4gICAgICAgICAgICB2YXIgZWxlbSA9IGVsZW1zW2ldO1xyXG4gICAgICAgICAgICByb3dzLnB1c2godGhpcy5yZW5kZXJSb3coZWxlbSkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gcm93cztcclxuICAgIH0sXHJcbiAgICBzY3JvbGxSb3dJbnRvVmlldzogZnVuY3Rpb24gKGluZGV4LCBoZWFkX2hlaWdodCkge1xyXG5cclxuICAgICAgICB2YXIgcm93X3RvcCA9IChpbmRleCAqIHRoaXMucHJvcHMucm93SGVpZ2h0KSArIGhlYWRfaGVpZ2h0O1xyXG4gICAgICAgIHZhciByb3dfYm90dG9tID0gcm93X3RvcCArIHRoaXMucHJvcHMucm93SGVpZ2h0O1xyXG5cclxuICAgICAgICB2YXIgdmlld3BvcnQgPSB0aGlzLmdldERPTU5vZGUoKTtcclxuICAgICAgICB2YXIgdmlld3BvcnRfdG9wID0gdmlld3BvcnQuc2Nyb2xsVG9wO1xyXG4gICAgICAgIHZhciB2aWV3cG9ydF9ib3R0b20gPSB2aWV3cG9ydF90b3AgKyB2aWV3cG9ydC5vZmZzZXRIZWlnaHQ7XHJcblxyXG4gICAgICAgIC8vIEFjY291bnQgZm9yIHBpbm5lZCB0aGVhZFxyXG4gICAgICAgIGlmIChyb3dfdG9wIC0gaGVhZF9oZWlnaHQgPCB2aWV3cG9ydF90b3ApIHtcclxuICAgICAgICAgICAgdmlld3BvcnQuc2Nyb2xsVG9wID0gcm93X3RvcCAtIGhlYWRfaGVpZ2h0O1xyXG4gICAgICAgIH0gZWxzZSBpZiAocm93X2JvdHRvbSA+IHZpZXdwb3J0X2JvdHRvbSkge1xyXG4gICAgICAgICAgICB2aWV3cG9ydC5zY3JvbGxUb3AgPSByb3dfYm90dG9tIC0gdmlld3BvcnQub2Zmc2V0SGVpZ2h0O1xyXG4gICAgICAgIH1cclxuICAgIH0sXHJcbn07XHJcblxyXG5tb2R1bGUuZXhwb3J0cyAgPSBWaXJ0dWFsU2Nyb2xsTWl4aW47IiwiXHJcbnZhciBhY3Rpb25zID0gcmVxdWlyZShcIi4vYWN0aW9ucy5qc1wiKTtcclxuXHJcbmZ1bmN0aW9uIENvbm5lY3Rpb24odXJsKSB7XHJcbiAgICBpZiAodXJsWzBdID09PSBcIi9cIikge1xyXG4gICAgICAgIHVybCA9IGxvY2F0aW9uLm9yaWdpbi5yZXBsYWNlKFwiaHR0cFwiLCBcIndzXCIpICsgdXJsO1xyXG4gICAgfVxyXG5cclxuICAgIHZhciB3cyA9IG5ldyBXZWJTb2NrZXQodXJsKTtcclxuICAgIHdzLm9ub3BlbiA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICBhY3Rpb25zLkNvbm5lY3Rpb25BY3Rpb25zLm9wZW4oKTtcclxuICAgIH07XHJcbiAgICB3cy5vbm1lc3NhZ2UgPSBmdW5jdGlvbiAobWVzc2FnZSkge1xyXG4gICAgICAgIHZhciBtID0gSlNPTi5wYXJzZShtZXNzYWdlLmRhdGEpO1xyXG4gICAgICAgIEFwcERpc3BhdGNoZXIuZGlzcGF0Y2hTZXJ2ZXJBY3Rpb24obSk7XHJcbiAgICB9O1xyXG4gICAgd3Mub25lcnJvciA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICBhY3Rpb25zLkNvbm5lY3Rpb25BY3Rpb25zLmVycm9yKCk7XHJcbiAgICAgICAgRXZlbnRMb2dBY3Rpb25zLmFkZF9ldmVudChcIldlYlNvY2tldCBjb25uZWN0aW9uIGVycm9yLlwiKTtcclxuICAgIH07XHJcbiAgICB3cy5vbmNsb3NlID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIGFjdGlvbnMuQ29ubmVjdGlvbkFjdGlvbnMuY2xvc2UoKTtcclxuICAgICAgICBFdmVudExvZ0FjdGlvbnMuYWRkX2V2ZW50KFwiV2ViU29ja2V0IGNvbm5lY3Rpb24gY2xvc2VkLlwiKTtcclxuICAgIH07XHJcbiAgICByZXR1cm4gd3M7XHJcbn1cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gQ29ubmVjdGlvbjsiLCJcclxudmFyIGZsdXggPSByZXF1aXJlKFwiZmx1eFwiKTtcclxuXHJcbmNvbnN0IFBheWxvYWRTb3VyY2VzID0ge1xyXG4gICAgVklFVzogXCJ2aWV3XCIsXHJcbiAgICBTRVJWRVI6IFwic2VydmVyXCJcclxufTtcclxuXHJcblxyXG5BcHBEaXNwYXRjaGVyID0gbmV3IGZsdXguRGlzcGF0Y2hlcigpO1xyXG5BcHBEaXNwYXRjaGVyLmRpc3BhdGNoVmlld0FjdGlvbiA9IGZ1bmN0aW9uIChhY3Rpb24pIHtcclxuICAgIGFjdGlvbi5zb3VyY2UgPSBQYXlsb2FkU291cmNlcy5WSUVXO1xyXG4gICAgdGhpcy5kaXNwYXRjaChhY3Rpb24pO1xyXG59O1xyXG5BcHBEaXNwYXRjaGVyLmRpc3BhdGNoU2VydmVyQWN0aW9uID0gZnVuY3Rpb24gKGFjdGlvbikge1xyXG4gICAgYWN0aW9uLnNvdXJjZSA9IFBheWxvYWRTb3VyY2VzLlNFUlZFUjtcclxuICAgIHRoaXMuZGlzcGF0Y2goYWN0aW9uKTtcclxufTtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0ge1xyXG4gICAgQXBwRGlzcGF0Y2hlcjogQXBwRGlzcGF0Y2hlclxyXG59OyIsIm1vZHVsZS5leHBvcnRzID0gKGZ1bmN0aW9uKCkge1xuICAvKlxuICAgKiBHZW5lcmF0ZWQgYnkgUEVHLmpzIDAuOC4wLlxuICAgKlxuICAgKiBodHRwOi8vcGVnanMubWFqZGEuY3ovXG4gICAqL1xuXG4gIGZ1bmN0aW9uIHBlZyRzdWJjbGFzcyhjaGlsZCwgcGFyZW50KSB7XG4gICAgZnVuY3Rpb24gY3RvcigpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGNoaWxkOyB9XG4gICAgY3Rvci5wcm90b3R5cGUgPSBwYXJlbnQucHJvdG90eXBlO1xuICAgIGNoaWxkLnByb3RvdHlwZSA9IG5ldyBjdG9yKCk7XG4gIH1cblxuICBmdW5jdGlvbiBTeW50YXhFcnJvcihtZXNzYWdlLCBleHBlY3RlZCwgZm91bmQsIG9mZnNldCwgbGluZSwgY29sdW1uKSB7XG4gICAgdGhpcy5tZXNzYWdlICA9IG1lc3NhZ2U7XG4gICAgdGhpcy5leHBlY3RlZCA9IGV4cGVjdGVkO1xuICAgIHRoaXMuZm91bmQgICAgPSBmb3VuZDtcbiAgICB0aGlzLm9mZnNldCAgID0gb2Zmc2V0O1xuICAgIHRoaXMubGluZSAgICAgPSBsaW5lO1xuICAgIHRoaXMuY29sdW1uICAgPSBjb2x1bW47XG5cbiAgICB0aGlzLm5hbWUgICAgID0gXCJTeW50YXhFcnJvclwiO1xuICB9XG5cbiAgcGVnJHN1YmNsYXNzKFN5bnRheEVycm9yLCBFcnJvcik7XG5cbiAgZnVuY3Rpb24gcGFyc2UoaW5wdXQpIHtcbiAgICB2YXIgb3B0aW9ucyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxID8gYXJndW1lbnRzWzFdIDoge30sXG5cbiAgICAgICAgcGVnJEZBSUxFRCA9IHt9LFxuXG4gICAgICAgIHBlZyRzdGFydFJ1bGVGdW5jdGlvbnMgPSB7IHN0YXJ0OiBwZWckcGFyc2VzdGFydCB9LFxuICAgICAgICBwZWckc3RhcnRSdWxlRnVuY3Rpb24gID0gcGVnJHBhcnNlc3RhcnQsXG5cbiAgICAgICAgcGVnJGMwID0geyB0eXBlOiBcIm90aGVyXCIsIGRlc2NyaXB0aW9uOiBcImZpbHRlciBleHByZXNzaW9uXCIgfSxcbiAgICAgICAgcGVnJGMxID0gcGVnJEZBSUxFRCxcbiAgICAgICAgcGVnJGMyID0gZnVuY3Rpb24ob3JFeHByKSB7IHJldHVybiBvckV4cHI7IH0sXG4gICAgICAgIHBlZyRjMyA9IFtdLFxuICAgICAgICBwZWckYzQgPSBmdW5jdGlvbigpIHtyZXR1cm4gdHJ1ZUZpbHRlcjsgfSxcbiAgICAgICAgcGVnJGM1ID0geyB0eXBlOiBcIm90aGVyXCIsIGRlc2NyaXB0aW9uOiBcIndoaXRlc3BhY2VcIiB9LFxuICAgICAgICBwZWckYzYgPSAvXlsgXFx0XFxuXFxyXS8sXG4gICAgICAgIHBlZyRjNyA9IHsgdHlwZTogXCJjbGFzc1wiLCB2YWx1ZTogXCJbIFxcXFx0XFxcXG5cXFxccl1cIiwgZGVzY3JpcHRpb246IFwiWyBcXFxcdFxcXFxuXFxcXHJdXCIgfSxcbiAgICAgICAgcGVnJGM4ID0geyB0eXBlOiBcIm90aGVyXCIsIGRlc2NyaXB0aW9uOiBcImNvbnRyb2wgY2hhcmFjdGVyXCIgfSxcbiAgICAgICAgcGVnJGM5ID0gL15bfCYhKCl+XCJdLyxcbiAgICAgICAgcGVnJGMxMCA9IHsgdHlwZTogXCJjbGFzc1wiLCB2YWx1ZTogXCJbfCYhKCl+XFxcIl1cIiwgZGVzY3JpcHRpb246IFwiW3wmISgpflxcXCJdXCIgfSxcbiAgICAgICAgcGVnJGMxMSA9IHsgdHlwZTogXCJvdGhlclwiLCBkZXNjcmlwdGlvbjogXCJvcHRpb25hbCB3aGl0ZXNwYWNlXCIgfSxcbiAgICAgICAgcGVnJGMxMiA9IFwifFwiLFxuICAgICAgICBwZWckYzEzID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwifFwiLCBkZXNjcmlwdGlvbjogXCJcXFwifFxcXCJcIiB9LFxuICAgICAgICBwZWckYzE0ID0gZnVuY3Rpb24oZmlyc3QsIHNlY29uZCkgeyByZXR1cm4gb3IoZmlyc3QsIHNlY29uZCk7IH0sXG4gICAgICAgIHBlZyRjMTUgPSBcIiZcIixcbiAgICAgICAgcGVnJGMxNiA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcIiZcIiwgZGVzY3JpcHRpb246IFwiXFxcIiZcXFwiXCIgfSxcbiAgICAgICAgcGVnJGMxNyA9IGZ1bmN0aW9uKGZpcnN0LCBzZWNvbmQpIHsgcmV0dXJuIGFuZChmaXJzdCwgc2Vjb25kKTsgfSxcbiAgICAgICAgcGVnJGMxOCA9IFwiIVwiLFxuICAgICAgICBwZWckYzE5ID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwiIVwiLCBkZXNjcmlwdGlvbjogXCJcXFwiIVxcXCJcIiB9LFxuICAgICAgICBwZWckYzIwID0gZnVuY3Rpb24oZXhwcikgeyByZXR1cm4gbm90KGV4cHIpOyB9LFxuICAgICAgICBwZWckYzIxID0gXCIoXCIsXG4gICAgICAgIHBlZyRjMjIgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCIoXCIsIGRlc2NyaXB0aW9uOiBcIlxcXCIoXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjMjMgPSBcIilcIixcbiAgICAgICAgcGVnJGMyNCA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcIilcIiwgZGVzY3JpcHRpb246IFwiXFxcIilcXFwiXCIgfSxcbiAgICAgICAgcGVnJGMyNSA9IGZ1bmN0aW9uKGV4cHIpIHsgcmV0dXJuIGJpbmRpbmcoZXhwcik7IH0sXG4gICAgICAgIHBlZyRjMjYgPSBcIn5hXCIsXG4gICAgICAgIHBlZyRjMjcgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJ+YVwiLCBkZXNjcmlwdGlvbjogXCJcXFwifmFcXFwiXCIgfSxcbiAgICAgICAgcGVnJGMyOCA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gYXNzZXRGaWx0ZXI7IH0sXG4gICAgICAgIHBlZyRjMjkgPSBcIn5lXCIsXG4gICAgICAgIHBlZyRjMzAgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJ+ZVwiLCBkZXNjcmlwdGlvbjogXCJcXFwifmVcXFwiXCIgfSxcbiAgICAgICAgcGVnJGMzMSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gZXJyb3JGaWx0ZXI7IH0sXG4gICAgICAgIHBlZyRjMzIgPSBcIn5xXCIsXG4gICAgICAgIHBlZyRjMzMgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJ+cVwiLCBkZXNjcmlwdGlvbjogXCJcXFwifnFcXFwiXCIgfSxcbiAgICAgICAgcGVnJGMzNCA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gbm9SZXNwb25zZUZpbHRlcjsgfSxcbiAgICAgICAgcGVnJGMzNSA9IFwifnNcIixcbiAgICAgICAgcGVnJGMzNiA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcIn5zXCIsIGRlc2NyaXB0aW9uOiBcIlxcXCJ+c1xcXCJcIiB9LFxuICAgICAgICBwZWckYzM3ID0gZnVuY3Rpb24oKSB7IHJldHVybiByZXNwb25zZUZpbHRlcjsgfSxcbiAgICAgICAgcGVnJGMzOCA9IFwidHJ1ZVwiLFxuICAgICAgICBwZWckYzM5ID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwidHJ1ZVwiLCBkZXNjcmlwdGlvbjogXCJcXFwidHJ1ZVxcXCJcIiB9LFxuICAgICAgICBwZWckYzQwID0gZnVuY3Rpb24oKSB7IHJldHVybiB0cnVlRmlsdGVyOyB9LFxuICAgICAgICBwZWckYzQxID0gXCJmYWxzZVwiLFxuICAgICAgICBwZWckYzQyID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwiZmFsc2VcIiwgZGVzY3JpcHRpb246IFwiXFxcImZhbHNlXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjNDMgPSBmdW5jdGlvbigpIHsgcmV0dXJuIGZhbHNlRmlsdGVyOyB9LFxuICAgICAgICBwZWckYzQ0ID0gXCJ+Y1wiLFxuICAgICAgICBwZWckYzQ1ID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwifmNcIiwgZGVzY3JpcHRpb246IFwiXFxcIn5jXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjNDYgPSBmdW5jdGlvbihzKSB7IHJldHVybiByZXNwb25zZUNvZGUocyk7IH0sXG4gICAgICAgIHBlZyRjNDcgPSBcIn5kXCIsXG4gICAgICAgIHBlZyRjNDggPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJ+ZFwiLCBkZXNjcmlwdGlvbjogXCJcXFwifmRcXFwiXCIgfSxcbiAgICAgICAgcGVnJGM0OSA9IGZ1bmN0aW9uKHMpIHsgcmV0dXJuIGRvbWFpbihzKTsgfSxcbiAgICAgICAgcGVnJGM1MCA9IFwifmhcIixcbiAgICAgICAgcGVnJGM1MSA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcIn5oXCIsIGRlc2NyaXB0aW9uOiBcIlxcXCJ+aFxcXCJcIiB9LFxuICAgICAgICBwZWckYzUyID0gZnVuY3Rpb24ocykgeyByZXR1cm4gaGVhZGVyKHMpOyB9LFxuICAgICAgICBwZWckYzUzID0gXCJ+aHFcIixcbiAgICAgICAgcGVnJGM1NCA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcIn5ocVwiLCBkZXNjcmlwdGlvbjogXCJcXFwifmhxXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjNTUgPSBmdW5jdGlvbihzKSB7IHJldHVybiByZXF1ZXN0SGVhZGVyKHMpOyB9LFxuICAgICAgICBwZWckYzU2ID0gXCJ+aHNcIixcbiAgICAgICAgcGVnJGM1NyA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcIn5oc1wiLCBkZXNjcmlwdGlvbjogXCJcXFwifmhzXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjNTggPSBmdW5jdGlvbihzKSB7IHJldHVybiByZXNwb25zZUhlYWRlcihzKTsgfSxcbiAgICAgICAgcGVnJGM1OSA9IFwifm1cIixcbiAgICAgICAgcGVnJGM2MCA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcIn5tXCIsIGRlc2NyaXB0aW9uOiBcIlxcXCJ+bVxcXCJcIiB9LFxuICAgICAgICBwZWckYzYxID0gZnVuY3Rpb24ocykgeyByZXR1cm4gbWV0aG9kKHMpOyB9LFxuICAgICAgICBwZWckYzYyID0gXCJ+dFwiLFxuICAgICAgICBwZWckYzYzID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwifnRcIiwgZGVzY3JpcHRpb246IFwiXFxcIn50XFxcIlwiIH0sXG4gICAgICAgIHBlZyRjNjQgPSBmdW5jdGlvbihzKSB7IHJldHVybiBjb250ZW50VHlwZShzKTsgfSxcbiAgICAgICAgcGVnJGM2NSA9IFwifnRxXCIsXG4gICAgICAgIHBlZyRjNjYgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJ+dHFcIiwgZGVzY3JpcHRpb246IFwiXFxcIn50cVxcXCJcIiB9LFxuICAgICAgICBwZWckYzY3ID0gZnVuY3Rpb24ocykgeyByZXR1cm4gcmVxdWVzdENvbnRlbnRUeXBlKHMpOyB9LFxuICAgICAgICBwZWckYzY4ID0gXCJ+dHNcIixcbiAgICAgICAgcGVnJGM2OSA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcIn50c1wiLCBkZXNjcmlwdGlvbjogXCJcXFwifnRzXFxcIlwiIH0sXG4gICAgICAgIHBlZyRjNzAgPSBmdW5jdGlvbihzKSB7IHJldHVybiByZXNwb25zZUNvbnRlbnRUeXBlKHMpOyB9LFxuICAgICAgICBwZWckYzcxID0gXCJ+dVwiLFxuICAgICAgICBwZWckYzcyID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwifnVcIiwgZGVzY3JpcHRpb246IFwiXFxcIn51XFxcIlwiIH0sXG4gICAgICAgIHBlZyRjNzMgPSBmdW5jdGlvbihzKSB7IHJldHVybiB1cmwocyk7IH0sXG4gICAgICAgIHBlZyRjNzQgPSB7IHR5cGU6IFwib3RoZXJcIiwgZGVzY3JpcHRpb246IFwiaW50ZWdlclwiIH0sXG4gICAgICAgIHBlZyRjNzUgPSBudWxsLFxuICAgICAgICBwZWckYzc2ID0gL15bJ1wiXS8sXG4gICAgICAgIHBlZyRjNzcgPSB7IHR5cGU6IFwiY2xhc3NcIiwgdmFsdWU6IFwiWydcXFwiXVwiLCBkZXNjcmlwdGlvbjogXCJbJ1xcXCJdXCIgfSxcbiAgICAgICAgcGVnJGM3OCA9IC9eWzAtOV0vLFxuICAgICAgICBwZWckYzc5ID0geyB0eXBlOiBcImNsYXNzXCIsIHZhbHVlOiBcIlswLTldXCIsIGRlc2NyaXB0aW9uOiBcIlswLTldXCIgfSxcbiAgICAgICAgcGVnJGM4MCA9IGZ1bmN0aW9uKGRpZ2l0cykgeyByZXR1cm4gcGFyc2VJbnQoZGlnaXRzLmpvaW4oXCJcIiksIDEwKTsgfSxcbiAgICAgICAgcGVnJGM4MSA9IHsgdHlwZTogXCJvdGhlclwiLCBkZXNjcmlwdGlvbjogXCJzdHJpbmdcIiB9LFxuICAgICAgICBwZWckYzgyID0gXCJcXFwiXCIsXG4gICAgICAgIHBlZyRjODMgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJcXFwiXCIsIGRlc2NyaXB0aW9uOiBcIlxcXCJcXFxcXFxcIlxcXCJcIiB9LFxuICAgICAgICBwZWckYzg0ID0gZnVuY3Rpb24oY2hhcnMpIHsgcmV0dXJuIGNoYXJzLmpvaW4oXCJcIik7IH0sXG4gICAgICAgIHBlZyRjODUgPSBcIidcIixcbiAgICAgICAgcGVnJGM4NiA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcIidcIiwgZGVzY3JpcHRpb246IFwiXFxcIidcXFwiXCIgfSxcbiAgICAgICAgcGVnJGM4NyA9IHZvaWQgMCxcbiAgICAgICAgcGVnJGM4OCA9IC9eW1wiXFxcXF0vLFxuICAgICAgICBwZWckYzg5ID0geyB0eXBlOiBcImNsYXNzXCIsIHZhbHVlOiBcIltcXFwiXFxcXFxcXFxdXCIsIGRlc2NyaXB0aW9uOiBcIltcXFwiXFxcXFxcXFxdXCIgfSxcbiAgICAgICAgcGVnJGM5MCA9IHsgdHlwZTogXCJhbnlcIiwgZGVzY3JpcHRpb246IFwiYW55IGNoYXJhY3RlclwiIH0sXG4gICAgICAgIHBlZyRjOTEgPSBmdW5jdGlvbihjaGFyKSB7IHJldHVybiBjaGFyOyB9LFxuICAgICAgICBwZWckYzkyID0gXCJcXFxcXCIsXG4gICAgICAgIHBlZyRjOTMgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJcXFxcXCIsIGRlc2NyaXB0aW9uOiBcIlxcXCJcXFxcXFxcXFxcXCJcIiB9LFxuICAgICAgICBwZWckYzk0ID0gL15bJ1xcXFxdLyxcbiAgICAgICAgcGVnJGM5NSA9IHsgdHlwZTogXCJjbGFzc1wiLCB2YWx1ZTogXCJbJ1xcXFxcXFxcXVwiLCBkZXNjcmlwdGlvbjogXCJbJ1xcXFxcXFxcXVwiIH0sXG4gICAgICAgIHBlZyRjOTYgPSAvXlsnXCJcXFxcXS8sXG4gICAgICAgIHBlZyRjOTcgPSB7IHR5cGU6IFwiY2xhc3NcIiwgdmFsdWU6IFwiWydcXFwiXFxcXFxcXFxdXCIsIGRlc2NyaXB0aW9uOiBcIlsnXFxcIlxcXFxcXFxcXVwiIH0sXG4gICAgICAgIHBlZyRjOTggPSBcIm5cIixcbiAgICAgICAgcGVnJGM5OSA9IHsgdHlwZTogXCJsaXRlcmFsXCIsIHZhbHVlOiBcIm5cIiwgZGVzY3JpcHRpb246IFwiXFxcIm5cXFwiXCIgfSxcbiAgICAgICAgcGVnJGMxMDAgPSBmdW5jdGlvbigpIHsgcmV0dXJuIFwiXFxuXCI7IH0sXG4gICAgICAgIHBlZyRjMTAxID0gXCJyXCIsXG4gICAgICAgIHBlZyRjMTAyID0geyB0eXBlOiBcImxpdGVyYWxcIiwgdmFsdWU6IFwiclwiLCBkZXNjcmlwdGlvbjogXCJcXFwiclxcXCJcIiB9LFxuICAgICAgICBwZWckYzEwMyA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gXCJcXHJcIjsgfSxcbiAgICAgICAgcGVnJGMxMDQgPSBcInRcIixcbiAgICAgICAgcGVnJGMxMDUgPSB7IHR5cGU6IFwibGl0ZXJhbFwiLCB2YWx1ZTogXCJ0XCIsIGRlc2NyaXB0aW9uOiBcIlxcXCJ0XFxcIlwiIH0sXG4gICAgICAgIHBlZyRjMTA2ID0gZnVuY3Rpb24oKSB7IHJldHVybiBcIlxcdFwiOyB9LFxuXG4gICAgICAgIHBlZyRjdXJyUG9zICAgICAgICAgID0gMCxcbiAgICAgICAgcGVnJHJlcG9ydGVkUG9zICAgICAgPSAwLFxuICAgICAgICBwZWckY2FjaGVkUG9zICAgICAgICA9IDAsXG4gICAgICAgIHBlZyRjYWNoZWRQb3NEZXRhaWxzID0geyBsaW5lOiAxLCBjb2x1bW46IDEsIHNlZW5DUjogZmFsc2UgfSxcbiAgICAgICAgcGVnJG1heEZhaWxQb3MgICAgICAgPSAwLFxuICAgICAgICBwZWckbWF4RmFpbEV4cGVjdGVkICA9IFtdLFxuICAgICAgICBwZWckc2lsZW50RmFpbHMgICAgICA9IDAsXG5cbiAgICAgICAgcGVnJHJlc3VsdDtcblxuICAgIGlmIChcInN0YXJ0UnVsZVwiIGluIG9wdGlvbnMpIHtcbiAgICAgIGlmICghKG9wdGlvbnMuc3RhcnRSdWxlIGluIHBlZyRzdGFydFJ1bGVGdW5jdGlvbnMpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbid0IHN0YXJ0IHBhcnNpbmcgZnJvbSBydWxlIFxcXCJcIiArIG9wdGlvbnMuc3RhcnRSdWxlICsgXCJcXFwiLlwiKTtcbiAgICAgIH1cblxuICAgICAgcGVnJHN0YXJ0UnVsZUZ1bmN0aW9uID0gcGVnJHN0YXJ0UnVsZUZ1bmN0aW9uc1tvcHRpb25zLnN0YXJ0UnVsZV07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdGV4dCgpIHtcbiAgICAgIHJldHVybiBpbnB1dC5zdWJzdHJpbmcocGVnJHJlcG9ydGVkUG9zLCBwZWckY3VyclBvcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb2Zmc2V0KCkge1xuICAgICAgcmV0dXJuIHBlZyRyZXBvcnRlZFBvcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsaW5lKCkge1xuICAgICAgcmV0dXJuIHBlZyRjb21wdXRlUG9zRGV0YWlscyhwZWckcmVwb3J0ZWRQb3MpLmxpbmU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29sdW1uKCkge1xuICAgICAgcmV0dXJuIHBlZyRjb21wdXRlUG9zRGV0YWlscyhwZWckcmVwb3J0ZWRQb3MpLmNvbHVtbjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBleHBlY3RlZChkZXNjcmlwdGlvbikge1xuICAgICAgdGhyb3cgcGVnJGJ1aWxkRXhjZXB0aW9uKFxuICAgICAgICBudWxsLFxuICAgICAgICBbeyB0eXBlOiBcIm90aGVyXCIsIGRlc2NyaXB0aW9uOiBkZXNjcmlwdGlvbiB9XSxcbiAgICAgICAgcGVnJHJlcG9ydGVkUG9zXG4gICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVycm9yKG1lc3NhZ2UpIHtcbiAgICAgIHRocm93IHBlZyRidWlsZEV4Y2VwdGlvbihtZXNzYWdlLCBudWxsLCBwZWckcmVwb3J0ZWRQb3MpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBlZyRjb21wdXRlUG9zRGV0YWlscyhwb3MpIHtcbiAgICAgIGZ1bmN0aW9uIGFkdmFuY2UoZGV0YWlscywgc3RhcnRQb3MsIGVuZFBvcykge1xuICAgICAgICB2YXIgcCwgY2g7XG5cbiAgICAgICAgZm9yIChwID0gc3RhcnRQb3M7IHAgPCBlbmRQb3M7IHArKykge1xuICAgICAgICAgIGNoID0gaW5wdXQuY2hhckF0KHApO1xuICAgICAgICAgIGlmIChjaCA9PT0gXCJcXG5cIikge1xuICAgICAgICAgICAgaWYgKCFkZXRhaWxzLnNlZW5DUikgeyBkZXRhaWxzLmxpbmUrKzsgfVxuICAgICAgICAgICAgZGV0YWlscy5jb2x1bW4gPSAxO1xuICAgICAgICAgICAgZGV0YWlscy5zZWVuQ1IgPSBmYWxzZTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGNoID09PSBcIlxcclwiIHx8IGNoID09PSBcIlxcdTIwMjhcIiB8fCBjaCA9PT0gXCJcXHUyMDI5XCIpIHtcbiAgICAgICAgICAgIGRldGFpbHMubGluZSsrO1xuICAgICAgICAgICAgZGV0YWlscy5jb2x1bW4gPSAxO1xuICAgICAgICAgICAgZGV0YWlscy5zZWVuQ1IgPSB0cnVlO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkZXRhaWxzLmNvbHVtbisrO1xuICAgICAgICAgICAgZGV0YWlscy5zZWVuQ1IgPSBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHBlZyRjYWNoZWRQb3MgIT09IHBvcykge1xuICAgICAgICBpZiAocGVnJGNhY2hlZFBvcyA+IHBvcykge1xuICAgICAgICAgIHBlZyRjYWNoZWRQb3MgPSAwO1xuICAgICAgICAgIHBlZyRjYWNoZWRQb3NEZXRhaWxzID0geyBsaW5lOiAxLCBjb2x1bW46IDEsIHNlZW5DUjogZmFsc2UgfTtcbiAgICAgICAgfVxuICAgICAgICBhZHZhbmNlKHBlZyRjYWNoZWRQb3NEZXRhaWxzLCBwZWckY2FjaGVkUG9zLCBwb3MpO1xuICAgICAgICBwZWckY2FjaGVkUG9zID0gcG9zO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcGVnJGNhY2hlZFBvc0RldGFpbHM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJGZhaWwoZXhwZWN0ZWQpIHtcbiAgICAgIGlmIChwZWckY3VyclBvcyA8IHBlZyRtYXhGYWlsUG9zKSB7IHJldHVybjsgfVxuXG4gICAgICBpZiAocGVnJGN1cnJQb3MgPiBwZWckbWF4RmFpbFBvcykge1xuICAgICAgICBwZWckbWF4RmFpbFBvcyA9IHBlZyRjdXJyUG9zO1xuICAgICAgICBwZWckbWF4RmFpbEV4cGVjdGVkID0gW107XG4gICAgICB9XG5cbiAgICAgIHBlZyRtYXhGYWlsRXhwZWN0ZWQucHVzaChleHBlY3RlZCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJGJ1aWxkRXhjZXB0aW9uKG1lc3NhZ2UsIGV4cGVjdGVkLCBwb3MpIHtcbiAgICAgIGZ1bmN0aW9uIGNsZWFudXBFeHBlY3RlZChleHBlY3RlZCkge1xuICAgICAgICB2YXIgaSA9IDE7XG5cbiAgICAgICAgZXhwZWN0ZWQuc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICAgICAgaWYgKGEuZGVzY3JpcHRpb24gPCBiLmRlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgICAgfSBlbHNlIGlmIChhLmRlc2NyaXB0aW9uID4gYi5kZXNjcmlwdGlvbikge1xuICAgICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgd2hpbGUgKGkgPCBleHBlY3RlZC5sZW5ndGgpIHtcbiAgICAgICAgICBpZiAoZXhwZWN0ZWRbaSAtIDFdID09PSBleHBlY3RlZFtpXSkge1xuICAgICAgICAgICAgZXhwZWN0ZWQuc3BsaWNlKGksIDEpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpKys7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGJ1aWxkTWVzc2FnZShleHBlY3RlZCwgZm91bmQpIHtcbiAgICAgICAgZnVuY3Rpb24gc3RyaW5nRXNjYXBlKHMpIHtcbiAgICAgICAgICBmdW5jdGlvbiBoZXgoY2gpIHsgcmV0dXJuIGNoLmNoYXJDb2RlQXQoMCkudG9TdHJpbmcoMTYpLnRvVXBwZXJDYXNlKCk7IH1cblxuICAgICAgICAgIHJldHVybiBzXG4gICAgICAgICAgICAucmVwbGFjZSgvXFxcXC9nLCAgICdcXFxcXFxcXCcpXG4gICAgICAgICAgICAucmVwbGFjZSgvXCIvZywgICAgJ1xcXFxcIicpXG4gICAgICAgICAgICAucmVwbGFjZSgvXFx4MDgvZywgJ1xcXFxiJylcbiAgICAgICAgICAgIC5yZXBsYWNlKC9cXHQvZywgICAnXFxcXHQnKVxuICAgICAgICAgICAgLnJlcGxhY2UoL1xcbi9nLCAgICdcXFxcbicpXG4gICAgICAgICAgICAucmVwbGFjZSgvXFxmL2csICAgJ1xcXFxmJylcbiAgICAgICAgICAgIC5yZXBsYWNlKC9cXHIvZywgICAnXFxcXHInKVxuICAgICAgICAgICAgLnJlcGxhY2UoL1tcXHgwMC1cXHgwN1xceDBCXFx4MEVcXHgwRl0vZywgZnVuY3Rpb24oY2gpIHsgcmV0dXJuICdcXFxceDAnICsgaGV4KGNoKTsgfSlcbiAgICAgICAgICAgIC5yZXBsYWNlKC9bXFx4MTAtXFx4MUZcXHg4MC1cXHhGRl0vZywgICAgZnVuY3Rpb24oY2gpIHsgcmV0dXJuICdcXFxceCcgICsgaGV4KGNoKTsgfSlcbiAgICAgICAgICAgIC5yZXBsYWNlKC9bXFx1MDE4MC1cXHUwRkZGXS9nLCAgICAgICAgIGZ1bmN0aW9uKGNoKSB7IHJldHVybiAnXFxcXHUwJyArIGhleChjaCk7IH0pXG4gICAgICAgICAgICAucmVwbGFjZSgvW1xcdTEwODAtXFx1RkZGRl0vZywgICAgICAgICBmdW5jdGlvbihjaCkgeyByZXR1cm4gJ1xcXFx1JyAgKyBoZXgoY2gpOyB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBleHBlY3RlZERlc2NzID0gbmV3IEFycmF5KGV4cGVjdGVkLmxlbmd0aCksXG4gICAgICAgICAgICBleHBlY3RlZERlc2MsIGZvdW5kRGVzYywgaTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgZXhwZWN0ZWQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBleHBlY3RlZERlc2NzW2ldID0gZXhwZWN0ZWRbaV0uZGVzY3JpcHRpb247XG4gICAgICAgIH1cblxuICAgICAgICBleHBlY3RlZERlc2MgPSBleHBlY3RlZC5sZW5ndGggPiAxXG4gICAgICAgICAgPyBleHBlY3RlZERlc2NzLnNsaWNlKDAsIC0xKS5qb2luKFwiLCBcIilcbiAgICAgICAgICAgICAgKyBcIiBvciBcIlxuICAgICAgICAgICAgICArIGV4cGVjdGVkRGVzY3NbZXhwZWN0ZWQubGVuZ3RoIC0gMV1cbiAgICAgICAgICA6IGV4cGVjdGVkRGVzY3NbMF07XG5cbiAgICAgICAgZm91bmREZXNjID0gZm91bmQgPyBcIlxcXCJcIiArIHN0cmluZ0VzY2FwZShmb3VuZCkgKyBcIlxcXCJcIiA6IFwiZW5kIG9mIGlucHV0XCI7XG5cbiAgICAgICAgcmV0dXJuIFwiRXhwZWN0ZWQgXCIgKyBleHBlY3RlZERlc2MgKyBcIiBidXQgXCIgKyBmb3VuZERlc2MgKyBcIiBmb3VuZC5cIjtcbiAgICAgIH1cblxuICAgICAgdmFyIHBvc0RldGFpbHMgPSBwZWckY29tcHV0ZVBvc0RldGFpbHMocG9zKSxcbiAgICAgICAgICBmb3VuZCAgICAgID0gcG9zIDwgaW5wdXQubGVuZ3RoID8gaW5wdXQuY2hhckF0KHBvcykgOiBudWxsO1xuXG4gICAgICBpZiAoZXhwZWN0ZWQgIT09IG51bGwpIHtcbiAgICAgICAgY2xlYW51cEV4cGVjdGVkKGV4cGVjdGVkKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG5ldyBTeW50YXhFcnJvcihcbiAgICAgICAgbWVzc2FnZSAhPT0gbnVsbCA/IG1lc3NhZ2UgOiBidWlsZE1lc3NhZ2UoZXhwZWN0ZWQsIGZvdW5kKSxcbiAgICAgICAgZXhwZWN0ZWQsXG4gICAgICAgIGZvdW5kLFxuICAgICAgICBwb3MsXG4gICAgICAgIHBvc0RldGFpbHMubGluZSxcbiAgICAgICAgcG9zRGV0YWlscy5jb2x1bW5cbiAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlc3RhcnQoKSB7XG4gICAgICB2YXIgczAsIHMxLCBzMiwgczM7XG5cbiAgICAgIHBlZyRzaWxlbnRGYWlscysrO1xuICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgIHMxID0gcGVnJHBhcnNlX18oKTtcbiAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMiA9IHBlZyRwYXJzZU9yRXhwcigpO1xuICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBzMyA9IHBlZyRwYXJzZV9fKCk7XG4gICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgIHMxID0gcGVnJGMyKHMyKTtcbiAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICB9XG4gICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgczEgPSBbXTtcbiAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgczEgPSBwZWckYzQoKTtcbiAgICAgICAgfVxuICAgICAgICBzMCA9IHMxO1xuICAgICAgfVxuICAgICAgcGVnJHNpbGVudEZhaWxzLS07XG4gICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjMCk7IH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHMwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBlZyRwYXJzZXdzKCkge1xuICAgICAgdmFyIHMwLCBzMTtcblxuICAgICAgcGVnJHNpbGVudEZhaWxzKys7XG4gICAgICBpZiAocGVnJGM2LnRlc3QoaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKSkpIHtcbiAgICAgICAgczAgPSBpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpO1xuICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgczAgPSBwZWckRkFJTEVEO1xuICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjNyk7IH1cbiAgICAgIH1cbiAgICAgIHBlZyRzaWxlbnRGYWlscy0tO1xuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzUpOyB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckcGFyc2VjYygpIHtcbiAgICAgIHZhciBzMCwgczE7XG5cbiAgICAgIHBlZyRzaWxlbnRGYWlscysrO1xuICAgICAgaWYgKHBlZyRjOS50ZXN0KGlucHV0LmNoYXJBdChwZWckY3VyclBvcykpKSB7XG4gICAgICAgIHMwID0gaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKTtcbiAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHMwID0gcGVnJEZBSUxFRDtcbiAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzEwKTsgfVxuICAgICAgfVxuICAgICAgcGVnJHNpbGVudEZhaWxzLS07XG4gICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjOCk7IH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHMwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBlZyRwYXJzZV9fKCkge1xuICAgICAgdmFyIHMwLCBzMTtcblxuICAgICAgcGVnJHNpbGVudEZhaWxzKys7XG4gICAgICBzMCA9IFtdO1xuICAgICAgczEgPSBwZWckcGFyc2V3cygpO1xuICAgICAgd2hpbGUgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMwLnB1c2goczEpO1xuICAgICAgICBzMSA9IHBlZyRwYXJzZXdzKCk7XG4gICAgICB9XG4gICAgICBwZWckc2lsZW50RmFpbHMtLTtcbiAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGMxMSk7IH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHMwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBlZyRwYXJzZU9yRXhwcigpIHtcbiAgICAgIHZhciBzMCwgczEsIHMyLCBzMywgczQsIHM1O1xuXG4gICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgczEgPSBwZWckcGFyc2VBbmRFeHByKCk7XG4gICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczIgPSBwZWckcGFyc2VfXygpO1xuICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBpZiAoaW5wdXQuY2hhckNvZGVBdChwZWckY3VyclBvcykgPT09IDEyNCkge1xuICAgICAgICAgICAgczMgPSBwZWckYzEyO1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgczMgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzEzKTsgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHM0ID0gcGVnJHBhcnNlX18oKTtcbiAgICAgICAgICAgIGlmIChzNCAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICBzNSA9IHBlZyRwYXJzZU9yRXhwcigpO1xuICAgICAgICAgICAgICBpZiAoczUgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICBzMSA9IHBlZyRjMTQoczEsIHM1KTtcbiAgICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgfVxuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMwID0gcGVnJHBhcnNlQW5kRXhwcigpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlQW5kRXhwcigpIHtcbiAgICAgIHZhciBzMCwgczEsIHMyLCBzMywgczQsIHM1O1xuXG4gICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgczEgPSBwZWckcGFyc2VOb3RFeHByKCk7XG4gICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczIgPSBwZWckcGFyc2VfXygpO1xuICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBpZiAoaW5wdXQuY2hhckNvZGVBdChwZWckY3VyclBvcykgPT09IDM4KSB7XG4gICAgICAgICAgICBzMyA9IHBlZyRjMTU7XG4gICAgICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzMyA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjMTYpOyB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgczQgPSBwZWckcGFyc2VfXygpO1xuICAgICAgICAgICAgaWYgKHM0ICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgIHM1ID0gcGVnJHBhcnNlQW5kRXhwcigpO1xuICAgICAgICAgICAgICBpZiAoczUgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICBzMSA9IHBlZyRjMTcoczEsIHM1KTtcbiAgICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgfVxuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgIHMxID0gcGVnJHBhcnNlTm90RXhwcigpO1xuICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBzMiA9IFtdO1xuICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHdoaWxlIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICBzMi5wdXNoKHMzKTtcbiAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzMiA9IHBlZyRjMTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICBzMyA9IHBlZyRwYXJzZUFuZEV4cHIoKTtcbiAgICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgczEgPSBwZWckYzE3KHMxLCBzMyk7XG4gICAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHMwID0gcGVnJHBhcnNlTm90RXhwcigpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckcGFyc2VOb3RFeHByKCkge1xuICAgICAgdmFyIHMwLCBzMSwgczIsIHMzO1xuXG4gICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgaWYgKGlucHV0LmNoYXJDb2RlQXQocGVnJGN1cnJQb3MpID09PSAzMykge1xuICAgICAgICBzMSA9IHBlZyRjMTg7XG4gICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGMxOSk7IH1cbiAgICAgIH1cbiAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMiA9IHBlZyRwYXJzZV9fKCk7XG4gICAgICAgIGlmIChzMiAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHMzID0gcGVnJHBhcnNlTm90RXhwcigpO1xuICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICBzMSA9IHBlZyRjMjAoczMpO1xuICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgIH1cbiAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMCA9IHBlZyRwYXJzZUJpbmRpbmdFeHByKCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckcGFyc2VCaW5kaW5nRXhwcigpIHtcbiAgICAgIHZhciBzMCwgczEsIHMyLCBzMywgczQsIHM1O1xuXG4gICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgaWYgKGlucHV0LmNoYXJDb2RlQXQocGVnJGN1cnJQb3MpID09PSA0MCkge1xuICAgICAgICBzMSA9IHBlZyRjMjE7XG4gICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGMyMik7IH1cbiAgICAgIH1cbiAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMiA9IHBlZyRwYXJzZV9fKCk7XG4gICAgICAgIGlmIChzMiAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHMzID0gcGVnJHBhcnNlT3JFeHByKCk7XG4gICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICBzNCA9IHBlZyRwYXJzZV9fKCk7XG4gICAgICAgICAgICBpZiAoczQgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgaWYgKGlucHV0LmNoYXJDb2RlQXQocGVnJGN1cnJQb3MpID09PSA0MSkge1xuICAgICAgICAgICAgICAgIHM1ID0gcGVnJGMyMztcbiAgICAgICAgICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHM1ID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjMjQpOyB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKHM1ICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICAgICAgczEgPSBwZWckYzI1KHMzKTtcbiAgICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgfVxuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMwID0gcGVnJHBhcnNlRXhwcigpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlRXhwcigpIHtcbiAgICAgIHZhciBzMDtcblxuICAgICAgczAgPSBwZWckcGFyc2VOdWxsYXJ5RXhwcigpO1xuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMwID0gcGVnJHBhcnNlVW5hcnlFeHByKCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckcGFyc2VOdWxsYXJ5RXhwcigpIHtcbiAgICAgIHZhciBzMCwgczE7XG5cbiAgICAgIHMwID0gcGVnJHBhcnNlQm9vbGVhbkxpdGVyYWwoKTtcbiAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgICBpZiAoaW5wdXQuc3Vic3RyKHBlZyRjdXJyUG9zLCAyKSA9PT0gcGVnJGMyNikge1xuICAgICAgICAgIHMxID0gcGVnJGMyNjtcbiAgICAgICAgICBwZWckY3VyclBvcyArPSAyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjMjcpOyB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgczEgPSBwZWckYzI4KCk7XG4gICAgICAgIH1cbiAgICAgICAgczAgPSBzMTtcbiAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICBpZiAoaW5wdXQuc3Vic3RyKHBlZyRjdXJyUG9zLCAyKSA9PT0gcGVnJGMyOSkge1xuICAgICAgICAgICAgczEgPSBwZWckYzI5O1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMjtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzMwKTsgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgczEgPSBwZWckYzMxKCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgICAgICAgaWYgKGlucHV0LnN1YnN0cihwZWckY3VyclBvcywgMikgPT09IHBlZyRjMzIpIHtcbiAgICAgICAgICAgICAgczEgPSBwZWckYzMyO1xuICAgICAgICAgICAgICBwZWckY3VyclBvcyArPSAyO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjMzMpOyB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICAgIHMxID0gcGVnJGMzNCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgICAgICAgICBpZiAoaW5wdXQuc3Vic3RyKHBlZyRjdXJyUG9zLCAyKSA9PT0gcGVnJGMzNSkge1xuICAgICAgICAgICAgICAgIHMxID0gcGVnJGMzNTtcbiAgICAgICAgICAgICAgICBwZWckY3VyclBvcyArPSAyO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjMzYpOyB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICAgICAgczEgPSBwZWckYzM3KCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHMwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBlZyRwYXJzZUJvb2xlYW5MaXRlcmFsKCkge1xuICAgICAgdmFyIHMwLCBzMTtcblxuICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgIGlmIChpbnB1dC5zdWJzdHIocGVnJGN1cnJQb3MsIDQpID09PSBwZWckYzM4KSB7XG4gICAgICAgIHMxID0gcGVnJGMzODtcbiAgICAgICAgcGVnJGN1cnJQb3MgKz0gNDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzM5KTsgfVxuICAgICAgfVxuICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICBzMSA9IHBlZyRjNDAoKTtcbiAgICAgIH1cbiAgICAgIHMwID0gczE7XG4gICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgaWYgKGlucHV0LnN1YnN0cihwZWckY3VyclBvcywgNSkgPT09IHBlZyRjNDEpIHtcbiAgICAgICAgICBzMSA9IHBlZyRjNDE7XG4gICAgICAgICAgcGVnJGN1cnJQb3MgKz0gNTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzQyKTsgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgIHMxID0gcGVnJGM0MygpO1xuICAgICAgICB9XG4gICAgICAgIHMwID0gczE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckcGFyc2VVbmFyeUV4cHIoKSB7XG4gICAgICB2YXIgczAsIHMxLCBzMiwgczM7XG5cbiAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICBpZiAoaW5wdXQuc3Vic3RyKHBlZyRjdXJyUG9zLCAyKSA9PT0gcGVnJGM0NCkge1xuICAgICAgICBzMSA9IHBlZyRjNDQ7XG4gICAgICAgIHBlZyRjdXJyUG9zICs9IDI7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM0NSk7IH1cbiAgICAgIH1cbiAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMiA9IFtdO1xuICAgICAgICBzMyA9IHBlZyRwYXJzZXdzKCk7XG4gICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHdoaWxlIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgczIucHVzaChzMyk7XG4gICAgICAgICAgICBzMyA9IHBlZyRwYXJzZXdzKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHMyID0gcGVnJGMxO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzMiAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHMzID0gcGVnJHBhcnNlSW50ZWdlckxpdGVyYWwoKTtcbiAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgczEgPSBwZWckYzQ2KHMzKTtcbiAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICB9XG4gICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgaWYgKGlucHV0LnN1YnN0cihwZWckY3VyclBvcywgMikgPT09IHBlZyRjNDcpIHtcbiAgICAgICAgICBzMSA9IHBlZyRjNDc7XG4gICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzQ4KTsgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgIHMyID0gW107XG4gICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgd2hpbGUgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgIHMyLnB1c2goczMpO1xuICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZXdzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHMyID0gcGVnJGMxO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHMzID0gcGVnJHBhcnNlU3RyaW5nTGl0ZXJhbCgpO1xuICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgICBzMSA9IHBlZyRjNDkoczMpO1xuICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgICAgIGlmIChpbnB1dC5zdWJzdHIocGVnJGN1cnJQb3MsIDIpID09PSBwZWckYzUwKSB7XG4gICAgICAgICAgICBzMSA9IHBlZyRjNTA7XG4gICAgICAgICAgICBwZWckY3VyclBvcyArPSAyO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjNTEpOyB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgczIgPSBbXTtcbiAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICB3aGlsZSAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICBzMi5wdXNoKHMzKTtcbiAgICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZXdzKCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHMyID0gcGVnJGMxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNlU3RyaW5nTGl0ZXJhbCgpO1xuICAgICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICBzMSA9IHBlZyRjNTIoczMpO1xuICAgICAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgICAgICAgaWYgKGlucHV0LnN1YnN0cihwZWckY3VyclBvcywgMykgPT09IHBlZyRjNTMpIHtcbiAgICAgICAgICAgICAgczEgPSBwZWckYzUzO1xuICAgICAgICAgICAgICBwZWckY3VyclBvcyArPSAzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjNTQpOyB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgczIgPSBbXTtcbiAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICB3aGlsZSAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgIHMyLnB1c2goczMpO1xuICAgICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzMiA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZVN0cmluZ0xpdGVyYWwoKTtcbiAgICAgICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgICAgICAgczEgPSBwZWckYzU1KHMzKTtcbiAgICAgICAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICAgICAgaWYgKGlucHV0LnN1YnN0cihwZWckY3VyclBvcywgMykgPT09IHBlZyRjNTYpIHtcbiAgICAgICAgICAgICAgICBzMSA9IHBlZyRjNTY7XG4gICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMztcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzU3KTsgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgIHMyID0gW107XG4gICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgd2hpbGUgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgIHMyLnB1c2goczMpO1xuICAgICAgICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZXdzKCk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIHMyID0gcGVnJGMxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNlU3RyaW5nTGl0ZXJhbCgpO1xuICAgICAgICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgICAgICAgICBzMSA9IHBlZyRjNTgoczMpO1xuICAgICAgICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgICAgICAgICAgIGlmIChpbnB1dC5zdWJzdHIocGVnJGN1cnJQb3MsIDIpID09PSBwZWckYzU5KSB7XG4gICAgICAgICAgICAgICAgICBzMSA9IHBlZyRjNTk7XG4gICAgICAgICAgICAgICAgICBwZWckY3VyclBvcyArPSAyO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjNjApOyB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgczIgPSBbXTtcbiAgICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICBzMi5wdXNoKHMzKTtcbiAgICAgICAgICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZXdzKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHMyID0gcGVnJGMxO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNlU3RyaW5nTGl0ZXJhbCgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgICBzMSA9IHBlZyRjNjEoczMpO1xuICAgICAgICAgICAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgICAgICAgICAgICAgaWYgKGlucHV0LnN1YnN0cihwZWckY3VyclBvcywgMikgPT09IHBlZyRjNjIpIHtcbiAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckYzYyO1xuICAgICAgICAgICAgICAgICAgICBwZWckY3VyclBvcyArPSAyO1xuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjNjMpOyB9XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgczIgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHMyLnB1c2goczMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICBzMiA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZVN0cmluZ0xpdGVyYWwoKTtcbiAgICAgICAgICAgICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckYzY0KHMzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlucHV0LnN1YnN0cihwZWckY3VyclBvcywgMykgPT09IHBlZyRjNjUpIHtcbiAgICAgICAgICAgICAgICAgICAgICBzMSA9IHBlZyRjNjU7XG4gICAgICAgICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgKz0gMztcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzY2KTsgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgICAgIHMyID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMyLnB1c2goczMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZXdzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHMyID0gcGVnJGMxO1xuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNlU3RyaW5nTGl0ZXJhbCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBzMSA9IHBlZyRjNjcoczMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgICAgICAgICAgICAgICAgIGlmIChpbnB1dC5zdWJzdHIocGVnJGN1cnJQb3MsIDMpID09PSBwZWckYzY4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzMSA9IHBlZyRjNjg7XG4gICAgICAgICAgICAgICAgICAgICAgICBwZWckY3VyclBvcyArPSAzO1xuICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzMSA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjNjkpOyB9XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgczIgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNld3MoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzMi5wdXNoKHMzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZXdzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMyID0gcGVnJGMxO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHMzID0gcGVnJHBhcnNlU3RyaW5nTGl0ZXJhbCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzMSA9IHBlZyRjNzAoczMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlucHV0LnN1YnN0cihwZWckY3VyclBvcywgMikgPT09IHBlZyRjNzEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckYzcxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBwZWckY3VyclBvcyArPSAyO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjNzIpOyB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgczIgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHMyLnB1c2goczMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2V3cygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzMiA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzMyA9IHBlZyRwYXJzZVN0cmluZ0xpdGVyYWwoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckYzczKHMzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgczEgPSBwZWckcGFyc2VTdHJpbmdMaXRlcmFsKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHMxID0gcGVnJGM3MyhzMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHMwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBlZyRwYXJzZUludGVnZXJMaXRlcmFsKCkge1xuICAgICAgdmFyIHMwLCBzMSwgczIsIHMzO1xuXG4gICAgICBwZWckc2lsZW50RmFpbHMrKztcbiAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICBpZiAocGVnJGM3Ni50ZXN0KGlucHV0LmNoYXJBdChwZWckY3VyclBvcykpKSB7XG4gICAgICAgIHMxID0gaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKTtcbiAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzc3KTsgfVxuICAgICAgfVxuICAgICAgaWYgKHMxID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMxID0gcGVnJGM3NTtcbiAgICAgIH1cbiAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMiA9IFtdO1xuICAgICAgICBpZiAocGVnJGM3OC50ZXN0KGlucHV0LmNoYXJBdChwZWckY3VyclBvcykpKSB7XG4gICAgICAgICAgczMgPSBpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpO1xuICAgICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgczMgPSBwZWckRkFJTEVEO1xuICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM3OSk7IH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICB3aGlsZSAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHMyLnB1c2goczMpO1xuICAgICAgICAgICAgaWYgKHBlZyRjNzgudGVzdChpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpKSkge1xuICAgICAgICAgICAgICBzMyA9IGlucHV0LmNoYXJBdChwZWckY3VyclBvcyk7XG4gICAgICAgICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBzMyA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM3OSk7IH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgczIgPSBwZWckYzE7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgaWYgKHBlZyRjNzYudGVzdChpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpKSkge1xuICAgICAgICAgICAgczMgPSBpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpO1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgczMgPSBwZWckRkFJTEVEO1xuICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzc3KTsgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoczMgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgIHMzID0gcGVnJGM3NTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgIHMxID0gcGVnJGM4MChzMik7XG4gICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgfVxuICAgICAgcGVnJHNpbGVudEZhaWxzLS07XG4gICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjNzQpOyB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckcGFyc2VTdHJpbmdMaXRlcmFsKCkge1xuICAgICAgdmFyIHMwLCBzMSwgczIsIHMzO1xuXG4gICAgICBwZWckc2lsZW50RmFpbHMrKztcbiAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICBpZiAoaW5wdXQuY2hhckNvZGVBdChwZWckY3VyclBvcykgPT09IDM0KSB7XG4gICAgICAgIHMxID0gcGVnJGM4MjtcbiAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzgzKTsgfVxuICAgICAgfVxuICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMyID0gW107XG4gICAgICAgIHMzID0gcGVnJHBhcnNlRG91YmxlU3RyaW5nQ2hhcigpO1xuICAgICAgICB3aGlsZSAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBzMi5wdXNoKHMzKTtcbiAgICAgICAgICBzMyA9IHBlZyRwYXJzZURvdWJsZVN0cmluZ0NoYXIoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBpZiAoaW5wdXQuY2hhckNvZGVBdChwZWckY3VyclBvcykgPT09IDM0KSB7XG4gICAgICAgICAgICBzMyA9IHBlZyRjODI7XG4gICAgICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzMyA9IHBlZyRGQUlMRUQ7XG4gICAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjODMpOyB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICBzMSA9IHBlZyRjODQoczIpO1xuICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgIH1cbiAgICAgIGlmIChzMCA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgICBpZiAoaW5wdXQuY2hhckNvZGVBdChwZWckY3VyclBvcykgPT09IDM5KSB7XG4gICAgICAgICAgczEgPSBwZWckYzg1O1xuICAgICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM4Nik7IH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBzMiA9IFtdO1xuICAgICAgICAgIHMzID0gcGVnJHBhcnNlU2luZ2xlU3RyaW5nQ2hhcigpO1xuICAgICAgICAgIHdoaWxlIChzMyAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgczIucHVzaChzMyk7XG4gICAgICAgICAgICBzMyA9IHBlZyRwYXJzZVNpbmdsZVN0cmluZ0NoYXIoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICBpZiAoaW5wdXQuY2hhckNvZGVBdChwZWckY3VyclBvcykgPT09IDM5KSB7XG4gICAgICAgICAgICAgIHMzID0gcGVnJGM4NTtcbiAgICAgICAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHMzID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzg2KTsgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgIHBlZyRyZXBvcnRlZFBvcyA9IHMwO1xuICAgICAgICAgICAgICBzMSA9IHBlZyRjODQoczIpO1xuICAgICAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgICAgIHMxID0gcGVnJGN1cnJQb3M7XG4gICAgICAgICAgcGVnJHNpbGVudEZhaWxzKys7XG4gICAgICAgICAgczIgPSBwZWckcGFyc2VjYygpO1xuICAgICAgICAgIHBlZyRzaWxlbnRGYWlscy0tO1xuICAgICAgICAgIGlmIChzMiA9PT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgczEgPSBwZWckYzg3O1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwZWckY3VyclBvcyA9IHMxO1xuICAgICAgICAgICAgczEgPSBwZWckYzE7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgczIgPSBbXTtcbiAgICAgICAgICAgIHMzID0gcGVnJHBhcnNlVW5xdW90ZWRTdHJpbmdDaGFyKCk7XG4gICAgICAgICAgICBpZiAoczMgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgd2hpbGUgKHMzICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICAgICAgczIucHVzaChzMyk7XG4gICAgICAgICAgICAgICAgczMgPSBwZWckcGFyc2VVbnF1b3RlZFN0cmluZ0NoYXIoKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgczIgPSBwZWckYzE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICAgIHMxID0gcGVnJGM4NChzMik7XG4gICAgICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcGVnJHNpbGVudEZhaWxzLS07XG4gICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjODEpOyB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckcGFyc2VEb3VibGVTdHJpbmdDaGFyKCkge1xuICAgICAgdmFyIHMwLCBzMSwgczI7XG5cbiAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICBzMSA9IHBlZyRjdXJyUG9zO1xuICAgICAgcGVnJHNpbGVudEZhaWxzKys7XG4gICAgICBpZiAocGVnJGM4OC50ZXN0KGlucHV0LmNoYXJBdChwZWckY3VyclBvcykpKSB7XG4gICAgICAgIHMyID0gaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKTtcbiAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHMyID0gcGVnJEZBSUxFRDtcbiAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzg5KTsgfVxuICAgICAgfVxuICAgICAgcGVnJHNpbGVudEZhaWxzLS07XG4gICAgICBpZiAoczIgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczEgPSBwZWckYzg3O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGVnJGN1cnJQb3MgPSBzMTtcbiAgICAgICAgczEgPSBwZWckYzE7XG4gICAgICB9XG4gICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgaWYgKGlucHV0Lmxlbmd0aCA+IHBlZyRjdXJyUG9zKSB7XG4gICAgICAgICAgczIgPSBpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpO1xuICAgICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgczIgPSBwZWckRkFJTEVEO1xuICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM5MCk7IH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICBzMSA9IHBlZyRjOTEoczIpO1xuICAgICAgICAgIHMwID0gczE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICB9XG4gICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgaWYgKGlucHV0LmNoYXJDb2RlQXQocGVnJGN1cnJQb3MpID09PSA5Mikge1xuICAgICAgICAgIHMxID0gcGVnJGM5MjtcbiAgICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjOTMpOyB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgczIgPSBwZWckcGFyc2VFc2NhcGVTZXF1ZW5jZSgpO1xuICAgICAgICAgIGlmIChzMiAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICBzMSA9IHBlZyRjOTEoczIpO1xuICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckcGFyc2VTaW5nbGVTdHJpbmdDaGFyKCkge1xuICAgICAgdmFyIHMwLCBzMSwgczI7XG5cbiAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICBzMSA9IHBlZyRjdXJyUG9zO1xuICAgICAgcGVnJHNpbGVudEZhaWxzKys7XG4gICAgICBpZiAocGVnJGM5NC50ZXN0KGlucHV0LmNoYXJBdChwZWckY3VyclBvcykpKSB7XG4gICAgICAgIHMyID0gaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKTtcbiAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHMyID0gcGVnJEZBSUxFRDtcbiAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzk1KTsgfVxuICAgICAgfVxuICAgICAgcGVnJHNpbGVudEZhaWxzLS07XG4gICAgICBpZiAoczIgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczEgPSBwZWckYzg3O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGVnJGN1cnJQb3MgPSBzMTtcbiAgICAgICAgczEgPSBwZWckYzE7XG4gICAgICB9XG4gICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgaWYgKGlucHV0Lmxlbmd0aCA+IHBlZyRjdXJyUG9zKSB7XG4gICAgICAgICAgczIgPSBpbnB1dC5jaGFyQXQocGVnJGN1cnJQb3MpO1xuICAgICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgczIgPSBwZWckRkFJTEVEO1xuICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM5MCk7IH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoczIgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICBzMSA9IHBlZyRjOTEoczIpO1xuICAgICAgICAgIHMwID0gczE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICBzMCA9IHBlZyRjMTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICB9XG4gICAgICBpZiAoczAgPT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgaWYgKGlucHV0LmNoYXJDb2RlQXQocGVnJGN1cnJQb3MpID09PSA5Mikge1xuICAgICAgICAgIHMxID0gcGVnJGM5MjtcbiAgICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjOTMpOyB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgczIgPSBwZWckcGFyc2VFc2NhcGVTZXF1ZW5jZSgpO1xuICAgICAgICAgIGlmIChzMiAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICBzMSA9IHBlZyRjOTEoczIpO1xuICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGVnJGN1cnJQb3MgPSBzMDtcbiAgICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwZWckY3VyclBvcyA9IHMwO1xuICAgICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwZWckcGFyc2VVbnF1b3RlZFN0cmluZ0NoYXIoKSB7XG4gICAgICB2YXIgczAsIHMxLCBzMjtcblxuICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgIHMxID0gcGVnJGN1cnJQb3M7XG4gICAgICBwZWckc2lsZW50RmFpbHMrKztcbiAgICAgIHMyID0gcGVnJHBhcnNld3MoKTtcbiAgICAgIHBlZyRzaWxlbnRGYWlscy0tO1xuICAgICAgaWYgKHMyID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMxID0gcGVnJGM4NztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlZyRjdXJyUG9zID0gczE7XG4gICAgICAgIHMxID0gcGVnJGMxO1xuICAgICAgfVxuICAgICAgaWYgKHMxICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIGlmIChpbnB1dC5sZW5ndGggPiBwZWckY3VyclBvcykge1xuICAgICAgICAgIHMyID0gaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKTtcbiAgICAgICAgICBwZWckY3VyclBvcysrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHMyID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICBpZiAocGVnJHNpbGVudEZhaWxzID09PSAwKSB7IHBlZyRmYWlsKHBlZyRjOTApOyB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMyICE9PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgczEgPSBwZWckYzkxKHMyKTtcbiAgICAgICAgICBzMCA9IHMxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgICAgczAgPSBwZWckYzE7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBlZyRjdXJyUG9zID0gczA7XG4gICAgICAgIHMwID0gcGVnJGMxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gczA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGVnJHBhcnNlRXNjYXBlU2VxdWVuY2UoKSB7XG4gICAgICB2YXIgczAsIHMxO1xuXG4gICAgICBpZiAocGVnJGM5Ni50ZXN0KGlucHV0LmNoYXJBdChwZWckY3VyclBvcykpKSB7XG4gICAgICAgIHMwID0gaW5wdXQuY2hhckF0KHBlZyRjdXJyUG9zKTtcbiAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHMwID0gcGVnJEZBSUxFRDtcbiAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzk3KTsgfVxuICAgICAgfVxuICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgIHMwID0gcGVnJGN1cnJQb3M7XG4gICAgICAgIGlmIChpbnB1dC5jaGFyQ29kZUF0KHBlZyRjdXJyUG9zKSA9PT0gMTEwKSB7XG4gICAgICAgICAgczEgPSBwZWckYzk4O1xuICAgICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgczEgPSBwZWckRkFJTEVEO1xuICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGM5OSk7IH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoczEgIT09IHBlZyRGQUlMRUQpIHtcbiAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICBzMSA9IHBlZyRjMTAwKCk7XG4gICAgICAgIH1cbiAgICAgICAgczAgPSBzMTtcbiAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgczAgPSBwZWckY3VyclBvcztcbiAgICAgICAgICBpZiAoaW5wdXQuY2hhckNvZGVBdChwZWckY3VyclBvcykgPT09IDExNCkge1xuICAgICAgICAgICAgczEgPSBwZWckYzEwMTtcbiAgICAgICAgICAgIHBlZyRjdXJyUG9zKys7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICAgIGlmIChwZWckc2lsZW50RmFpbHMgPT09IDApIHsgcGVnJGZhaWwocGVnJGMxMDIpOyB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgcGVnJHJlcG9ydGVkUG9zID0gczA7XG4gICAgICAgICAgICBzMSA9IHBlZyRjMTAzKCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHMwID0gczE7XG4gICAgICAgICAgaWYgKHMwID09PSBwZWckRkFJTEVEKSB7XG4gICAgICAgICAgICBzMCA9IHBlZyRjdXJyUG9zO1xuICAgICAgICAgICAgaWYgKGlucHV0LmNoYXJDb2RlQXQocGVnJGN1cnJQb3MpID09PSAxMTYpIHtcbiAgICAgICAgICAgICAgczEgPSBwZWckYzEwNDtcbiAgICAgICAgICAgICAgcGVnJGN1cnJQb3MrKztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHMxID0gcGVnJEZBSUxFRDtcbiAgICAgICAgICAgICAgaWYgKHBlZyRzaWxlbnRGYWlscyA9PT0gMCkgeyBwZWckZmFpbChwZWckYzEwNSk7IH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzMSAhPT0gcGVnJEZBSUxFRCkge1xuICAgICAgICAgICAgICBwZWckcmVwb3J0ZWRQb3MgPSBzMDtcbiAgICAgICAgICAgICAgczEgPSBwZWckYzEwNigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgczAgPSBzMTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHMwO1xuICAgIH1cblxuXHJcbiAgICB2YXIgZmxvd3V0aWxzID0gcmVxdWlyZShcIi4uL2Zsb3cvdXRpbHMuanNcIik7XHJcblxyXG4gICAgZnVuY3Rpb24gb3IoZmlyc3QsIHNlY29uZCkge1xyXG4gICAgICAgIC8vIEFkZCBleHBsaWNpdCBmdW5jdGlvbiBuYW1lcyB0byBlYXNlIGRlYnVnZ2luZy5cclxuICAgICAgICBmdW5jdGlvbiBvckZpbHRlcigpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZpcnN0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgc2Vjb25kLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIG9yRmlsdGVyLmRlc2MgPSBmaXJzdC5kZXNjICsgXCIgb3IgXCIgKyBzZWNvbmQuZGVzYztcclxuICAgICAgICByZXR1cm4gb3JGaWx0ZXI7XHJcbiAgICB9XHJcbiAgICBmdW5jdGlvbiBhbmQoZmlyc3QsIHNlY29uZCkge1xyXG4gICAgICAgIGZ1bmN0aW9uIGFuZEZpbHRlcigpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZpcnN0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgJiYgc2Vjb25kLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGFuZEZpbHRlci5kZXNjID0gZmlyc3QuZGVzYyArIFwiIGFuZCBcIiArIHNlY29uZC5kZXNjO1xyXG4gICAgICAgIHJldHVybiBhbmRGaWx0ZXI7XHJcbiAgICB9XHJcbiAgICBmdW5jdGlvbiBub3QoZXhwcikge1xyXG4gICAgICAgIGZ1bmN0aW9uIG5vdEZpbHRlcigpIHtcclxuICAgICAgICAgICAgcmV0dXJuICFleHByLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIG5vdEZpbHRlci5kZXNjID0gXCJub3QgXCIgKyBleHByLmRlc2M7XHJcbiAgICAgICAgcmV0dXJuIG5vdEZpbHRlcjtcclxuICAgIH1cclxuICAgIGZ1bmN0aW9uIGJpbmRpbmcoZXhwcikge1xyXG4gICAgICAgIGZ1bmN0aW9uIGJpbmRpbmdGaWx0ZXIoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBleHByLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGJpbmRpbmdGaWx0ZXIuZGVzYyA9IFwiKFwiICsgZXhwci5kZXNjICsgXCIpXCI7XHJcbiAgICAgICAgcmV0dXJuIGJpbmRpbmdGaWx0ZXI7XHJcbiAgICB9XHJcbiAgICBmdW5jdGlvbiB0cnVlRmlsdGVyKGZsb3cpIHtcclxuICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH1cclxuICAgIHRydWVGaWx0ZXIuZGVzYyA9IFwidHJ1ZVwiO1xyXG4gICAgZnVuY3Rpb24gZmFsc2VGaWx0ZXIoZmxvdykge1xyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuICAgIGZhbHNlRmlsdGVyLmRlc2MgPSBcImZhbHNlXCI7XHJcblxyXG4gICAgdmFyIEFTU0VUX1RZUEVTID0gW1xyXG4gICAgICAgIG5ldyBSZWdFeHAoXCJ0ZXh0L2phdmFzY3JpcHRcIiksXHJcbiAgICAgICAgbmV3IFJlZ0V4cChcImFwcGxpY2F0aW9uL3gtamF2YXNjcmlwdFwiKSxcclxuICAgICAgICBuZXcgUmVnRXhwKFwiYXBwbGljYXRpb24vamF2YXNjcmlwdFwiKSxcclxuICAgICAgICBuZXcgUmVnRXhwKFwidGV4dC9jc3NcIiksXHJcbiAgICAgICAgbmV3IFJlZ0V4cChcImltYWdlLy4qXCIpLFxyXG4gICAgICAgIG5ldyBSZWdFeHAoXCJhcHBsaWNhdGlvbi94LXNob2Nrd2F2ZS1mbGFzaFwiKVxyXG4gICAgXTtcclxuICAgIGZ1bmN0aW9uIGFzc2V0RmlsdGVyKGZsb3cpIHtcclxuICAgICAgICBpZiAoZmxvdy5yZXNwb25zZSkge1xyXG4gICAgICAgICAgICB2YXIgY3QgPSBmbG93dXRpbHMuUmVzcG9uc2VVdGlscy5nZXRDb250ZW50VHlwZShmbG93LnJlc3BvbnNlKTtcclxuICAgICAgICAgICAgdmFyIGkgPSBBU1NFVF9UWVBFUy5sZW5ndGg7XHJcbiAgICAgICAgICAgIHdoaWxlIChpLS0pIHtcclxuICAgICAgICAgICAgICAgIGlmIChBU1NFVF9UWVBFU1tpXS50ZXN0KGN0KSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuICAgIGFzc2V0RmlsdGVyLmRlc2MgPSBcImlzIGFzc2V0XCI7XHJcbiAgICBmdW5jdGlvbiByZXNwb25zZUNvZGUoY29kZSl7XHJcbiAgICAgICAgZnVuY3Rpb24gcmVzcG9uc2VDb2RlRmlsdGVyKGZsb3cpe1xyXG4gICAgICAgICAgICByZXR1cm4gZmxvdy5yZXNwb25zZSAmJiBmbG93LnJlc3BvbnNlLmNvZGUgPT09IGNvZGU7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJlc3BvbnNlQ29kZUZpbHRlci5kZXNjID0gXCJyZXNwLiBjb2RlIGlzIFwiICsgY29kZTtcclxuICAgICAgICByZXR1cm4gcmVzcG9uc2VDb2RlRmlsdGVyO1xyXG4gICAgfVxyXG4gICAgZnVuY3Rpb24gZG9tYWluKHJlZ2V4KXtcclxuICAgICAgICByZWdleCA9IG5ldyBSZWdFeHAocmVnZXgsIFwiaVwiKTtcclxuICAgICAgICBmdW5jdGlvbiBkb21haW5GaWx0ZXIoZmxvdyl7XHJcbiAgICAgICAgICAgIHJldHVybiBmbG93LnJlcXVlc3QgJiYgcmVnZXgudGVzdChmbG93LnJlcXVlc3QuaG9zdCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGRvbWFpbkZpbHRlci5kZXNjID0gXCJkb21haW4gbWF0Y2hlcyBcIiArIHJlZ2V4O1xyXG4gICAgICAgIHJldHVybiBkb21haW5GaWx0ZXI7XHJcbiAgICB9XHJcbiAgICBmdW5jdGlvbiBlcnJvckZpbHRlcihmbG93KXtcclxuICAgICAgICByZXR1cm4gISFmbG93LmVycm9yO1xyXG4gICAgfVxyXG4gICAgZXJyb3JGaWx0ZXIuZGVzYyA9IFwiaGFzIGVycm9yXCI7XHJcbiAgICBmdW5jdGlvbiBoZWFkZXIocmVnZXgpe1xyXG4gICAgICAgIHJlZ2V4ID0gbmV3IFJlZ0V4cChyZWdleCwgXCJpXCIpO1xyXG4gICAgICAgIGZ1bmN0aW9uIGhlYWRlckZpbHRlcihmbG93KXtcclxuICAgICAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgICAgIChmbG93LnJlcXVlc3QgJiYgZmxvd3V0aWxzLlJlcXVlc3RVdGlscy5tYXRjaF9oZWFkZXIoZmxvdy5yZXF1ZXN0LCByZWdleCkpXHJcbiAgICAgICAgICAgICAgICB8fFxyXG4gICAgICAgICAgICAgICAgKGZsb3cucmVzcG9uc2UgJiYgZmxvd3V0aWxzLlJlc3BvbnNlVXRpbHMubWF0Y2hfaGVhZGVyKGZsb3cucmVzcG9uc2UsIHJlZ2V4KSlcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaGVhZGVyRmlsdGVyLmRlc2MgPSBcImhlYWRlciBtYXRjaGVzIFwiICsgcmVnZXg7XHJcbiAgICAgICAgcmV0dXJuIGhlYWRlckZpbHRlcjtcclxuICAgIH1cclxuICAgIGZ1bmN0aW9uIHJlcXVlc3RIZWFkZXIocmVnZXgpe1xyXG4gICAgICAgIHJlZ2V4ID0gbmV3IFJlZ0V4cChyZWdleCwgXCJpXCIpO1xyXG4gICAgICAgIGZ1bmN0aW9uIHJlcXVlc3RIZWFkZXJGaWx0ZXIoZmxvdyl7XHJcbiAgICAgICAgICAgIHJldHVybiAoZmxvdy5yZXF1ZXN0ICYmIGZsb3d1dGlscy5SZXF1ZXN0VXRpbHMubWF0Y2hfaGVhZGVyKGZsb3cucmVxdWVzdCwgcmVnZXgpKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmVxdWVzdEhlYWRlckZpbHRlci5kZXNjID0gXCJyZXEuIGhlYWRlciBtYXRjaGVzIFwiICsgcmVnZXg7XHJcbiAgICAgICAgcmV0dXJuIHJlcXVlc3RIZWFkZXJGaWx0ZXI7XHJcbiAgICB9XHJcbiAgICBmdW5jdGlvbiByZXNwb25zZUhlYWRlcihyZWdleCl7XHJcbiAgICAgICAgcmVnZXggPSBuZXcgUmVnRXhwKHJlZ2V4LCBcImlcIik7XHJcbiAgICAgICAgZnVuY3Rpb24gcmVzcG9uc2VIZWFkZXJGaWx0ZXIoZmxvdyl7XHJcbiAgICAgICAgICAgIHJldHVybiAoZmxvdy5yZXNwb25zZSAmJiBmbG93dXRpbHMuUmVzcG9uc2VVdGlscy5tYXRjaF9oZWFkZXIoZmxvdy5yZXNwb25zZSwgcmVnZXgpKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmVzcG9uc2VIZWFkZXJGaWx0ZXIuZGVzYyA9IFwicmVzcC4gaGVhZGVyIG1hdGNoZXMgXCIgKyByZWdleDtcclxuICAgICAgICByZXR1cm4gcmVzcG9uc2VIZWFkZXJGaWx0ZXI7XHJcbiAgICB9XHJcbiAgICBmdW5jdGlvbiBtZXRob2QocmVnZXgpe1xyXG4gICAgICAgIHJlZ2V4ID0gbmV3IFJlZ0V4cChyZWdleCwgXCJpXCIpO1xyXG4gICAgICAgIGZ1bmN0aW9uIG1ldGhvZEZpbHRlcihmbG93KXtcclxuICAgICAgICAgICAgcmV0dXJuIGZsb3cucmVxdWVzdCAmJiByZWdleC50ZXN0KGZsb3cucmVxdWVzdC5tZXRob2QpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBtZXRob2RGaWx0ZXIuZGVzYyA9IFwibWV0aG9kIG1hdGNoZXMgXCIgKyByZWdleDtcclxuICAgICAgICByZXR1cm4gbWV0aG9kRmlsdGVyO1xyXG4gICAgfVxyXG4gICAgZnVuY3Rpb24gbm9SZXNwb25zZUZpbHRlcihmbG93KXtcclxuICAgICAgICByZXR1cm4gZmxvdy5yZXF1ZXN0ICYmICFmbG93LnJlc3BvbnNlO1xyXG4gICAgfVxyXG4gICAgbm9SZXNwb25zZUZpbHRlci5kZXNjID0gXCJoYXMgbm8gcmVzcG9uc2VcIjtcclxuICAgIGZ1bmN0aW9uIHJlc3BvbnNlRmlsdGVyKGZsb3cpe1xyXG4gICAgICAgIHJldHVybiAhIWZsb3cucmVzcG9uc2U7XHJcbiAgICB9XHJcbiAgICByZXNwb25zZUZpbHRlci5kZXNjID0gXCJoYXMgcmVzcG9uc2VcIjtcclxuXHJcbiAgICBmdW5jdGlvbiBjb250ZW50VHlwZShyZWdleCl7XHJcbiAgICAgICAgcmVnZXggPSBuZXcgUmVnRXhwKHJlZ2V4LCBcImlcIik7XHJcbiAgICAgICAgZnVuY3Rpb24gY29udGVudFR5cGVGaWx0ZXIoZmxvdyl7XHJcbiAgICAgICAgICAgIHJldHVybiAoXHJcbiAgICAgICAgICAgICAgICAoZmxvdy5yZXF1ZXN0ICYmIHJlZ2V4LnRlc3QoZmxvd3V0aWxzLlJlcXVlc3RVdGlscy5nZXRDb250ZW50VHlwZShmbG93LnJlcXVlc3QpKSlcclxuICAgICAgICAgICAgICAgIHx8XHJcbiAgICAgICAgICAgICAgICAoZmxvdy5yZXNwb25zZSAmJiByZWdleC50ZXN0KGZsb3d1dGlscy5SZXNwb25zZVV0aWxzLmdldENvbnRlbnRUeXBlKGZsb3cucmVzcG9uc2UpKSlcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY29udGVudFR5cGVGaWx0ZXIuZGVzYyA9IFwiY29udGVudCB0eXBlIG1hdGNoZXMgXCIgKyByZWdleDtcclxuICAgICAgICByZXR1cm4gY29udGVudFR5cGVGaWx0ZXI7XHJcbiAgICB9XHJcbiAgICBmdW5jdGlvbiByZXF1ZXN0Q29udGVudFR5cGUocmVnZXgpe1xyXG4gICAgICAgIHJlZ2V4ID0gbmV3IFJlZ0V4cChyZWdleCwgXCJpXCIpO1xyXG4gICAgICAgIGZ1bmN0aW9uIHJlcXVlc3RDb250ZW50VHlwZUZpbHRlcihmbG93KXtcclxuICAgICAgICAgICAgcmV0dXJuIGZsb3cucmVxdWVzdCAmJiByZWdleC50ZXN0KGZsb3d1dGlscy5SZXF1ZXN0VXRpbHMuZ2V0Q29udGVudFR5cGUoZmxvdy5yZXF1ZXN0KSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJlcXVlc3RDb250ZW50VHlwZUZpbHRlci5kZXNjID0gXCJyZXEuIGNvbnRlbnQgdHlwZSBtYXRjaGVzIFwiICsgcmVnZXg7XHJcbiAgICAgICAgcmV0dXJuIHJlcXVlc3RDb250ZW50VHlwZUZpbHRlcjtcclxuICAgIH1cclxuICAgIGZ1bmN0aW9uIHJlc3BvbnNlQ29udGVudFR5cGUocmVnZXgpe1xyXG4gICAgICAgIHJlZ2V4ID0gbmV3IFJlZ0V4cChyZWdleCwgXCJpXCIpO1xyXG4gICAgICAgIGZ1bmN0aW9uIHJlc3BvbnNlQ29udGVudFR5cGVGaWx0ZXIoZmxvdyl7XHJcbiAgICAgICAgICAgIHJldHVybiBmbG93LnJlc3BvbnNlICYmIHJlZ2V4LnRlc3QoZmxvd3V0aWxzLlJlc3BvbnNlVXRpbHMuZ2V0Q29udGVudFR5cGUoZmxvdy5yZXNwb25zZSkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXNwb25zZUNvbnRlbnRUeXBlRmlsdGVyLmRlc2MgPSBcInJlc3AuIGNvbnRlbnQgdHlwZSBtYXRjaGVzIFwiICsgcmVnZXg7XHJcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlQ29udGVudFR5cGVGaWx0ZXI7XHJcbiAgICB9XHJcbiAgICBmdW5jdGlvbiB1cmwocmVnZXgpe1xyXG4gICAgICAgIHJlZ2V4ID0gbmV3IFJlZ0V4cChyZWdleCwgXCJpXCIpO1xyXG4gICAgICAgIGZ1bmN0aW9uIHVybEZpbHRlcihmbG93KXtcclxuICAgICAgICAgICAgcmV0dXJuIGZsb3cucmVxdWVzdCAmJiByZWdleC50ZXN0KGZsb3d1dGlscy5SZXF1ZXN0VXRpbHMucHJldHR5X3VybChmbG93LnJlcXVlc3QpKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdXJsRmlsdGVyLmRlc2MgPSBcInVybCBtYXRjaGVzIFwiICsgcmVnZXg7XHJcbiAgICAgICAgcmV0dXJuIHVybEZpbHRlcjtcclxuICAgIH1cclxuXG5cbiAgICBwZWckcmVzdWx0ID0gcGVnJHN0YXJ0UnVsZUZ1bmN0aW9uKCk7XG5cbiAgICBpZiAocGVnJHJlc3VsdCAhPT0gcGVnJEZBSUxFRCAmJiBwZWckY3VyclBvcyA9PT0gaW5wdXQubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gcGVnJHJlc3VsdDtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHBlZyRyZXN1bHQgIT09IHBlZyRGQUlMRUQgJiYgcGVnJGN1cnJQb3MgPCBpbnB1dC5sZW5ndGgpIHtcbiAgICAgICAgcGVnJGZhaWwoeyB0eXBlOiBcImVuZFwiLCBkZXNjcmlwdGlvbjogXCJlbmQgb2YgaW5wdXRcIiB9KTtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgcGVnJGJ1aWxkRXhjZXB0aW9uKG51bGwsIHBlZyRtYXhGYWlsRXhwZWN0ZWQsIHBlZyRtYXhGYWlsUG9zKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIFN5bnRheEVycm9yOiBTeW50YXhFcnJvcixcbiAgICBwYXJzZTogICAgICAgcGFyc2VcbiAgfTtcbn0pKCk7IiwidmFyIF8gPSByZXF1aXJlKFwibG9kYXNoXCIpO1xyXG5cclxudmFyIF9NZXNzYWdlVXRpbHMgPSB7XHJcbiAgICBnZXRDb250ZW50VHlwZTogZnVuY3Rpb24gKG1lc3NhZ2UpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5nZXRfZmlyc3RfaGVhZGVyKG1lc3NhZ2UsIC9eQ29udGVudC1UeXBlJC9pKTtcclxuICAgIH0sXHJcbiAgICBnZXRfZmlyc3RfaGVhZGVyOiBmdW5jdGlvbiAobWVzc2FnZSwgcmVnZXgpIHtcclxuICAgICAgICAvL0ZJWE1FOiBDYWNoZSBJbnZhbGlkYXRpb24uXHJcbiAgICAgICAgaWYgKCFtZXNzYWdlLl9oZWFkZXJMb29rdXBzKVxyXG4gICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobWVzc2FnZSwgXCJfaGVhZGVyTG9va3Vwc1wiLCB7XHJcbiAgICAgICAgICAgICAgICB2YWx1ZToge30sXHJcbiAgICAgICAgICAgICAgICBjb25maWd1cmFibGU6IGZhbHNlLFxyXG4gICAgICAgICAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXHJcbiAgICAgICAgICAgICAgICB3cml0YWJsZTogZmFsc2VcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgaWYgKCEocmVnZXggaW4gbWVzc2FnZS5faGVhZGVyTG9va3VwcykpIHtcclxuICAgICAgICAgICAgdmFyIGhlYWRlcjtcclxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLmhlYWRlcnMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgIGlmICghIW1lc3NhZ2UuaGVhZGVyc1tpXVswXS5tYXRjaChyZWdleCkpIHtcclxuICAgICAgICAgICAgICAgICAgICBoZWFkZXIgPSBtZXNzYWdlLmhlYWRlcnNbaV07XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgbWVzc2FnZS5faGVhZGVyTG9va3Vwc1tyZWdleF0gPSBoZWFkZXIgPyBoZWFkZXJbMV0gOiB1bmRlZmluZWQ7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBtZXNzYWdlLl9oZWFkZXJMb29rdXBzW3JlZ2V4XTtcclxuICAgIH0sXHJcbiAgICBtYXRjaF9oZWFkZXI6IGZ1bmN0aW9uIChtZXNzYWdlLCByZWdleCkge1xyXG4gICAgICAgIHZhciBoZWFkZXJzID0gbWVzc2FnZS5oZWFkZXJzO1xyXG4gICAgICAgIHZhciBpID0gaGVhZGVycy5sZW5ndGg7XHJcbiAgICAgICAgd2hpbGUgKGktLSkge1xyXG4gICAgICAgICAgICBpZiAocmVnZXgudGVzdChoZWFkZXJzW2ldLmpvaW4oXCIgXCIpKSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhlYWRlcnNbaV07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG59O1xyXG5cclxudmFyIGRlZmF1bHRQb3J0cyA9IHtcclxuICAgIFwiaHR0cFwiOiA4MCxcclxuICAgIFwiaHR0cHNcIjogNDQzXHJcbn07XHJcblxyXG52YXIgUmVxdWVzdFV0aWxzID0gXy5leHRlbmQoX01lc3NhZ2VVdGlscywge1xyXG4gICAgcHJldHR5X2hvc3Q6IGZ1bmN0aW9uIChyZXF1ZXN0KSB7XHJcbiAgICAgICAgLy9GSVhNRTogQWRkIGhvc3RoZWFkZXJcclxuICAgICAgICByZXR1cm4gcmVxdWVzdC5ob3N0O1xyXG4gICAgfSxcclxuICAgIHByZXR0eV91cmw6IGZ1bmN0aW9uIChyZXF1ZXN0KSB7XHJcbiAgICAgICAgdmFyIHBvcnQgPSBcIlwiO1xyXG4gICAgICAgIGlmIChkZWZhdWx0UG9ydHNbcmVxdWVzdC5zY2hlbWVdICE9PSByZXF1ZXN0LnBvcnQpIHtcclxuICAgICAgICAgICAgcG9ydCA9IFwiOlwiICsgcmVxdWVzdC5wb3J0O1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gcmVxdWVzdC5zY2hlbWUgKyBcIjovL1wiICsgdGhpcy5wcmV0dHlfaG9zdChyZXF1ZXN0KSArIHBvcnQgKyByZXF1ZXN0LnBhdGg7XHJcbiAgICB9XHJcbn0pO1xyXG5cclxudmFyIFJlc3BvbnNlVXRpbHMgPSBfLmV4dGVuZChfTWVzc2FnZVV0aWxzLCB7fSk7XHJcblxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSB7XHJcbiAgICBSZXNwb25zZVV0aWxzOiBSZXNwb25zZVV0aWxzLFxyXG4gICAgUmVxdWVzdFV0aWxzOiBSZXF1ZXN0VXRpbHNcclxuXHJcbn0iLCJcclxudmFyIF8gPSByZXF1aXJlKFwibG9kYXNoXCIpO1xyXG52YXIgJCA9IHJlcXVpcmUoXCJqcXVlcnlcIik7XHJcbnZhciBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXI7XHJcblxyXG52YXIgdXRpbHMgPSByZXF1aXJlKFwiLi4vdXRpbHMuanNcIik7XHJcbnZhciBhY3Rpb25zID0gcmVxdWlyZShcIi4uL2FjdGlvbnMuanNcIik7XHJcbnZhciBkaXNwYXRjaGVyID0gcmVxdWlyZShcIi4uL2Rpc3BhdGNoZXIuanNcIik7XHJcblxyXG5cclxuZnVuY3Rpb24gTGlzdFN0b3JlKCkge1xyXG4gICAgRXZlbnRFbWl0dGVyLmNhbGwodGhpcyk7XHJcbiAgICB0aGlzLnJlc2V0KCk7XHJcbn1cclxuXy5leHRlbmQoTGlzdFN0b3JlLnByb3RvdHlwZSwgRXZlbnRFbWl0dGVyLnByb3RvdHlwZSwge1xyXG4gICAgYWRkOiBmdW5jdGlvbiAoZWxlbSkge1xyXG4gICAgICAgIGlmIChlbGVtLmlkIGluIHRoaXMuX3Bvc19tYXApIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLl9wb3NfbWFwW2VsZW0uaWRdID0gdGhpcy5saXN0Lmxlbmd0aDtcclxuICAgICAgICB0aGlzLmxpc3QucHVzaChlbGVtKTtcclxuICAgICAgICB0aGlzLmVtaXQoXCJhZGRcIiwgZWxlbSk7XHJcbiAgICB9LFxyXG4gICAgdXBkYXRlOiBmdW5jdGlvbiAoZWxlbSkge1xyXG4gICAgICAgIGlmICghKGVsZW0uaWQgaW4gdGhpcy5fcG9zX21hcCkpIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLmxpc3RbdGhpcy5fcG9zX21hcFtlbGVtLmlkXV0gPSBlbGVtO1xyXG4gICAgICAgIHRoaXMuZW1pdChcInVwZGF0ZVwiLCBlbGVtKTtcclxuICAgIH0sXHJcbiAgICByZW1vdmU6IGZ1bmN0aW9uIChlbGVtX2lkKSB7XHJcbiAgICAgICAgaWYgKCEoZWxlbV9pZCBpbiB0aGlzLl9wb3NfbWFwKSkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMubGlzdC5zcGxpY2UodGhpcy5fcG9zX21hcFtlbGVtX2lkXSwgMSk7XHJcbiAgICAgICAgdGhpcy5fYnVpbGRfbWFwKCk7XHJcbiAgICAgICAgdGhpcy5lbWl0KFwicmVtb3ZlXCIsIGVsZW1faWQpO1xyXG4gICAgfSxcclxuICAgIHJlc2V0OiBmdW5jdGlvbiAoZWxlbXMpIHtcclxuICAgICAgICB0aGlzLmxpc3QgPSBlbGVtcyB8fCBbXTtcclxuICAgICAgICB0aGlzLl9idWlsZF9tYXAoKTtcclxuICAgICAgICB0aGlzLmVtaXQoXCJyZWNhbGN1bGF0ZVwiKTtcclxuICAgIH0sXHJcbiAgICBfYnVpbGRfbWFwOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgdGhpcy5fcG9zX21hcCA9IHt9O1xyXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5saXN0Lmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIHZhciBlbGVtID0gdGhpcy5saXN0W2ldO1xyXG4gICAgICAgICAgICB0aGlzLl9wb3NfbWFwW2VsZW0uaWRdID0gaTtcclxuICAgICAgICB9XHJcbiAgICB9LFxyXG4gICAgZ2V0OiBmdW5jdGlvbiAoZWxlbV9pZCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RbdGhpcy5fcG9zX21hcFtlbGVtX2lkXV07XHJcbiAgICB9LFxyXG4gICAgaW5kZXg6IGZ1bmN0aW9uIChlbGVtX2lkKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX3Bvc19tYXBbZWxlbV9pZF07XHJcbiAgICB9XHJcbn0pO1xyXG5cclxuXHJcbmZ1bmN0aW9uIERpY3RTdG9yZSgpIHtcclxuICAgIEV2ZW50RW1pdHRlci5jYWxsKHRoaXMpO1xyXG4gICAgdGhpcy5yZXNldCgpO1xyXG59XHJcbl8uZXh0ZW5kKERpY3RTdG9yZS5wcm90b3R5cGUsIEV2ZW50RW1pdHRlci5wcm90b3R5cGUsIHtcclxuICAgIHVwZGF0ZTogZnVuY3Rpb24gKGRpY3QpIHtcclxuICAgICAgICBfLm1lcmdlKHRoaXMuZGljdCwgZGljdCk7XHJcbiAgICAgICAgdGhpcy5lbWl0KFwicmVjYWxjdWxhdGVcIik7XHJcbiAgICB9LFxyXG4gICAgcmVzZXQ6IGZ1bmN0aW9uIChkaWN0KSB7XHJcbiAgICAgICAgdGhpcy5kaWN0ID0gZGljdCB8fCB7fTtcclxuICAgICAgICB0aGlzLmVtaXQoXCJyZWNhbGN1bGF0ZVwiKTtcclxuICAgIH1cclxufSk7XHJcblxyXG5mdW5jdGlvbiBMaXZlU3RvcmVNaXhpbih0eXBlKSB7XHJcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xyXG5cclxuICAgIHRoaXMuX3VwZGF0ZXNfYmVmb3JlX2ZldGNoID0gdW5kZWZpbmVkO1xyXG4gICAgdGhpcy5fZmV0Y2h4aHIgPSBmYWxzZTtcclxuXHJcbiAgICB0aGlzLmhhbmRsZSA9IHRoaXMuaGFuZGxlLmJpbmQodGhpcyk7XHJcbiAgICBkaXNwYXRjaGVyLkFwcERpc3BhdGNoZXIucmVnaXN0ZXIodGhpcy5oYW5kbGUpO1xyXG5cclxuICAgIC8vIEF2b2lkIGRvdWJsZS1mZXRjaCBvbiBzdGFydHVwLlxyXG4gICAgaWYgKCEod2luZG93LndzICYmIHdpbmRvdy53cy5yZWFkeVN0YXRlID09PSBXZWJTb2NrZXQuQ09OTkVDVElORykpIHtcclxuICAgICAgICB0aGlzLmZldGNoKCk7XHJcbiAgICB9XHJcbn1cclxuXy5leHRlbmQoTGl2ZVN0b3JlTWl4aW4ucHJvdG90eXBlLCB7XHJcbiAgICBoYW5kbGU6IGZ1bmN0aW9uIChldmVudCkge1xyXG4gICAgICAgIGlmIChldmVudC50eXBlID09PSBhY3Rpb25zLkFjdGlvblR5cGVzLkNPTk5FQ1RJT05fT1BFTikge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5mZXRjaCgpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoZXZlbnQudHlwZSA9PT0gdGhpcy50eXBlKSB7XHJcbiAgICAgICAgICAgIGlmIChldmVudC5jbWQgPT09IGFjdGlvbnMuU3RvcmVDbWRzLlJFU0VUKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmZldGNoKGV2ZW50LmRhdGEpO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX3VwZGF0ZXNfYmVmb3JlX2ZldGNoKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcImRlZmVyIHVwZGF0ZVwiLCBldmVudCk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGVzX2JlZm9yZV9mZXRjaC5wdXNoKGV2ZW50KTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHRoaXNbZXZlbnQuY21kXShldmVudC5kYXRhKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH0sXHJcbiAgICBjbG9zZTogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIGRpc3BhdGNoZXIuQXBwRGlzcGF0Y2hlci51bnJlZ2lzdGVyKHRoaXMuaGFuZGxlKTtcclxuICAgIH0sXHJcbiAgICBmZXRjaDogZnVuY3Rpb24gKGRhdGEpIHtcclxuICAgICAgICBjb25zb2xlLmxvZyhcImZldGNoIFwiICsgdGhpcy50eXBlKTtcclxuICAgICAgICBpZiAodGhpcy5fZmV0Y2h4aHIpIHtcclxuICAgICAgICAgICAgdGhpcy5fZmV0Y2h4aHIuYWJvcnQoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5fdXBkYXRlc19iZWZvcmVfZmV0Y2ggPSBbXTsgLy8gKEpTOiBlbXB0eSBhcnJheSBpcyB0cnVlKVxyXG4gICAgICAgIGlmIChkYXRhKSB7XHJcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlX2ZldGNoKGRhdGEpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRoaXMuX2ZldGNoeGhyID0gJC5nZXRKU09OKFwiL1wiICsgdGhpcy50eXBlKVxyXG4gICAgICAgICAgICAgICAgLmRvbmUoZnVuY3Rpb24gKG1lc3NhZ2UpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZV9mZXRjaChtZXNzYWdlLmRhdGEpO1xyXG4gICAgICAgICAgICAgICAgfS5iaW5kKHRoaXMpKVxyXG4gICAgICAgICAgICAgICAgLmZhaWwoZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgIEV2ZW50TG9nQWN0aW9ucy5hZGRfZXZlbnQoXCJDb3VsZCBub3QgZmV0Y2ggXCIgKyB0aGlzLnR5cGUpO1xyXG4gICAgICAgICAgICAgICAgfS5iaW5kKHRoaXMpKTtcclxuICAgICAgICB9XHJcbiAgICB9LFxyXG4gICAgaGFuZGxlX2ZldGNoOiBmdW5jdGlvbiAoZGF0YSkge1xyXG4gICAgICAgIHRoaXMuX2ZldGNoeGhyID0gZmFsc2U7XHJcbiAgICAgICAgY29uc29sZS5sb2codGhpcy50eXBlICsgXCIgZmV0Y2hlZC5cIiwgdGhpcy5fdXBkYXRlc19iZWZvcmVfZmV0Y2gpO1xyXG4gICAgICAgIHRoaXMucmVzZXQoZGF0YSk7XHJcbiAgICAgICAgdmFyIHVwZGF0ZXMgPSB0aGlzLl91cGRhdGVzX2JlZm9yZV9mZXRjaDtcclxuICAgICAgICB0aGlzLl91cGRhdGVzX2JlZm9yZV9mZXRjaCA9IGZhbHNlO1xyXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdXBkYXRlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICB0aGlzLmhhbmRsZSh1cGRhdGVzW2ldKTtcclxuICAgICAgICB9XHJcbiAgICB9LFxyXG59KTtcclxuXHJcbmZ1bmN0aW9uIExpdmVMaXN0U3RvcmUodHlwZSkge1xyXG4gICAgTGlzdFN0b3JlLmNhbGwodGhpcyk7XHJcbiAgICBMaXZlU3RvcmVNaXhpbi5jYWxsKHRoaXMsIHR5cGUpO1xyXG59XHJcbl8uZXh0ZW5kKExpdmVMaXN0U3RvcmUucHJvdG90eXBlLCBMaXN0U3RvcmUucHJvdG90eXBlLCBMaXZlU3RvcmVNaXhpbi5wcm90b3R5cGUpO1xyXG5cclxuZnVuY3Rpb24gTGl2ZURpY3RTdG9yZSh0eXBlKSB7XHJcbiAgICBEaWN0U3RvcmUuY2FsbCh0aGlzKTtcclxuICAgIExpdmVTdG9yZU1peGluLmNhbGwodGhpcywgdHlwZSk7XHJcbn1cclxuXy5leHRlbmQoTGl2ZURpY3RTdG9yZS5wcm90b3R5cGUsIERpY3RTdG9yZS5wcm90b3R5cGUsIExpdmVTdG9yZU1peGluLnByb3RvdHlwZSk7XHJcblxyXG5cclxuZnVuY3Rpb24gRmxvd1N0b3JlKCkge1xyXG4gICAgcmV0dXJuIG5ldyBMaXZlTGlzdFN0b3JlKGFjdGlvbnMuQWN0aW9uVHlwZXMuRkxPV19TVE9SRSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIFNldHRpbmdzU3RvcmUoKSB7XHJcbiAgICByZXR1cm4gbmV3IExpdmVEaWN0U3RvcmUoYWN0aW9ucy5BY3Rpb25UeXBlcy5TRVRUSU5HU19TVE9SRSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIEV2ZW50TG9nU3RvcmUoKSB7XHJcbiAgICBMaXZlTGlzdFN0b3JlLmNhbGwodGhpcywgYWN0aW9ucy5BY3Rpb25UeXBlcy5FVkVOVF9TVE9SRSk7XHJcbn1cclxuXy5leHRlbmQoRXZlbnRMb2dTdG9yZS5wcm90b3R5cGUsIExpdmVMaXN0U3RvcmUucHJvdG90eXBlLCB7XHJcbiAgICBmZXRjaDogZnVuY3Rpb24oKXtcclxuICAgICAgICBMaXZlTGlzdFN0b3JlLnByb3RvdHlwZS5mZXRjaC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG5cclxuICAgICAgICAvLyBNYWtlIHN1cmUgdG8gZGlzcGxheSB1cGRhdGVzIGV2ZW4gaWYgZmV0Y2hpbmcgYWxsIGV2ZW50cyBmYWlsZWQuXHJcbiAgICAgICAgLy8gVGhpcyB3YXksIHdlIGNhbiBzZW5kIFwiZmV0Y2ggZmFpbGVkXCIgbG9nIG1lc3NhZ2VzIHRvIHRoZSBsb2cuXHJcbiAgICAgICAgaWYodGhpcy5fZmV0Y2h4aHIpe1xyXG4gICAgICAgICAgICB0aGlzLl9mZXRjaHhoci5mYWlsKGZ1bmN0aW9uKCl7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZV9mZXRjaChudWxsKTtcclxuICAgICAgICAgICAgfS5iaW5kKHRoaXMpKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn0pO1xyXG5cclxuXHJcbm1vZHVsZS5leHBvcnRzID0ge1xyXG4gICAgRXZlbnRMb2dTdG9yZTogRXZlbnRMb2dTdG9yZSxcclxuICAgIFNldHRpbmdzU3RvcmU6IFNldHRpbmdzU3RvcmUsXHJcbiAgICBGbG93U3RvcmU6IEZsb3dTdG9yZVxyXG59OyIsIlxyXG52YXIgRXZlbnRFbWl0dGVyID0gcmVxdWlyZSgnZXZlbnRzJykuRXZlbnRFbWl0dGVyO1xyXG52YXIgXyA9IHJlcXVpcmUoXCJsb2Rhc2hcIik7XHJcblxyXG5cclxudmFyIHV0aWxzID0gcmVxdWlyZShcIi4uL3V0aWxzLmpzXCIpO1xyXG5cclxuZnVuY3Rpb24gU29ydEJ5U3RvcmVPcmRlcihlbGVtKSB7XHJcbiAgICByZXR1cm4gdGhpcy5zdG9yZS5pbmRleChlbGVtLmlkKTtcclxufVxyXG5cclxudmFyIGRlZmF1bHRfc29ydCA9IFNvcnRCeVN0b3JlT3JkZXI7XHJcbnZhciBkZWZhdWx0X2ZpbHQgPSBmdW5jdGlvbihlbGVtKXtcclxuICAgIHJldHVybiB0cnVlO1xyXG59O1xyXG5cclxuZnVuY3Rpb24gU3RvcmVWaWV3KHN0b3JlLCBmaWx0LCBzb3J0ZnVuKSB7XHJcbiAgICBFdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcclxuICAgIGZpbHQgPSBmaWx0IHx8IGRlZmF1bHRfZmlsdDtcclxuICAgIHNvcnRmdW4gPSBzb3J0ZnVuIHx8IGRlZmF1bHRfc29ydDtcclxuXHJcbiAgICB0aGlzLnN0b3JlID0gc3RvcmU7XHJcblxyXG4gICAgdGhpcy5hZGQgPSB0aGlzLmFkZC5iaW5kKHRoaXMpO1xyXG4gICAgdGhpcy51cGRhdGUgPSB0aGlzLnVwZGF0ZS5iaW5kKHRoaXMpO1xyXG4gICAgdGhpcy5yZW1vdmUgPSB0aGlzLnJlbW92ZS5iaW5kKHRoaXMpO1xyXG4gICAgdGhpcy5yZWNhbGN1bGF0ZSA9IHRoaXMucmVjYWxjdWxhdGUuYmluZCh0aGlzKTtcclxuICAgIHRoaXMuc3RvcmUuYWRkTGlzdGVuZXIoXCJhZGRcIiwgdGhpcy5hZGQpO1xyXG4gICAgdGhpcy5zdG9yZS5hZGRMaXN0ZW5lcihcInVwZGF0ZVwiLCB0aGlzLnVwZGF0ZSk7XHJcbiAgICB0aGlzLnN0b3JlLmFkZExpc3RlbmVyKFwicmVtb3ZlXCIsIHRoaXMucmVtb3ZlKTtcclxuICAgIHRoaXMuc3RvcmUuYWRkTGlzdGVuZXIoXCJyZWNhbGN1bGF0ZVwiLCB0aGlzLnJlY2FsY3VsYXRlKTtcclxuXHJcbiAgICB0aGlzLnJlY2FsY3VsYXRlKGZpbHQsIHNvcnRmdW4pO1xyXG59XHJcblxyXG5fLmV4dGVuZChTdG9yZVZpZXcucHJvdG90eXBlLCBFdmVudEVtaXR0ZXIucHJvdG90eXBlLCB7XHJcbiAgICBjbG9zZTogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHRoaXMuc3RvcmUucmVtb3ZlTGlzdGVuZXIoXCJhZGRcIiwgdGhpcy5hZGQpO1xyXG4gICAgICAgIHRoaXMuc3RvcmUucmVtb3ZlTGlzdGVuZXIoXCJ1cGRhdGVcIiwgdGhpcy51cGRhdGUpO1xyXG4gICAgICAgIHRoaXMuc3RvcmUucmVtb3ZlTGlzdGVuZXIoXCJyZW1vdmVcIiwgdGhpcy5yZW1vdmUpO1xyXG4gICAgICAgIHRoaXMuc3RvcmUucmVtb3ZlTGlzdGVuZXIoXCJyZWNhbGN1bGF0ZVwiLCB0aGlzLnJlY2FsY3VsYXRlKTtcclxuICAgICAgICB9LFxyXG4gICAgICAgIHJlY2FsY3VsYXRlOiBmdW5jdGlvbiAoZmlsdCwgc29ydGZ1bikge1xyXG4gICAgICAgIGlmIChmaWx0KSB7XHJcbiAgICAgICAgICAgIHRoaXMuZmlsdCA9IGZpbHQuYmluZCh0aGlzKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKHNvcnRmdW4pIHtcclxuICAgICAgICAgICAgdGhpcy5zb3J0ZnVuID0gc29ydGZ1bi5iaW5kKHRoaXMpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5saXN0ID0gdGhpcy5zdG9yZS5saXN0LmZpbHRlcih0aGlzLmZpbHQpO1xyXG4gICAgICAgIHRoaXMubGlzdC5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNvcnRmdW4oYSkgLSB0aGlzLnNvcnRmdW4oYik7XHJcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcclxuICAgICAgICB0aGlzLmVtaXQoXCJyZWNhbGN1bGF0ZVwiKTtcclxuICAgIH0sXHJcbiAgICBpbmRleDogZnVuY3Rpb24gKGVsZW0pIHtcclxuICAgICAgICByZXR1cm4gXy5zb3J0ZWRJbmRleCh0aGlzLmxpc3QsIGVsZW0sIHRoaXMuc29ydGZ1bik7XHJcbiAgICB9LFxyXG4gICAgYWRkOiBmdW5jdGlvbiAoZWxlbSkge1xyXG4gICAgICAgIGlmICh0aGlzLmZpbHQoZWxlbSkpIHtcclxuICAgICAgICAgICAgdmFyIGlkeCA9IHRoaXMuaW5kZXgoZWxlbSk7XHJcbiAgICAgICAgICAgIGlmIChpZHggPT09IHRoaXMubGlzdC5sZW5ndGgpIHsgLy9oYXBwZW5zIG9mdGVuLCAucHVzaCBpcyB3YXkgZmFzdGVyLlxyXG4gICAgICAgICAgICAgICAgdGhpcy5saXN0LnB1c2goZWxlbSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmxpc3Quc3BsaWNlKGlkeCwgMCwgZWxlbSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdGhpcy5lbWl0KFwiYWRkXCIsIGVsZW0sIGlkeCk7XHJcbiAgICAgICAgfVxyXG4gICAgfSxcclxuICAgIHVwZGF0ZTogZnVuY3Rpb24gKGVsZW0pIHtcclxuICAgICAgICB2YXIgaWR4O1xyXG4gICAgICAgIHZhciBpID0gdGhpcy5saXN0Lmxlbmd0aDtcclxuICAgICAgICAvLyBTZWFyY2ggZnJvbSB0aGUgYmFjaywgd2UgdXN1YWxseSB1cGRhdGUgdGhlIGxhdGVzdCBlbnRyaWVzLlxyXG4gICAgICAgIHdoaWxlIChpLS0pIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMubGlzdFtpXS5pZCA9PT0gZWxlbS5pZCkge1xyXG4gICAgICAgICAgICAgICAgaWR4ID0gaTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoaWR4ID09PSAtMSkgeyAvL25vdCBjb250YWluZWQgaW4gbGlzdFxyXG4gICAgICAgICAgICB0aGlzLmFkZChlbGVtKTtcclxuICAgICAgICB9IGVsc2UgaWYgKCF0aGlzLmZpbHQoZWxlbSkpIHtcclxuICAgICAgICAgICAgdGhpcy5yZW1vdmUoZWxlbS5pZCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuc29ydGZ1bih0aGlzLmxpc3RbaWR4XSkgIT09IHRoaXMuc29ydGZ1bihlbGVtKSkgeyAvL3NvcnRwb3MgaGFzIGNoYW5nZWRcclxuICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlKHRoaXMubGlzdFtpZHhdKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuYWRkKGVsZW0pO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5saXN0W2lkeF0gPSBlbGVtO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0KFwidXBkYXRlXCIsIGVsZW0sIGlkeCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9LFxyXG4gICAgcmVtb3ZlOiBmdW5jdGlvbiAoZWxlbV9pZCkge1xyXG4gICAgICAgIHZhciBpZHggPSB0aGlzLmxpc3QubGVuZ3RoO1xyXG4gICAgICAgIHdoaWxlIChpZHgtLSkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5saXN0W2lkeF0uaWQgPT09IGVsZW1faWQpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMubGlzdC5zcGxpY2UoaWR4LCAxKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuZW1pdChcInJlbW92ZVwiLCBlbGVtX2lkLCBpZHgpO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcbn0pO1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSB7XHJcbiAgICBTdG9yZVZpZXc6IFN0b3JlVmlld1xyXG59OyIsInZhciAkID0gcmVxdWlyZShcImpxdWVyeVwiKTtcclxuXHJcblxyXG52YXIgS2V5ID0ge1xyXG4gICAgVVA6IDM4LFxyXG4gICAgRE9XTjogNDAsXHJcbiAgICBQQUdFX1VQOiAzMyxcclxuICAgIFBBR0VfRE9XTjogMzQsXHJcbiAgICBIT01FOiAzNixcclxuICAgIEVORDogMzUsXHJcbiAgICBMRUZUOiAzNyxcclxuICAgIFJJR0hUOiAzOSxcclxuICAgIEVOVEVSOiAxMyxcclxuICAgIEVTQzogMjcsXHJcbiAgICBUQUI6IDksXHJcbiAgICBTUEFDRTogMzIsXHJcbiAgICBCQUNLU1BBQ0U6IDgsXHJcbn07XHJcbi8vIEFkZCBBLVpcclxuZm9yICh2YXIgaSA9IDY1OyBpIDw9IDkwOyBpKyspIHtcclxuICAgIEtleVtTdHJpbmcuZnJvbUNoYXJDb2RlKGkpXSA9IGk7XHJcbn1cclxuXHJcblxyXG52YXIgZm9ybWF0U2l6ZSA9IGZ1bmN0aW9uIChieXRlcykge1xyXG4gICAgaWYgKGJ5dGVzID09PSAwKVxyXG4gICAgICAgIHJldHVybiBcIjBcIjtcclxuICAgIHZhciBwcmVmaXggPSBbXCJiXCIsIFwia2JcIiwgXCJtYlwiLCBcImdiXCIsIFwidGJcIl07XHJcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHByZWZpeC5sZW5ndGg7IGkrKyl7XHJcbiAgICAgICAgaWYgKE1hdGgucG93KDEwMjQsIGkgKyAxKSA+IGJ5dGVzKXtcclxuICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgdmFyIHByZWNpc2lvbjtcclxuICAgIGlmIChieXRlcyVNYXRoLnBvdygxMDI0LCBpKSA9PT0gMClcclxuICAgICAgICBwcmVjaXNpb24gPSAwO1xyXG4gICAgZWxzZVxyXG4gICAgICAgIHByZWNpc2lvbiA9IDE7XHJcbiAgICByZXR1cm4gKGJ5dGVzL01hdGgucG93KDEwMjQsIGkpKS50b0ZpeGVkKHByZWNpc2lvbikgKyBwcmVmaXhbaV07XHJcbn07XHJcblxyXG5cclxudmFyIGZvcm1hdFRpbWVEZWx0YSA9IGZ1bmN0aW9uIChtaWxsaXNlY29uZHMpIHtcclxuICAgIHZhciB0aW1lID0gbWlsbGlzZWNvbmRzO1xyXG4gICAgdmFyIHByZWZpeCA9IFtcIm1zXCIsIFwic1wiLCBcIm1pblwiLCBcImhcIl07XHJcbiAgICB2YXIgZGl2ID0gWzEwMDAsIDYwLCA2MF07XHJcbiAgICB2YXIgaSA9IDA7XHJcbiAgICB3aGlsZSAoTWF0aC5hYnModGltZSkgPj0gZGl2W2ldICYmIGkgPCBkaXYubGVuZ3RoKSB7XHJcbiAgICAgICAgdGltZSA9IHRpbWUgLyBkaXZbaV07XHJcbiAgICAgICAgaSsrO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIE1hdGgucm91bmQodGltZSkgKyBwcmVmaXhbaV07XHJcbn07XHJcblxyXG5cclxudmFyIGZvcm1hdFRpbWVTdGFtcCA9IGZ1bmN0aW9uIChzZWNvbmRzKSB7XHJcbiAgICB2YXIgdHMgPSAobmV3IERhdGUoc2Vjb25kcyAqIDEwMDApKS50b0lTT1N0cmluZygpO1xyXG4gICAgcmV0dXJuIHRzLnJlcGxhY2UoXCJUXCIsIFwiIFwiKS5yZXBsYWNlKFwiWlwiLCBcIlwiKTtcclxufTtcclxuXHJcblxyXG5mdW5jdGlvbiBnZXRDb29raWUobmFtZSkge1xyXG4gICAgdmFyIHIgPSBkb2N1bWVudC5jb29raWUubWF0Y2goXCJcXFxcYlwiICsgbmFtZSArIFwiPShbXjtdKilcXFxcYlwiKTtcclxuICAgIHJldHVybiByID8gclsxXSA6IHVuZGVmaW5lZDtcclxufVxyXG52YXIgeHNyZiA9ICQucGFyYW0oe194c3JmOiBnZXRDb29raWUoXCJfeHNyZlwiKX0pO1xyXG5cclxuLy9Ub3JuYWRvIFhTUkYgUHJvdGVjdGlvbi5cclxuJC5hamF4UHJlZmlsdGVyKGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcbiAgICBpZiAoW1wicG9zdFwiLCBcInB1dFwiLCBcImRlbGV0ZVwiXS5pbmRleE9mKG9wdGlvbnMudHlwZS50b0xvd2VyQ2FzZSgpKSA+PSAwICYmIG9wdGlvbnMudXJsWzBdID09PSBcIi9cIikge1xyXG4gICAgICAgIGlmIChvcHRpb25zLmRhdGEpIHtcclxuICAgICAgICAgICAgb3B0aW9ucy5kYXRhICs9IChcIiZcIiArIHhzcmYpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIG9wdGlvbnMuZGF0YSA9IHhzcmY7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59KTtcclxuLy8gTG9nIEFKQVggRXJyb3JzXHJcbiQoZG9jdW1lbnQpLmFqYXhFcnJvcihmdW5jdGlvbiAoZXZlbnQsIGpxWEhSLCBhamF4U2V0dGluZ3MsIHRocm93bkVycm9yKSB7XHJcbiAgICB2YXIgbWVzc2FnZSA9IGpxWEhSLnJlc3BvbnNlVGV4dDtcclxuICAgIGNvbnNvbGUuZXJyb3IobWVzc2FnZSwgYXJndW1lbnRzKTtcclxuICAgIEV2ZW50TG9nQWN0aW9ucy5hZGRfZXZlbnQodGhyb3duRXJyb3IgKyBcIjogXCIgKyBtZXNzYWdlKTtcclxuICAgIHdpbmRvdy5hbGVydChtZXNzYWdlKTtcclxufSk7XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IHtcclxuICAgIGZvcm1hdFNpemU6IGZvcm1hdFNpemUsXHJcbiAgICBmb3JtYXRUaW1lRGVsdGE6IGZvcm1hdFRpbWVEZWx0YSxcclxuICAgIGZvcm1hdFRpbWVTdGFtcDogZm9ybWF0VGltZVN0YW1wLFxyXG4gICAgS2V5OiBLZXlcclxufTsiXX0= diff --git a/libmproxy/web/static/vendor.css b/libmproxy/web/static/vendor.css index 31aed3a3..149372c8 100644 --- a/libmproxy/web/static/vendor.css +++ b/libmproxy/web/static/vendor.css @@ -256,7 +256,7 @@ th { @font-face { font-family: 'Glyphicons Halflings'; src: url('../fonts/glyphicons-halflings-regular.eot'); - src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); + src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); } .glyphicon { position: relative; @@ -870,6 +870,180 @@ th { .glyphicon-tree-deciduous:before { content: "\e200"; } +.glyphicon-cd:before { + content: "\e201"; +} +.glyphicon-save-file:before { + content: "\e202"; +} +.glyphicon-open-file:before { + content: "\e203"; +} +.glyphicon-level-up:before { + content: "\e204"; +} +.glyphicon-copy:before { + content: "\e205"; +} +.glyphicon-paste:before { + content: "\e206"; +} +.glyphicon-alert:before { + content: "\e209"; +} +.glyphicon-equalizer:before { + content: "\e210"; +} +.glyphicon-king:before { + content: "\e211"; +} +.glyphicon-queen:before { + content: "\e212"; +} +.glyphicon-pawn:before { + content: "\e213"; +} +.glyphicon-bishop:before { + content: "\e214"; +} +.glyphicon-knight:before { + content: "\e215"; +} +.glyphicon-baby-formula:before { + content: "\e216"; +} +.glyphicon-tent:before { + content: "\26fa"; +} +.glyphicon-blackboard:before { + content: "\e218"; +} +.glyphicon-bed:before { + content: "\e219"; +} +.glyphicon-apple:before { + content: "\f8ff"; +} +.glyphicon-erase:before { + content: "\e221"; +} +.glyphicon-hourglass:before { + content: "\231b"; +} +.glyphicon-lamp:before { + content: "\e223"; +} +.glyphicon-duplicate:before { + content: "\e224"; +} +.glyphicon-piggy-bank:before { + content: "\e225"; +} +.glyphicon-scissors:before { + content: "\e226"; +} +.glyphicon-bitcoin:before { + content: "\e227"; +} +.glyphicon-yen:before { + content: "\00a5"; +} +.glyphicon-ruble:before { + content: "\20bd"; +} +.glyphicon-scale:before { + content: "\e230"; +} +.glyphicon-ice-lolly:before { + content: "\e231"; +} +.glyphicon-ice-lolly-tasted:before { + content: "\e232"; +} +.glyphicon-education:before { + content: "\e233"; +} +.glyphicon-option-horizontal:before { + content: "\e234"; +} +.glyphicon-option-vertical:before { + content: "\e235"; +} +.glyphicon-menu-hamburger:before { + content: "\e236"; +} +.glyphicon-modal-window:before { + content: "\e237"; +} +.glyphicon-oil:before { + content: "\e238"; +} +.glyphicon-grain:before { + content: "\e239"; +} +.glyphicon-sunglasses:before { + content: "\e240"; +} +.glyphicon-text-size:before { + content: "\e241"; +} +.glyphicon-text-color:before { + content: "\e242"; +} +.glyphicon-text-background:before { + content: "\e243"; +} +.glyphicon-object-align-top:before { + content: "\e244"; +} +.glyphicon-object-align-bottom:before { + content: "\e245"; +} +.glyphicon-object-align-horizontal:before { + content: "\e246"; +} +.glyphicon-object-align-left:before { + content: "\e247"; +} +.glyphicon-object-align-vertical:before { + content: "\e248"; +} +.glyphicon-object-align-right:before { + content: "\e249"; +} +.glyphicon-triangle-right:before { + content: "\e250"; +} +.glyphicon-triangle-left:before { + content: "\e251"; +} +.glyphicon-triangle-bottom:before { + content: "\e252"; +} +.glyphicon-triangle-top:before { + content: "\e253"; +} +.glyphicon-console:before { + content: "\e254"; +} +.glyphicon-superscript:before { + content: "\e255"; +} +.glyphicon-subscript:before { + content: "\e256"; +} +.glyphicon-menu-left:before { + content: "\e257"; +} +.glyphicon-menu-right:before { + content: "\e258"; +} +.glyphicon-menu-down:before { + content: "\e259"; +} +.glyphicon-menu-up:before { + content: "\e260"; +} * { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; @@ -2107,7 +2281,7 @@ th { .table-bordered > thead > tr > td { border-bottom-width: 2px; } -.table-striped > tbody > tr:nth-child(odd) { +.table-striped > tbody > tr:nth-of-type(odd) { background-color: #f9f9f9; } .table-hover > tbody > tr:hover { @@ -2394,13 +2568,21 @@ input[type="search"] { input[type="date"].input-sm, input[type="time"].input-sm, input[type="datetime-local"].input-sm, - input[type="month"].input-sm { + input[type="month"].input-sm, + .input-group-sm input[type="date"], + .input-group-sm input[type="time"], + .input-group-sm input[type="datetime-local"], + .input-group-sm input[type="month"] { line-height: 30px; } input[type="date"].input-lg, input[type="time"].input-lg, input[type="datetime-local"].input-lg, - input[type="month"].input-lg { + input[type="month"].input-lg, + .input-group-lg input[type="date"], + .input-group-lg input[type="time"], + .input-group-lg input[type="datetime-local"], + .input-group-lg input[type="month"] { line-height: 46px; } } @@ -2478,7 +2660,21 @@ fieldset[disabled] .checkbox label { padding-left: 0; padding-right: 0; } -.input-sm, +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} .form-group-sm .form-control { height: 30px; padding: 5px 10px; @@ -2486,36 +2682,56 @@ fieldset[disabled] .checkbox label { line-height: 1.5; border-radius: 3px; } -select.input-sm, select.form-group-sm .form-control { height: 30px; line-height: 30px; } -textarea.input-sm, textarea.form-group-sm .form-control, -select[multiple].input-sm, select[multiple].form-group-sm .form-control { height: auto; } -.input-lg, +.form-group-sm .form-control-static { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; +} +.input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} .form-group-lg .form-control { height: 46px; padding: 10px 16px; font-size: 18px; - line-height: 1.33; + line-height: 1.3333333; border-radius: 6px; } -select.input-lg, select.form-group-lg .form-control { height: 46px; line-height: 46px; } -textarea.input-lg, textarea.form-group-lg .form-control, -select[multiple].input-lg, select[multiple].form-group-lg .form-control { height: auto; } +.form-group-lg .form-control-static { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; +} .has-feedback { position: relative; } @@ -2724,7 +2940,7 @@ select[multiple].form-group-lg .form-control { } @media (min-width: 768px) { .form-horizontal .form-group-lg .control-label { - padding-top: 14.3px; + padding-top: 14.333333px; } } @media (min-width: 768px) { @@ -3092,7 +3308,7 @@ fieldset[disabled] .btn-link:focus { .btn-group-lg > .btn { padding: 10px 16px; font-size: 18px; - line-height: 1.33; + line-height: 1.3333333; border-radius: 6px; } .btn-sm, @@ -3165,6 +3381,7 @@ tbody.collapse.in { border-right: 4px solid transparent; border-left: 4px solid transparent; } +.dropup, .dropdown { position: relative; } @@ -3282,7 +3499,7 @@ tbody.collapse.in { .navbar-fixed-bottom .dropdown .dropdown-menu { top: auto; bottom: 100%; - margin-bottom: 1px; + margin-bottom: 2px; } @media (min-width: 768px) { .navbar-right .dropdown-menu { @@ -3354,12 +3571,12 @@ tbody.collapse.in { .btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { border-radius: 0; } -.btn-group > .btn-group:first-child > .btn:last-child, -.btn-group > .btn-group:first-child > .dropdown-toggle { +.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { border-bottom-right-radius: 0; border-top-right-radius: 0; } -.btn-group > .btn-group:last-child > .btn:first-child { +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { border-bottom-left-radius: 0; border-top-left-radius: 0; } @@ -3485,7 +3702,7 @@ tbody.collapse.in { height: 46px; padding: 10px 16px; font-size: 18px; - line-height: 1.33; + line-height: 1.3333333; border-radius: 6px; } select.input-group-lg > .form-control, @@ -4096,6 +4313,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn { border-top-left-radius: 0; } .navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; border-top-right-radius: 4px; border-top-left-radius: 4px; border-bottom-right-radius: 0; @@ -4828,6 +5046,17 @@ a.thumbnail.active { .media:first-child { margin-top: 0; } +.media, +.media-body { + zoom: 1; + overflow: hidden; +} +.media-body { + width: 10000px; +} +.media-object { + display: block; +} .media-right, .media > .pull-right { padding-left: 10px; @@ -5052,7 +5281,11 @@ a.list-group-item-danger.active:focus { font-size: 16px; color: inherit; } -.panel-title > a { +.panel-title > a, +.panel-title > small, +.panel-title > .small, +.panel-title > small > a, +.panel-title > .small > a { color: inherit; } .panel-footer { @@ -5802,23 +6035,33 @@ button.close { } @media all and (transform-3d), (-webkit-transform-3d) { .carousel-inner > .item { + -webkit-transition: -webkit-transform 0.6s ease-in-out; + -moz-transition: -moz-transform 0.6s ease-in-out; + -o-transition: -o-transform 0.6s ease-in-out; transition: transform 0.6s ease-in-out; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; backface-visibility: hidden; + -webkit-perspective: 1000; + -moz-perspective: 1000; perspective: 1000; } .carousel-inner > .item.next, .carousel-inner > .item.active.right { + -webkit-transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0); left: 0; } .carousel-inner > .item.prev, .carousel-inner > .item.active.left { + -webkit-transform: translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0); left: 0; } .carousel-inner > .item.next.left, .carousel-inner > .item.prev.right, .carousel-inner > .item.active { + -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); left: 0; } @@ -5914,6 +6157,7 @@ button.close { width: 20px; height: 20px; margin-top: -10px; + line-height: 1; font-family: serif; } .carousel-control .icon-prev:before { diff --git a/libmproxy/web/static/vendor.js b/libmproxy/web/static/vendor.js index ed551ac5..59ef0473 100644 --- a/libmproxy/web/static/vendor.js +++ b/libmproxy/web/static/vendor.js @@ -1,1301 +1,4 @@ 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 - * @license MIT - */ - -var base64 = require('base64-js') -var ieee754 = require('ieee754') -var isArray = require('is-array') - -exports.Buffer = Buffer -exports.SlowBuffer = Buffer -exports.INSPECT_MAX_BYTES = 50 -Buffer.poolSize = 8192 // not used by this implementation - -var kMaxLength = 0x3fffffff - -/** - * If `Buffer.TYPED_ARRAY_SUPPORT`: - * === true Use Uint8Array implementation (fastest) - * === false Use Object implementation (most compatible, even IE6) - * - * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, - * Opera 11.6+, iOS 4.2+. - * - * Note: - * - * - Implementation must support adding new properties to `Uint8Array` instances. - * Firefox 4-29 lacked support, fixed in Firefox 30+. - * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. - * - * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. - * - * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of - * incorrect length in some situations. - * - * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they will - * get the Object implementation, which is slower but will work correctly. - */ -Buffer.TYPED_ARRAY_SUPPORT = (function () { - try { - var buf = new ArrayBuffer(0) - var arr = new Uint8Array(buf) - arr.foo = function () { return 42 } - return 42 === arr.foo() && // typed array instances can be augmented - typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` - new Uint8Array(1).subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` - } catch (e) { - return false - } -})() - -/** - * Class: Buffer - * ============= - * - * The Buffer constructor returns instances of `Uint8Array` that are augmented - * with function properties for all the node `Buffer` API functions. We use - * `Uint8Array` so that square bracket notation works as expected -- it returns - * a single octet. - * - * By augmenting the instances, we can avoid modifying the `Uint8Array` - * prototype. - */ -function Buffer (subject, encoding, noZero) { - if (!(this instanceof Buffer)) - return new Buffer(subject, encoding, noZero) - - var type = typeof subject - - // Find the length - var length - if (type === 'number') - length = subject > 0 ? subject >>> 0 : 0 - else if (type === 'string') { - if (encoding === 'base64') - subject = base64clean(subject) - length = Buffer.byteLength(subject, encoding) - } else if (type === 'object' && subject !== null) { // assume object is array-like - if (subject.type === 'Buffer' && isArray(subject.data)) - subject = subject.data - length = +subject.length > 0 ? Math.floor(+subject.length) : 0 - } else - throw new TypeError('must start with number, buffer, array or string') - - if (this.length > kMaxLength) - throw new RangeError('Attempt to allocate Buffer larger than maximum ' + - 'size: 0x' + kMaxLength.toString(16) + ' bytes') - - var buf - if (Buffer.TYPED_ARRAY_SUPPORT) { - // Preferred: Return an augmented `Uint8Array` instance for best performance - buf = Buffer._augment(new Uint8Array(length)) - } else { - // Fallback: Return THIS instance of Buffer (created by `new`) - buf = this - buf.length = length - buf._isBuffer = true - } - - var i - if (Buffer.TYPED_ARRAY_SUPPORT && typeof subject.byteLength === 'number') { - // Speed optimization -- use set if we're copying from a typed array - buf._set(subject) - } else if (isArrayish(subject)) { - // Treat array-ish objects as a byte array - if (Buffer.isBuffer(subject)) { - for (i = 0; i < length; i++) - buf[i] = subject.readUInt8(i) - } else { - for (i = 0; i < length; i++) - buf[i] = ((subject[i] % 256) + 256) % 256 - } - } else if (type === 'string') { - buf.write(subject, 0, encoding) - } else if (type === 'number' && !Buffer.TYPED_ARRAY_SUPPORT && !noZero) { - for (i = 0; i < length; i++) { - buf[i] = 0 - } - } - - return buf -} - -Buffer.isBuffer = function (b) { - return !!(b != null && b._isBuffer) -} - -Buffer.compare = function (a, b) { - if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) - throw new TypeError('Arguments must be Buffers') - - var x = a.length - var y = b.length - for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {} - if (i !== len) { - x = a[i] - y = b[i] - } - if (x < y) return -1 - if (y < x) return 1 - return 0 -} - -Buffer.isEncoding = function (encoding) { - switch (String(encoding).toLowerCase()) { - case 'hex': - case 'utf8': - case 'utf-8': - case 'ascii': - case 'binary': - case 'base64': - case 'raw': - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return true - default: - return false - } -} - -Buffer.concat = function (list, totalLength) { - if (!isArray(list)) throw new TypeError('Usage: Buffer.concat(list[, length])') - - if (list.length === 0) { - return new Buffer(0) - } else if (list.length === 1) { - return list[0] - } - - var i - if (totalLength === undefined) { - totalLength = 0 - for (i = 0; i < list.length; i++) { - totalLength += list[i].length - } - } - - var buf = new Buffer(totalLength) - var pos = 0 - for (i = 0; i < list.length; i++) { - var item = list[i] - item.copy(buf, pos) - pos += item.length - } - return buf -} - -Buffer.byteLength = function (str, encoding) { - var ret - str = str + '' - switch (encoding || 'utf8') { - case 'ascii': - case 'binary': - case 'raw': - ret = str.length - break - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - ret = str.length * 2 - break - case 'hex': - ret = str.length >>> 1 - break - case 'utf8': - case 'utf-8': - ret = utf8ToBytes(str).length - break - case 'base64': - ret = base64ToBytes(str).length - break - default: - ret = str.length - } - return ret -} - -// pre-set for values that may exist in the future -Buffer.prototype.length = undefined -Buffer.prototype.parent = undefined - -// toString(encoding, start=0, end=buffer.length) -Buffer.prototype.toString = function (encoding, start, end) { - var loweredCase = false - - start = start >>> 0 - end = end === undefined || end === Infinity ? this.length : end >>> 0 - - if (!encoding) encoding = 'utf8' - if (start < 0) start = 0 - if (end > this.length) end = this.length - if (end <= start) return '' - - while (true) { - switch (encoding) { - case 'hex': - return hexSlice(this, start, end) - - case 'utf8': - case 'utf-8': - return utf8Slice(this, start, end) - - case 'ascii': - return asciiSlice(this, start, end) - - case 'binary': - return binarySlice(this, start, end) - - case 'base64': - return base64Slice(this, start, end) - - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return utf16leSlice(this, start, end) - - default: - if (loweredCase) - throw new TypeError('Unknown encoding: ' + encoding) - encoding = (encoding + '').toLowerCase() - loweredCase = true - } - } -} - -Buffer.prototype.equals = function (b) { - if(!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') - return Buffer.compare(this, b) === 0 -} - -Buffer.prototype.inspect = function () { - var str = '' - var max = exports.INSPECT_MAX_BYTES - if (this.length > 0) { - str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') - if (this.length > max) - str += ' ... ' - } - return '' -} - -Buffer.prototype.compare = function (b) { - if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') - return Buffer.compare(this, b) -} - -// `get` will be removed in Node 0.13+ -Buffer.prototype.get = function (offset) { - console.log('.get() is deprecated. Access using array indexes instead.') - return this.readUInt8(offset) -} - -// `set` will be removed in Node 0.13+ -Buffer.prototype.set = function (v, offset) { - console.log('.set() is deprecated. Access using array indexes instead.') - return this.writeUInt8(v, offset) -} - -function hexWrite (buf, string, offset, length) { - offset = Number(offset) || 0 - var remaining = buf.length - offset - if (!length) { - length = remaining - } else { - length = Number(length) - if (length > remaining) { - length = remaining - } - } - - // must be an even number of digits - var strLen = string.length - if (strLen % 2 !== 0) throw new Error('Invalid hex string') - - if (length > strLen / 2) { - length = strLen / 2 - } - for (var i = 0; i < length; i++) { - var byte = parseInt(string.substr(i * 2, 2), 16) - if (isNaN(byte)) throw new Error('Invalid hex string') - buf[offset + i] = byte - } - return i -} - -function utf8Write (buf, string, offset, length) { - var charsWritten = blitBuffer(utf8ToBytes(string), buf, offset, length) - return charsWritten -} - -function asciiWrite (buf, string, offset, length) { - var charsWritten = blitBuffer(asciiToBytes(string), buf, offset, length) - return charsWritten -} - -function binaryWrite (buf, string, offset, length) { - return asciiWrite(buf, string, offset, length) -} - -function base64Write (buf, string, offset, length) { - var charsWritten = blitBuffer(base64ToBytes(string), buf, offset, length) - return charsWritten -} - -function utf16leWrite (buf, string, offset, length) { - var charsWritten = blitBuffer(utf16leToBytes(string), buf, offset, length, 2) - return charsWritten -} - -Buffer.prototype.write = function (string, offset, length, encoding) { - // Support both (string, offset, length, encoding) - // and the legacy (string, encoding, offset, length) - if (isFinite(offset)) { - if (!isFinite(length)) { - encoding = length - length = undefined - } - } else { // legacy - var swap = encoding - encoding = offset - offset = length - length = swap - } - - offset = Number(offset) || 0 - var remaining = this.length - offset - if (!length) { - length = remaining - } else { - length = Number(length) - if (length > remaining) { - length = remaining - } - } - encoding = String(encoding || 'utf8').toLowerCase() - - var ret - switch (encoding) { - case 'hex': - ret = hexWrite(this, string, offset, length) - break - case 'utf8': - case 'utf-8': - ret = utf8Write(this, string, offset, length) - break - case 'ascii': - ret = asciiWrite(this, string, offset, length) - break - case 'binary': - ret = binaryWrite(this, string, offset, length) - break - case 'base64': - ret = base64Write(this, string, offset, length) - break - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - ret = utf16leWrite(this, string, offset, length) - break - default: - throw new TypeError('Unknown encoding: ' + encoding) - } - return ret -} - -Buffer.prototype.toJSON = function () { - return { - type: 'Buffer', - data: Array.prototype.slice.call(this._arr || this, 0) - } -} - -function base64Slice (buf, start, end) { - if (start === 0 && end === buf.length) { - return base64.fromByteArray(buf) - } else { - return base64.fromByteArray(buf.slice(start, end)) - } -} - -function utf8Slice (buf, start, end) { - var res = '' - var tmp = '' - end = Math.min(buf.length, end) - - for (var i = start; i < end; i++) { - if (buf[i] <= 0x7F) { - res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i]) - tmp = '' - } else { - tmp += '%' + buf[i].toString(16) - } - } - - return res + decodeUtf8Char(tmp) -} - -function asciiSlice (buf, start, end) { - var ret = '' - end = Math.min(buf.length, end) - - for (var i = start; i < end; i++) { - ret += String.fromCharCode(buf[i]) - } - return ret -} - -function binarySlice (buf, start, end) { - return asciiSlice(buf, start, end) -} - -function hexSlice (buf, start, end) { - var len = buf.length - - if (!start || start < 0) start = 0 - if (!end || end < 0 || end > len) end = len - - var out = '' - for (var i = start; i < end; i++) { - out += toHex(buf[i]) - } - return out -} - -function utf16leSlice (buf, start, end) { - var bytes = buf.slice(start, end) - var res = '' - for (var i = 0; i < bytes.length; i += 2) { - res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) - } - return res -} - -Buffer.prototype.slice = function (start, end) { - var len = this.length - start = ~~start - end = end === undefined ? len : ~~end - - if (start < 0) { - start += len; - if (start < 0) - start = 0 - } else if (start > len) { - start = len - } - - if (end < 0) { - end += len - if (end < 0) - end = 0 - } else if (end > len) { - end = len - } - - if (end < start) - end = start - - if (Buffer.TYPED_ARRAY_SUPPORT) { - return Buffer._augment(this.subarray(start, end)) - } else { - var sliceLen = end - start - var newBuf = new Buffer(sliceLen, undefined, true) - for (var i = 0; i < sliceLen; i++) { - newBuf[i] = this[i + start] - } - return newBuf - } -} - -/* - * Need to make sure that buffer isn't trying to write out of bounds. - */ -function checkOffset (offset, ext, length) { - if ((offset % 1) !== 0 || offset < 0) - throw new RangeError('offset is not uint') - if (offset + ext > length) - throw new RangeError('Trying to access beyond buffer length') -} - -Buffer.prototype.readUInt8 = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 1, this.length) - return this[offset] -} - -Buffer.prototype.readUInt16LE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 2, this.length) - return this[offset] | (this[offset + 1] << 8) -} - -Buffer.prototype.readUInt16BE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 2, this.length) - return (this[offset] << 8) | this[offset + 1] -} - -Buffer.prototype.readUInt32LE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 4, this.length) - - return ((this[offset]) | - (this[offset + 1] << 8) | - (this[offset + 2] << 16)) + - (this[offset + 3] * 0x1000000) -} - -Buffer.prototype.readUInt32BE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 4, this.length) - - return (this[offset] * 0x1000000) + - ((this[offset + 1] << 16) | - (this[offset + 2] << 8) | - this[offset + 3]) -} - -Buffer.prototype.readInt8 = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 1, this.length) - if (!(this[offset] & 0x80)) - return (this[offset]) - return ((0xff - this[offset] + 1) * -1) -} - -Buffer.prototype.readInt16LE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 2, this.length) - var val = this[offset] | (this[offset + 1] << 8) - return (val & 0x8000) ? val | 0xFFFF0000 : val -} - -Buffer.prototype.readInt16BE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 2, this.length) - var val = this[offset + 1] | (this[offset] << 8) - return (val & 0x8000) ? val | 0xFFFF0000 : val -} - -Buffer.prototype.readInt32LE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 4, this.length) - - return (this[offset]) | - (this[offset + 1] << 8) | - (this[offset + 2] << 16) | - (this[offset + 3] << 24) -} - -Buffer.prototype.readInt32BE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 4, this.length) - - return (this[offset] << 24) | - (this[offset + 1] << 16) | - (this[offset + 2] << 8) | - (this[offset + 3]) -} - -Buffer.prototype.readFloatLE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 4, this.length) - return ieee754.read(this, offset, true, 23, 4) -} - -Buffer.prototype.readFloatBE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 4, this.length) - return ieee754.read(this, offset, false, 23, 4) -} - -Buffer.prototype.readDoubleLE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 8, this.length) - return ieee754.read(this, offset, true, 52, 8) -} - -Buffer.prototype.readDoubleBE = function (offset, noAssert) { - if (!noAssert) - checkOffset(offset, 8, this.length) - return ieee754.read(this, offset, false, 52, 8) -} - -function checkInt (buf, value, offset, ext, max, min) { - if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance') - if (value > max || value < min) throw new TypeError('value is out of bounds') - if (offset + ext > buf.length) throw new TypeError('index out of range') -} - -Buffer.prototype.writeUInt8 = function (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 1, 0xff, 0) - if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) - this[offset] = value - return offset + 1 -} - -function objectWriteUInt16 (buf, value, offset, littleEndian) { - if (value < 0) value = 0xffff + value + 1 - for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) { - buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> - (littleEndian ? i : 1 - i) * 8 - } -} - -Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 2, 0xffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = value - this[offset + 1] = (value >>> 8) - } else objectWriteUInt16(this, value, offset, true) - return offset + 2 -} - -Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 2, 0xffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 8) - this[offset + 1] = value - } else objectWriteUInt16(this, value, offset, false) - return offset + 2 -} - -function objectWriteUInt32 (buf, value, offset, littleEndian) { - if (value < 0) value = 0xffffffff + value + 1 - for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) { - buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff - } -} - -Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 4, 0xffffffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset + 3] = (value >>> 24) - this[offset + 2] = (value >>> 16) - this[offset + 1] = (value >>> 8) - this[offset] = value - } else objectWriteUInt32(this, value, offset, true) - return offset + 4 -} - -Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 4, 0xffffffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) - this[offset + 3] = value - } else objectWriteUInt32(this, value, offset, false) - return offset + 4 -} - -Buffer.prototype.writeInt8 = function (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 1, 0x7f, -0x80) - if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) - if (value < 0) value = 0xff + value + 1 - this[offset] = value - return offset + 1 -} - -Buffer.prototype.writeInt16LE = function (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 2, 0x7fff, -0x8000) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = value - this[offset + 1] = (value >>> 8) - } else objectWriteUInt16(this, value, offset, true) - return offset + 2 -} - -Buffer.prototype.writeInt16BE = function (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 2, 0x7fff, -0x8000) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 8) - this[offset + 1] = value - } else objectWriteUInt16(this, value, offset, false) - return offset + 2 -} - -Buffer.prototype.writeInt32LE = function (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = value - this[offset + 1] = (value >>> 8) - this[offset + 2] = (value >>> 16) - this[offset + 3] = (value >>> 24) - } else objectWriteUInt32(this, value, offset, true) - return offset + 4 -} - -Buffer.prototype.writeInt32BE = function (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) - checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) - if (value < 0) value = 0xffffffff + value + 1 - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) - this[offset + 3] = value - } else objectWriteUInt32(this, value, offset, false) - return offset + 4 -} - -function checkIEEE754 (buf, value, offset, ext, max, min) { - if (value > max || value < min) throw new TypeError('value is out of bounds') - if (offset + ext > buf.length) throw new TypeError('index out of range') -} - -function writeFloat (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) - checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) - ieee754.write(buf, value, offset, littleEndian, 23, 4) - return offset + 4 -} - -Buffer.prototype.writeFloatLE = function (value, offset, noAssert) { - return writeFloat(this, value, offset, true, noAssert) -} - -Buffer.prototype.writeFloatBE = function (value, offset, noAssert) { - return writeFloat(this, value, offset, false, noAssert) -} - -function writeDouble (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) - checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) - ieee754.write(buf, value, offset, littleEndian, 52, 8) - return offset + 8 -} - -Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) { - return writeDouble(this, value, offset, true, noAssert) -} - -Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) { - return writeDouble(this, value, offset, false, noAssert) -} - -// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) -Buffer.prototype.copy = function (target, target_start, start, end) { - var source = this - - if (!start) start = 0 - if (!end && end !== 0) end = this.length - if (!target_start) target_start = 0 - - // Copy 0 bytes; we're done - if (end === start) return - if (target.length === 0 || source.length === 0) return - - // Fatal error conditions - if (end < start) throw new TypeError('sourceEnd < sourceStart') - if (target_start < 0 || target_start >= target.length) - throw new TypeError('targetStart out of bounds') - if (start < 0 || start >= source.length) throw new TypeError('sourceStart out of bounds') - if (end < 0 || end > source.length) throw new TypeError('sourceEnd out of bounds') - - // Are we oob? - if (end > this.length) - end = this.length - if (target.length - target_start < end - start) - end = target.length - target_start + start - - var len = end - start - - if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { - for (var i = 0; i < len; i++) { - target[i + target_start] = this[i + start] - } - } else { - target._set(this.subarray(start, start + len), target_start) - } -} - -// fill(value, start=0, end=buffer.length) -Buffer.prototype.fill = function (value, start, end) { - if (!value) value = 0 - if (!start) start = 0 - if (!end) end = this.length - - if (end < start) throw new TypeError('end < start') - - // Fill 0 bytes; we're done - if (end === start) return - if (this.length === 0) return - - if (start < 0 || start >= this.length) throw new TypeError('start out of bounds') - if (end < 0 || end > this.length) throw new TypeError('end out of bounds') - - var i - if (typeof value === 'number') { - for (i = start; i < end; i++) { - this[i] = value - } - } else { - var bytes = utf8ToBytes(value.toString()) - var len = bytes.length - for (i = start; i < end; i++) { - this[i] = bytes[i % len] - } - } - - return this -} - -/** - * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. - * Added in Node 0.12. Only available in browsers that support ArrayBuffer. - */ -Buffer.prototype.toArrayBuffer = function () { - if (typeof Uint8Array !== 'undefined') { - if (Buffer.TYPED_ARRAY_SUPPORT) { - return (new Buffer(this)).buffer - } else { - var buf = new Uint8Array(this.length) - for (var i = 0, len = buf.length; i < len; i += 1) { - buf[i] = this[i] - } - return buf.buffer - } - } else { - throw new TypeError('Buffer.toArrayBuffer not supported in this browser') - } -} - -// HELPER FUNCTIONS -// ================ - -var BP = Buffer.prototype - -/** - * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods - */ -Buffer._augment = function (arr) { - arr.constructor = Buffer - arr._isBuffer = true - - // save reference to original Uint8Array get/set methods before overwriting - arr._get = arr.get - arr._set = arr.set - - // deprecated, will be removed in node 0.13+ - arr.get = BP.get - arr.set = BP.set - - arr.write = BP.write - arr.toString = BP.toString - arr.toLocaleString = BP.toString - arr.toJSON = BP.toJSON - arr.equals = BP.equals - arr.compare = BP.compare - arr.copy = BP.copy - arr.slice = BP.slice - arr.readUInt8 = BP.readUInt8 - arr.readUInt16LE = BP.readUInt16LE - arr.readUInt16BE = BP.readUInt16BE - arr.readUInt32LE = BP.readUInt32LE - arr.readUInt32BE = BP.readUInt32BE - arr.readInt8 = BP.readInt8 - arr.readInt16LE = BP.readInt16LE - arr.readInt16BE = BP.readInt16BE - arr.readInt32LE = BP.readInt32LE - arr.readInt32BE = BP.readInt32BE - arr.readFloatLE = BP.readFloatLE - arr.readFloatBE = BP.readFloatBE - arr.readDoubleLE = BP.readDoubleLE - arr.readDoubleBE = BP.readDoubleBE - arr.writeUInt8 = BP.writeUInt8 - arr.writeUInt16LE = BP.writeUInt16LE - arr.writeUInt16BE = BP.writeUInt16BE - arr.writeUInt32LE = BP.writeUInt32LE - arr.writeUInt32BE = BP.writeUInt32BE - arr.writeInt8 = BP.writeInt8 - arr.writeInt16LE = BP.writeInt16LE - arr.writeInt16BE = BP.writeInt16BE - arr.writeInt32LE = BP.writeInt32LE - arr.writeInt32BE = BP.writeInt32BE - arr.writeFloatLE = BP.writeFloatLE - arr.writeFloatBE = BP.writeFloatBE - arr.writeDoubleLE = BP.writeDoubleLE - arr.writeDoubleBE = BP.writeDoubleBE - arr.fill = BP.fill - arr.inspect = BP.inspect - arr.toArrayBuffer = BP.toArrayBuffer - - return arr -} - -var INVALID_BASE64_RE = /[^+\/0-9A-z]/g - -function base64clean (str) { - // Node strips out invalid characters like \n and \t from the string, base64-js does not - str = stringtrim(str).replace(INVALID_BASE64_RE, '') - // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not - while (str.length % 4 !== 0) { - str = str + '=' - } - return str -} - -function stringtrim (str) { - if (str.trim) return str.trim() - return str.replace(/^\s+|\s+$/g, '') -} - -function isArrayish (subject) { - return isArray(subject) || Buffer.isBuffer(subject) || - subject && typeof subject === 'object' && - typeof subject.length === 'number' -} - -function toHex (n) { - if (n < 16) return '0' + n.toString(16) - return n.toString(16) -} - -function utf8ToBytes (str) { - var byteArray = [] - for (var i = 0; i < str.length; i++) { - var b = str.charCodeAt(i) - if (b <= 0x7F) { - byteArray.push(b) - } else { - var start = i - if (b >= 0xD800 && b <= 0xDFFF) i++ - var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%') - for (var j = 0; j < h.length; j++) { - byteArray.push(parseInt(h[j], 16)) - } - } - } - return byteArray -} - -function asciiToBytes (str) { - var byteArray = [] - for (var i = 0; i < str.length; i++) { - // Node's code seems to be doing this and not & 0x7F.. - byteArray.push(str.charCodeAt(i) & 0xFF) - } - return byteArray -} - -function utf16leToBytes (str) { - var c, hi, lo - var byteArray = [] - for (var i = 0; i < str.length; i++) { - c = str.charCodeAt(i) - hi = c >> 8 - lo = c % 256 - byteArray.push(lo) - byteArray.push(hi) - } - - return byteArray -} - -function base64ToBytes (str) { - return base64.toByteArray(str) -} - -function blitBuffer (src, dst, offset, length, unitSize) { - if (unitSize) length -= length % unitSize; - for (var i = 0; i < length; i++) { - if ((i + offset >= dst.length) || (i >= src.length)) - break - dst[i + offset] = src[i] - } - return i -} - -function decodeUtf8Char (str) { - try { - return decodeURIComponent(str) - } catch (err) { - return String.fromCharCode(0xFFFD) // UTF 8 invalid char - } -} - -},{"base64-js":2,"ieee754":3,"is-array":4}],2:[function(require,module,exports){ -var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - -;(function (exports) { - 'use strict'; - - var Arr = (typeof Uint8Array !== 'undefined') - ? Uint8Array - : Array - - var PLUS = '+'.charCodeAt(0) - var SLASH = '/'.charCodeAt(0) - var NUMBER = '0'.charCodeAt(0) - var LOWER = 'a'.charCodeAt(0) - var UPPER = 'A'.charCodeAt(0) - - function decode (elt) { - var code = elt.charCodeAt(0) - if (code === PLUS) - return 62 // '+' - if (code === SLASH) - return 63 // '/' - if (code < NUMBER) - return -1 //no match - if (code < NUMBER + 10) - return code - NUMBER + 26 + 26 - if (code < UPPER + 26) - return code - UPPER - if (code < LOWER + 26) - return code - LOWER + 26 - } - - function b64ToByteArray (b64) { - var i, j, l, tmp, placeHolders, arr - - if (b64.length % 4 > 0) { - throw new Error('Invalid string. Length must be a multiple of 4') - } - - // the number of equal signs (place holders) - // if there are two placeholders, than the two characters before it - // represent one byte - // if there is only one, then the three characters before it represent 2 bytes - // this is just a cheap hack to not do indexOf twice - var len = b64.length - placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0 - - // base64 is 4/3 + up to two characters of the original data - arr = new Arr(b64.length * 3 / 4 - placeHolders) - - // if there are placeholders, only get up to the last complete 4 chars - l = placeHolders > 0 ? b64.length - 4 : b64.length - - var L = 0 - - function push (v) { - arr[L++] = v - } - - for (i = 0, j = 0; i < l; i += 4, j += 3) { - tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3)) - push((tmp & 0xFF0000) >> 16) - push((tmp & 0xFF00) >> 8) - push(tmp & 0xFF) - } - - if (placeHolders === 2) { - tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4) - push(tmp & 0xFF) - } else if (placeHolders === 1) { - tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2) - push((tmp >> 8) & 0xFF) - push(tmp & 0xFF) - } - - return arr - } - - function uint8ToBase64 (uint8) { - var i, - extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes - output = "", - temp, length - - function encode (num) { - return lookup.charAt(num) - } - - function tripletToBase64 (num) { - return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F) - } - - // go through the array every three bytes, we'll deal with trailing stuff later - for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { - temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) - output += tripletToBase64(temp) - } - - // pad the end with zeros, but make sure to not forget the extra bytes - switch (extraBytes) { - case 1: - temp = uint8[uint8.length - 1] - output += encode(temp >> 2) - output += encode((temp << 4) & 0x3F) - output += '==' - break - case 2: - temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]) - output += encode(temp >> 10) - output += encode((temp >> 4) & 0x3F) - output += encode((temp << 2) & 0x3F) - output += '=' - break - } - - return output - } - - exports.toByteArray = b64ToByteArray - exports.fromByteArray = uint8ToBase64 -}(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) - -},{}],3:[function(require,module,exports){ -exports.read = function(buffer, offset, isLE, mLen, nBytes) { - var e, m, - eLen = nBytes * 8 - mLen - 1, - eMax = (1 << eLen) - 1, - eBias = eMax >> 1, - nBits = -7, - i = isLE ? (nBytes - 1) : 0, - d = isLE ? -1 : 1, - s = buffer[offset + i]; - - i += d; - - e = s & ((1 << (-nBits)) - 1); - s >>= (-nBits); - nBits += eLen; - for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); - - m = e & ((1 << (-nBits)) - 1); - e >>= (-nBits); - nBits += mLen; - for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); - - if (e === 0) { - e = 1 - eBias; - } else if (e === eMax) { - return m ? NaN : ((s ? -1 : 1) * Infinity); - } else { - m = m + Math.pow(2, mLen); - e = e - eBias; - } - return (s ? -1 : 1) * m * Math.pow(2, e - mLen); -}; - -exports.write = function(buffer, value, offset, isLE, mLen, nBytes) { - var e, m, c, - eLen = nBytes * 8 - mLen - 1, - eMax = (1 << eLen) - 1, - eBias = eMax >> 1, - rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), - i = isLE ? 0 : (nBytes - 1), - d = isLE ? 1 : -1, - s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; - - value = Math.abs(value); - - if (isNaN(value) || value === Infinity) { - m = isNaN(value) ? 1 : 0; - e = eMax; - } else { - e = Math.floor(Math.log(value) / Math.LN2); - if (value * (c = Math.pow(2, -e)) < 1) { - e--; - c *= 2; - } - if (e + eBias >= 1) { - value += rt / c; - } else { - value += rt * Math.pow(2, 1 - eBias); - } - if (value * c >= 2) { - e++; - c /= 2; - } - - if (e + eBias >= eMax) { - m = 0; - e = eMax; - } else if (e + eBias >= 1) { - m = (value * c - 1) * Math.pow(2, mLen); - e = e + eBias; - } else { - m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); - e = 0; - } - } - - for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); - - e = (e << mLen) | m; - eLen += mLen; - for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); - - buffer[offset + i - d] |= s * 128; -}; - -},{}],4:[function(require,module,exports){ - -/** - * isArray - */ - -var isArray = Array.isArray; - -/** - * toString - */ - -var str = Object.prototype.toString; - -/** - * Whether or not the given `val` - * is an array. - * - * example: - * - * isArray([]); - * // > true - * isArray(arguments); - * // > false - * isArray(''); - * // > false - * - * @param {mixed} val - * @return {bool} - */ - -module.exports = isArray || function (val) { - return !! val && '[object Array]' == str.call(val); -}; - -},{}],5:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; @@ -1383,7 +86,7 @@ process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; -},{}],6:[function(require,module,exports){ +},{}],2:[function(require,module,exports){ /* * Copyright (c) 2014, Facebook, Inc. * All rights reserved. @@ -1635,7 +338,7 @@ var _prefix = 'ID_'; module.exports = Dispatcher; -},{"./invariant":7}],7:[function(require,module,exports){ +},{"./invariant":3}],3:[function(require,module,exports){ /** * Copyright (c) 2014, Facebook, Inc. * All rights reserved. @@ -1690,785 +393,742 @@ var invariant = function(condition, format, a, b, c, d, e, f) { module.exports = invariant; -},{}],8:[function(require,module,exports){ +},{}],4:[function(require,module,exports){ +"use strict"; + /** - * Actions that modify the URL. + * Represents a cancellation caused by navigating away + * before the previous transition has fully resolved. */ -var LocationActions = { - - /** - * Indicates a new location is being pushed to the history stack. - */ - PUSH: 'push', +function Cancellation() {} - /** - * Indicates the current location should be replaced. - */ - REPLACE: 'replace', +module.exports = Cancellation; +},{}],5:[function(require,module,exports){ +"use strict"; - /** - * Indicates the most recent entry should be removed from the history stack. - */ - POP: 'pop' +var warning = require("react/lib/warning"); +var invariant = require("react/lib/invariant"); -}; +function checkPropTypes(componentName, propTypes, props) { + for (var propName in propTypes) { + if (propTypes.hasOwnProperty(propName)) { + var error = propTypes[propName](props, propName, componentName); -module.exports = LocationActions; + if (error instanceof Error) warning(false, error.message); + } + } +} -},{}],9:[function(require,module,exports){ -var LocationActions = require('../actions/LocationActions'); +var Configuration = { -/** - * A scroll behavior that attempts to imitate the default behavior - * of modern browsers. - */ -var ImitateBrowserBehavior = { + statics: { - updateScrollPosition: function (position, actionType) { - switch (actionType) { - case LocationActions.PUSH: - case LocationActions.REPLACE: - window.scrollTo(0, 0); - break; - case LocationActions.POP: - if (position) { - window.scrollTo(position.x, position.y); - } else { - window.scrollTo(0, 0); - } - break; + validateProps: function validateProps(props) { + checkPropTypes(this.displayName, this.propTypes, props); } + + }, + + render: function render() { + invariant(false, "%s elements are for router configuration only and should not be rendered", this.constructor.displayName); } }; -module.exports = ImitateBrowserBehavior; +module.exports = Configuration; +},{"react/lib/invariant":182,"react/lib/warning":202}],6:[function(require,module,exports){ +"use strict"; -},{"../actions/LocationActions":8}],10:[function(require,module,exports){ -/** - * A scroll behavior that always scrolls to the top of the page - * after a transition. - */ -var ScrollToTopBehavior = { +var invariant = require("react/lib/invariant"); +var canUseDOM = require("react/lib/ExecutionEnvironment").canUseDOM; - updateScrollPosition: function () { - window.scrollTo(0, 0); - } +var History = { -}; + /** + * The current number of entries in the history. + * + * Note: This property is read-only. + */ + length: 1, -module.exports = ScrollToTopBehavior; + /** + * Sends the browser back one entry in the history. + */ + back: function back() { + invariant(canUseDOM, "Cannot use History.back without a DOM"); -},{}],11:[function(require,module,exports){ -var React = require('react'); -var FakeNode = require('../mixins/FakeNode'); -var PropTypes = require('../utils/PropTypes'); + // Do this first so that History.length will + // be accurate in location change listeners. + History.length -= 1; -/** - * A component is a special kind of that - * renders when its parent matches but none of its siblings do. - * Only one such route may be used at any given level in the - * route hierarchy. - */ -var DefaultRoute = React.createClass({ + window.history.back(); + } - displayName: 'DefaultRoute', +}; - mixins: [ FakeNode ], +module.exports = History; +},{"react/lib/ExecutionEnvironment":64,"react/lib/invariant":182}],7:[function(require,module,exports){ +"use strict"; - propTypes: { - name: React.PropTypes.string, - path: PropTypes.falsy, - handler: React.PropTypes.func.isRequired - } +var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; -}); +var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; -module.exports = DefaultRoute; +/* jshint -W084 */ +var PathUtils = require("./PathUtils"); -},{"../mixins/FakeNode":20,"../utils/PropTypes":31,"react":"react"}],12:[function(require,module,exports){ -var React = require('react'); -var classSet = require('react/lib/cx'); -var assign = require('react/lib/Object.assign'); -var Navigation = require('../mixins/Navigation'); -var State = require('../mixins/State'); +function deepSearch(route, pathname, query) { + // Check the subtree first to find the most deeply-nested match. + var childRoutes = route.childRoutes; + if (childRoutes) { + var match, childRoute; + for (var i = 0, len = childRoutes.length; i < len; ++i) { + childRoute = childRoutes[i]; -function isLeftClickEvent(event) { - return event.button === 0; -} + if (childRoute.isDefault || childRoute.isNotFound) continue; // Check these in order later. -function isModifiedEvent(event) { - return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); + if (match = deepSearch(childRoute, pathname, query)) { + // A route in the subtree matched! Add this route and we're done. + match.routes.unshift(route); + return match; + } + } + } + + // No child routes matched; try the default route. + var defaultRoute = route.defaultRoute; + if (defaultRoute && (params = PathUtils.extractParams(defaultRoute.path, pathname))) { + return new Match(pathname, params, query, [route, defaultRoute]); + } // Does the "not found" route match? + var notFoundRoute = route.notFoundRoute; + if (notFoundRoute && (params = PathUtils.extractParams(notFoundRoute.path, pathname))) { + return new Match(pathname, params, query, [route, notFoundRoute]); + } // Last attempt: check this route. + var params = PathUtils.extractParams(route.path, pathname); + if (params) { + return new Match(pathname, params, query, [route]); + }return null; } -/** - * components are used to create an element that links to a route. - * When that route is active, the link gets an "active" class name (or the - * value of its `activeClassName` prop). - * - * For example, assuming you have the following route: - * - * - * - * You could use the following component to link to that route: - * - * - * - * In addition to params, links may pass along query string parameters - * using the `query` prop. - * - * - */ -var Link = React.createClass({ +var Match = (function () { + function Match(pathname, params, query, routes) { + _classCallCheck(this, Match); - displayName: 'Link', + this.pathname = pathname; + this.params = params; + this.query = query; + this.routes = routes; + } - mixins: [ Navigation, State ], + _prototypeProperties(Match, { + findMatch: { - propTypes: { - activeClassName: React.PropTypes.string.isRequired, - to: React.PropTypes.string.isRequired, - params: React.PropTypes.object, - query: React.PropTypes.object, - onClick: React.PropTypes.func - }, + /** + * Attempts to match depth-first a route in the given route's + * subtree against the given path and returns the match if it + * succeeds, null if no match can be made. + */ - getDefaultProps: function () { - return { - activeClassName: 'active' - }; - }, + value: function findMatch(routes, path) { + var pathname = PathUtils.withoutQuery(path); + var query = PathUtils.extractQuery(path); + var match = null; - handleClick: function (event) { - var allowTransition = true; - var clickResult; + for (var i = 0, len = routes.length; match == null && i < len; ++i) match = deepSearch(routes[i], pathname, query); + + return match; + }, + writable: true, + configurable: true + } + }); - if (this.props.onClick) - clickResult = this.props.onClick(event); + return Match; +})(); - if (isModifiedEvent(event) || !isLeftClickEvent(event)) - return; +module.exports = Match; +},{"./PathUtils":10}],8:[function(require,module,exports){ +"use strict"; - if (clickResult === false || event.defaultPrevented === true) - allowTransition = false; +var PropTypes = require("./PropTypes"); - event.preventDefault(); +/** + * A mixin for components that modify the URL. + * + * Example: + * + * var MyLink = React.createClass({ + * mixins: [ Router.Navigation ], + * handleClick: function (event) { + * event.preventDefault(); + * this.transitionTo('aRoute', { the: 'params' }, { the: 'query' }); + * }, + * render: function () { + * return ( + * Click me! + * ); + * } + * }); + */ +var Navigation = { - if (allowTransition) - this.transitionTo(this.props.to, this.props.params, this.props.query); + contextTypes: { + makePath: PropTypes.func.isRequired, + makeHref: PropTypes.func.isRequired, + transitionTo: PropTypes.func.isRequired, + replaceWith: PropTypes.func.isRequired, + goBack: PropTypes.func.isRequired }, /** - * Returns the value of the "href" attribute to use on the DOM element. + * Returns an absolute URL path created from the given route + * name, URL parameters, and query values. */ - getHref: function () { - return this.makeHref(this.props.to, this.props.params, this.props.query); + makePath: function makePath(to, params, query) { + return this.context.makePath(to, params, query); }, /** - * Returns the value of the "class" attribute to use on the DOM element, which contains - * the value of the activeClassName property when this is active. + * Returns a string that may safely be used as the href of a + * link to the route with the given name. */ - getClassName: function () { - var classNames = {}; - - if (this.props.className) - classNames[this.props.className] = true; - - if (this.isActive(this.props.to, this.props.params, this.props.query)) - classNames[this.props.activeClassName] = true; + makeHref: function makeHref(to, params, query) { + return this.context.makeHref(to, params, query); + }, - return classSet(classNames); + /** + * Transitions to the URL specified in the arguments by pushing + * a new URL onto the history stack. + */ + transitionTo: function transitionTo(to, params, query) { + this.context.transitionTo(to, params, query); }, - render: function () { - var props = assign({}, this.props, { - href: this.getHref(), - className: this.getClassName(), - onClick: this.handleClick - }); + /** + * Transitions to the URL specified in the arguments by replacing + * the current URL in the history stack. + */ + replaceWith: function replaceWith(to, params, query) { + this.context.replaceWith(to, params, query); + }, - return React.DOM.a(props, this.props.children); + /** + * Transitions to the previous URL. + */ + goBack: function goBack() { + return this.context.goBack(); } -}); +}; -module.exports = Link; +module.exports = Navigation; +},{"./PropTypes":11}],9:[function(require,module,exports){ +"use strict"; -},{"../mixins/Navigation":21,"../mixins/State":25,"react":"react","react/lib/Object.assign":77,"react/lib/cx":167}],13:[function(require,module,exports){ -var React = require('react'); -var FakeNode = require('../mixins/FakeNode'); -var PropTypes = require('../utils/PropTypes'); +var PropTypes = require("./PropTypes"); /** - * A is a special kind of that - * renders when the beginning of its parent's path matches - * but none of its siblings do, including any . - * Only one such route may be used at any given level in the - * route hierarchy. + * Provides the router with context for Router.Navigation. */ -var NotFoundRoute = React.createClass({ - - displayName: 'NotFoundRoute', +var NavigationContext = { - mixins: [ FakeNode ], + childContextTypes: { + makePath: PropTypes.func.isRequired, + makeHref: PropTypes.func.isRequired, + transitionTo: PropTypes.func.isRequired, + replaceWith: PropTypes.func.isRequired, + goBack: PropTypes.func.isRequired + }, - propTypes: { - name: React.PropTypes.string, - path: PropTypes.falsy, - handler: React.PropTypes.func.isRequired + getChildContext: function getChildContext() { + return { + makePath: this.constructor.makePath.bind(this.constructor), + makeHref: this.constructor.makeHref.bind(this.constructor), + transitionTo: this.constructor.transitionTo.bind(this.constructor), + replaceWith: this.constructor.replaceWith.bind(this.constructor), + goBack: this.constructor.goBack.bind(this.constructor) + }; } -}); - -module.exports = NotFoundRoute; +}; -},{"../mixins/FakeNode":20,"../utils/PropTypes":31,"react":"react"}],14:[function(require,module,exports){ -var React = require('react'); -var FakeNode = require('../mixins/FakeNode'); -var PropTypes = require('../utils/PropTypes'); +module.exports = NavigationContext; +},{"./PropTypes":11}],10:[function(require,module,exports){ +"use strict"; -/** - * A component is a special kind of that always - * redirects to another route when it matches. - */ -var Redirect = React.createClass({ +var invariant = require("react/lib/invariant"); +var merge = require("qs/lib/utils").merge; +var qs = require("qs"); - displayName: 'Redirect', +var paramCompileMatcher = /:([a-zA-Z_$][a-zA-Z0-9_$]*)|[*.()\[\]\\+|{}^$]/g; +var paramInjectMatcher = /:([a-zA-Z_$][a-zA-Z0-9_$?]*[?]?)|[*]/g; +var paramInjectTrailingSlashMatcher = /\/\/\?|\/\?\/|\/\?/g; +var queryMatcher = /\?(.+)/; - mixins: [ FakeNode ], +var _compiledPatterns = {}; - propTypes: { - path: React.PropTypes.string, - from: React.PropTypes.string, // Alias for path. - to: React.PropTypes.string, - handler: PropTypes.falsy - } - -}); - -module.exports = Redirect; - -},{"../mixins/FakeNode":20,"../utils/PropTypes":31,"react":"react"}],15:[function(require,module,exports){ -var React = require('react'); -var FakeNode = require('../mixins/FakeNode'); - -/** - * components specify components that are rendered to the page when the - * URL matches a given pattern. - * - * Routes are arranged in a nested tree structure. When a new URL is requested, - * the tree is searched depth-first to find a route whose path matches the URL. - * When one is found, all routes in the tree that lead to it are considered - * "active" and their components are rendered into the DOM, nested in the same - * order as they are in the tree. - * - * The preferred way to configure a router is using JSX. The XML-like syntax is - * a great way to visualize how routes are laid out in an application. - * - * var routes = [ - * - * - * - * - * - * ]; - * - * Router.run(routes, function (Handler) { - * React.render(, document.body); - * }); - * - * Handlers for Route components that contain children can render their active - * child route using a element. - * - * var App = React.createClass({ - * render: function () { - * return ( - *
- * - *
- * ); - * } - * }); - */ -var Route = React.createClass({ - - displayName: 'Route', - - mixins: [ FakeNode ], - - propTypes: { - name: React.PropTypes.string, - path: React.PropTypes.string, - handler: React.PropTypes.func.isRequired, - ignoreScrollBehavior: React.PropTypes.bool - } - -}); - -module.exports = Route; - -},{"../mixins/FakeNode":20,"react":"react"}],16:[function(require,module,exports){ -var React = require('react'); -var RouteHandlerMixin = require('../mixins/RouteHandler'); - -/** - * A component renders the active child route handler - * when routes are nested. - */ -var RouteHandler = React.createClass({ - - displayName: 'RouteHandler', - - mixins: [RouteHandlerMixin], +function compilePattern(pattern) { + if (!(pattern in _compiledPatterns)) { + var paramNames = []; + var source = pattern.replace(paramCompileMatcher, function (match, paramName) { + if (paramName) { + paramNames.push(paramName); + return "([^/?#]+)"; + } else if (match === "*") { + paramNames.push("splat"); + return "(.*?)"; + } else { + return "\\" + match; + } + }); - getDefaultProps: function () { - return { - ref: '__routeHandler__' + _compiledPatterns[pattern] = { + matcher: new RegExp("^" + source + "$", "i"), + paramNames: paramNames }; - }, - - render: function () { - return this.getRouteHandler(); } -}); - -module.exports = RouteHandler; - -},{"../mixins/RouteHandler":23,"react":"react"}],17:[function(require,module,exports){ -var LocationActions = require('../actions/LocationActions'); -var History = require('../utils/History'); -var Path = require('../utils/Path'); - -/** - * Returns the current URL path from the `hash` portion of the URL, including - * query string. - */ -function getHashPath() { - return Path.decode( - // We can't use window.location.hash here because it's not - // consistent across browsers - Firefox will pre-decode it! - window.location.href.split('#')[1] || '' - ); + return _compiledPatterns[pattern]; } -var _actionType; - -function ensureSlash() { - var path = getHashPath(); +var PathUtils = { - if (path.charAt(0) === '/') - return true; + /** + * Returns true if the given path is absolute. + */ + isAbsolute: function isAbsolute(path) { + return path.charAt(0) === "/"; + }, - HashLocation.replace('/' + path); + /** + * Joins two URL paths together. + */ + join: function join(a, b) { + return a.replace(/\/*$/, "/") + b; + }, - return false; -} + /** + * Returns an array of the names of all parameters in the given pattern. + */ + extractParamNames: function extractParamNames(pattern) { + return compilePattern(pattern).paramNames; + }, -var _changeListeners = []; + /** + * Extracts the portions of the given URL path that match the given pattern + * and returns an object of param name => value pairs. Returns null if the + * pattern does not match the given path. + */ + extractParams: function extractParams(pattern, path) { + var _compilePattern = compilePattern(pattern); -function notifyChange(type) { - if (type === LocationActions.PUSH) - History.length += 1; + var matcher = _compilePattern.matcher; + var paramNames = _compilePattern.paramNames; - var change = { - path: getHashPath(), - type: type - }; + var match = path.match(matcher); - _changeListeners.forEach(function (listener) { - listener(change); - }); -} + if (!match) { + return null; + }var params = {}; -var _isListening = false; + paramNames.forEach(function (paramName, index) { + params[paramName] = match[index + 1]; + }); -function onHashChange() { - if (ensureSlash()) { - // If we don't have an _actionType then all we know is the hash - // changed. It was probably caused by the user clicking the Back - // button, but may have also been the Forward button or manual - // manipulation. So just guess 'pop'. - notifyChange(_actionType || LocationActions.POP); - _actionType = null; - } -} + return params; + }, -/** - * A Location that uses `window.location.hash`. - */ -var HashLocation = { + /** + * Returns a version of the given route path with params interpolated. Throws + * if there is a dynamic segment of the route path for which there is no param. + */ + injectParams: function injectParams(pattern, params) { + params = params || {}; - addChangeListener: function (listener) { - _changeListeners.push(listener); + var splatIndex = 0; - // Do this BEFORE listening for hashchange. - ensureSlash(); + return pattern.replace(paramInjectMatcher, function (match, paramName) { + paramName = paramName || "splat"; - if (_isListening) - return; + // If param is optional don't check for existence + if (paramName.slice(-1) === "?") { + paramName = paramName.slice(0, -1); - if (window.addEventListener) { - window.addEventListener('hashchange', onHashChange, false); - } else { - window.attachEvent('onhashchange', onHashChange); - } + if (params[paramName] == null) return ""; + } else { + invariant(params[paramName] != null, "Missing \"%s\" parameter for path \"%s\"", paramName, pattern); + } - _isListening = true; - }, + var segment; + if (paramName === "splat" && Array.isArray(params[paramName])) { + segment = params[paramName][splatIndex++]; - removeChangeListener: function(listener) { - for (var i = 0, l = _changeListeners.length; i < l; i ++) { - if (_changeListeners[i] === listener) { - _changeListeners.splice(i, 1); - break; + invariant(segment != null, "Missing splat # %s for path \"%s\"", splatIndex, pattern); + } else { + segment = params[paramName]; } - } - if (window.removeEventListener) { - window.removeEventListener('hashchange', onHashChange, false); - } else { - window.removeEvent('onhashchange', onHashChange); - } - - if (_changeListeners.length === 0) - _isListening = false; + return segment; + }).replace(paramInjectTrailingSlashMatcher, "/"); }, - - - push: function (path) { - _actionType = LocationActions.PUSH; - window.location.hash = Path.encode(path); + /** + * Returns an object that is the result of parsing any query string contained + * in the given path, null if the path contains no query string. + */ + extractQuery: function extractQuery(path) { + var match = path.match(queryMatcher); + return match && qs.parse(match[1]); }, - replace: function (path) { - _actionType = LocationActions.REPLACE; - window.location.replace(window.location.pathname + '#' + Path.encode(path)); + /** + * Returns a version of the given path without the query string. + */ + withoutQuery: function withoutQuery(path) { + return path.replace(queryMatcher, ""); }, - pop: function () { - _actionType = LocationActions.POP; - History.back(); - }, + /** + * Returns a version of the given path with the parameters in the given + * query merged into the query string. + */ + withQuery: function withQuery(path, query) { + var existingQuery = PathUtils.extractQuery(path); - getCurrentPath: getHashPath, + if (existingQuery) query = query ? merge(existingQuery, query) : existingQuery; - toString: function () { - return ''; + var queryString = qs.stringify(query, { indices: false }); + + if (queryString) { + return PathUtils.withoutQuery(path) + "?" + queryString; + }return path; } }; -module.exports = HashLocation; - -},{"../actions/LocationActions":8,"../utils/History":28,"../utils/Path":29}],18:[function(require,module,exports){ -var LocationActions = require('../actions/LocationActions'); -var History = require('../utils/History'); -var Path = require('../utils/Path'); - -/** - * Returns the current URL path from `window.location`, including query string. - */ -function getWindowPath() { - return Path.decode( - window.location.pathname + window.location.search - ); -} +module.exports = PathUtils; +},{"qs":38,"qs/lib/utils":42,"react/lib/invariant":182}],11:[function(require,module,exports){ +"use strict"; -var _changeListeners = []; +var assign = require("react/lib/Object.assign"); +var ReactPropTypes = require("react").PropTypes; -function notifyChange(type) { - var change = { - path: getWindowPath(), - type: type - }; +var PropTypes = assign({ - _changeListeners.forEach(function (listener) { - listener(change); - }); -} + /** + * Requires that the value of a prop be falsy. + */ + falsy: function falsy(props, propName, componentName) { + if (props[propName]) { + return new Error("<" + componentName + "> may not have a \"" + propName + "\" prop"); + } + } -var _isListening = false; +}, ReactPropTypes); -function onPopState() { - notifyChange(LocationActions.POP); -} +module.exports = PropTypes; +},{"react":"react","react/lib/Object.assign":70}],12:[function(require,module,exports){ +"use strict"; /** - * A Location that uses HTML5 history. + * Encapsulates a redirect to the given route. */ -var HistoryLocation = { - - addChangeListener: function (listener) { - _changeListeners.push(listener); - - if (_isListening) - return; - - if (window.addEventListener) { - window.addEventListener('popstate', onPopState, false); - } else { - window.attachEvent('popstate', onPopState); - } - - _isListening = true; - }, - - removeChangeListener: function(listener) { - for (var i = 0, l = _changeListeners.length; i < l; i ++) { - if (_changeListeners[i] === listener) { - _changeListeners.splice(i, 1); - break; - } - } - - if (window.addEventListener) { - window.removeEventListener('popstate', onPopState); - } else { - window.removeEvent('popstate', onPopState); - } - - if (_changeListeners.length === 0) - _isListening = false; - }, +function Redirect(to, params, query) { + this.to = to; + this.params = params; + this.query = query; +} +module.exports = Redirect; +},{}],13:[function(require,module,exports){ +"use strict"; +var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; - push: function (path) { - window.history.pushState({ path: path }, '', Path.encode(path)); - History.length += 1; - notifyChange(LocationActions.PUSH); - }, +var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; - replace: function (path) { - window.history.replaceState({ path: path }, '', Path.encode(path)); - notifyChange(LocationActions.REPLACE); - }, +var assign = require("react/lib/Object.assign"); +var invariant = require("react/lib/invariant"); +var warning = require("react/lib/warning"); +var PathUtils = require("./PathUtils"); - pop: History.back, +var _currentRoute; - getCurrentPath: getWindowPath, +var Route = (function () { + function Route(name, path, ignoreScrollBehavior, isDefault, isNotFound, onEnter, onLeave, handler) { + _classCallCheck(this, Route); - toString: function () { - return ''; + this.name = name; + this.path = path; + this.paramNames = PathUtils.extractParamNames(this.path); + this.ignoreScrollBehavior = !!ignoreScrollBehavior; + this.isDefault = !!isDefault; + this.isNotFound = !!isNotFound; + this.onEnter = onEnter; + this.onLeave = onLeave; + this.handler = handler; } -}; + _prototypeProperties(Route, { + createRoute: { -module.exports = HistoryLocation; + /** + * Creates and returns a new route. Options may be a URL pathname string + * with placeholders for named params or an object with any of the following + * properties: + * + * - name The name of the route. This is used to lookup a + * route relative to its parent route and should be + * unique among all child routes of the same parent + * - path A URL pathname string with optional placeholders + * that specify the names of params to extract from + * the URL when the path matches. Defaults to `/${name}` + * when there is a name given, or the path of the parent + * route, or / + * - ignoreScrollBehavior True to make this route (and all descendants) ignore + * the scroll behavior of the router + * - isDefault True to make this route the default route among all + * its siblings + * - isNotFound True to make this route the "not found" route among + * all its siblings + * - onEnter A transition hook that will be called when the + * router is going to enter this route + * - onLeave A transition hook that will be called when the + * router is going to leave this route + * - handler A React component that will be rendered when + * this route is active + * - parentRoute The parent route to use for this route. This option + * is automatically supplied when creating routes inside + * the callback to another invocation of createRoute. You + * only ever need to use this when declaring routes + * independently of one another to manually piece together + * the route hierarchy + * + * The callback may be used to structure your route hierarchy. Any call to + * createRoute, createDefaultRoute, createNotFoundRoute, or createRedirect + * inside the callback automatically uses this route as its parent. + */ -},{"../actions/LocationActions":8,"../utils/History":28,"../utils/Path":29}],19:[function(require,module,exports){ -var HistoryLocation = require('./HistoryLocation'); -var History = require('../utils/History'); -var Path = require('../utils/Path'); + value: function createRoute(options, callback) { + options = options || {}; -/** - * A Location that uses full page refreshes. This is used as - * the fallback for HistoryLocation in browsers that do not - * support the HTML5 history API. - */ -var RefreshLocation = { + if (typeof options === "string") options = { path: options }; - push: function (path) { - window.location = Path.encode(path); - }, + var parentRoute = _currentRoute; - replace: function (path) { - window.location.replace(Path.encode(path)); - }, + if (parentRoute) { + warning(options.parentRoute == null || options.parentRoute === parentRoute, "You should not use parentRoute with createRoute inside another route's child callback; it is ignored"); + } else { + parentRoute = options.parentRoute; + } - pop: History.back, + var name = options.name; + var path = options.path || name; - getCurrentPath: HistoryLocation.getCurrentPath, + if (path && !(options.isDefault || options.isNotFound)) { + if (PathUtils.isAbsolute(path)) { + if (parentRoute) { + invariant(parentRoute.paramNames.length === 0, "You cannot nest path \"%s\" inside \"%s\"; the parent requires URL parameters", path, parentRoute.path); + } + } else if (parentRoute) { + // Relative paths extend their parent. + path = PathUtils.join(parentRoute.path, path); + } else { + path = "/" + path; + } + } else { + path = parentRoute ? parentRoute.path : "/"; + } - toString: function () { - return ''; - } + if (options.isNotFound && !/\*$/.test(path)) path += "*"; // Auto-append * to the path of not found routes. -}; + var route = new Route(name, path, options.ignoreScrollBehavior, options.isDefault, options.isNotFound, options.onEnter, options.onLeave, options.handler); -module.exports = RefreshLocation; + if (parentRoute) { + if (route.isDefault) { + invariant(parentRoute.defaultRoute == null, "%s may not have more than one default route", parentRoute); -},{"../utils/History":28,"../utils/Path":29,"./HistoryLocation":18}],20:[function(require,module,exports){ -var invariant = require('react/lib/invariant'); + parentRoute.defaultRoute = route; + } else if (route.isNotFound) { + invariant(parentRoute.notFoundRoute == null, "%s may not have more than one not found route", parentRoute); -var FakeNode = { + parentRoute.notFoundRoute = route; + } - render: function () { - invariant( - false, - '%s elements should not be rendered', - this.constructor.displayName - ); - } + parentRoute.appendChild(route); + } -}; + // Any routes created in the callback + // use this route as their parent. + if (typeof callback === "function") { + var currentRoute = _currentRoute; + _currentRoute = route; + callback.call(route, route); + _currentRoute = currentRoute; + } -module.exports = FakeNode; + return route; + }, + writable: true, + configurable: true + }, + createDefaultRoute: { -},{"react/lib/invariant":189}],21:[function(require,module,exports){ -var React = require('react'); + /** + * Creates and returns a route that is rendered when its parent matches + * the current URL. + */ -/** - * A mixin for components that modify the URL. - * - * Example: - * - * var MyLink = React.createClass({ - * mixins: [ Router.Navigation ], - * handleClick: function (event) { - * event.preventDefault(); - * this.transitionTo('aRoute', { the: 'params' }, { the: 'query' }); - * }, - * render: function () { - * return ( - * Click me! - * ); - * } - * }); - */ -var Navigation = { + value: function createDefaultRoute(options) { + return Route.createRoute(assign({}, options, { isDefault: true })); + }, + writable: true, + configurable: true + }, + createNotFoundRoute: { - contextTypes: { - makePath: React.PropTypes.func.isRequired, - makeHref: React.PropTypes.func.isRequired, - transitionTo: React.PropTypes.func.isRequired, - replaceWith: React.PropTypes.func.isRequired, - goBack: React.PropTypes.func.isRequired - }, + /** + * Creates and returns a route that is rendered when its parent matches + * the current URL but none of its siblings do. + */ - /** - * Returns an absolute URL path created from the given route - * name, URL parameters, and query values. - */ - makePath: function (to, params, query) { - return this.context.makePath(to, params, query); - }, + value: function createNotFoundRoute(options) { + return Route.createRoute(assign({}, options, { isNotFound: true })); + }, + writable: true, + configurable: true + }, + createRedirect: { - /** - * Returns a string that may safely be used as the href of a - * link to the route with the given name. - */ - makeHref: function (to, params, query) { - return this.context.makeHref(to, params, query); - }, + /** + * Creates and returns a route that automatically redirects the transition + * to another route. In addition to the normal options to createRoute, this + * function accepts the following options: + * + * - from An alias for the `path` option. Defaults to * + * - to The path/route/route name to redirect to + * - params The params to use in the redirect URL. Defaults + * to using the current params + * - query The query to use in the redirect URL. Defaults + * to using the current query + */ - /** - * Transitions to the URL specified in the arguments by pushing - * a new URL onto the history stack. - */ - transitionTo: function (to, params, query) { - this.context.transitionTo(to, params, query); - }, + value: function createRedirect(options) { + return Route.createRoute(assign({}, options, { + path: options.path || options.from || "*", + onEnter: function onEnter(transition, params, query) { + transition.redirect(options.to, options.params || params, options.query || query); + } + })); + }, + writable: true, + configurable: true + } + }, { + appendChild: { - /** - * Transitions to the URL specified in the arguments by replacing - * the current URL in the history stack. - */ - replaceWith: function (to, params, query) { - this.context.replaceWith(to, params, query); - }, + /** + * Appends the given route to this route's child routes. + */ - /** - * Transitions to the previous URL. - */ - goBack: function () { - this.context.goBack(); - } + value: function appendChild(route) { + invariant(route instanceof Route, "route.appendChild must use a valid Route"); -}; + if (!this.childRoutes) this.childRoutes = []; -module.exports = Navigation; + this.childRoutes.push(route); + }, + writable: true, + configurable: true + }, + toString: { + value: function toString() { + var string = ""; - childContextTypes: { - makePath: React.PropTypes.func.isRequired, - makeHref: React.PropTypes.func.isRequired, - transitionTo: React.PropTypes.func.isRequired, - replaceWith: React.PropTypes.func.isRequired, - goBack: React.PropTypes.func.isRequired - }, + return string; + }, + writable: true, + configurable: true + } + }); - getChildContext: function () { - return { - makePath: this.constructor.makePath, - makeHref: this.constructor.makeHref, - transitionTo: this.constructor.transitionTo, - replaceWith: this.constructor.replaceWith, - goBack: this.constructor.goBack - }; - } + return Route; +})(); -}; +module.exports = Route; +},{"./PathUtils":10,"react/lib/Object.assign":70,"react/lib/invariant":182,"react/lib/warning":202}],14:[function(require,module,exports){ +"use strict"; -module.exports = NavigationContext; +var React = require("react"); +var assign = require("react/lib/Object.assign"); +var PropTypes = require("./PropTypes"); -},{"react":"react"}],23:[function(require,module,exports){ -var React = require('react'); +var REF_NAME = "__routeHandler__"; + +var RouteHandlerMixin = { -module.exports = { contextTypes: { - getRouteAtDepth: React.PropTypes.func.isRequired, - getRouteComponents: React.PropTypes.func.isRequired, - routeHandlers: React.PropTypes.array.isRequired + getRouteAtDepth: PropTypes.func.isRequired, + setRouteComponentAtDepth: PropTypes.func.isRequired, + routeHandlers: PropTypes.array.isRequired }, childContextTypes: { - routeHandlers: React.PropTypes.array.isRequired + routeHandlers: PropTypes.array.isRequired }, - getChildContext: function () { + getChildContext: function getChildContext() { return { - routeHandlers: this.context.routeHandlers.concat([ this ]) + routeHandlers: this.context.routeHandlers.concat([this]) }; }, - getRouteDepth: function () { - return this.context.routeHandlers.length - 1; + componentDidMount: function componentDidMount() { + this._updateRouteComponent(this.refs[REF_NAME]); + }, + + componentDidUpdate: function componentDidUpdate() { + this._updateRouteComponent(this.refs[REF_NAME]); }, - componentDidMount: function () { - this._updateRouteComponent(); + componentWillUnmount: function componentWillUnmount() { + this._updateRouteComponent(null); }, - componentDidUpdate: function () { - this._updateRouteComponent(); + _updateRouteComponent: function _updateRouteComponent(component) { + this.context.setRouteComponentAtDepth(this.getRouteDepth(), component); }, - _updateRouteComponent: function () { - var depth = this.getRouteDepth(); - var components = this.context.getRouteComponents(); - components[depth] = this.refs[this.props.ref || '__routeHandler__']; + getRouteDepth: function getRouteDepth() { + return this.context.routeHandlers.length; }, - getRouteHandler: function (props) { + createChildRouteHandler: function createChildRouteHandler(props) { var route = this.context.getRouteAtDepth(this.getRouteDepth()); - return route ? React.createElement(route.handler, props || this.props) : null; + return route ? React.createElement(route.handler, assign({}, props || this.props, { ref: REF_NAME })) : null; } + }; -},{"react":"react"}],24:[function(require,module,exports){ -var invariant = require('react/lib/invariant'); -var canUseDOM = require('react/lib/ExecutionEnvironment').canUseDOM; -var getWindowScrollPosition = require('../utils/getWindowScrollPosition'); + +module.exports = RouteHandlerMixin; +},{"./PropTypes":11,"react":"react","react/lib/Object.assign":70}],15:[function(require,module,exports){ +"use strict"; + +var invariant = require("react/lib/invariant"); +var canUseDOM = require("react/lib/ExecutionEnvironment").canUseDOM; +var getWindowScrollPosition = require("./getWindowScrollPosition"); function shouldUpdateScroll(state, prevState) { - if (!prevState) + if (!prevState) { return true; - - // Don't update scroll position when only the query has changed. - if (state.pathname === prevState.pathname) + } // Don't update scroll position when only the query has changed. + if (state.pathname === prevState.pathname) { return false; - - var routes = state.routes; + }var routes = state.routes; var prevRoutes = prevState.routes; var sharedAncestorRoutes = routes.filter(function (route) { @@ -2484,15 +1144,15 @@ function shouldUpdateScroll(state, prevState) { * Provides the router with the ability to manage window scroll position * according to its scroll behavior. */ -var Scrolling = { +var ScrollHistory = { statics: { + /** * Records curent scroll position as the last known position for the given URL path. */ - recordScrollPosition: function (path) { - if (!this.scrollHistory) - this.scrollHistory = {}; + recordScrollPosition: function recordScrollPosition(path) { + if (!this.scrollHistory) this.scrollHistory = {}; this.scrollHistory[path] = getWindowScrollPosition(); }, @@ -2500,48 +1160,41 @@ var Scrolling = { /** * Returns the last known scroll position for the given URL path. */ - getScrollPosition: function (path) { - if (!this.scrollHistory) - this.scrollHistory = {}; + getScrollPosition: function getScrollPosition(path) { + if (!this.scrollHistory) this.scrollHistory = {}; return this.scrollHistory[path] || null; } + }, - componentWillMount: function () { - invariant( - this.getScrollBehavior() == null || canUseDOM, - 'Cannot use scroll behavior without a DOM' - ); + componentWillMount: function componentWillMount() { + invariant(this.constructor.getScrollBehavior() == null || canUseDOM, "Cannot use scroll behavior without a DOM"); }, - componentDidMount: function () { + componentDidMount: function componentDidMount() { this._updateScroll(); }, - componentDidUpdate: function (prevProps, prevState) { + componentDidUpdate: function componentDidUpdate(prevProps, prevState) { this._updateScroll(prevState); }, - _updateScroll: function (prevState) { - if (!shouldUpdateScroll(this.state, prevState)) + _updateScroll: function _updateScroll(prevState) { + if (!shouldUpdateScroll(this.state, prevState)) { return; + }var scrollBehavior = this.constructor.getScrollBehavior(); - var scrollBehavior = this.getScrollBehavior(); - - if (scrollBehavior) - scrollBehavior.updateScrollPosition( - this.constructor.getScrollPosition(this.state.path), - this.state.action - ); + if (scrollBehavior) scrollBehavior.updateScrollPosition(this.constructor.getScrollPosition(this.state.path), this.state.action); } }; -module.exports = Scrolling; +module.exports = ScrollHistory; +},{"./getWindowScrollPosition":30,"react/lib/ExecutionEnvironment":64,"react/lib/invariant":182}],16:[function(require,module,exports){ +"use strict"; -},{"../utils/getWindowScrollPosition":36,"react/lib/ExecutionEnvironment":71,"react/lib/invariant":189}],25:[function(require,module,exports){ -var React = require('react'); +var PropTypes = require("./PropTypes"); /** * A mixin for components that need to know the path, routes, URL @@ -2564,46 +1217,46 @@ var React = require('react'); var State = { contextTypes: { - getCurrentPath: React.PropTypes.func.isRequired, - getCurrentRoutes: React.PropTypes.func.isRequired, - getCurrentPathname: React.PropTypes.func.isRequired, - getCurrentParams: React.PropTypes.func.isRequired, - getCurrentQuery: React.PropTypes.func.isRequired, - isActive: React.PropTypes.func.isRequired + getCurrentPath: PropTypes.func.isRequired, + getCurrentRoutes: PropTypes.func.isRequired, + getCurrentPathname: PropTypes.func.isRequired, + getCurrentParams: PropTypes.func.isRequired, + getCurrentQuery: PropTypes.func.isRequired, + isActive: PropTypes.func.isRequired }, /** * Returns the current URL path. */ - getPath: function () { + getPath: function getPath() { return this.context.getCurrentPath(); }, /** * Returns an array of the routes that are currently active. */ - getRoutes: function () { + getRoutes: function getRoutes() { return this.context.getCurrentRoutes(); }, /** * Returns the current URL path without the query string. */ - getPathname: function () { + getPathname: function getPathname() { return this.context.getCurrentPathname(); }, /** * Returns an object of the URL params that are currently active. */ - getParams: function () { + getParams: function getParams() { return this.context.getCurrentParams(); }, /** * Returns an object of the query params that are currently active. */ - getQuery: function () { + getQuery: function getQuery() { return this.context.getCurrentQuery(); }, @@ -2611,18 +1264,19 @@ var State = { * A helper method to determine if a given route, params, and query * are active. */ - isActive: function (to, params, query) { + isActive: function isActive(to, params, query) { return this.context.isActive(to, params, query); } }; module.exports = State; +},{"./PropTypes":11}],17:[function(require,module,exports){ +"use strict"; -},{"react":"react"}],26:[function(require,module,exports){ -var React = require('react'); -var assign = require('react/lib/Object.assign'); -var Path = require('../utils/Path'); +var assign = require("react/lib/Object.assign"); +var PropTypes = require("./PropTypes"); +var PathUtils = require("./PathUtils"); function routeIsActive(activeRoutes, routeName) { return activeRoutes.some(function (route) { @@ -2631,19 +1285,15 @@ function routeIsActive(activeRoutes, routeName) { } function paramsAreActive(activeParams, params) { - for (var property in params) - if (String(activeParams[property]) !== String(params[property])) - return false; - - return true; + for (var property in params) if (String(activeParams[property]) !== String(params[property])) { + return false; + }return true; } function queryIsActive(activeQuery, query) { - for (var property in query) - if (String(activeQuery[property]) !== String(query[property])) - return false; - - return true; + for (var property in query) if (String(activeQuery[property]) !== String(query[property])) { + return false; + }return true; } /** @@ -2654,60 +1304,57 @@ var StateContext = { /** * Returns the current URL path + query string. */ - getCurrentPath: function () { + getCurrentPath: function getCurrentPath() { return this.state.path; }, /** * Returns a read-only array of the currently active routes. */ - getCurrentRoutes: function () { + getCurrentRoutes: function getCurrentRoutes() { return this.state.routes.slice(0); }, /** * Returns the current URL path without the query string. */ - getCurrentPathname: function () { + getCurrentPathname: function getCurrentPathname() { return this.state.pathname; }, /** * Returns a read-only object of the currently active URL parameters. */ - getCurrentParams: function () { + getCurrentParams: function getCurrentParams() { return assign({}, this.state.params); }, /** * Returns a read-only object of the currently active query parameters. */ - getCurrentQuery: function () { + getCurrentQuery: function getCurrentQuery() { return assign({}, this.state.query); }, /** * Returns true if the given route, params, and query are active. */ - isActive: function (to, params, query) { - if (Path.isAbsolute(to)) + isActive: function isActive(to, params, query) { + if (PathUtils.isAbsolute(to)) { return to === this.state.path; - - return routeIsActive(this.state.routes, to) && - paramsAreActive(this.state.params, params) && - (query == null || queryIsActive(this.state.query, query)); + }return routeIsActive(this.state.routes, to) && paramsAreActive(this.state.params, params) && (query == null || queryIsActive(this.state.query, query)); }, childContextTypes: { - getCurrentPath: React.PropTypes.func.isRequired, - getCurrentRoutes: React.PropTypes.func.isRequired, - getCurrentPathname: React.PropTypes.func.isRequired, - getCurrentParams: React.PropTypes.func.isRequired, - getCurrentQuery: React.PropTypes.func.isRequired, - isActive: React.PropTypes.func.isRequired + getCurrentPath: PropTypes.func.isRequired, + getCurrentRoutes: PropTypes.func.isRequired, + getCurrentPathname: PropTypes.func.isRequired, + getCurrentParams: PropTypes.func.isRequired, + getCurrentQuery: PropTypes.func.isRequired, + isActive: PropTypes.func.isRequired }, - getChildContext: function () { + getChildContext: function getChildContext() { return { getCurrentPath: this.getCurrentPath, getCurrentRoutes: this.getCurrentRoutes, @@ -2721,500 +1368,494 @@ var StateContext = { }; module.exports = StateContext; +},{"./PathUtils":10,"./PropTypes":11,"react/lib/Object.assign":70}],18:[function(require,module,exports){ +"use strict"; -},{"../utils/Path":29,"react":"react","react/lib/Object.assign":77}],27:[function(require,module,exports){ -/** - * Represents a cancellation caused by navigating away - * before the previous transition has fully resolved. - */ -function Cancellation() { } - -module.exports = Cancellation; - -},{}],28:[function(require,module,exports){ -var invariant = require('react/lib/invariant'); -var canUseDOM = require('react/lib/ExecutionEnvironment').canUseDOM; - -var History = { - - /** - * Sends the browser back one entry in the history. - */ - back: function () { - invariant( - canUseDOM, - 'Cannot use History.back without a DOM' - ); - - // Do this first so that History.length will - // be accurate in location change listeners. - History.length -= 1; +/* jshint -W058 */ - window.history.back(); - }, +var Cancellation = require("./Cancellation"); +var Redirect = require("./Redirect"); - /** - * The current number of entries in the history. - */ - length: 1 +/** + * Encapsulates a transition to a given path. + * + * The willTransitionTo and willTransitionFrom handlers receive + * an instance of this class as their first argument. + */ +function Transition(path, retry) { + this.path = path; + this.abortReason = null; + // TODO: Change this to router.retryTransition(transition) + this.retry = retry.bind(this); +} +Transition.prototype.abort = function (reason) { + if (this.abortReason == null) this.abortReason = reason || "ABORT"; }; -module.exports = History; - -},{"react/lib/ExecutionEnvironment":71,"react/lib/invariant":189}],29:[function(require,module,exports){ -var invariant = require('react/lib/invariant'); -var merge = require('qs/lib/utils').merge; -var qs = require('qs'); - -var paramCompileMatcher = /:([a-zA-Z_$][a-zA-Z0-9_$]*)|[*.()\[\]\\+|{}^$]/g; -var paramInjectMatcher = /:([a-zA-Z_$][a-zA-Z0-9_$?]*[?]?)|[*]/g; -var paramInjectTrailingSlashMatcher = /\/\/\?|\/\?/g; -var queryMatcher = /\?(.+)/; +Transition.prototype.redirect = function (to, params, query) { + this.abort(new Redirect(to, params, query)); +}; -var _compiledPatterns = {}; +Transition.prototype.cancel = function () { + this.abort(new Cancellation()); +}; -function compilePattern(pattern) { - if (!(pattern in _compiledPatterns)) { - var paramNames = []; - var source = pattern.replace(paramCompileMatcher, function (match, paramName) { - if (paramName) { - paramNames.push(paramName); - return '([^/?#]+)'; - } else if (match === '*') { - paramNames.push('splat'); - return '(.*?)'; +Transition.from = function (transition, routes, components, callback) { + routes.reduce(function (callback, route, index) { + return function (error) { + if (error || transition.abortReason) { + callback(error); + } else if (route.onLeave) { + try { + route.onLeave(transition, components[index], callback); + + // If there is no callback in the argument list, call it automatically. + if (route.onLeave.length < 3) callback(); + } catch (e) { + callback(e); + } } else { - return '\\' + match; + callback(); } - }); + }; + }, callback)(); +}; - _compiledPatterns[pattern] = { - matcher: new RegExp('^' + source + '$', 'i'), - paramNames: paramNames +Transition.to = function (transition, routes, params, query, callback) { + routes.reduceRight(function (callback, route) { + return function (error) { + if (error || transition.abortReason) { + callback(error); + } else if (route.onEnter) { + try { + route.onEnter(transition, params, query, callback); + + // If there is no callback in the argument list, call it automatically. + if (route.onEnter.length < 4) callback(); + } catch (e) { + callback(e); + } + } else { + callback(); + } }; - } + }, callback)(); +}; - return _compiledPatterns[pattern]; -} +module.exports = Transition; +},{"./Cancellation":4,"./Redirect":12}],19:[function(require,module,exports){ +"use strict"; -var Path = { +/** + * Actions that modify the URL. + */ +var LocationActions = { /** - * Safely decodes special characters in the given URL path. + * Indicates a new location is being pushed to the history stack. */ - decode: function (path) { - return decodeURI(path.replace(/\+/g, ' ')); - }, + PUSH: "push", /** - * Safely encodes special characters in the given URL path. + * Indicates the current location should be replaced. */ - encode: function (path) { - return encodeURI(path).replace(/%20/g, '+'); - }, + REPLACE: "replace", /** - * Returns an array of the names of all parameters in the given pattern. + * Indicates the most recent entry should be removed from the history stack. */ - extractParamNames: function (pattern) { - return compilePattern(pattern).paramNames; - }, + POP: "pop" - /** - * Extracts the portions of the given URL path that match the given pattern - * and returns an object of param name => value pairs. Returns null if the - * pattern does not match the given path. - */ - extractParams: function (pattern, path) { - var object = compilePattern(pattern); - var match = path.match(object.matcher); +}; - if (!match) - return null; +module.exports = LocationActions; +},{}],20:[function(require,module,exports){ +"use strict"; - var params = {}; +var LocationActions = require("../actions/LocationActions"); - object.paramNames.forEach(function (paramName, index) { - params[paramName] = match[index + 1]; - }); +/** + * A scroll behavior that attempts to imitate the default behavior + * of modern browsers. + */ +var ImitateBrowserBehavior = { - return params; - }, + updateScrollPosition: function updateScrollPosition(position, actionType) { + switch (actionType) { + case LocationActions.PUSH: + case LocationActions.REPLACE: + window.scrollTo(0, 0); + break; + case LocationActions.POP: + if (position) { + window.scrollTo(position.x, position.y); + } else { + window.scrollTo(0, 0); + } + break; + } + } - /** - * Returns a version of the given route path with params interpolated. Throws - * if there is a dynamic segment of the route path for which there is no param. - */ - injectParams: function (pattern, params) { - params = params || {}; +}; - var splatIndex = 0; +module.exports = ImitateBrowserBehavior; +},{"../actions/LocationActions":19}],21:[function(require,module,exports){ +"use strict"; - return pattern.replace(paramInjectMatcher, function (match, paramName) { - paramName = paramName || 'splat'; +/** + * A scroll behavior that always scrolls to the top of the page + * after a transition. + */ +var ScrollToTopBehavior = { - // If param is optional don't check for existence - if (paramName.slice(-1) !== '?') { - invariant( - params[paramName] != null, - 'Missing "' + paramName + '" parameter for path "' + pattern + '"' - ); - } else { - paramName = paramName.slice(0, -1); + updateScrollPosition: function updateScrollPosition() { + window.scrollTo(0, 0); + } - if (params[paramName] == null) - return ''; - } +}; - var segment; - if (paramName === 'splat' && Array.isArray(params[paramName])) { - segment = params[paramName][splatIndex++]; +module.exports = ScrollToTopBehavior; +},{}],22:[function(require,module,exports){ +"use strict"; - invariant( - segment != null, - 'Missing splat # ' + splatIndex + ' for path "' + pattern + '"' - ); - } else { - segment = params[paramName]; - } +var React = require("react"); +var Configuration = require("../Configuration"); +var PropTypes = require("../PropTypes"); - return segment; - }).replace(paramInjectTrailingSlashMatcher, '/'); - }, +/** + * A component is a special kind of that + * renders when its parent matches but none of its siblings do. + * Only one such route may be used at any given level in the + * route hierarchy. + */ +var DefaultRoute = React.createClass({ - /** - * Returns an object that is the result of parsing any query string contained - * in the given path, null if the path contains no query string. - */ - extractQuery: function (path) { - var match = path.match(queryMatcher); - return match && qs.parse(match[1]); - }, + displayName: "DefaultRoute", - /** - * Returns a version of the given path without the query string. - */ - withoutQuery: function (path) { - return path.replace(queryMatcher, ''); - }, + mixins: [Configuration], - /** - * Returns a version of the given path with the parameters in the given - * query merged into the query string. - */ - withQuery: function (path, query) { - var existingQuery = Path.extractQuery(path); + propTypes: { + name: PropTypes.string, + path: PropTypes.falsy, + children: PropTypes.falsy, + handler: PropTypes.func.isRequired + } + +}); + +module.exports = DefaultRoute; +},{"../Configuration":5,"../PropTypes":11,"react":"react"}],23:[function(require,module,exports){ +"use strict"; + +var React = require("react"); +var classSet = require("react/lib/cx"); +var assign = require("react/lib/Object.assign"); +var Navigation = require("../Navigation"); +var State = require("../State"); +var PropTypes = require("../PropTypes"); +var Route = require("../Route"); + +function isLeftClickEvent(event) { + return event.button === 0; +} + +function isModifiedEvent(event) { + return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); +} + +/** + * components are used to create an element that links to a route. + * When that route is active, the link gets an "active" class name (or the + * value of its `activeClassName` prop). + * + * For example, assuming you have the following route: + * + * + * + * You could use the following component to link to that route: + * + * + * + * In addition to params, links may pass along query string parameters + * using the `query` prop. + * + * + */ +var Link = React.createClass({ - if (existingQuery) - query = query ? merge(existingQuery, query) : existingQuery; + displayName: "Link", - var queryString = query && qs.stringify(query); + mixins: [Navigation, State], - if (queryString) - return Path.withoutQuery(path) + '?' + queryString; + propTypes: { + activeClassName: PropTypes.string.isRequired, + to: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Route)]), + params: PropTypes.object, + query: PropTypes.object, + activeStyle: PropTypes.object, + onClick: PropTypes.func + }, - return path; + getDefaultProps: function getDefaultProps() { + return { + activeClassName: "active" + }; }, - /** - * Returns true if the given path is absolute. - */ - isAbsolute: function (path) { - return path.charAt(0) === '/'; + handleClick: function handleClick(event) { + var allowTransition = true; + var clickResult; + + if (this.props.onClick) clickResult = this.props.onClick(event); + + if (isModifiedEvent(event) || !isLeftClickEvent(event)) { + return; + }if (clickResult === false || event.defaultPrevented === true) allowTransition = false; + + event.preventDefault(); + + if (allowTransition) this.transitionTo(this.props.to, this.props.params, this.props.query); }, /** - * Returns a normalized version of the given path. + * Returns the value of the "href" attribute to use on the DOM element. */ - normalize: function (path, parentRoute) { - return path.replace(/^\/*/, '/'); + getHref: function getHref() { + return this.makeHref(this.props.to, this.props.params, this.props.query); }, /** - * Joins two URL paths together. + * Returns the value of the "class" attribute to use on the DOM element, which contains + * the value of the activeClassName property when this is active. */ - join: function (a, b) { - return a.replace(/\/*$/, '/') + b; - } + getClassName: function getClassName() { + var classNames = {}; -}; + if (this.props.className) classNames[this.props.className] = true; -module.exports = Path; + if (this.getActiveState()) classNames[this.props.activeClassName] = true; -},{"qs":40,"qs/lib/utils":44,"react/lib/invariant":189}],30:[function(require,module,exports){ -var Promise = require('when/lib/Promise'); + return classSet(classNames); + }, -// TODO: Use process.env.NODE_ENV check + envify to enable -// when's promise monitor here when in dev. + getActiveState: function getActiveState() { + return this.isActive(this.props.to, this.props.params, this.props.query); + }, -module.exports = Promise; + render: function render() { + var props = assign({}, this.props, { + href: this.getHref(), + className: this.getClassName(), + onClick: this.handleClick + }); -},{"when/lib/Promise":45}],31:[function(require,module,exports){ -var PropTypes = { + if (props.activeStyle && this.getActiveState()) props.style = props.activeStyle; - /** - * Requires that the value of a prop be falsy. - */ - falsy: function (props, propName, componentName) { - if (props[propName]) - return new Error('<' + componentName + '> may not have a "' + propName + '" prop'); + return React.DOM.a(props, this.props.children); } -}; +}); -module.exports = PropTypes; +module.exports = Link; +},{"../Navigation":8,"../PropTypes":11,"../Route":13,"../State":16,"react":"react","react/lib/Object.assign":70,"react/lib/cx":160}],24:[function(require,module,exports){ +"use strict"; + +var React = require("react"); +var Configuration = require("../Configuration"); +var PropTypes = require("../PropTypes"); -},{}],32:[function(require,module,exports){ /** - * Encapsulates a redirect to the given route. + * A is a special kind of that + * renders when the beginning of its parent's path matches + * but none of its siblings do, including any . + * Only one such route may be used at any given level in the + * route hierarchy. */ -function Redirect(to, params, query) { - this.to = to; - this.params = params; - this.query = query; -} +var NotFoundRoute = React.createClass({ -module.exports = Redirect; + displayName: "NotFoundRoute", -},{}],33:[function(require,module,exports){ -var assign = require('react/lib/Object.assign'); -var reversedArray = require('./reversedArray'); -var Redirect = require('./Redirect'); -var Promise = require('./Promise'); + mixins: [Configuration], -/** - * Runs all hook functions serially and calls callback(error) when finished. - * A hook may return a promise if it needs to execute asynchronously. - */ -function runHooks(hooks, callback) { - var promise; - try { - promise = hooks.reduce(function (promise, hook) { - // The first hook to use transition.wait makes the rest - // of the transition async from that point forward. - return promise ? promise.then(hook) : hook(); - }, null); - } catch (error) { - return callback(error); // Sync error. + propTypes: { + name: PropTypes.string, + path: PropTypes.falsy, + children: PropTypes.falsy, + handler: PropTypes.func.isRequired } - if (promise) { - // Use setTimeout to break the promise chain. - promise.then(function () { - setTimeout(callback); - }, function (error) { - setTimeout(function () { - callback(error); - }); - }); - } else { - callback(); - } -} +}); + +module.exports = NotFoundRoute; +},{"../Configuration":5,"../PropTypes":11,"react":"react"}],25:[function(require,module,exports){ +"use strict"; + +var React = require("react"); +var Configuration = require("../Configuration"); +var PropTypes = require("../PropTypes"); /** - * Calls the willTransitionFrom hook of all handlers in the given matches - * serially in reverse with the transition object and the current instance of - * the route's handler, so that the deepest nested handlers are called first. - * Calls callback(error) when finished. + * A component is a special kind of that always + * redirects to another route when it matches. */ -function runTransitionFromHooks(transition, routes, components, callback) { - components = reversedArray(components); +var Redirect = React.createClass({ - var hooks = reversedArray(routes).map(function (route, index) { - return function () { - var handler = route.handler; + displayName: "Redirect", - if (!transition.isAborted && handler.willTransitionFrom) - return handler.willTransitionFrom(transition, components[index]); + mixins: [Configuration], - var promise = transition._promise; - transition._promise = null; + propTypes: { + path: PropTypes.string, + from: PropTypes.string, // Alias for path. + to: PropTypes.string, + handler: PropTypes.falsy + } - return promise; - }; - }); +}); - runHooks(hooks, callback); -} +module.exports = Redirect; +},{"../Configuration":5,"../PropTypes":11,"react":"react"}],26:[function(require,module,exports){ +"use strict"; +var React = require("react"); +var Configuration = require("../Configuration"); +var PropTypes = require("../PropTypes"); +var RouteHandler = require("./RouteHandler"); /** - * Calls the willTransitionTo hook of all handlers in the given matches - * serially with the transition object and any params that apply to that - * handler. Calls callback(error) when finished. + * components specify components that are rendered to the page when the + * URL matches a given pattern. + * + * Routes are arranged in a nested tree structure. When a new URL is requested, + * the tree is searched depth-first to find a route whose path matches the URL. + * When one is found, all routes in the tree that lead to it are considered + * "active" and their components are rendered into the DOM, nested in the same + * order as they are in the tree. + * + * The preferred way to configure a router is using JSX. The XML-like syntax is + * a great way to visualize how routes are laid out in an application. + * + * var routes = [ + * + * + * + * + * + * ]; + * + * Router.run(routes, function (Handler) { + * React.render(, document.body); + * }); + * + * Handlers for Route components that contain children can render their active + * child route using a element. + * + * var App = React.createClass({ + * render: function () { + * return ( + *
+ * + *
+ * ); + * } + * }); + * + * If no handler is provided for the route, it will render a matched child route. */ -function runTransitionToHooks(transition, routes, params, query, callback) { - var hooks = routes.map(function (route) { - return function () { - var handler = route.handler; - - if (!transition.isAborted && handler.willTransitionTo) - handler.willTransitionTo(transition, params, query); +var Route = React.createClass({ - var promise = transition._promise; - transition._promise = null; + displayName: "Route", - return promise; - }; - }); + mixins: [Configuration], - runHooks(hooks, callback); -} + propTypes: { + name: PropTypes.string, + path: PropTypes.string, + handler: PropTypes.func, + ignoreScrollBehavior: PropTypes.bool + }, -/** - * Encapsulates a transition to a given path. - * - * The willTransitionTo and willTransitionFrom handlers receive - * an instance of this class as their first argument. - */ -function Transition(path, retry) { - this.path = path; - this.abortReason = null; - this.isAborted = false; - this.retry = retry.bind(this); - this._promise = null; -} + getDefaultProps: function getDefaultProps() { + return { + handler: RouteHandler + }; + } -assign(Transition.prototype, { +}); - abort: function (reason) { - if (this.isAborted) { - // First abort wins. - return; - } +module.exports = Route; +},{"../Configuration":5,"../PropTypes":11,"./RouteHandler":27,"react":"react"}],27:[function(require,module,exports){ +"use strict"; - this.abortReason = reason; - this.isAborted = true; - }, +var React = require("react"); +var RouteHandlerMixin = require("../RouteHandlerMixin"); - redirect: function (to, params, query) { - this.abort(new Redirect(to, params, query)); - }, +/** + * A component renders the active child route handler + * when routes are nested. + */ +var RouteHandler = React.createClass({ - wait: function (value) { - this._promise = Promise.resolve(value); - }, + displayName: "RouteHandler", - from: function (routes, components, callback) { - return runTransitionFromHooks(this, routes, components, callback); - }, + mixins: [RouteHandlerMixin], - to: function (routes, params, query, callback) { - return runTransitionToHooks(this, routes, params, query, callback); + render: function render() { + return this.createChildRouteHandler(); } }); -module.exports = Transition; - -},{"./Promise":30,"./Redirect":32,"./reversedArray":37,"react/lib/Object.assign":77}],34:[function(require,module,exports){ +module.exports = RouteHandler; +},{"../RouteHandlerMixin":14,"react":"react"}],28:[function(require,module,exports){ (function (process){ +"use strict"; + /* jshint -W058 */ -var React = require('react'); -var warning = require('react/lib/warning'); -var invariant = require('react/lib/invariant'); -var canUseDOM = require('react/lib/ExecutionEnvironment').canUseDOM; -var ImitateBrowserBehavior = require('../behaviors/ImitateBrowserBehavior'); -var RouteHandler = require('../components/RouteHandler'); -var LocationActions = require('../actions/LocationActions'); -var HashLocation = require('../locations/HashLocation'); -var HistoryLocation = require('../locations/HistoryLocation'); -var RefreshLocation = require('../locations/RefreshLocation'); -var NavigationContext = require('../mixins/NavigationContext'); -var StateContext = require('../mixins/StateContext'); -var Scrolling = require('../mixins/Scrolling'); -var createRoutesFromChildren = require('./createRoutesFromChildren'); -var supportsHistory = require('./supportsHistory'); -var Transition = require('./Transition'); -var PropTypes = require('./PropTypes'); -var Redirect = require('./Redirect'); -var History = require('./History'); -var Cancellation = require('./Cancellation'); -var Path = require('./Path'); +var React = require("react"); +var warning = require("react/lib/warning"); +var invariant = require("react/lib/invariant"); +var canUseDOM = require("react/lib/ExecutionEnvironment").canUseDOM; +var LocationActions = require("./actions/LocationActions"); +var ImitateBrowserBehavior = require("./behaviors/ImitateBrowserBehavior"); +var HashLocation = require("./locations/HashLocation"); +var HistoryLocation = require("./locations/HistoryLocation"); +var RefreshLocation = require("./locations/RefreshLocation"); +var StaticLocation = require("./locations/StaticLocation"); +var NavigationContext = require("./NavigationContext"); +var ScrollHistory = require("./ScrollHistory"); +var StateContext = require("./StateContext"); +var createRoutesFromReactChildren = require("./createRoutesFromReactChildren"); +var isReactChildren = require("./isReactChildren"); +var Transition = require("./Transition"); +var PropTypes = require("./PropTypes"); +var Redirect = require("./Redirect"); +var History = require("./History"); +var Cancellation = require("./Cancellation"); +var Match = require("./Match"); +var Route = require("./Route"); +var supportsHistory = require("./supportsHistory"); +var PathUtils = require("./PathUtils"); /** * The default location for new routers. */ -var DEFAULT_LOCATION = canUseDOM ? HashLocation : '/'; +var DEFAULT_LOCATION = canUseDOM ? HashLocation : "/"; /** * The default scroll behavior for new routers. */ var DEFAULT_SCROLL_BEHAVIOR = canUseDOM ? ImitateBrowserBehavior : null; -/** - * The default error handler for new routers. - */ -function defaultErrorHandler(error) { - // Throw so we don't silently swallow async errors. - throw error; // This error probably originated in a transition hook. -} - -/** - * The default aborted transition handler for new routers. - */ -function defaultAbortHandler(abortReason, location) { - if (typeof location === 'string') - throw new Error('Unhandled aborted transition! Reason: ' + abortReason); - - if (abortReason instanceof Cancellation) { - return; - } else if (abortReason instanceof Redirect) { - location.replace(this.makePath(abortReason.to, abortReason.params, abortReason.query)); - } else { - location.pop(); - } -} - -function findMatch(pathname, routes, defaultRoute, notFoundRoute) { - var match, route, params; - - for (var i = 0, len = routes.length; i < len; ++i) { - route = routes[i]; - - // Check the subtree first to find the most deeply-nested match. - match = findMatch(pathname, route.childRoutes, route.defaultRoute, route.notFoundRoute); - - if (match != null) { - match.routes.unshift(route); - return match; - } - - // No routes in the subtree matched, so check this route. - params = Path.extractParams(route.path, pathname); - - if (params) - return createMatch(route, params); - } - - // No routes matched, so try the default route if there is one. - if (defaultRoute && (params = Path.extractParams(defaultRoute.path, pathname))) - return createMatch(defaultRoute, params); - - // Last attempt: does the "not found" route match? - if (notFoundRoute && (params = Path.extractParams(notFoundRoute.path, pathname))) - return createMatch(notFoundRoute, params); - - return match; -} - -function createMatch(route, params) { - return { routes: [ route ], params: params }; -} - function hasProperties(object, properties) { - for (var propertyName in properties) - if (properties.hasOwnProperty(propertyName) && object[propertyName] !== properties[propertyName]) - return false; - - return true; + for (var propertyName in properties) if (properties.hasOwnProperty(propertyName) && object[propertyName] !== properties[propertyName]) { + return false; + }return true; } function hasMatch(routes, route, prevParams, nextParams, prevQuery, nextQuery) { return routes.some(function (r) { - if (r !== route) - return false; + if (r !== route) return false; var paramNames = route.paramNames; var paramName; @@ -3223,8 +1864,7 @@ function hasMatch(routes, route, prevParams, nextParams, prevQuery, nextQuery) { for (var i = 0, len = paramNames.length; i < len; ++i) { paramName = paramNames[i]; - if (nextParams[paramName] !== prevParams[paramName]) - return false; + if (nextParams[paramName] !== prevParams[paramName]) return false; } // Ensure the query hasn't changed. @@ -3232,6 +1872,21 @@ function hasMatch(routes, route, prevParams, nextParams, prevQuery, nextQuery) { }); } +function addRoutesToNamedRoutes(routes, namedRoutes) { + var route; + for (var i = 0, len = routes.length; i < len; ++i) { + route = routes[i]; + + if (route.name) { + invariant(namedRoutes[route.name] == null, "You may not have more than one route named \"%s\"", route.name); + + namedRoutes[route.name] = route; + } + + if (route.childRoutes) addRoutesToNamedRoutes(route.childRoutes, namedRoutes); + } +} + /** * Creates and returns a new router using the given options. A router * is a ReactComponent class that knows how to react to changes in the @@ -3253,107 +1908,111 @@ function hasMatch(routes, route, prevParams, nextParams, prevQuery, nextQuery) { function createRouter(options) { options = options || {}; - if (typeof options === 'function') { - options = { routes: options }; // Router.create() - } else if (Array.isArray(options)) { - options = { routes: options }; // Router.create([ , ]) - } + if (isReactChildren(options)) options = { routes: options }; - var routes = []; - var namedRoutes = {}; - var components = []; + var mountedComponents = []; var location = options.location || DEFAULT_LOCATION; var scrollBehavior = options.scrollBehavior || DEFAULT_SCROLL_BEHAVIOR; - var onError = options.onError || defaultErrorHandler; - var onAbort = options.onAbort || defaultAbortHandler; var state = {}; var nextState = {}; var pendingTransition = null; + var dispatchHandler = null; - function updateState() { - state = nextState; - nextState = {}; - } + if (typeof location === "string") location = new StaticLocation(location); - if (typeof location === 'string') { - warning( - !canUseDOM || process.env.NODE_ENV === 'test', - 'You should not use a static location in a DOM environment because ' + - 'the router will not be kept in sync with the current URL' - ); + if (location instanceof StaticLocation) { + warning(!canUseDOM || process.env.NODE_ENV === "test", "You should not use a static location in a DOM environment because " + "the router will not be kept in sync with the current URL"); } else { - invariant( - canUseDOM, - 'You cannot use %s without a DOM', - location - ); + invariant(canUseDOM || location.needsDOM === false, "You cannot use %s without a DOM", location); } // Automatically fall back to full page refreshes in // browsers that don't support the HTML history API. - if (location === HistoryLocation && !supportsHistory()) - location = RefreshLocation; - - var router = React.createClass({ + if (location === HistoryLocation && !supportsHistory()) location = RefreshLocation; - displayName: 'Router', + var Router = React.createClass({ - mixins: [ NavigationContext, StateContext, Scrolling ], + displayName: "Router", statics: { - defaultRoute: null, - notFoundRoute: null, + isRunning: false, + + cancelPendingTransition: function cancelPendingTransition() { + if (pendingTransition) { + pendingTransition.cancel(); + pendingTransition = null; + } + }, + + clearAllRoutes: function clearAllRoutes() { + this.cancelPendingTransition(); + this.namedRoutes = {}; + this.routes = []; + }, /** * Adds routes to this router from the given children object (see ReactChildren). */ - addRoutes: function (children) { - routes.push.apply(routes, createRoutesFromChildren(children, this, namedRoutes)); + addRoutes: function addRoutes(routes) { + if (isReactChildren(routes)) routes = createRoutesFromReactChildren(routes); + + addRoutesToNamedRoutes(routes, this.namedRoutes); + + this.routes.push.apply(this.routes, routes); + }, + + /** + * Replaces routes of this router from the given children object (see ReactChildren). + */ + replaceRoutes: function replaceRoutes(routes) { + this.clearAllRoutes(); + this.addRoutes(routes); + this.refresh(); + }, + + /** + * Performs a match of the given path against this router and returns an object + * with the { routes, params, pathname, query } that match. Returns null if no + * match can be made. + */ + match: function match(path) { + return Match.findMatch(this.routes, path); }, /** * Returns an absolute URL path created from the given route * name, URL parameters, and query. */ - makePath: function (to, params, query) { + makePath: function makePath(to, params, query) { var path; - if (Path.isAbsolute(to)) { - path = Path.normalize(to); + if (PathUtils.isAbsolute(to)) { + path = to; } else { - var route = namedRoutes[to]; + var route = to instanceof Route ? to : this.namedRoutes[to]; - invariant( - route, - 'Unable to find ', - to - ); + invariant(route instanceof Route, "Cannot find a route named \"%s\"", to); path = route.path; } - return Path.withQuery(Path.injectParams(path, params), query); + return PathUtils.withQuery(PathUtils.injectParams(path, params), query); }, /** * Returns a string that may safely be used as the href of a link * to the route with the given name, URL parameters, and query. */ - makeHref: function (to, params, query) { + makeHref: function makeHref(to, params, query) { var path = this.makePath(to, params, query); - return (location === HashLocation) ? '#' + path : path; + return location === HashLocation ? "#" + path : path; }, /** * Transitions to the URL specified in the arguments by pushing * a new URL onto the history stack. */ - transitionTo: function (to, params, query) { - invariant( - typeof location !== 'string', - 'You cannot use transitionTo with a static location' - ); - + transitionTo: function transitionTo(to, params, query) { var path = this.makePath(to, params, query); if (pendingTransition) { @@ -3368,12 +2027,7 @@ function createRouter(options) { * Transitions to the URL specified in the arguments by replacing * the current URL in the history stack. */ - replaceWith: function (to, params, query) { - invariant( - typeof location !== 'string', - 'You cannot use replaceWith with a static location' - ); - + replaceWith: function replaceWith(to, params, query) { location.replace(this.makePath(to, params, query)); }, @@ -3388,28 +2042,36 @@ function createRouter(options) { * don't support HTML5 history) this method will *always* send the client back * because we cannot reliably track history length. */ - goBack: function () { - invariant( - typeof location !== 'string', - 'You cannot use goBack with a static location' - ); - + goBack: function goBack() { if (History.length > 1 || location === RefreshLocation) { location.pop(); return true; } - warning(false, 'goBack() was ignored because there is no router history'); + warning(false, "goBack() was ignored because there is no router history"); return false; }, - /** - * Performs a match of the given pathname against this router and returns an object - * with the { routes, params } that match. Returns null if no match can be made. - */ - match: function (pathname) { - return findMatch(pathname, routes, this.defaultRoute, this.notFoundRoute) || null; + handleAbort: options.onAbort || function (abortReason) { + if (location instanceof StaticLocation) throw new Error("Unhandled aborted transition! Reason: " + abortReason); + + if (abortReason instanceof Cancellation) { + return; + } else if (abortReason instanceof Redirect) { + location.replace(this.makePath(abortReason.to, abortReason.params, abortReason.query)); + } else { + location.pop(); + } + }, + + handleError: options.onError || function (error) { + // Throw so we don't silently swallow async errors. + throw error; // This error probably originated in a transition hook. + }, + + handleLocationChange: function handleLocationChange(change) { + this.dispatch(change.path, change.type); }, /** @@ -3425,35 +2087,28 @@ function createRouter(options) { * all route handlers we're transitioning to. * * Both willTransitionFrom and willTransitionTo hooks may either abort or redirect the - * transition. To resolve asynchronously, they may use transition.wait(promise). If no + * transition. To resolve asynchronously, they may use the callback argument. If no * hooks wait, the transition is fully synchronous. */ - dispatch: function (path, action, callback) { - if (pendingTransition) { - pendingTransition.abort(new Cancellation); - pendingTransition = null; - } + dispatch: function dispatch(path, action) { + this.cancelPendingTransition(); var prevPath = state.path; - if (prevPath === path) - return; // Nothing to do! + var isRefreshing = action == null; + + if (prevPath === path && !isRefreshing) { + return; + } // Nothing to do! // Record the scroll position as early as possible to // get it before browsers try update it automatically. - if (prevPath && action !== LocationActions.REPLACE) - this.recordScrollPosition(prevPath); + if (prevPath && action === LocationActions.PUSH) this.recordScrollPosition(prevPath); - var pathname = Path.withoutQuery(path); - var match = this.match(pathname); + var match = this.match(path); - warning( - match != null, - 'No route matches path "%s". Make sure you have somewhere in your routes', - path, path - ); + warning(match != null, "No route matches path \"%s\". Make sure you have somewhere in your routes", path, path); - if (match == null) - match = {}; + if (match == null) match = {}; var prevRoutes = state.routes || []; var prevParams = state.params || {}; @@ -3461,7 +2116,7 @@ function createRouter(options) { var nextRoutes = match.routes || []; var nextParams = match.params || {}; - var nextQuery = Path.extractQuery(path) || {}; + var nextQuery = match.query || {}; var fromRoutes, toRoutes; if (prevRoutes.length) { @@ -3480,22 +2135,20 @@ function createRouter(options) { var transition = new Transition(path, this.replaceWith.bind(this, path)); pendingTransition = transition; - transition.from(fromRoutes, components, function (error) { - if (error || transition.isAborted) - return callback.call(router, error, transition); + var fromComponents = mountedComponents.slice(prevRoutes.length - fromRoutes.length); - transition.to(toRoutes, nextParams, nextQuery, function (error) { - if (error || transition.isAborted) - return callback.call(router, error, transition); + Transition.from(transition, fromRoutes, fromComponents, function (error) { + if (error || transition.abortReason) return dispatchHandler.call(Router, error, transition); // No need to continue. - nextState.path = path; - nextState.action = action; - nextState.pathname = pathname; - nextState.routes = nextRoutes; - nextState.params = nextParams; - nextState.query = nextQuery; - - callback.call(router, null, transition); + Transition.to(transition, toRoutes, nextParams, nextQuery, function (error) { + dispatchHandler.call(Router, error, transition, { + path: path, + action: action, + pathname: match.pathname, + routes: nextRoutes, + params: nextParams, + query: nextQuery + }); }); }); }, @@ -3507,284 +2160,207 @@ function createRouter(options) { * the callback is called only once. Otherwise, the location should be one of the * Router.*Location objects (e.g. Router.HashLocation or Router.HistoryLocation). */ - run: function (callback) { - var dispatchHandler = function (error, transition) { + run: function run(callback) { + invariant(!this.isRunning, "Router is already running"); + + dispatchHandler = function (error, transition, newState) { + if (error) Router.handleError(error); + + if (pendingTransition !== transition) return; + pendingTransition = null; - if (error) { - onError.call(router, error); - } else if (transition.isAborted) { - onAbort.call(router, transition.abortReason, location); + if (transition.abortReason) { + Router.handleAbort(transition.abortReason); } else { - callback.call(router, router, nextState); + callback.call(this, this, nextState = newState); } }; - if (typeof location === 'string') { - router.dispatch(location, null, dispatchHandler); - } else { - // Listen for changes to the location. - var changeListener = function (change) { - router.dispatch(change.path, change.type, dispatchHandler); - }; - - if (location.addChangeListener) - location.addChangeListener(changeListener); + if (!(location instanceof StaticLocation)) { + if (location.addChangeListener) location.addChangeListener(Router.handleLocationChange); - // Bootstrap using the current path. - router.dispatch(location.getCurrentPath(), null, dispatchHandler); + this.isRunning = true; } + + // Bootstrap using the current path. + this.refresh(); + }, + + refresh: function refresh() { + Router.dispatch(location.getCurrentPath(), null); + }, + + stop: function stop() { + this.cancelPendingTransition(); + + if (location.removeChangeListener) location.removeChangeListener(Router.handleLocationChange); + + this.isRunning = false; }, - teardown: function() { - location.removeChangeListener(this.changeListener); + getScrollBehavior: function getScrollBehavior() { + return scrollBehavior; } }, + mixins: [NavigationContext, StateContext, ScrollHistory], + propTypes: { children: PropTypes.falsy }, - getLocation: function () { - return location; - }, - - getScrollBehavior: function () { - return scrollBehavior; + childContextTypes: { + getRouteAtDepth: React.PropTypes.func.isRequired, + setRouteComponentAtDepth: React.PropTypes.func.isRequired, + routeHandlers: React.PropTypes.array.isRequired }, - getRouteAtDepth: function (depth) { - var routes = this.state.routes; - return routes && routes[depth]; + getChildContext: function getChildContext() { + return { + getRouteAtDepth: this.getRouteAtDepth, + setRouteComponentAtDepth: this.setRouteComponentAtDepth, + routeHandlers: [this] + }; }, - getRouteComponents: function () { - return components; + getInitialState: function getInitialState() { + return state = nextState; }, - getInitialState: function () { - updateState(); - return state; + componentWillReceiveProps: function componentWillReceiveProps() { + this.setState(state = nextState); }, - componentWillReceiveProps: function () { - updateState(); - this.setState(state); + componentWillUnmount: function componentWillUnmount() { + Router.stop(); }, - componentWillUnmount: function() { - router.teardown(); + getLocation: function getLocation() { + return location; }, - render: function () { - return this.getRouteAtDepth(0) ? React.createElement(RouteHandler, this.props) : null; + getRouteAtDepth: function getRouteAtDepth(depth) { + var routes = this.state.routes; + return routes && routes[depth]; }, - childContextTypes: { - getRouteAtDepth: React.PropTypes.func.isRequired, - getRouteComponents: React.PropTypes.func.isRequired, - routeHandlers: React.PropTypes.array.isRequired + setRouteComponentAtDepth: function setRouteComponentAtDepth(depth, component) { + mountedComponents[depth] = component; }, - getChildContext: function () { - return { - getRouteComponents: this.getRouteComponents, - getRouteAtDepth: this.getRouteAtDepth, - routeHandlers: [ this ] - }; + render: function render() { + var route = this.getRouteAtDepth(0); + return route ? React.createElement(route.handler, this.props) : null; } }); - if (options.routes) - router.addRoutes(options.routes); + Router.clearAllRoutes(); - return router; + if (options.routes) Router.addRoutes(options.routes); + + return Router; } module.exports = createRouter; - }).call(this,require('_process')) -},{"../actions/LocationActions":8,"../behaviors/ImitateBrowserBehavior":9,"../components/RouteHandler":16,"../locations/HashLocation":17,"../locations/HistoryLocation":18,"../locations/RefreshLocation":19,"../mixins/NavigationContext":22,"../mixins/Scrolling":24,"../mixins/StateContext":26,"./Cancellation":27,"./History":28,"./Path":29,"./PropTypes":31,"./Redirect":32,"./Transition":33,"./createRoutesFromChildren":35,"./supportsHistory":39,"_process":5,"react":"react","react/lib/ExecutionEnvironment":71,"react/lib/invariant":189,"react/lib/warning":209}],35:[function(require,module,exports){ -/* jshint -W084 */ -var React = require('react'); -var warning = require('react/lib/warning'); -var invariant = require('react/lib/invariant'); -var DefaultRoute = require('../components/DefaultRoute'); -var NotFoundRoute = require('../components/NotFoundRoute'); -var Redirect = require('../components/Redirect'); -var Route = require('../components/Route'); -var Path = require('./Path'); - -var CONFIG_ELEMENT_TYPES = [ - DefaultRoute.type, - NotFoundRoute.type, - Redirect.type, - Route.type -]; -function createRedirectHandler(to, _params, _query) { - return React.createClass({ - statics: { - willTransitionTo: function (transition, params, query) { - transition.redirect(to, _params || params, _query || query); - } - }, +},{"./Cancellation":4,"./History":6,"./Match":7,"./NavigationContext":9,"./PathUtils":10,"./PropTypes":11,"./Redirect":12,"./Route":13,"./ScrollHistory":15,"./StateContext":17,"./Transition":18,"./actions/LocationActions":19,"./behaviors/ImitateBrowserBehavior":20,"./createRoutesFromReactChildren":29,"./isReactChildren":31,"./locations/HashLocation":32,"./locations/HistoryLocation":33,"./locations/RefreshLocation":34,"./locations/StaticLocation":35,"./supportsHistory":37,"_process":1,"react":"react","react/lib/ExecutionEnvironment":64,"react/lib/invariant":182,"react/lib/warning":202}],29:[function(require,module,exports){ +"use strict"; - render: function () { - return null; - } - }); -} +/* jshint -W084 */ + +var React = require("react"); +var assign = require("react/lib/Object.assign"); +var warning = require("react/lib/warning"); +var DefaultRouteType = require("./components/DefaultRoute").type; +var NotFoundRouteType = require("./components/NotFoundRoute").type; +var RedirectType = require("./components/Redirect").type; +var Route = require("./Route"); function checkPropTypes(componentName, propTypes, props) { + componentName = componentName || "UnknownComponent"; + for (var propName in propTypes) { if (propTypes.hasOwnProperty(propName)) { var error = propTypes[propName](props, propName, componentName); - if (error instanceof Error) - warning(false, error.message); + if (error instanceof Error) warning(false, error.message); } } } -function createRoute(element, parentRoute, namedRoutes) { - var type = element.type; - var props = element.props; - var componentName = (type && type.displayName) || 'UnknownComponent'; - - invariant( - CONFIG_ELEMENT_TYPES.indexOf(type) !== -1, - 'Unrecognized route configuration element "<%s>"', - componentName - ); - - if (type.propTypes) - checkPropTypes(componentName, type.propTypes, props); - - var route = { name: props.name }; - - if (props.ignoreScrollBehavior) { - route.ignoreScrollBehavior = true; - } - - if (type === Redirect.type) { - route.handler = createRedirectHandler(props.to, props.params, props.query); - props.path = props.path || props.from || '*'; - } else { - route.handler = props.handler; - } - - var parentPath = (parentRoute && parentRoute.path) || '/'; - - if ((props.path || props.name) && type !== DefaultRoute.type && type !== NotFoundRoute.type) { - var path = props.path || props.name; - - // Relative paths extend their parent. - if (!Path.isAbsolute(path)) - path = Path.join(parentPath, path); - - route.path = Path.normalize(path); - } else { - route.path = parentPath; - - if (type === NotFoundRoute.type) - route.path += '*'; - } - - route.paramNames = Path.extractParamNames(route.path); - - // Make sure the route's path has all params its parent needs. - if (parentRoute && Array.isArray(parentRoute.paramNames)) { - parentRoute.paramNames.forEach(function (paramName) { - invariant( - route.paramNames.indexOf(paramName) !== -1, - 'The nested route path "%s" is missing the "%s" parameter of its parent path "%s"', - route.path, paramName, parentRoute.path - ); - }); - } - - // Make sure the route can be looked up by s. - if (props.name) { - invariant( - namedRoutes[props.name] == null, - 'You cannot use the name "%s" for more than one route', - props.name - ); - - namedRoutes[props.name] = route; - } - - // Handle . - if (type === NotFoundRoute.type) { - invariant( - parentRoute, - ' must have a parent ' - ); - - invariant( - parentRoute.notFoundRoute == null, - 'You may not have more than one per ' - ); - - parentRoute.notFoundRoute = route; +function createRouteOptions(props) { + var options = assign({}, props); + var handler = options.handler; - return null; + if (handler) { + options.onEnter = handler.willTransitionTo; + options.onLeave = handler.willTransitionFrom; } - // Handle . - if (type === DefaultRoute.type) { - invariant( - parentRoute, - ' must have a parent ' - ); - - invariant( - parentRoute.defaultRoute == null, - 'You may not have more than one per ' - ); - - parentRoute.defaultRoute = route; + return options; +} - return null; - } +function createRouteFromReactElement(element) { + if (!React.isValidElement(element)) { + return; + }var type = element.type; + var props = element.props; - route.childRoutes = createRoutesFromChildren(props.children, route, namedRoutes); + if (type.propTypes) checkPropTypes(type.displayName, type.propTypes, props); - return route; + if (type === DefaultRouteType) { + return Route.createDefaultRoute(createRouteOptions(props)); + }if (type === NotFoundRouteType) { + return Route.createNotFoundRoute(createRouteOptions(props)); + }if (type === RedirectType) { + return Route.createRedirect(createRouteOptions(props)); + }return Route.createRoute(createRouteOptions(props), function () { + if (props.children) createRoutesFromReactChildren(props.children); + }); } /** - * Creates and returns an array of route objects from the given ReactChildren. + * Creates and returns an array of routes created from the given + * ReactChildren, all of which should be one of , , + * , or , e.g.: + * + * var { createRoutesFromReactChildren, Route, Redirect } = require('react-router'); + * + * var routes = createRoutesFromReactChildren( + * + * + * + * + * + * + * ); */ -function createRoutesFromChildren(children, parentRoute, namedRoutes) { +function createRoutesFromReactChildren(children) { var routes = []; React.Children.forEach(children, function (child) { - // Exclude s and s. - if (child = createRoute(child, parentRoute, namedRoutes)) - routes.push(child); + if (child = createRouteFromReactElement(child)) routes.push(child); }); return routes; } -module.exports = createRoutesFromChildren; +module.exports = createRoutesFromReactChildren; +},{"./Route":13,"./components/DefaultRoute":22,"./components/NotFoundRoute":24,"./components/Redirect":25,"react":"react","react/lib/Object.assign":70,"react/lib/warning":202}],30:[function(require,module,exports){ +"use strict"; -},{"../components/DefaultRoute":11,"../components/NotFoundRoute":13,"../components/Redirect":14,"../components/Route":15,"./Path":29,"react":"react","react/lib/invariant":189,"react/lib/warning":209}],36:[function(require,module,exports){ -var invariant = require('react/lib/invariant'); -var canUseDOM = require('react/lib/ExecutionEnvironment').canUseDOM; +var invariant = require("react/lib/invariant"); +var canUseDOM = require("react/lib/ExecutionEnvironment").canUseDOM; /** * Returns the current scroll position of the window as { x, y }. */ function getWindowScrollPosition() { - invariant( - canUseDOM, - 'Cannot get current scroll position without a DOM' - ); + invariant(canUseDOM, "Cannot get current scroll position without a DOM"); return { x: window.pageXOffset || document.documentElement.scrollLeft, @@ -3793,51 +2369,356 @@ function getWindowScrollPosition() { } module.exports = getWindowScrollPosition; +},{"react/lib/ExecutionEnvironment":64,"react/lib/invariant":182}],31:[function(require,module,exports){ +"use strict"; -},{"react/lib/ExecutionEnvironment":71,"react/lib/invariant":189}],37:[function(require,module,exports){ -function reversedArray(array) { - return array.slice(0).reverse(); +var React = require("react"); + +function isValidChild(object) { + return object == null || React.isValidElement(object); } -module.exports = reversedArray; +function isReactChildren(object) { + return isValidChild(object) || Array.isArray(object) && object.every(isValidChild); +} -},{}],38:[function(require,module,exports){ -var createRouter = require('./createRouter'); +module.exports = isReactChildren; +},{"react":"react"}],32:[function(require,module,exports){ +"use strict"; + +var LocationActions = require("../actions/LocationActions"); +var History = require("../History"); /** - * A high-level convenience method that creates, configures, and - * runs a router in one shot. The method signature is: - * - * Router.run(routes[, location ], callback); - * - * Using `window.location.hash` to manage the URL, you could do: - * - * Router.run(routes, function (Handler) { - * React.render(, document.body); - * }); - * - * Using HTML5 history and a custom "cursor" prop: - * - * Router.run(routes, Router.HistoryLocation, function (Handler) { - * React.render(, document.body); - * }); - * - * Returns the newly created router. - * - * Note: If you need to specify further options for your router such - * as error/abort handling or custom scroll behavior, use Router.create - * instead. - * - * var router = Router.create(options); - * router.run(function (Handler) { - * // ... - * }); + * Returns the current URL path from the `hash` portion of the URL, including + * query string. */ -function runRouter(routes, location, callback) { - if (typeof location === 'function') { - callback = location; - location = null; - } +function getHashPath() { + return decodeURI( + // We can't use window.location.hash here because it's not + // consistent across browsers - Firefox will pre-decode it! + window.location.href.split("#")[1] || ""); +} + +var _actionType; + +function ensureSlash() { + var path = getHashPath(); + + if (path.charAt(0) === "/") { + return true; + }HashLocation.replace("/" + path); + + return false; +} + +var _changeListeners = []; + +function notifyChange(type) { + if (type === LocationActions.PUSH) History.length += 1; + + var change = { + path: getHashPath(), + type: type + }; + + _changeListeners.forEach(function (listener) { + listener(change); + }); +} + +var _isListening = false; + +function onHashChange() { + if (ensureSlash()) { + // If we don't have an _actionType then all we know is the hash + // changed. It was probably caused by the user clicking the Back + // button, but may have also been the Forward button or manual + // manipulation. So just guess 'pop'. + notifyChange(_actionType || LocationActions.POP); + _actionType = null; + } +} + +/** + * A Location that uses `window.location.hash`. + */ +var HashLocation = { + + addChangeListener: function addChangeListener(listener) { + _changeListeners.push(listener); + + // Do this BEFORE listening for hashchange. + ensureSlash(); + + if (!_isListening) { + if (window.addEventListener) { + window.addEventListener("hashchange", onHashChange, false); + } else { + window.attachEvent("onhashchange", onHashChange); + } + + _isListening = true; + } + }, + + removeChangeListener: function removeChangeListener(listener) { + _changeListeners = _changeListeners.filter(function (l) { + return l !== listener; + }); + + if (_changeListeners.length === 0) { + if (window.removeEventListener) { + window.removeEventListener("hashchange", onHashChange, false); + } else { + window.removeEvent("onhashchange", onHashChange); + } + + _isListening = false; + } + }, + + push: function push(path) { + _actionType = LocationActions.PUSH; + window.location.hash = path; + }, + + replace: function replace(path) { + _actionType = LocationActions.REPLACE; + window.location.replace(window.location.pathname + window.location.search + "#" + path); + }, + + pop: function pop() { + _actionType = LocationActions.POP; + History.back(); + }, + + getCurrentPath: getHashPath, + + toString: function toString() { + return ""; + } + +}; + +module.exports = HashLocation; +},{"../History":6,"../actions/LocationActions":19}],33:[function(require,module,exports){ +"use strict"; + +var LocationActions = require("../actions/LocationActions"); +var History = require("../History"); + +/** + * Returns the current URL path from `window.location`, including query string. + */ +function getWindowPath() { + return decodeURI(window.location.pathname + window.location.search); +} + +var _changeListeners = []; + +function notifyChange(type) { + var change = { + path: getWindowPath(), + type: type + }; + + _changeListeners.forEach(function (listener) { + listener(change); + }); +} + +var _isListening = false; + +function onPopState(event) { + if (event.state === undefined) { + return; + } // Ignore extraneous popstate events in WebKit. + + notifyChange(LocationActions.POP); +} + +/** + * A Location that uses HTML5 history. + */ +var HistoryLocation = { + + addChangeListener: function addChangeListener(listener) { + _changeListeners.push(listener); + + if (!_isListening) { + if (window.addEventListener) { + window.addEventListener("popstate", onPopState, false); + } else { + window.attachEvent("onpopstate", onPopState); + } + + _isListening = true; + } + }, + + removeChangeListener: function removeChangeListener(listener) { + _changeListeners = _changeListeners.filter(function (l) { + return l !== listener; + }); + + if (_changeListeners.length === 0) { + if (window.addEventListener) { + window.removeEventListener("popstate", onPopState, false); + } else { + window.removeEvent("onpopstate", onPopState); + } + + _isListening = false; + } + }, + + push: function push(path) { + window.history.pushState({ path: path }, "", path); + History.length += 1; + notifyChange(LocationActions.PUSH); + }, + + replace: function replace(path) { + window.history.replaceState({ path: path }, "", path); + notifyChange(LocationActions.REPLACE); + }, + + pop: History.back, + + getCurrentPath: getWindowPath, + + toString: function toString() { + return ""; + } + +}; + +module.exports = HistoryLocation; +},{"../History":6,"../actions/LocationActions":19}],34:[function(require,module,exports){ +"use strict"; + +var HistoryLocation = require("./HistoryLocation"); +var History = require("../History"); + +/** + * A Location that uses full page refreshes. This is used as + * the fallback for HistoryLocation in browsers that do not + * support the HTML5 history API. + */ +var RefreshLocation = { + + push: function push(path) { + window.location = path; + }, + + replace: function replace(path) { + window.location.replace(path); + }, + + pop: History.back, + + getCurrentPath: HistoryLocation.getCurrentPath, + + toString: function toString() { + return ""; + } + +}; + +module.exports = RefreshLocation; +},{"../History":6,"./HistoryLocation":33}],35:[function(require,module,exports){ +"use strict"; + +var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); }; + +var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + +var invariant = require("react/lib/invariant"); + +function throwCannotModify() { + invariant(false, "You cannot modify a static location"); +} + +/** + * A location that only ever contains a single path. Useful in + * stateless environments like servers where there is no path history, + * only the path that was used in the request. + */ + +var StaticLocation = (function () { + function StaticLocation(path) { + _classCallCheck(this, StaticLocation); + + this.path = path; + } + + _prototypeProperties(StaticLocation, null, { + getCurrentPath: { + value: function getCurrentPath() { + return this.path; + }, + writable: true, + configurable: true + }, + toString: { + value: function toString() { + return ""; + }, + writable: true, + configurable: true + } + }); + + return StaticLocation; +})(); + +// TODO: Include these in the above class definition +// once we can use ES7 property initializers. +StaticLocation.prototype.push = throwCannotModify; +StaticLocation.prototype.replace = throwCannotModify; +StaticLocation.prototype.pop = throwCannotModify; + +module.exports = StaticLocation; +},{"react/lib/invariant":182}],36:[function(require,module,exports){ +"use strict"; + +var createRouter = require("./createRouter"); + +/** + * A high-level convenience method that creates, configures, and + * runs a router in one shot. The method signature is: + * + * Router.run(routes[, location ], callback); + * + * Using `window.location.hash` to manage the URL, you could do: + * + * Router.run(routes, function (Handler) { + * React.render(, document.body); + * }); + * + * Using HTML5 history and a custom "cursor" prop: + * + * Router.run(routes, Router.HistoryLocation, function (Handler) { + * React.render(, document.body); + * }); + * + * Returns the newly created router. + * + * Note: If you need to specify further options for your router such + * as error/abort handling or custom scroll behavior, use Router.create + * instead. + * + * var router = Router.create(options); + * router.run(function (Handler) { + * // ... + * }); + */ +function runRouter(routes, location, callback) { + if (typeof location === "function") { + callback = location; + location = null; + } var router = createRouter({ routes: routes, @@ -3850,8 +2731,9 @@ function runRouter(routes, location, callback) { } module.exports = runRouter; +},{"./createRouter":28}],37:[function(require,module,exports){ +"use strict"; -},{"./createRouter":34}],39:[function(require,module,exports){ function supportsHistory() { /*! taken from modernizr * https://github.com/Modernizr/Modernizr/blob/master/LICENSE @@ -3859,22 +2741,17 @@ function supportsHistory() { * changed to avoid false negatives for Windows Phones: https://github.com/rackt/react-router/issues/586 */ var ua = navigator.userAgent; - if ((ua.indexOf('Android 2.') !== -1 || - (ua.indexOf('Android 4.0') !== -1)) && - ua.indexOf('Mobile Safari') !== -1 && - ua.indexOf('Chrome') === -1 && - ua.indexOf('Windows Phone') === -1) { + if ((ua.indexOf("Android 2.") !== -1 || ua.indexOf("Android 4.0") !== -1) && ua.indexOf("Mobile Safari") !== -1 && ua.indexOf("Chrome") === -1 && ua.indexOf("Windows Phone") === -1) { return false; } - return (window.history && 'pushState' in window.history); + return window.history && "pushState" in window.history; } module.exports = supportsHistory; +},{}],38:[function(require,module,exports){ +module.exports = require('./lib/'); -},{}],40:[function(require,module,exports){ -module.exports = require('./lib'); - -},{"./lib":41}],41:[function(require,module,exports){ +},{"./lib/":39}],39:[function(require,module,exports){ // Load modules var Stringify = require('./stringify'); @@ -3891,7 +2768,7 @@ module.exports = { parse: Parse }; -},{"./parse":42,"./stringify":43}],42:[function(require,module,exports){ +},{"./parse":40,"./stringify":41}],40:[function(require,module,exports){ // Load modules var Utils = require('./utils'); @@ -3923,7 +2800,7 @@ internals.parseValues = function (str, options) { var key = Utils.decode(part.slice(0, pos)); var val = Utils.decode(part.slice(pos + 1)); - if (!obj[key]) { + if (!obj.hasOwnProperty(key)) { obj[key] = val; } else { @@ -3952,8 +2829,11 @@ internals.parseObject = function (chain, val, options) { else { var cleanRoot = root[0] === '[' && root[root.length - 1] === ']' ? root.slice(1, root.length - 1) : root; var index = parseInt(cleanRoot, 10); + var indexString = '' + index; if (!isNaN(index) && root !== cleanRoot && + indexString === cleanRoot && + index >= 0 && index <= options.arrayLimit) { obj = []; @@ -4047,7 +2927,7 @@ module.exports = function (str, options) { return Utils.compact(obj); }; -},{"./utils":44}],43:[function(require,module,exports){ +},{"./utils":42}],41:[function(require,module,exports){ // Load modules var Utils = require('./utils'); @@ -4056,11 +2936,12 @@ var Utils = require('./utils'); // Declare internals var internals = { - delimiter: '&' + delimiter: '&', + indices: true }; -internals.stringify = function (obj, prefix) { +internals.stringify = function (obj, prefix, options) { if (Utils.isBuffer(obj)) { obj = obj.toString(); @@ -4081,9 +2962,20 @@ internals.stringify = function (obj, prefix) { var values = []; - for (var key in obj) { - if (obj.hasOwnProperty(key)) { - values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']')); + if (typeof obj === 'undefined') { + return values; + } + + var objKeys = Object.keys(obj); + for (var i = 0, il = objKeys.length; i < il; ++i) { + var key = objKeys[i]; + if (!options.indices && + Array.isArray(obj)) { + + values = values.concat(internals.stringify(obj[key], prefix, options)); + } + else { + values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']', options)); } } @@ -4095,20 +2987,26 @@ module.exports = function (obj, options) { options = options || {}; var delimiter = typeof options.delimiter === 'undefined' ? internals.delimiter : options.delimiter; + options.indices = typeof options.indices === 'boolean' ? options.indices : internals.indices; var keys = []; - for (var key in obj) { - if (obj.hasOwnProperty(key)) { - keys = keys.concat(internals.stringify(obj[key], key)); - } + if (typeof obj !== 'object' || + obj === null) { + + return ''; + } + + var objKeys = Object.keys(obj); + for (var i = 0, il = objKeys.length; i < il; ++i) { + var key = objKeys[i]; + keys = keys.concat(internals.stringify(obj[key], key, options)); } return keys.join(delimiter); }; -},{"./utils":44}],44:[function(require,module,exports){ -(function (Buffer){ +},{"./utils":42}],42:[function(require,module,exports){ // Load modules @@ -4137,29 +3035,26 @@ exports.merge = function (target, source) { return target; } - if (Array.isArray(source)) { - for (var i = 0, il = source.length; i < il; ++i) { - if (typeof source[i] !== 'undefined') { - if (typeof target[i] === 'object') { - target[i] = exports.merge(target[i], source[i]); - } - else { - target[i] = source[i]; - } - } + if (typeof source !== 'object') { + if (Array.isArray(target)) { + target.push(source); + } + else { + target[source] = true; } return target; } - if (Array.isArray(target)) { - if (typeof source !== 'object') { - target.push(source); - return target; - } - else { - target = exports.arrayToObject(target); - } + if (typeof target !== 'object') { + target = [target].concat(source); + return target; + } + + if (Array.isArray(target) && + !Array.isArray(source)) { + + target = exports.arrayToObject(target); } var keys = Object.keys(source); @@ -4167,18 +3062,11 @@ exports.merge = function (target, source) { var key = keys[k]; var value = source[key]; - if (value && - typeof value === 'object') { - - if (!target[key]) { - target[key] = value; - } - else { - target[key] = exports.merge(target[key], value); - } + if (!target[key]) { + target[key] = value; } else { - target[key] = value; + target[key] = exports.merge(target[key], value); } } @@ -4215,7 +3103,7 @@ exports.compact = function (obj, refs) { if (Array.isArray(obj)) { var compacted = []; - for (var i = 0, l = obj.length; i < l; ++i) { + for (var i = 0, il = obj.length; i < il; ++i) { if (typeof obj[i] !== 'undefined') { compacted.push(obj[i]); } @@ -4225,7 +3113,7 @@ exports.compact = function (obj, refs) { } var keys = Object.keys(obj); - for (var i = 0, il = keys.length; i < il; ++i) { + for (i = 0, il = keys.length; i < il; ++i) { var key = keys[i]; obj[key] = exports.compact(obj[key], refs); } @@ -4241,1302 +3129,256 @@ exports.isRegExp = function (obj) { exports.isBuffer = function (obj) { - if (typeof Buffer !== 'undefined') { - return Buffer.isBuffer(obj); - } - else { + if (obj === null || + typeof obj === 'undefined') { + return false; } -}; -}).call(this,require("buffer").Buffer) -},{"buffer":1}],45:[function(require,module,exports){ -/** @license MIT License (c) copyright 2010-2014 original author or authors */ -/** @author Brian Cavalier */ -/** @author John Hann */ + return !!(obj.constructor && + obj.constructor.isBuffer && + obj.constructor.isBuffer(obj)); +}; -(function(define) { 'use strict'; -define(function (require) { +},{}],43:[function(require,module,exports){ +/** + * Copyright 2013-2014, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule AutoFocusMixin + * @typechecks static-only + */ - var makePromise = require('./makePromise'); - var Scheduler = require('./Scheduler'); - var async = require('./async'); +"use strict"; - return makePromise({ - scheduler: new Scheduler(async) - }); +var focusNode = require("./focusNode"); -}); -})(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); }); - -},{"./Scheduler":47,"./async":48,"./makePromise":49}],46:[function(require,module,exports){ -/** @license MIT License (c) copyright 2010-2014 original author or authors */ -/** @author Brian Cavalier */ -/** @author John Hann */ - -(function(define) { 'use strict'; -define(function() { - /** - * Circular queue - * @param {number} capacityPow2 power of 2 to which this queue's capacity - * will be set initially. eg when capacityPow2 == 3, queue capacity - * will be 8. - * @constructor - */ - function Queue(capacityPow2) { - this.head = this.tail = this.length = 0; - this.buffer = new Array(1 << capacityPow2); - } +var AutoFocusMixin = { + componentDidMount: function() { + if (this.props.autoFocus) { + focusNode(this.getDOMNode()); + } + } +}; - Queue.prototype.push = function(x) { - if(this.length === this.buffer.length) { - this._ensureCapacity(this.length * 2); - } +module.exports = AutoFocusMixin; - this.buffer[this.tail] = x; - this.tail = (this.tail + 1) & (this.buffer.length - 1); - ++this.length; - return this.length; - }; +},{"./focusNode":167}],44:[function(require,module,exports){ +/** + * Copyright 2013 Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule BeforeInputEventPlugin + * @typechecks static-only + */ - Queue.prototype.shift = function() { - var x = this.buffer[this.head]; - this.buffer[this.head] = void 0; - this.head = (this.head + 1) & (this.buffer.length - 1); - --this.length; - return x; - }; +"use strict"; - Queue.prototype._ensureCapacity = function(capacity) { - var head = this.head; - var buffer = this.buffer; - var newBuffer = new Array(capacity); - var i = 0; - var len; +var EventConstants = require("./EventConstants"); +var EventPropagators = require("./EventPropagators"); +var ExecutionEnvironment = require("./ExecutionEnvironment"); +var SyntheticInputEvent = require("./SyntheticInputEvent"); - if(head === 0) { - len = this.length; - for(; i 0) { - queue.shift().run(); - } - } + hasSpaceKeypress = true; + chars = SPACEBAR_CHAR; + break; - return Scheduler; + case topLevelTypes.topTextInput: + // Record the characters to be added to the DOM. + chars = nativeEvent.data; -}); -}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); })); + // If it's a spacebar character, assume that we have already handled + // it at the keypress level and bail immediately. Android Chrome + // doesn't give us keycodes, so we need to blacklist it. + if (chars === SPACEBAR_CHAR && hasSpaceKeypress) { + return; + } -},{"./Queue":46}],48:[function(require,module,exports){ -(function (process){ -/** @license MIT License (c) copyright 2010-2014 original author or authors */ -/** @author Brian Cavalier */ -/** @author John Hann */ + // Otherwise, carry on. + break; -(function(define) { 'use strict'; -define(function(require) { + default: + // For other native event types, do nothing. + return; + } + } else { + switch (topLevelType) { + case topLevelTypes.topPaste: + // If a paste event occurs after a keypress, throw out the input + // chars. Paste events should not lead to BeforeInput events. + fallbackChars = null; + break; + case topLevelTypes.topKeyPress: + /** + * As of v27, Firefox may fire keypress events even when no character + * will be inserted. A few possibilities: + * + * - `which` is `0`. Arrow keys, Esc key, etc. + * + * - `which` is the pressed key code, but no char is available. + * Ex: 'AltGr + d` in Polish. There is no modified character for + * this key combination and no character is inserted into the + * document, but FF fires the keypress for char code `100` anyway. + * No `input` event will occur. + * + * - `which` is the pressed key code, but a command combination is + * being used. Ex: `Cmd+C`. No character is inserted, and no + * `input` event will occur. + */ + if (nativeEvent.which && !isKeypressCommand(nativeEvent)) { + fallbackChars = String.fromCharCode(nativeEvent.which); + } + break; + case topLevelTypes.topCompositionEnd: + fallbackChars = nativeEvent.data; + break; + } - // Sniff "best" async scheduling option - // Prefer process.nextTick or MutationObserver, then check for - // vertx and finally fall back to setTimeout + // If no changes have occurred to the fallback string, no relevant + // event has fired and we're done. + if (fallbackChars === null) { + return; + } - /*jshint maxcomplexity:6*/ - /*global process,document,setTimeout,MutationObserver,WebKitMutationObserver*/ - var nextTick, MutationObs; + chars = fallbackChars; + } - if (typeof process !== 'undefined' && process !== null && - typeof process.nextTick === 'function') { - nextTick = function(f) { - process.nextTick(f); - }; + // If no characters are being inserted, no BeforeInput event should + // be fired. + if (!chars) { + return; + } - } else if (MutationObs = - (typeof MutationObserver === 'function' && MutationObserver) || - (typeof WebKitMutationObserver === 'function' && WebKitMutationObserver)) { - nextTick = (function (document, MutationObserver) { - var scheduled; - var el = document.createElement('div'); - var o = new MutationObserver(run); - o.observe(el, { attributes: true }); - - function run() { - var f = scheduled; - scheduled = void 0; - f(); - } - - return function (f) { - scheduled = f; - el.setAttribute('class', 'x'); - }; - }(document, MutationObs)); - - } else { - nextTick = (function(cjsRequire) { - var vertx; - try { - // vert.x 1.x || 2.x - vertx = cjsRequire('vertx'); - } catch (ignore) {} - - if (vertx) { - if (typeof vertx.runOnLoop === 'function') { - return vertx.runOnLoop; - } - if (typeof vertx.runOnContext === 'function') { - return vertx.runOnContext; - } - } - - // capture setTimeout to avoid being caught by fake timers - // used in time based tests - var capturedSetTimeout = setTimeout; - return function (t) { - capturedSetTimeout(t, 0); - }; - }(require)); - } - - return nextTick; -}); -}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); })); - -}).call(this,require('_process')) -},{"_process":5}],49:[function(require,module,exports){ -/** @license MIT License (c) copyright 2010-2014 original author or authors */ -/** @author Brian Cavalier */ -/** @author John Hann */ - -(function(define) { 'use strict'; -define(function() { - - return function makePromise(environment) { - - var tasks = environment.scheduler; - - var objectCreate = Object.create || - function(proto) { - function Child() {} - Child.prototype = proto; - return new Child(); - }; - - /** - * Create a promise whose fate is determined by resolver - * @constructor - * @returns {Promise} promise - * @name Promise - */ - function Promise(resolver, handler) { - this._handler = resolver === Handler ? handler : init(resolver); - } - - /** - * Run the supplied resolver - * @param resolver - * @returns {Pending} - */ - function init(resolver) { - var handler = new Pending(); - - try { - resolver(promiseResolve, promiseReject, promiseNotify); - } catch (e) { - promiseReject(e); - } - - return handler; - - /** - * Transition from pre-resolution state to post-resolution state, notifying - * all listeners of the ultimate fulfillment or rejection - * @param {*} x resolution value - */ - function promiseResolve (x) { - handler.resolve(x); - } - /** - * Reject this promise with reason, which will be used verbatim - * @param {Error|*} reason rejection reason, strongly suggested - * to be an Error type - */ - function promiseReject (reason) { - handler.reject(reason); - } - - /** - * Issue a progress event, notifying all progress listeners - * @param {*} x progress event payload to pass to all listeners - */ - function promiseNotify (x) { - handler.notify(x); - } - } - - // Creation - - Promise.resolve = resolve; - Promise.reject = reject; - Promise.never = never; - - Promise._defer = defer; - Promise._handler = getHandler; - - /** - * Returns a trusted promise. If x is already a trusted promise, it is - * returned, otherwise returns a new trusted Promise which follows x. - * @param {*} x - * @return {Promise} promise - */ - function resolve(x) { - return isPromise(x) ? x - : new Promise(Handler, new Async(getHandler(x))); - } - - /** - * Return a reject promise with x as its reason (x is used verbatim) - * @param {*} x - * @returns {Promise} rejected promise - */ - function reject(x) { - return new Promise(Handler, new Async(new Rejected(x))); - } - - /** - * Return a promise that remains pending forever - * @returns {Promise} forever-pending promise. - */ - function never() { - return foreverPendingPromise; // Should be frozen - } - - /** - * Creates an internal {promise, resolver} pair - * @private - * @returns {Promise} - */ - function defer() { - return new Promise(Handler, new Pending()); - } - - // Transformation and flow control - - /** - * Transform this promise's fulfillment value, returning a new Promise - * for the transformed result. If the promise cannot be fulfilled, onRejected - * is called with the reason. onProgress *may* be called with updates toward - * this promise's fulfillment. - * @param {function=} onFulfilled fulfillment handler - * @param {function=} onRejected rejection handler - * @deprecated @param {function=} onProgress progress handler - * @return {Promise} new promise - */ - Promise.prototype.then = function(onFulfilled, onRejected) { - var parent = this._handler; - var state = parent.join().state(); - - if ((typeof onFulfilled !== 'function' && state > 0) || - (typeof onRejected !== 'function' && state < 0)) { - // Short circuit: value will not change, simply share handler - return new this.constructor(Handler, parent); - } - - var p = this._beget(); - var child = p._handler; - - parent.chain(child, parent.receiver, onFulfilled, onRejected, - arguments.length > 2 ? arguments[2] : void 0); - - return p; - }; - - /** - * If this promise cannot be fulfilled due to an error, call onRejected to - * handle the error. Shortcut for .then(undefined, onRejected) - * @param {function?} onRejected - * @return {Promise} - */ - Promise.prototype['catch'] = function(onRejected) { - return this.then(void 0, onRejected); - }; - - /** - * Creates a new, pending promise of the same type as this promise - * @private - * @returns {Promise} - */ - Promise.prototype._beget = function() { - var parent = this._handler; - var child = new Pending(parent.receiver, parent.join().context); - return new this.constructor(Handler, child); - }; - - // Array combinators - - Promise.all = all; - Promise.race = race; - - /** - * Return a promise that will fulfill when all promises in the - * input array have fulfilled, or will reject when one of the - * promises rejects. - * @param {array} promises array of promises - * @returns {Promise} promise for array of fulfillment values - */ - function all(promises) { - /*jshint maxcomplexity:8*/ - var resolver = new Pending(); - var pending = promises.length >>> 0; - var results = new Array(pending); - - var i, h, x, s; - for (i = 0; i < promises.length; ++i) { - x = promises[i]; - - if (x === void 0 && !(i in promises)) { - --pending; - continue; - } - - if (maybeThenable(x)) { - h = getHandlerMaybeThenable(x); - - s = h.state(); - if (s === 0) { - h.fold(settleAt, i, results, resolver); - } else if (s > 0) { - results[i] = h.value; - --pending; - } else { - unreportRemaining(promises, i+1, h); - resolver.become(h); - break; - } - - } else { - results[i] = x; - --pending; - } - } - - if(pending === 0) { - resolver.become(new Fulfilled(results)); - } - - return new Promise(Handler, resolver); - - function settleAt(i, x, resolver) { - /*jshint validthis:true*/ - this[i] = x; - if(--pending === 0) { - resolver.become(new Fulfilled(this)); - } - } - } - - function unreportRemaining(promises, start, rejectedHandler) { - var i, h, x; - for(i=start; i - * Build: `lodash modern -o ./dist/lodash.js` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license + * lodash 3.3.1 (Custom Build) + * Build: `lodash modern -d -o ./index.js` + * Copyright 2012-2015 The Dojo Foundation + * Based on Underscore.js 1.8.2 + * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + * Available under MIT license */ ;(function() { - /** Used as a safe reference for `undefined` in pre ES5 environments */ + /** Used as a safe reference for `undefined` in pre-ES5 environments. */ var undefined; - /** Used to pool arrays and objects used internally */ - var arrayPool = [], - objectPool = []; - - /** Used to generate unique IDs */ - var idCounter = 0; - - /** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */ - var keyPrefix = +new Date + ''; - - /** Used as the size when optimizations are enabled for large arrays */ - var largeArraySize = 75; - - /** Used as the max size of the `arrayPool` and `objectPool` */ - var maxPoolSize = 40; - - /** Used to detect and test whitespace */ - var whitespace = ( - // whitespace - ' \t\x0B\f\xA0\ufeff' + - - // line terminators - '\n\r\u2028\u2029' + - - // unicode category "Zs" space separators - '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' - ); - - /** Used to match empty string literals in compiled template source */ + /** Used as the semantic version number. */ + var VERSION = '3.3.1'; + + /** Used to compose bitmasks for wrapper metadata. */ + var BIND_FLAG = 1, + BIND_KEY_FLAG = 2, + CURRY_BOUND_FLAG = 4, + CURRY_FLAG = 8, + CURRY_RIGHT_FLAG = 16, + PARTIAL_FLAG = 32, + PARTIAL_RIGHT_FLAG = 64, + REARG_FLAG = 128, + ARY_FLAG = 256; + + /** Used as default options for `_.trunc`. */ + var DEFAULT_TRUNC_LENGTH = 30, + DEFAULT_TRUNC_OMISSION = '...'; + + /** Used to detect when a function becomes hot. */ + var HOT_COUNT = 150, + HOT_SPAN = 16; + + /** Used to indicate the type of lazy iteratees. */ + var LAZY_FILTER_FLAG = 0, + LAZY_MAP_FLAG = 1, + LAZY_WHILE_FLAG = 2; + + /** Used as the `TypeError` message for "Functions" methods. */ + var FUNC_ERROR_TEXT = 'Expected a function'; + + /** Used as the internal argument placeholder. */ + var PLACEHOLDER = '__lodash_placeholder__'; + + /** `Object#toString` result references. */ + var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + mapTag = '[object Map]', + numberTag = '[object Number]', + objectTag = '[object Object]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + weakMapTag = '[object WeakMap]'; + + var arrayBufferTag = '[object ArrayBuffer]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + + /** Used to match empty string literals in compiled template source. */ var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + /** Used to match HTML entities and HTML characters. */ + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, + reUnescapedHtml = /[&<>"'`]/g, + reHasEscapedHtml = RegExp(reEscapedHtml.source), + reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + + /** Used to match template delimiters. */ + var reEscape = /<%-([\s\S]+?)%>/g, + reEvaluate = /<%([\s\S]+?)%>/g, + reInterpolate = /<%=([\s\S]+?)%>/g; + /** - * Used to match ES6 template delimiters - * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals + * Used to match ES template delimiters. + * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components) + * for more details. */ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; - /** Used to match regexp flags from their coerced string values */ + /** Used to match `RegExp` flags from their coerced string values. */ var reFlags = /\w*$/; - /** Used to detected named functions */ + /** Used to detect named functions. */ var reFuncName = /^\s*function[ \n\r\t]+\w/; - /** Used to match "interpolate" template delimiters */ - var reInterpolate = /<%=([\s\S]+?)%>/g; + /** Used to detect hexadecimal string values. */ + var reHexPrefix = /^0[xX]/; + + /** Used to detect host constructors (Safari > 5). */ + var reHostCtor = /^\[object .+?Constructor\]$/; - /** Used to match leading whitespace and zeros to be removed */ - var reLeadingSpacesAndZeros = RegExp('^[' + whitespace + ']*0+(?=.$)'); + /** Used to match latin-1 supplementary letters (excluding mathematical operators). */ + var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; - /** Used to ensure capturing order of template delimiters */ + /** Used to ensure capturing order of template delimiters. */ var reNoMatch = /($^)/; - /** Used to detect functions containing a `this` reference */ + /** + * Used to match `RegExp` special characters. + * See this [article on `RegExp` characters](http://www.regular-expressions.info/characters.html#special) + * for more details. + */ + var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g, + reHasRegExpChars = RegExp(reRegExpChars.source); + + /** Used to detect functions containing a `this` reference. */ var reThis = /\bthis\b/; - /** Used to match unescaped characters in compiled string literals */ - var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g; + /** Used to match unescaped characters in compiled string literals. */ + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + + /** Used to match words to create compound words. */ + var reWords = (function() { + var upper = '[A-Z\\xc0-\\xd6\\xd8-\\xde]', + lower = '[a-z\\xdf-\\xf6\\xf8-\\xff]+'; + + return RegExp(upper + '{2,}(?=' + upper + lower + ')|' + upper + '?' + lower + '|' + upper + '+|[0-9]+', 'g'); + }()); + + /** Used to detect and test for whitespace. */ + var whitespace = ( + // Basic whitespace characters. + ' \t\x0b\f\xa0\ufeff' + + + // Line terminators. + '\n\r\u2028\u2029' + - /** Used to assign default `context` object properties */ + // Unicode category "Zs" space separators. + '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000' + ); + + /** Used to assign default `context` object properties. */ var contextProps = [ - 'Array', 'Boolean', 'Date', 'Function', 'Math', 'Number', 'Object', - 'RegExp', 'String', '_', 'attachEvent', 'clearTimeout', 'isFinite', 'isNaN', - 'parseInt', 'setTimeout' + 'Array', 'ArrayBuffer', 'Date', 'Error', 'Float32Array', 'Float64Array', + 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number', + 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document', + 'isFinite', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array', + 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', + 'window', 'WinRTError' ]; - /** Used to make template sourceURLs easier to identify */ - var templateCounter = 0; - - /** `Object#toString` result shortcuts */ - var argsClass = '[object Arguments]', - arrayClass = '[object Array]', - boolClass = '[object Boolean]', - dateClass = '[object Date]', - funcClass = '[object Function]', - numberClass = '[object Number]', - objectClass = '[object Object]', - regexpClass = '[object RegExp]', - stringClass = '[object String]'; - - /** Used to identify object classifications that `_.clone` supports */ - var cloneableClasses = {}; - cloneableClasses[funcClass] = false; - cloneableClasses[argsClass] = cloneableClasses[arrayClass] = - cloneableClasses[boolClass] = cloneableClasses[dateClass] = - cloneableClasses[numberClass] = cloneableClasses[objectClass] = - cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true; - - /** Used as an internal `_.debounce` options object */ + /** Used to make template sourceURLs easier to identify. */ + var templateCounter = -1; + + /** Used to identify `toStringTag` values of typed arrays. */ + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = + typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = + typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = + typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = + typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = + typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = + typedArrayTags[dateTag] = typedArrayTags[errorTag] = + typedArrayTags[funcTag] = typedArrayTags[mapTag] = + typedArrayTags[numberTag] = typedArrayTags[objectTag] = + typedArrayTags[regexpTag] = typedArrayTags[setTag] = + typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; + + /** Used to identify `toStringTag` values supported by `_.clone`. */ + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = + cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = + cloneableTags[dateTag] = cloneableTags[float32Tag] = + cloneableTags[float64Tag] = cloneableTags[int8Tag] = + cloneableTags[int16Tag] = cloneableTags[int32Tag] = + cloneableTags[numberTag] = cloneableTags[objectTag] = + cloneableTags[regexpTag] = cloneableTags[stringTag] = + cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = + cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = + cloneableTags[mapTag] = cloneableTags[setTag] = + cloneableTags[weakMapTag] = false; + + /** Used as an internal `_.debounce` options object by `_.throttle`. */ var debounceOptions = { 'leading': false, 'maxWait': 0, 'trailing': false }; - /** Used as the property descriptor for `__bindData__` */ - var descriptor = { - 'configurable': false, - 'enumerable': false, - 'value': null, - 'writable': false + /** Used to map latin-1 supplementary letters to basic latin letters. */ + var deburredLetters = { + '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', + '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', + '\xc7': 'C', '\xe7': 'c', + '\xd0': 'D', '\xf0': 'd', + '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', + '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', + '\xcC': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', + '\xeC': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', + '\xd1': 'N', '\xf1': 'n', + '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', + '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', + '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U', + '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u', + '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', + '\xc6': 'Ae', '\xe6': 'ae', + '\xde': 'Th', '\xfe': 'th', + '\xdf': 'ss' + }; + + /** Used to map characters to HTML entities. */ + var htmlEscapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '`': '`' + }; + + /** Used to map HTML entities to characters. */ + var htmlUnescapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + ''': "'", + '`': '`' }; - /** Used to determine if values are of the language type Object */ + /** Used to determine if values are of the language type `Object`. */ var objectTypes = { - 'boolean': false, 'function': true, - 'object': true, - 'number': false, - 'string': false, - 'undefined': false + 'object': true }; - /** Used to escape characters for inclusion in compiled string literals */ + /** Used to escape characters for inclusion in compiled string literals. */ var stringEscapes = { '\\': '\\', "'": "'", '\n': 'n', '\r': 'r', - '\t': 't', '\u2028': 'u2028', '\u2029': 'u2029' }; - /** Used as a reference to the global object */ - var root = (objectTypes[typeof window] && window) || this; + /** + * Used as a reference to the global object. + * + * The `this` value is used if it is the global object to avoid Greasemonkey's + * restricted `window` object, otherwise the `window` object is used. + */ + var root = (objectTypes[typeof window] && window !== (this && this.window)) ? window : this; - /** Detect free variable `exports` */ + /** Detect free variable `exports`. */ var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; - /** Detect free variable `module` */ + /** Detect free variable `module`. */ var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; - /** Detect the popular CommonJS extension `module.exports` */ - var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; - - /** Detect free variable `global` from Node.js or Browserified code and use it as `root` */ - var freeGlobal = objectTypes[typeof global] && global; - if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) { + /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */ + var freeGlobal = freeExports && freeModule && typeof global == 'object' && global; + if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) { root = freeGlobal; } + /** Detect the popular CommonJS extension `module.exports`. */ + var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; + /*--------------------------------------------------------------------------*/ /** - * The base implementation of `_.indexOf` without support for binary searches - * or `fromIndex` constraints. + * The base implementation of `compareAscending` which compares values and + * sorts them in ascending order without guaranteeing a stable sort. + * + * @private + * @param {*} value The value to compare to `other`. + * @param {*} other The value to compare to `value`. + * @returns {number} Returns the sort order indicator for `value`. + */ + function baseCompareAscending(value, other) { + if (value !== other) { + var valIsReflexive = value === value, + othIsReflexive = other === other; + + if (value > other || !valIsReflexive || (typeof value == 'undefined' && othIsReflexive)) { + return 1; + } + if (value < other || !othIsReflexive || (typeof other == 'undefined' && valIsReflexive)) { + return -1; + } + } + return 0; + } + + /** + * The base implementation of `_.indexOf` without support for binary searches. * * @private * @param {Array} array The array to search. * @param {*} value The value to search for. * @param {number} [fromIndex=0] The index to search from. - * @returns {number} Returns the index of the matched value or `-1`. + * @returns {number} Returns the index of the matched value, else `-1`. */ function baseIndexOf(array, value, fromIndex) { + if (value !== value) { + return indexOfNaN(array, fromIndex); + } var index = (fromIndex || 0) - 1, - length = array ? array.length : 0; + length = array.length; while (++index < length) { if (array[index] === value) { @@ -34642,266 +32693,365 @@ return jQuery; } /** - * An implementation of `_.contains` for cache objects that mimics the return - * signature of `_.indexOf` by returning `0` if the value is found, else `-1`. + * The base implementation of `_.isFunction` without support for environments + * with incorrect `typeof` results. * * @private - * @param {Object} cache The cache object to inspect. - * @param {*} value The value to search for. - * @returns {number} Returns `0` if `value` is found, else `-1`. + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. */ - function cacheIndexOf(cache, value) { - var type = typeof value; - cache = cache.cache; + function baseIsFunction(value) { + // Avoid a Chakra JIT bug in compatibility modes of IE 11. + // See https://github.com/jashkenas/underscore/issues/1621 for more details. + return typeof value == 'function' || false; + } - if (type == 'boolean' || value == null) { - return cache[value] ? 0 : -1; + /** + * The base implementation of `_.sortBy` and `_.sortByAll` which uses `comparer` + * to define the sort order of `array` and replaces criteria objects with their + * corresponding values. + * + * @private + * @param {Array} array The array to sort. + * @param {Function} comparer The function to define sort order. + * @returns {Array} Returns `array`. + */ + function baseSortBy(array, comparer) { + var length = array.length; + + array.sort(comparer); + while (length--) { + array[length] = array[length].value; } - if (type != 'number' && type != 'string') { - type = 'object'; + return array; + } + + /** + * Converts `value` to a string if it is not one. An empty string is returned + * for `null` or `undefined` values. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ + function baseToString(value) { + if (typeof value == 'string') { + return value; } - var key = type == 'number' ? value : keyPrefix + value; - cache = (cache = cache[type]) && cache[key]; + return value == null ? '' : (value + ''); + } - return type == 'object' - ? (cache && baseIndexOf(cache, value) > -1 ? 0 : -1) - : (cache ? 0 : -1); + /** + * Used by `_.max` and `_.min` as the default callback for string values. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the code unit of the first character of the string. + */ + function charAtCallback(string) { + return string.charCodeAt(0); } /** - * Adds a given value to the corresponding cache object. + * Used by `_.trim` and `_.trimLeft` to get the index of the first character + * of `string` that is not found in `chars`. * * @private - * @param {*} value The value to add to the cache. + * @param {string} string The string to inspect. + * @param {string} chars The characters to find. + * @returns {number} Returns the index of the first character not found in `chars`. */ - function cachePush(value) { - var cache = this.cache, - type = typeof value; + function charsLeftIndex(string, chars) { + var index = -1, + length = string.length; - if (type == 'boolean' || value == null) { - cache[value] = true; - } else { - if (type != 'number' && type != 'string') { - type = 'object'; - } - var key = type == 'number' ? value : keyPrefix + value, - typeCache = cache[type] || (cache[type] = {}); + while (++index < length && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } - if (type == 'object') { - (typeCache[key] || (typeCache[key] = [])).push(value); - } else { - typeCache[key] = true; - } - } + /** + * Used by `_.trim` and `_.trimRight` to get the index of the last character + * of `string` that is not found in `chars`. + * + * @private + * @param {string} string The string to inspect. + * @param {string} chars The characters to find. + * @returns {number} Returns the index of the last character not found in `chars`. + */ + function charsRightIndex(string, chars) { + var index = string.length; + + while (index-- && chars.indexOf(string.charAt(index)) > -1) {} + return index; } /** - * Used by `_.max` and `_.min` as the default callback when a given - * collection is a string value. + * Used by `_.sortBy` to compare transformed elements of a collection and stable + * sort them in ascending order. * * @private - * @param {string} value The character to inspect. - * @returns {number} Returns the code unit of given character. + * @param {Object} object The object to compare to `other`. + * @param {Object} other The object to compare to `object`. + * @returns {number} Returns the sort order indicator for `object`. */ - function charAtCallback(value) { - return value.charCodeAt(0); + function compareAscending(object, other) { + return baseCompareAscending(object.criteria, other.criteria) || (object.index - other.index); } /** - * Used by `sortBy` to compare transformed `collection` elements, stable sorting - * them in ascending order. + * Used by `_.sortByAll` to compare multiple properties of each element + * in a collection and stable sort them in ascending order. * * @private - * @param {Object} a The object to compare to `b`. - * @param {Object} b The object to compare to `a`. - * @returns {number} Returns the sort order indicator of `1` or `-1`. + * @param {Object} object The object to compare to `other`. + * @param {Object} other The object to compare to `object`. + * @returns {number} Returns the sort order indicator for `object`. */ - function compareAscending(a, b) { - var ac = a.criteria, - bc = b.criteria, - index = -1, - length = ac.length; + function compareMultipleAscending(object, other) { + var index = -1, + objCriteria = object.criteria, + othCriteria = other.criteria, + length = objCriteria.length; while (++index < length) { - var value = ac[index], - other = bc[index]; - - if (value !== other) { - if (value > other || typeof value == 'undefined') { - return 1; - } - if (value < other || typeof other == 'undefined') { - return -1; - } + var result = baseCompareAscending(objCriteria[index], othCriteria[index]); + if (result) { + return result; } } // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications - // that causes it, under certain circumstances, to return the same value for - // `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247 + // that causes it, under certain circumstances, to provide the same value for + // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247 + // for more details. // // This also ensures a stable sort in V8 and other engines. - // See http://code.google.com/p/v8/issues/detail?id=90 - return a.index - b.index; + // See https://code.google.com/p/v8/issues/detail?id=90 for more details. + return object.index - other.index; } /** - * Creates a cache object to optimize linear searches of large arrays. + * Used by `_.deburr` to convert latin-1 supplementary letters to basic latin letters. * * @private - * @param {Array} [array=[]] The array to search. - * @returns {null|Object} Returns the cache object or `null` if caching should not be used. + * @param {string} letter The matched letter to deburr. + * @returns {string} Returns the deburred letter. */ - function createCache(array) { - var index = -1, - length = array.length, - first = array[0], - mid = array[(length / 2) | 0], - last = array[length - 1]; - - if (first && typeof first == 'object' && - mid && typeof mid == 'object' && last && typeof last == 'object') { - return false; - } - var cache = getObject(); - cache['false'] = cache['null'] = cache['true'] = cache['undefined'] = false; - - var result = getObject(); - result.array = array; - result.cache = cache; - result.push = cachePush; + function deburrLetter(letter) { + return deburredLetters[letter]; + } - while (++index < length) { - result.push(array[index]); - } - return result; + /** + * Used by `_.escape` to convert characters to HTML entities. + * + * @private + * @param {string} chr The matched character to escape. + * @returns {string} Returns the escaped character. + */ + function escapeHtmlChar(chr) { + return htmlEscapes[chr]; } /** - * Used by `template` to escape characters for inclusion in compiled + * Used by `_.template` to escape characters for inclusion in compiled * string literals. * * @private - * @param {string} match The matched character to escape. + * @param {string} chr The matched character to escape. * @returns {string} Returns the escaped character. */ - function escapeStringChar(match) { - return '\\' + stringEscapes[match]; + function escapeStringChar(chr) { + return '\\' + stringEscapes[chr]; } /** - * Gets an array from the array pool or creates a new one if the pool is empty. + * Gets the index at which the first occurrence of `NaN` is found in `array`. + * If `fromRight` is provided elements of `array` are iterated from right to left. * * @private - * @returns {Array} The array from the pool. + * @param {Array} array The array to search. + * @param {number} [fromIndex] The index to search from. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched `NaN`, else `-1`. */ - function getArray() { - return arrayPool.pop() || []; + function indexOfNaN(array, fromIndex, fromRight) { + var length = array.length, + index = fromRight ? (fromIndex || length) : ((fromIndex || 0) - 1); + + while ((fromRight ? index-- : ++index < length)) { + var other = array[index]; + if (other !== other) { + return index; + } + } + return -1; } /** - * Gets an object from the object pool or creates a new one if the pool is empty. + * Checks if `value` is object-like. * * @private - * @returns {Object} The object from the pool. - */ - function getObject() { - return objectPool.pop() || { - 'array': null, - 'cache': null, - 'criteria': null, - 'false': false, - 'index': 0, - 'null': false, - 'number': null, - 'object': null, - 'push': null, - 'string': null, - 'true': false, - 'undefined': false, - 'value': null - }; + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + */ + function isObjectLike(value) { + return (value && typeof value == 'object') || false; } /** - * Releases the given array back to the array pool. + * Used by `trimmedLeftIndex` and `trimmedRightIndex` to determine if a + * character code is whitespace. * * @private - * @param {Array} [array] The array to release. + * @param {number} charCode The character code to inspect. + * @returns {boolean} Returns `true` if `charCode` is whitespace, else `false`. */ - function releaseArray(array) { - array.length = 0; - if (arrayPool.length < maxPoolSize) { - arrayPool.push(array); - } + function isSpace(charCode) { + return ((charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160) || charCode == 5760 || charCode == 6158 || + (charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279))); } /** - * Releases the given object back to the object pool. + * Replaces all `placeholder` elements in `array` with an internal placeholder + * and returns an array of their indexes. * * @private - * @param {Object} [object] The object to release. + * @param {Array} array The array to modify. + * @param {*} placeholder The placeholder to replace. + * @returns {Array} Returns the new array of placeholder indexes. */ - function releaseObject(object) { - var cache = object.cache; - if (cache) { - releaseObject(cache); - } - object.array = object.cache = object.criteria = object.object = object.number = object.string = object.value = null; - if (objectPool.length < maxPoolSize) { - objectPool.push(object); + function replaceHolders(array, placeholder) { + var index = -1, + length = array.length, + resIndex = -1, + result = []; + + while (++index < length) { + if (array[index] === placeholder) { + array[index] = PLACEHOLDER; + result[++resIndex] = index; + } } + return result; } /** - * Slices the `collection` from the `start` index up to, but not including, - * the `end` index. - * - * Note: This function is used instead of `Array#slice` to support node lists - * in IE < 9 and to ensure dense arrays are returned. + * An implementation of `_.uniq` optimized for sorted arrays without support + * for callback shorthands and `this` binding. * * @private - * @param {Array|Object|string} collection The collection to slice. - * @param {number} start The start index. - * @param {number} end The end index. - * @returns {Array} Returns the new array. + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The function invoked per iteration. + * @returns {Array} Returns the new duplicate-value-free array. */ - function slice(array, start, end) { - start || (start = 0); - if (typeof end == 'undefined') { - end = array ? array.length : 0; - } - var index = -1, - length = end - start || 0, - result = Array(length < 0 ? 0 : length); + function sortedUniq(array, iteratee) { + var seen, + index = -1, + length = array.length, + resIndex = -1, + result = []; while (++index < length) { - result[index] = array[start + index]; + var value = array[index], + computed = iteratee ? iteratee(value, index, array) : value; + + if (!index || seen !== computed) { + seen = computed; + result[++resIndex] = value; + } } return result; } + /** + * Used by `_.trim` and `_.trimLeft` to get the index of the first non-whitespace + * character of `string`. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the index of the first non-whitespace character. + */ + function trimmedLeftIndex(string) { + var index = -1, + length = string.length; + + while (++index < length && isSpace(string.charCodeAt(index))) {} + return index; + } + + /** + * Used by `_.trim` and `_.trimRight` to get the index of the last non-whitespace + * character of `string`. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the index of the last non-whitespace character. + */ + function trimmedRightIndex(string) { + var index = string.length; + + while (index-- && isSpace(string.charCodeAt(index))) {} + return index; + } + + /** + * Used by `_.unescape` to convert HTML entities to characters. + * + * @private + * @param {string} chr The matched character to unescape. + * @returns {string} Returns the unescaped character. + */ + function unescapeHtmlChar(chr) { + return htmlUnescapes[chr]; + } + /*--------------------------------------------------------------------------*/ /** - * Create a new `lodash` function using the given context object. + * Create a new pristine `lodash` function using the given `context` object. * * @static * @memberOf _ - * @category Utilities + * @category Utility * @param {Object} [context=root] The context object. - * @returns {Function} Returns the `lodash` function. + * @returns {Function} Returns a new `lodash` function. + * @example + * + * _.mixin({ 'add': function(a, b) { return a + b; } }); + * + * var lodash = _.runInContext(); + * lodash.mixin({ 'sub': function(a, b) { return a - b; } }); + * + * _.isFunction(_.add); + * // => true + * _.isFunction(_.sub); + * // => false + * + * lodash.isFunction(lodash.add); + * // => false + * lodash.isFunction(lodash.sub); + * // => true + * + * // using `context` to mock `Date#getTime` use in `_.now` + * var mock = _.runInContext({ + * 'Date': function() { + * return { 'getTime': getTimeMock }; + * } + * }); + * + * // or creating a suped-up `defer` in Node.js + * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer; */ function runInContext(context) { // Avoid issues with some ES3 environments that attempt to use values, named // after built-in constructors like `Object`, for the creation of literals. // ES5 clears this up by stating that literals must use built-in constructors. - // See http://es5.github.io/#x11.1.5. + // See https://es5.github.io/#x11.1.5 for more details. context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; - /** Native constructor references */ + /** Native constructor references. */ var Array = context.Array, - Boolean = context.Boolean, Date = context.Date, + Error = context.Error, Function = context.Function, Math = context.Math, Number = context.Number, @@ -34910,134 +33060,184 @@ return jQuery; String = context.String, TypeError = context.TypeError; + /** Used for native method references. */ + var arrayProto = Array.prototype, + objectProto = Object.prototype; + + /** Used to detect DOM support. */ + var document = (document = context.window) && document.document; + + /** Used to resolve the decompiled source of functions. */ + var fnToString = Function.prototype.toString; + + /** Used to the length of n-tuples for `_.unzip`. */ + var getLength = baseProperty('length'); + + /** Used to check objects for own properties. */ + var hasOwnProperty = objectProto.hasOwnProperty; + + /** Used to generate unique IDs. */ + var idCounter = 0; + /** - * Used for `Array` method references. - * - * Normally `Array.prototype` would suffice, however, using an array literal - * avoids issues in Narwhal. + * Used to resolve the `toStringTag` of values. + * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring) + * for more details. */ - var arrayRef = []; + var objToString = objectProto.toString; - /** Used for native method references */ - var objectProto = Object.prototype; - - /** Used to restore the original `_` reference in `noConflict` */ + /** Used to restore the original `_` reference in `_.noConflict`. */ var oldDash = context._; - /** Used to resolve the internal [[Class]] of values */ - var toString = objectProto.toString; - - /** Used to detect if a method is native */ + /** Used to detect if a method is native. */ var reNative = RegExp('^' + - String(toString) - .replace(/[.*+?^${}()|[\]\\]/g, '\\$&') - .replace(/toString| for [^\]]+/g, '.*?') + '$' + escapeRegExp(objToString) + .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' ); - /** Native method shortcuts */ - var ceil = Math.ceil, + /** Native method references. */ + var ArrayBuffer = isNative(ArrayBuffer = context.ArrayBuffer) && ArrayBuffer, + bufferSlice = isNative(bufferSlice = ArrayBuffer && new ArrayBuffer(0).slice) && bufferSlice, + ceil = Math.ceil, clearTimeout = context.clearTimeout, floor = Math.floor, - fnToString = Function.prototype.toString, getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf, - hasOwnProperty = objectProto.hasOwnProperty, - push = arrayRef.push, + push = arrayProto.push, + propertyIsEnumerable = objectProto.propertyIsEnumerable, + Set = isNative(Set = context.Set) && Set, setTimeout = context.setTimeout, - splice = arrayRef.splice, - unshift = arrayRef.unshift; - - /** Used to set meta data on functions */ - var defineProperty = (function() { - // IE 8 only accepts DOM elements + splice = arrayProto.splice, + Uint8Array = isNative(Uint8Array = context.Uint8Array) && Uint8Array, + WeakMap = isNative(WeakMap = context.WeakMap) && WeakMap; + + /** Used to clone array buffers. */ + var Float64Array = (function() { + // Safari 5 errors when using an array buffer to initialize a typed array + // where the array buffer's `byteLength` is not a multiple of the typed + // array's `BYTES_PER_ELEMENT`. try { - var o = {}, - func = isNative(func = Object.defineProperty) && func, - result = func(o, o, o) && func; - } catch(e) { } + var func = isNative(func = context.Float64Array) && func, + result = new func(new ArrayBuffer(10), 0, 1) && func; + } catch(e) {} return result; }()); - /* Native method shortcuts for methods with the same name as other `lodash` methods */ - var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate, - nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray, + /* Native method references for those with the same name as other `lodash` methods. */ + var nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray, + nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate, nativeIsFinite = context.isFinite, - nativeIsNaN = context.isNaN, nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys, nativeMax = Math.max, nativeMin = Math.min, + nativeNow = isNative(nativeNow = Date.now) && nativeNow, + nativeNumIsFinite = isNative(nativeNumIsFinite = Number.isFinite) && nativeNumIsFinite, nativeParseInt = context.parseInt, nativeRandom = Math.random; - /** Used to lookup a built-in constructor by [[Class]] */ - var ctorByClass = {}; - ctorByClass[arrayClass] = Array; - ctorByClass[boolClass] = Boolean; - ctorByClass[dateClass] = Date; - ctorByClass[funcClass] = Function; - ctorByClass[objectClass] = Object; - ctorByClass[numberClass] = Number; - ctorByClass[regexpClass] = RegExp; - ctorByClass[stringClass] = String; + /** Used as references for `-Infinity` and `Infinity`. */ + var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY, + POSITIVE_INFINITY = Number.POSITIVE_INFINITY; + + /** Used as references for the maximum length and index of an array. */ + var MAX_ARRAY_LENGTH = Math.pow(2, 32) - 1, + MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, + HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; - /*--------------------------------------------------------------------------*/ + /** Used as the size, in bytes, of each `Float64Array` element. */ + var FLOAT64_BYTES_PER_ELEMENT = Float64Array ? Float64Array.BYTES_PER_ELEMENT : 0; /** - * Creates a `lodash` object which wraps the given value to enable intuitive - * method chaining. - * - * In addition to Lo-Dash methods, wrappers also have the following `Array` methods: + * Used as the maximum length of an array-like value. + * See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer) + * for more details. + */ + var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1; + + /** Used to store function metadata. */ + var metaMap = WeakMap && new WeakMap; + + /*------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` object which wraps `value` to enable implicit chaining. + * Methods that operate on and return arrays, collections, and functions can + * be chained together. Methods that return a boolean or single value will + * automatically end the chain returning the unwrapped value. Explicit chaining + * may be enabled using `_.chain`. The execution of chained methods is lazy, + * that is, execution is deferred until `_#value` is implicitly or explicitly + * called. + * + * Lazy evaluation allows several methods to support shortcut fusion. Shortcut + * fusion is an optimization that merges iteratees to avoid creating intermediate + * arrays and reduce the number of iteratee executions. + * + * Chaining is supported in custom builds as long as the `_#value` method is + * directly or indirectly included in the build. + * + * In addition to lodash methods, wrappers also have the following `Array` methods: * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`, * and `unshift` * - * Chaining is supported in custom builds as long as the `value` method is - * implicitly or explicitly included in the build. - * - * The chainable wrapper functions are: - * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, - * `compose`, `concat`, `countBy`, `create`, `createCallback`, `curry`, - * `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`, - * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, - * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, - * `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`, - * `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `pull`, `push`, - * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, - * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`, - * `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`, - * and `zip` - * - * The non-chainable wrapper functions are: - * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`, - * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `has`, `identity`, - * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, - * `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`, - * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`, - * `lastIndexOf`, `mixin`, `noConflict`, `parseInt`, `pop`, `random`, `reduce`, - * `reduceRight`, `result`, `shift`, `size`, `some`, `sortedIndex`, `runInContext`, - * `template`, `unescape`, `uniqueId`, and `value` - * - * The wrapper functions `first` and `last` return wrapped values when `n` is - * provided, otherwise they return unwrapped values. - * - * Explicit chaining can be enabled by using the `_.chain` method. + * The wrapper methods that support shortcut fusion are: + * `compact`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, + * `first`, `initial`, `last`, `map`, `pluck`, `reject`, `rest`, `reverse`, + * `slice`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `toArray`, + * and `where` + * + * The chainable wrapper methods are: + * `after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`, + * `callback`, `chain`, `chunk`, `commit`, `compact`, `concat`, `constant`, + * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`, + * `difference`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `fill`, + * `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`, `forEach`, + * `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `functions`, + * `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, `invoke`, `keys`, + * `keysIn`, `map`, `mapValues`, `matches`, `matchesProperty`, `memoize`, `merge`, + * `mixin`, `negate`, `noop`, `omit`, `once`, `pairs`, `partial`, `partialRight`, + * `partition`, `pick`, `plant`, `pluck`, `property`, `propertyOf`, `pull`, + * `pullAt`, `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `reverse`, + * `shuffle`, `slice`, `sort`, `sortBy`, `sortByAll`, `splice`, `spread`, + * `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `tap`, `throttle`, + * `thru`, `times`, `toArray`, `toPlainObject`, `transform`, `union`, `uniq`, + * `unshift`, `unzip`, `values`, `valuesIn`, `where`, `without`, `wrap`, `xor`, + * `zip`, and `zipObject` + * + * The wrapper methods that are **not** chainable by default are: + * `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `deburr`, + * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, + * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `has`, + * `identity`, `includes`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, + * `isDate`, `isElement`, `isEmpty`, `isEqual`, `isError`, `isFinite`, + * `isFunction`, `isMatch`, `isNative`, `isNaN`, `isNull`, `isNumber`, + * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, + * `isTypedArray`, `join`, `kebabCase`, `last`, `lastIndexOf`, `max`, `min`, + * `noConflict`, `now`, `pad`, `padLeft`, `padRight`, `parseInt`, `pop`, + * `random`, `reduce`, `reduceRight`, `repeat`, `result`, `runInContext`, + * `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, + * `startCase`, `startsWith`, `template`, `trim`, `trimLeft`, `trimRight`, + * `trunc`, `unescape`, `uniqueId`, `value`, and `words` + * + * The wrapper method `sample` will return a wrapped value when `n` is provided, + * otherwise an unwrapped value is returned. * * @name _ * @constructor - * @category Chaining + * @category Chain * @param {*} value The value to wrap in a `lodash` instance. - * @returns {Object} Returns a `lodash` instance. + * @returns {Object} Returns the new `lodash` wrapper instance. * @example * * var wrapped = _([1, 2, 3]); * * // returns an unwrapped value - * wrapped.reduce(function(sum, num) { - * return sum + num; + * wrapped.reduce(function(sum, n) { + * return sum + n; * }); * // => 6 * * // returns a wrapped value - * var squares = wrapped.map(function(num) { - * return num * num; + * var squares = wrapped.map(function(n) { + * return n * n; * }); * * _.isArray(squares); @@ -35047,29 +33247,42 @@ return jQuery; * // => true */ function lodash(value) { - // don't wrap if already wrapped, even if wrapped by a different `lodash` constructor - return (value && typeof value == 'object' && !isArray(value) && hasOwnProperty.call(value, '__wrapped__')) - ? value - : new lodashWrapper(value); + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, '__chain__') && hasOwnProperty.call(value, '__wrapped__')) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); } /** - * A fast path for creating `lodash` wrapper objects. + * The function whose prototype all chaining wrappers inherit from. * * @private - * @param {*} value The value to wrap in a `lodash` instance. - * @param {boolean} chainAll A flag to enable chaining for all methods - * @returns {Object} Returns a `lodash` instance. */ - function lodashWrapper(value, chainAll) { - this.__chain__ = !!chainAll; + function baseLodash() { + // No operation performed. + } + + /** + * The base constructor for creating `lodash` wrapper objects. + * + * @private + * @param {*} value The value to wrap. + * @param {boolean} [chainAll] Enable chaining for all wrapper methods. + * @param {Array} [actions=[]] Actions to peform to resolve the unwrapped value. + */ + function LodashWrapper(value, chainAll, actions) { this.__wrapped__ = value; + this.__actions__ = actions || []; + this.__chain__ = !!chainAll; } - // ensure `new lodashWrapper` is an instance of `lodash` - lodashWrapper.prototype = lodash.prototype; /** - * An object used to flag environments features. + * An object environment feature flags. * * @static * @memberOf _ @@ -35077,27 +33290,61 @@ return jQuery; */ var support = lodash.support = {}; - /** - * Detect if functions can be decompiled by `Function#toString` - * (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps). - * - * @memberOf _.support - * @type boolean - */ - support.funcDecomp = !isNative(context.WinRTError) && reThis.test(runInContext); + (function(x) { - /** - * Detect if `Function#name` is supported (all but IE). - * - * @memberOf _.support - * @type boolean - */ - support.funcNames = typeof Function.name == 'string'; + /** + * Detect if functions can be decompiled by `Function#toString` + * (all but Firefox OS certified apps, older Opera mobile browsers, and + * the PlayStation 3; forced `false` for Windows 8 apps). + * + * @memberOf _.support + * @type boolean + */ + support.funcDecomp = !isNative(context.WinRTError) && reThis.test(runInContext); + + /** + * Detect if `Function#name` is supported (all but IE). + * + * @memberOf _.support + * @type boolean + */ + support.funcNames = typeof Function.name == 'string'; + + /** + * Detect if the DOM is supported. + * + * @memberOf _.support + * @type boolean + */ + try { + support.dom = document.createDocumentFragment().nodeType === 11; + } catch(e) { + support.dom = false; + } + + /** + * Detect if `arguments` object indexes are non-enumerable. + * + * In Firefox < 4, IE < 9, PhantomJS, and Safari < 5.1 `arguments` object + * indexes are non-enumerable. Chrome < 25 and Node.js < 0.11.0 treat + * `arguments` object indexes as non-enumerable and fail `hasOwnProperty` + * checks for indexes that exceed their function's formal parameters with + * associated values of `0`. + * + * @memberOf _.support + * @type boolean + */ + try { + support.nonEnumArgs = !propertyIsEnumerable.call(arguments, 1); + } catch(e) { + support.nonEnumArgs = true; + } + }(0, 0)); /** - * By default, the template delimiters used by Lo-Dash are similar to those in - * embedded Ruby (ERB). Change the following template settings to use alternative - * delimiters. + * By default, the template delimiters used by lodash are like those in + * embedded Ruby (ERB). Change the following template settings to use + * alternative delimiters. * * @static * @memberOf _ @@ -35111,7 +33358,7 @@ return jQuery; * @memberOf _.templateSettings * @type RegExp */ - 'escape': /<%-([\s\S]+?)%>/g, + 'escape': reEscape, /** * Used to detect code to be evaluated. @@ -35119,7 +33366,7 @@ return jQuery; * @memberOf _.templateSettings * @type RegExp */ - 'evaluate': /<%([\s\S]+?)%>/g, + 'evaluate': reEvaluate, /** * Used to detect `data` property values to inject. @@ -35155,5065 +33402,9513 @@ return jQuery; } }; - /*--------------------------------------------------------------------------*/ + /*------------------------------------------------------------------------*/ /** - * The base implementation of `_.bind` that creates the bound function and - * sets its meta data. + * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation. * * @private - * @param {Array} bindData The bind data array. - * @returns {Function} Returns the new bound function. + * @param {*} value The value to wrap. */ - function baseBind(bindData) { - var func = bindData[0], - partialArgs = bindData[2], - thisArg = bindData[4]; - - function bound() { - // `Function#bind` spec - // http://es5.github.io/#x15.3.4.5 - if (partialArgs) { - // avoid `arguments` object deoptimizations by using `slice` instead - // of `Array.prototype.slice.call` and not assigning `arguments` to a - // variable as a ternary expression - var args = slice(partialArgs); - push.apply(args, arguments); - } - // mimic the constructor's `return` behavior - // http://es5.github.io/#x13.2.2 - if (this instanceof bound) { - // ensure `new bound` is an instance of `func` - var thisBinding = baseCreate(func.prototype), - result = func.apply(thisBinding, args || arguments); - return isObject(result) ? result : thisBinding; - } - return func.apply(thisArg, args || arguments); - } - setBindData(bound, bindData); - return bound; + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = null; + this.__dir__ = 1; + this.__dropCount__ = 0; + this.__filtered__ = false; + this.__iteratees__ = null; + this.__takeCount__ = POSITIVE_INFINITY; + this.__views__ = null; } /** - * The base implementation of `_.clone` without argument juggling or support - * for `thisArg` binding. + * Creates a clone of the lazy wrapper object. * * @private - * @param {*} value The value to clone. - * @param {boolean} [isDeep=false] Specify a deep clone. - * @param {Function} [callback] The function to customize cloning values. - * @param {Array} [stackA=[]] Tracks traversed source objects. - * @param {Array} [stackB=[]] Associates clones with source counterparts. - * @returns {*} Returns the cloned value. + * @name clone + * @memberOf LazyWrapper + * @returns {Object} Returns the cloned `LazyWrapper` object. */ - function baseClone(value, isDeep, callback, stackA, stackB) { - if (callback) { - var result = callback(value); - if (typeof result != 'undefined') { - return result; - } - } - // inspect [[Class]] - var isObj = isObject(value); - if (isObj) { - var className = toString.call(value); - if (!cloneableClasses[className]) { - return value; - } - var ctor = ctorByClass[className]; - switch (className) { - case boolClass: - case dateClass: - return new ctor(+value); - - case numberClass: - case stringClass: - return new ctor(value); - - case regexpClass: - result = ctor(value.source, reFlags.exec(value)); - result.lastIndex = value.lastIndex; - return result; - } + function lazyClone() { + var actions = this.__actions__, + iteratees = this.__iteratees__, + views = this.__views__, + result = new LazyWrapper(this.__wrapped__); + + result.__actions__ = actions ? arrayCopy(actions) : null; + result.__dir__ = this.__dir__; + result.__dropCount__ = this.__dropCount__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = iteratees ? arrayCopy(iteratees) : null; + result.__takeCount__ = this.__takeCount__; + result.__views__ = views ? arrayCopy(views) : null; + return result; + } + + /** + * Reverses the direction of lazy iteration. + * + * @private + * @name reverse + * @memberOf LazyWrapper + * @returns {Object} Returns the new reversed `LazyWrapper` object. + */ + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; } else { - return value; + result = this.clone(); + result.__dir__ *= -1; } - var isArr = isArray(value); - if (isDeep) { - // check for circular references and return corresponding clone - var initedStack = !stackA; - stackA || (stackA = getArray()); - stackB || (stackB = getArray()); + return result; + } - var length = stackA.length; - while (length--) { - if (stackA[length] == value) { - return stackB[length]; + /** + * Extracts the unwrapped value from its lazy wrapper. + * + * @private + * @name value + * @memberOf LazyWrapper + * @returns {*} Returns the unwrapped value. + */ + function lazyValue() { + var array = this.__wrapped__.value(); + if (!isArray(array)) { + return baseWrapperValue(array, this.__actions__); + } + var dir = this.__dir__, + isRight = dir < 0, + view = getView(0, array.length, this.__views__), + start = view.start, + end = view.end, + length = end - start, + dropCount = this.__dropCount__, + takeCount = nativeMin(length, this.__takeCount__), + index = isRight ? end : start - 1, + iteratees = this.__iteratees__, + iterLength = iteratees ? iteratees.length : 0, + resIndex = 0, + result = []; + + outer: + while (length-- && resIndex < takeCount) { + index += dir; + + var iterIndex = -1, + value = array[index]; + + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], + iteratee = data.iteratee, + computed = iteratee(value, index, array), + type = data.type; + + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } } } - result = isArr ? ctor(value.length) : {}; - } - else { - result = isArr ? slice(value) : assign({}, value); - } - // add array properties assigned by `RegExp#exec` - if (isArr) { - if (hasOwnProperty.call(value, 'index')) { - result.index = value.index; - } - if (hasOwnProperty.call(value, 'input')) { - result.input = value.input; + if (dropCount) { + dropCount--; + } else { + result[resIndex++] = value; } } - // exit for shallow clone - if (!isDeep) { - return result; - } - // add the source value to the stack of traversed objects - // and associate it with its clone - stackA.push(value); - stackB.push(result); + return result; + } - // recursively populate clone (susceptible to call stack limits) - (isArr ? forEach : forOwn)(value, function(objValue, key) { - result[key] = baseClone(objValue, isDeep, callback, stackA, stackB); - }); + /*------------------------------------------------------------------------*/ - if (initedStack) { - releaseArray(stackA); - releaseArray(stackB); - } - return result; + /** + * Creates a cache object to store key/value pairs. + * + * @private + * @static + * @name Cache + * @memberOf _.memoize + */ + function MapCache() { + this.__data__ = {}; } /** - * The base implementation of `_.create` without support for assigning - * properties to the created object. + * Removes `key` and its value from the cache. * * @private - * @param {Object} prototype The object to inherit from. - * @returns {Object} Returns the new object. + * @name delete + * @memberOf _.memoize.Cache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed successfully, else `false`. */ - function baseCreate(prototype, properties) { - return isObject(prototype) ? nativeCreate(prototype) : {}; - } - // fallback for browsers without `Object.create` - if (!nativeCreate) { - baseCreate = (function() { - function Object() {} - return function(prototype) { - if (isObject(prototype)) { - Object.prototype = prototype; - var result = new Object; - Object.prototype = null; - } - return result || context.Object(); - }; - }()); + function mapDelete(key) { + return this.has(key) && delete this.__data__[key]; } /** - * The base implementation of `_.createCallback` without support for creating - * "_.pluck" or "_.where" style callbacks. + * Gets the cached value for `key`. * * @private - * @param {*} [func=identity] The value to convert to a callback. - * @param {*} [thisArg] The `this` binding of the created callback. - * @param {number} [argCount] The number of arguments the callback accepts. - * @returns {Function} Returns a callback function. + * @name get + * @memberOf _.memoize.Cache + * @param {string} key The key of the value to get. + * @returns {*} Returns the cached value. */ - function baseCreateCallback(func, thisArg, argCount) { - if (typeof func != 'function') { - return identity; - } - // exit early for no `thisArg` or already bound by `Function#bind` - if (typeof thisArg == 'undefined' || !('prototype' in func)) { - return func; - } - var bindData = func.__bindData__; - if (typeof bindData == 'undefined') { - if (support.funcNames) { - bindData = !func.name; - } - bindData = bindData || !support.funcDecomp; - if (!bindData) { - var source = fnToString.call(func); - if (!support.funcNames) { - bindData = !reFuncName.test(source); - } - if (!bindData) { - // checks if `func` references the `this` keyword and stores the result - bindData = reThis.test(source); - setBindData(func, bindData); - } - } - } - // exit early if there are no `this` references or `func` is bound - if (bindData === false || (bindData !== true && bindData[1] & 1)) { - return func; + function mapGet(key) { + return key == '__proto__' ? undefined : this.__data__[key]; + } + + /** + * Checks if a cached value for `key` exists. + * + * @private + * @name has + * @memberOf _.memoize.Cache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ + function mapHas(key) { + return key != '__proto__' && hasOwnProperty.call(this.__data__, key); + } + + /** + * Adds `value` to `key` of the cache. + * + * @private + * @name set + * @memberOf _.memoize.Cache + * @param {string} key The key of the value to cache. + * @param {*} value The value to cache. + * @returns {Object} Returns the cache object. + */ + function mapSet(key, value) { + if (key != '__proto__') { + this.__data__[key] = value; } - switch (argCount) { - case 1: return function(value) { - return func.call(thisArg, value); - }; - case 2: return function(a, b) { - return func.call(thisArg, a, b); - }; - case 3: return function(value, index, collection) { - return func.call(thisArg, value, index, collection); - }; - case 4: return function(accumulator, value, index, collection) { - return func.call(thisArg, accumulator, value, index, collection); - }; + return this; + } + + /*------------------------------------------------------------------------*/ + + /** + * + * Creates a cache object to store unique values. + * + * @private + * @param {Array} [values] The values to cache. + */ + function SetCache(values) { + var length = values ? values.length : 0; + + this.data = { 'hash': nativeCreate(null), 'set': new Set }; + while (length--) { + this.push(values[length]); } - return bind(func, thisArg); } /** - * The base implementation of `createWrapper` that creates the wrapper and - * sets its meta data. + * Checks if `value` is in `cache` mimicking the return signature of + * `_.indexOf` by returning `0` if the value is found, else `-1`. * * @private - * @param {Array} bindData The bind data array. - * @returns {Function} Returns the new function. + * @param {Object} cache The cache to search. + * @param {*} value The value to search for. + * @returns {number} Returns `0` if `value` is found, else `-1`. */ - function baseCreateWrapper(bindData) { - var func = bindData[0], - bitmask = bindData[1], - partialArgs = bindData[2], - partialRightArgs = bindData[3], - thisArg = bindData[4], - arity = bindData[5]; - - var isBind = bitmask & 1, - isBindKey = bitmask & 2, - isCurry = bitmask & 4, - isCurryBound = bitmask & 8, - key = func; + function cacheIndexOf(cache, value) { + var data = cache.data, + result = (typeof value == 'string' || isObject(value)) ? data.set.has(value) : data.hash[value]; - function bound() { - var thisBinding = isBind ? thisArg : this; - if (partialArgs) { - var args = slice(partialArgs); - push.apply(args, arguments); - } - if (partialRightArgs || isCurry) { - args || (args = slice(arguments)); - if (partialRightArgs) { - push.apply(args, partialRightArgs); - } - if (isCurry && args.length < arity) { - bitmask |= 16 & ~32; - return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]); - } - } - args || (args = arguments); - if (isBindKey) { - func = thisBinding[key]; - } - if (this instanceof bound) { - thisBinding = baseCreate(func.prototype); - var result = func.apply(thisBinding, args); - return isObject(result) ? result : thisBinding; - } - return func.apply(thisBinding, args); + return result ? 0 : -1; + } + + /** + * Adds `value` to the cache. + * + * @private + * @name push + * @memberOf SetCache + * @param {*} value The value to cache. + */ + function cachePush(value) { + var data = this.data; + if (typeof value == 'string' || isObject(value)) { + data.set.add(value); + } else { + data.hash[value] = true; } - setBindData(bound, bindData); - return bound; } + /*------------------------------------------------------------------------*/ + /** - * The base implementation of `_.difference` that accepts a single array - * of values to exclude. + * Copies the values of `source` to `array`. * * @private - * @param {Array} array The array to process. - * @param {Array} [values] The array of values to exclude. - * @returns {Array} Returns a new array of filtered values. + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. */ - function baseDifference(array, values) { + function arrayCopy(source, array) { var index = -1, - indexOf = getIndexOf(), - length = array ? array.length : 0, - isLarge = length >= largeArraySize && indexOf === baseIndexOf, - result = []; + length = source.length; - if (isLarge) { - var cache = createCache(values); - if (cache) { - indexOf = cacheIndexOf; - values = cache; - } else { - isLarge = false; - } - } + array || (array = Array(length)); while (++index < length) { - var value = array[index]; - if (indexOf(values, value) < 0) { - result.push(value); - } + array[index] = source[index]; } - if (isLarge) { - releaseObject(values); - } - return result; + return array; } /** - * The base implementation of `_.flatten` without support for callback - * shorthands or `thisArg` binding. + * A specialized version of `_.forEach` for arrays without support for callback + * shorthands or `this` binding. * * @private - * @param {Array} array The array to flatten. - * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level. - * @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects. - * @param {number} [fromIndex=0] The index to start from. - * @returns {Array} Returns a new flattened array. + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. */ - function baseFlatten(array, isShallow, isStrict, fromIndex) { - var index = (fromIndex || 0) - 1, - length = array ? array.length : 0, - result = []; + function arrayEach(array, iteratee) { + var index = -1, + length = array.length; while (++index < length) { - var value = array[index]; - - if (value && typeof value == 'object' && typeof value.length == 'number' - && (isArray(value) || isArguments(value))) { - // recursively flatten arrays (susceptible to call stack limits) - if (!isShallow) { - value = baseFlatten(value, isShallow, isStrict); - } - var valIndex = -1, - valLength = value.length, - resIndex = result.length; - - result.length += valLength; - while (++valIndex < valLength) { - result[resIndex++] = value[valIndex]; - } - } else if (!isStrict) { - result.push(value); + if (iteratee(array[index], index, array) === false) { + break; } } - return result; + return array; } /** - * The base implementation of `_.isEqual`, without support for `thisArg` binding, - * that allows partial "_.where" style comparisons. + * A specialized version of `_.forEachRight` for arrays without support for + * callback shorthands or `this` binding. * * @private - * @param {*} a The value to compare. - * @param {*} b The other value to compare. - * @param {Function} [callback] The function to customize comparing values. - * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons. - * @param {Array} [stackA=[]] Tracks traversed `a` objects. - * @param {Array} [stackB=[]] Tracks traversed `b` objects. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. */ - function baseIsEqual(a, b, callback, isWhere, stackA, stackB) { - // used to indicate that when comparing objects, `a` has at least the properties of `b` - if (callback) { - var result = callback(a, b); - if (typeof result != 'undefined') { - return !!result; + function arrayEachRight(array, iteratee) { + var length = array.length; + + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; } } - // exit early for identical values - if (a === b) { - // treat `+0` vs. `-0` as not equal - return a !== 0 || (1 / a == 1 / b); - } - var type = typeof a, - otherType = typeof b; + return array; + } - // exit early for unlike primitive values - if (a === a && - !(a && objectTypes[type]) && - !(b && objectTypes[otherType])) { - return false; - } - // exit early for `null` and `undefined` avoiding ES3's Function#call behavior - // http://es5.github.io/#x15.3.4.4 - if (a == null || b == null) { - return a === b; - } - // compare [[Class]] names - var className = toString.call(a), - otherClass = toString.call(b); + /** + * A specialized version of `_.every` for arrays without support for callback + * shorthands or `this` binding. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + */ + function arrayEvery(array, predicate) { + var index = -1, + length = array.length; - if (className == argsClass) { - className = objectClass; - } - if (otherClass == argsClass) { - otherClass = objectClass; - } - if (className != otherClass) { - return false; - } - switch (className) { - case boolClass: - case dateClass: - // coerce dates and booleans to numbers, dates to milliseconds and booleans - // to `1` or `0` treating invalid dates coerced to `NaN` as not equal - return +a == +b; - - case numberClass: - // treat `NaN` vs. `NaN` as equal - return (a != +a) - ? b != +b - // but treat `+0` vs. `-0` as not equal - : (a == 0 ? (1 / a == 1 / b) : a == +b); - - case regexpClass: - case stringClass: - // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) - // treat string primitives and their corresponding object instances as equal - return a == String(b); - } - var isArr = className == arrayClass; - if (!isArr) { - // unwrap any `lodash` wrapped values - var aWrapped = hasOwnProperty.call(a, '__wrapped__'), - bWrapped = hasOwnProperty.call(b, '__wrapped__'); - - if (aWrapped || bWrapped) { - return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB); - } - // exit for functions and DOM nodes - if (className != objectClass) { - return false; - } - // in older versions of Opera, `arguments` objects have `Array` constructors - var ctorA = a.constructor, - ctorB = b.constructor; - - // non `Object` object instances with different constructors are not equal - if (ctorA != ctorB && - !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) && - ('constructor' in a && 'constructor' in b) - ) { + while (++index < length) { + if (!predicate(array[index], index, array)) { return false; } } - // assume cyclic structures are equal - // the algorithm for detecting cyclic structures is adapted from ES 5.1 - // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3) - var initedStack = !stackA; - stackA || (stackA = getArray()); - stackB || (stackB = getArray()); - - var length = stackA.length; - while (length--) { - if (stackA[length] == a) { - return stackB[length] == b; - } - } - var size = 0; - result = true; + return true; + } - // add `a` and `b` to the stack of traversed objects - stackA.push(a); - stackB.push(b); + /** + * A specialized version of `_.filter` for arrays without support for callback + * shorthands or `this` binding. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function arrayFilter(array, predicate) { + var index = -1, + length = array.length, + resIndex = -1, + result = []; - // recursively compare objects and arrays (susceptible to call stack limits) - if (isArr) { - // compare lengths to determine if a deep comparison is necessary - length = a.length; - size = b.length; - result = size == length; - - if (result || isWhere) { - // deep compare the contents, ignoring non-numeric properties - while (size--) { - var index = length, - value = b[size]; - - if (isWhere) { - while (index--) { - if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) { - break; - } - } - } else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) { - break; - } - } + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[++resIndex] = value; } } - else { - // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys` - // which, in this case, is more costly - forIn(b, function(value, key, b) { - if (hasOwnProperty.call(b, key)) { - // count the number of properties. - size++; - // deep compare each property value. - return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB)); - } - }); + return result; + } - if (result && !isWhere) { - // ensure both objects have the same number of properties - forIn(a, function(value, key, a) { - if (hasOwnProperty.call(a, key)) { - // `size` will be `-1` if `a` has more properties than `b` - return (result = --size > -1); - } - }); - } - } - stackA.pop(); - stackB.pop(); + /** + * A specialized version of `_.map` for arrays without support for callback + * shorthands or `this` binding. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function arrayMap(array, iteratee) { + var index = -1, + length = array.length, + result = Array(length); - if (initedStack) { - releaseArray(stackA); - releaseArray(stackB); + while (++index < length) { + result[index] = iteratee(array[index], index, array); } return result; } /** - * The base implementation of `_.merge` without argument juggling or support - * for `thisArg` binding. + * A specialized version of `_.max` for arrays without support for iteratees. * * @private - * @param {Object} object The destination object. - * @param {Object} source The source object. - * @param {Function} [callback] The function to customize merging properties. - * @param {Array} [stackA=[]] Tracks traversed source objects. - * @param {Array} [stackB=[]] Associates values with source counterparts. + * @param {Array} array The array to iterate over. + * @returns {*} Returns the maximum value. */ - function baseMerge(object, source, callback, stackA, stackB) { - (isArray(source) ? forEach : forOwn)(source, function(source, key) { - var found, - isArr, - result = source, - value = object[key]; - - if (source && ((isArr = isArray(source)) || isPlainObject(source))) { - // avoid merging previously merged cyclic sources - var stackLength = stackA.length; - while (stackLength--) { - if ((found = stackA[stackLength] == source)) { - value = stackB[stackLength]; - break; - } - } - if (!found) { - var isShallow; - if (callback) { - result = callback(value, source); - if ((isShallow = typeof result != 'undefined')) { - value = result; - } - } - if (!isShallow) { - value = isArr - ? (isArray(value) ? value : []) - : (isPlainObject(value) ? value : {}); - } - // add `source` and associated `value` to the stack of traversed objects - stackA.push(source); - stackB.push(value); + function arrayMax(array) { + var index = -1, + length = array.length, + result = NEGATIVE_INFINITY; - // recursively merge objects and arrays (susceptible to call stack limits) - if (!isShallow) { - baseMerge(value, source, callback, stackA, stackB); - } - } - } - else { - if (callback) { - result = callback(value, source); - if (typeof result == 'undefined') { - result = source; - } - } - if (typeof result != 'undefined') { - value = result; - } + while (++index < length) { + var value = array[index]; + if (value > result) { + result = value; } - object[key] = value; - }); + } + return result; } /** - * The base implementation of `_.random` without argument juggling or support - * for returning floating-point numbers. + * A specialized version of `_.min` for arrays without support for iteratees. * * @private - * @param {number} min The minimum possible value. - * @param {number} max The maximum possible value. - * @returns {number} Returns a random number. + * @param {Array} array The array to iterate over. + * @returns {*} Returns the minimum value. */ - function baseRandom(min, max) { - return min + floor(nativeRandom() * (max - min + 1)); + function arrayMin(array) { + var index = -1, + length = array.length, + result = POSITIVE_INFINITY; + + while (++index < length) { + var value = array[index]; + if (value < result) { + result = value; + } + } + return result; } /** - * The base implementation of `_.uniq` without support for callback shorthands - * or `thisArg` binding. + * A specialized version of `_.reduce` for arrays without support for callback + * shorthands or `this` binding. * * @private - * @param {Array} array The array to process. - * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. - * @param {Function} [callback] The function called per iteration. - * @returns {Array} Returns a duplicate-value-free array. + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initFromArray] Specify using the first element of `array` + * as the initial value. + * @returns {*} Returns the accumulated value. */ - function baseUniq(array, isSorted, callback) { + function arrayReduce(array, iteratee, accumulator, initFromArray) { var index = -1, - indexOf = getIndexOf(), - length = array ? array.length : 0, - result = []; - - var isLarge = !isSorted && length >= largeArraySize && indexOf === baseIndexOf, - seen = (callback || isLarge) ? getArray() : result; + length = array.length; - if (isLarge) { - var cache = createCache(seen); - indexOf = cacheIndexOf; - seen = cache; + if (initFromArray && length) { + accumulator = array[++index]; } while (++index < length) { - var value = array[index], - computed = callback ? callback(value, index, array) : value; - - if (isSorted - ? !index || seen[seen.length - 1] !== computed - : indexOf(seen, computed) < 0 - ) { - if (callback || isLarge) { - seen.push(computed); - } - result.push(value); - } + accumulator = iteratee(accumulator, array[index], index, array); } - if (isLarge) { - releaseArray(seen.array); - releaseObject(seen); - } else if (callback) { - releaseArray(seen); - } - return result; + return accumulator; } /** - * Creates a function that aggregates a collection, creating an object composed - * of keys generated from the results of running each element of the collection - * through a callback. The given `setter` function sets the keys and values - * of the composed object. + * A specialized version of `_.reduceRight` for arrays without support for + * callback shorthands or `this` binding. * * @private - * @param {Function} setter The setter function. - * @returns {Function} Returns the new aggregator function. + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {boolean} [initFromArray] Specify using the last element of `array` + * as the initial value. + * @returns {*} Returns the accumulated value. */ - function createAggregator(setter) { - return function(collection, callback, thisArg) { - var result = {}; - callback = lodash.createCallback(callback, thisArg, 3); - - var index = -1, - length = collection ? collection.length : 0; - - if (typeof length == 'number') { - while (++index < length) { - var value = collection[index]; - setter(result, value, callback(value, index, collection), collection); - } - } else { - forOwn(collection, function(value, key, collection) { - setter(result, value, callback(value, key, collection), collection); - }); - } - return result; - }; + function arrayReduceRight(array, iteratee, accumulator, initFromArray) { + var length = array.length; + if (initFromArray && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; } /** - * Creates a function that, when called, either curries or invokes `func` - * with an optional `this` binding and partially applied arguments. + * A specialized version of `_.some` for arrays without support for callback + * shorthands or `this` binding. * * @private - * @param {Function|string} func The function or method name to reference. - * @param {number} bitmask The bitmask of method flags to compose. - * The bitmask may be composed of the following flags: - * 1 - `_.bind` - * 2 - `_.bindKey` - * 4 - `_.curry` - * 8 - `_.curry` (bound) - * 16 - `_.partial` - * 32 - `_.partialRight` - * @param {Array} [partialArgs] An array of arguments to prepend to those - * provided to the new function. - * @param {Array} [partialRightArgs] An array of arguments to append to those - * provided to the new function. - * @param {*} [thisArg] The `this` binding of `func`. - * @param {number} [arity] The arity of `func`. - * @returns {Function} Returns the new function. + * @param {Array} array The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. */ - function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) { - var isBind = bitmask & 1, - isBindKey = bitmask & 2, - isCurry = bitmask & 4, - isCurryBound = bitmask & 8, - isPartial = bitmask & 16, - isPartialRight = bitmask & 32; - - if (!isBindKey && !isFunction(func)) { - throw new TypeError; - } - if (isPartial && !partialArgs.length) { - bitmask &= ~16; - isPartial = partialArgs = false; - } - if (isPartialRight && !partialRightArgs.length) { - bitmask &= ~32; - isPartialRight = partialRightArgs = false; - } - var bindData = func && func.__bindData__; - if (bindData && bindData !== true) { - // clone `bindData` - bindData = slice(bindData); - if (bindData[2]) { - bindData[2] = slice(bindData[2]); - } - if (bindData[3]) { - bindData[3] = slice(bindData[3]); - } - // set `thisBinding` is not previously bound - if (isBind && !(bindData[1] & 1)) { - bindData[4] = thisArg; - } - // set if previously bound but not currently (subsequent curried functions) - if (!isBind && bindData[1] & 1) { - bitmask |= 8; - } - // set curried arity if not yet set - if (isCurry && !(bindData[1] & 4)) { - bindData[5] = arity; - } - // append partial left arguments - if (isPartial) { - push.apply(bindData[2] || (bindData[2] = []), partialArgs); - } - // append partial right arguments - if (isPartialRight) { - unshift.apply(bindData[3] || (bindData[3] = []), partialRightArgs); + function arraySome(array, predicate) { + var index = -1, + length = array.length; + + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; } - // merge flags - bindData[1] |= bitmask; - return createWrapper.apply(null, bindData); } - // fast path for `_.bind` - var creater = (bitmask == 1 || bitmask === 17) ? baseBind : baseCreateWrapper; - return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]); + return false; } /** - * Used by `escape` to convert characters to HTML entities. + * Used by `_.defaults` to customize its `_.assign` use. * * @private - * @param {string} match The matched character to escape. - * @returns {string} Returns the escaped character. + * @param {*} objectValue The destination object property value. + * @param {*} sourceValue The source object property value. + * @returns {*} Returns the value to assign to the destination object. */ - function escapeHtmlChar(match) { - return htmlEscapes[match]; + function assignDefaults(objectValue, sourceValue) { + return typeof objectValue == 'undefined' ? sourceValue : objectValue; } /** - * Gets the appropriate "indexOf" function. If the `_.indexOf` method is - * customized, this method returns the custom method, otherwise it returns - * the `baseIndexOf` function. + * Used by `_.template` to customize its `_.assign` use. + * + * **Note:** This method is like `assignDefaults` except that it ignores + * inherited property values when checking if a property is `undefined`. * * @private - * @returns {Function} Returns the "indexOf" function. + * @param {*} objectValue The destination object property value. + * @param {*} sourceValue The source object property value. + * @param {string} key The key associated with the object and source values. + * @param {Object} object The destination object. + * @returns {*} Returns the value to assign to the destination object. */ - function getIndexOf() { - var result = (result = lodash.indexOf) === indexOf ? baseIndexOf : result; - return result; + function assignOwnDefaults(objectValue, sourceValue, key, object) { + return (typeof objectValue == 'undefined' || !hasOwnProperty.call(object, key)) + ? sourceValue + : objectValue; } /** - * Checks if `value` is a native function. + * The base implementation of `_.assign` without support for argument juggling, + * multiple sources, and `this` binding `customizer` functions. * * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a native function, else `false`. + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {Function} [customizer] The function to customize assigning values. + * @returns {Object} Returns the destination object. */ - function isNative(value) { - return typeof value == 'function' && reNative.test(value); + function baseAssign(object, source, customizer) { + var props = keys(source); + if (!customizer) { + return baseCopy(source, object, props); + } + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index], + value = object[key], + result = customizer(value, source[key], key, object, source); + + if ((result === result ? result !== value : value === value) || + (typeof value == 'undefined' && !(key in object))) { + object[key] = result; + } + } + return object; } /** - * Sets `this` binding data on a given function. + * The base implementation of `_.at` without support for strings and individual + * key arguments. * * @private - * @param {Function} func The function to set data on. - * @param {Array} value The data array to set. + * @param {Array|Object} collection The collection to iterate over. + * @param {number[]|string[]} [props] The property names or indexes of elements to pick. + * @returns {Array} Returns the new array of picked elements. */ - var setBindData = !defineProperty ? noop : function(func, value) { - descriptor.value = value; - defineProperty(func, '__bindData__', descriptor); - }; + function baseAt(collection, props) { + var index = -1, + length = collection.length, + isArr = isLength(length), + propsLength = props.length, + result = Array(propsLength); + + while(++index < propsLength) { + var key = props[index]; + if (isArr) { + key = parseFloat(key); + result[index] = isIndex(key, length) ? collection[key] : undefined; + } else { + result[index] = collection[key]; + } + } + return result; + } /** - * A fallback implementation of `isPlainObject` which checks if a given value - * is an object created by the `Object` constructor, assuming objects created - * by the `Object` constructor have no inherited enumerable properties and that - * there are no `Object.prototype` extensions. + * Copies the properties of `source` to `object`. * * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @param {Object} source The object to copy properties from. + * @param {Object} [object={}] The object to copy properties to. + * @param {Array} props The property names to copy. + * @returns {Object} Returns `object`. */ - function shimIsPlainObject(value) { - var ctor, - result; + function baseCopy(source, object, props) { + if (!props) { + props = object; + object = {}; + } + var index = -1, + length = props.length; - // avoid non Object objects, `arguments` objects, and DOM elements - if (!(value && toString.call(value) == objectClass) || - (ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor))) { - return false; + while (++index < length) { + var key = props[index]; + object[key] = source[key]; } - // In most environments an object's own properties are iterated before - // its inherited properties. If the last iterated property is an object's - // own property then there are no inherited enumerable properties. - forIn(value, function(value, key) { - result = key; - }); - return typeof result == 'undefined' || hasOwnProperty.call(value, result); + return object; } /** - * Used by `unescape` to convert HTML entities to characters. + * The base implementation of `_.bindAll` without support for individual + * method name arguments. * * @private - * @param {string} match The matched character to unescape. - * @returns {string} Returns the unescaped character. + * @param {Object} object The object to bind and assign the bound methods to. + * @param {string[]} methodNames The object method names to bind. + * @returns {Object} Returns `object`. */ - function unescapeHtmlChar(match) { - return htmlUnescapes[match]; - } + function baseBindAll(object, methodNames) { + var index = -1, + length = methodNames.length; - /*--------------------------------------------------------------------------*/ + while (++index < length) { + var key = methodNames[index]; + object[key] = createWrapper(object[key], BIND_FLAG, object); + } + return object; + } /** - * Checks if `value` is an `arguments` object. - * - * @static - * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`. - * @example + * The base implementation of `_.callback` which supports specifying the + * number of arguments to provide to `func`. * - * (function() { return _.isArguments(arguments); })(1, 2, 3); - * // => true - * - * _.isArguments([1, 2, 3]); - * // => false + * @private + * @param {*} [func=_.identity] The value to convert to a callback. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {number} [argCount] The number of arguments to provide to `func`. + * @returns {Function} Returns the callback. */ - function isArguments(value) { - return value && typeof value == 'object' && typeof value.length == 'number' && - toString.call(value) == argsClass || false; + function baseCallback(func, thisArg, argCount) { + var type = typeof func; + if (type == 'function') { + return (typeof thisArg != 'undefined' && isBindable(func)) + ? bindCallback(func, thisArg, argCount) + : func; + } + if (func == null) { + return identity; + } + if (type == 'object') { + return baseMatches(func); + } + return typeof thisArg == 'undefined' + ? baseProperty(func + '') + : baseMatchesProperty(func + '', thisArg); } /** - * Checks if `value` is an array. - * - * @static - * @memberOf _ - * @type Function - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is an array, else `false`. - * @example - * - * (function() { return _.isArray(arguments); })(); - * // => false + * The base implementation of `_.clone` without support for argument juggling + * and `this` binding `customizer` functions. * - * _.isArray([1, 2, 3]); - * // => true + * @private + * @param {*} value The value to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @param {Function} [customizer] The function to customize cloning values. + * @param {string} [key] The key of `value`. + * @param {Object} [object] The object `value` belongs to. + * @param {Array} [stackA=[]] Tracks traversed source objects. + * @param {Array} [stackB=[]] Associates clones with source counterparts. + * @returns {*} Returns the cloned value. */ - var isArray = nativeIsArray || function(value) { - return value && typeof value == 'object' && typeof value.length == 'number' && - toString.call(value) == arrayClass || false; - }; + function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { + var result; + if (customizer) { + result = object ? customizer(value, key, object) : customizer(value); + } + if (typeof result != 'undefined') { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return arrayCopy(value, result); + } + } else { + var tag = objToString.call(value), + isFunc = tag == funcTag; + + if (tag == objectTag || tag == argsTag || (isFunc && !object)) { + result = initCloneObject(isFunc ? {} : value); + if (!isDeep) { + return baseCopy(value, result, keys(value)); + } + } else { + return cloneableTags[tag] + ? initCloneByTag(value, tag, isDeep) + : (object ? value : {}); + } + } + // Check for circular references and return corresponding clone. + stackA || (stackA = []); + stackB || (stackB = []); + + var length = stackA.length; + while (length--) { + if (stackA[length] == value) { + return stackB[length]; + } + } + // Add the source value to the stack of traversed objects and associate it with its clone. + stackA.push(value); + stackB.push(result); + + // Recursively populate clone (susceptible to call stack limits). + (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) { + result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB); + }); + return result; + } /** - * A fallback implementation of `Object.keys` which produces an array of the - * given object's own enumerable property names. + * The base implementation of `_.create` without support for assigning + * properties to the created object. * * @private - * @type Function - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property names. - */ - var shimKeys = function(object) { - var index, iterable = object, result = []; - if (!iterable) return result; - if (!(objectTypes[typeof object])) return result; - for (index in iterable) { - if (hasOwnProperty.call(iterable, index)) { - result.push(index); - } + * @param {Object} prototype The object to inherit from. + * @returns {Object} Returns the new object. + */ + var baseCreate = (function() { + function Object() {} + return function(prototype) { + if (isObject(prototype)) { + Object.prototype = prototype; + var result = new Object; + Object.prototype = null; } - return result - }; + return result || context.Object(); + }; + }()); /** - * Creates an array composed of the own enumerable property names of an object. - * - * @static - * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property names. - * @example + * The base implementation of `_.delay` and `_.defer` which accepts an index + * of where to slice the arguments to provide to `func`. * - * _.keys({ 'one': 1, 'two': 2, 'three': 3 }); - * // => ['one', 'two', 'three'] (property order is not guaranteed across environments) + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {Object} args The `arguments` object to slice and provide to `func`. + * @returns {number} Returns the timer id. */ - var keys = !nativeKeys ? shimKeys : function(object) { - if (!isObject(object)) { - return []; + function baseDelay(func, wait, args, fromIndex) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); } - return nativeKeys(object); - }; + return setTimeout(function() { func.apply(undefined, baseSlice(args, fromIndex)); }, wait); + } /** - * Used to convert characters to HTML entities: + * The base implementation of `_.difference` which accepts a single array + * of values to exclude. * - * Though the `>` character is escaped for symmetry, characters like `>` and `/` - * don't require escaping in HTML and have no special meaning unless they're part - * of a tag or an unquoted attribute value. - * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact") + * @private + * @param {Array} array The array to inspect. + * @param {Array} values The values to exclude. + * @returns {Array} Returns the new array of filtered values. */ - var htmlEscapes = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''' - }; + function baseDifference(array, values) { + var length = array ? array.length : 0, + result = []; - /** Used to convert HTML entities to characters */ - var htmlUnescapes = invert(htmlEscapes); + if (!length) { + return result; + } + var index = -1, + indexOf = getIndexOf(), + isCommon = indexOf == baseIndexOf, + cache = (isCommon && values.length >= 200) ? createCache(values) : null, + valuesLength = values.length; - /** Used to match HTML entities and HTML characters */ - var reEscapedHtml = RegExp('(' + keys(htmlUnescapes).join('|') + ')', 'g'), - reUnescapedHtml = RegExp('[' + keys(htmlEscapes).join('') + ']', 'g'); + if (cache) { + indexOf = cacheIndexOf; + isCommon = false; + values = cache; + } + outer: + while (++index < length) { + var value = array[index]; - /*--------------------------------------------------------------------------*/ + if (isCommon && value === value) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === value) { + continue outer; + } + } + result.push(value); + } + else if (indexOf(values, value) < 0) { + result.push(value); + } + } + return result; + } /** - * Assigns own enumerable properties of source object(s) to the destination - * object. Subsequent sources will overwrite property assignments of previous - * sources. If a callback is provided it will be executed to produce the - * assigned values. The callback is bound to `thisArg` and invoked with two - * arguments; (objectValue, sourceValue). - * - * @static - * @memberOf _ - * @type Function - * @alias extend - * @category Objects - * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. - * @param {Function} [callback] The function to customize assigning values. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns the destination object. - * @example + * The base implementation of `_.forEach` without support for callback + * shorthands and `this` binding. * - * _.assign({ 'name': 'fred' }, { 'employer': 'slate' }); - * // => { 'name': 'fred', 'employer': 'slate' } - * - * var defaults = _.partialRight(_.assign, function(a, b) { - * return typeof a == 'undefined' ? b : a; - * }); - * - * var object = { 'name': 'barney' }; - * defaults(object, { 'name': 'fred', 'employer': 'slate' }); - * // => { 'name': 'barney', 'employer': 'slate' } - */ - var assign = function(object, source, guard) { - var index, iterable = object, result = iterable; - if (!iterable) return result; - var args = arguments, - argsIndex = 0, - argsLength = typeof guard == 'number' ? 2 : args.length; - if (argsLength > 3 && typeof args[argsLength - 2] == 'function') { - var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2); - } else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') { - callback = args[--argsLength]; + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object|string} Returns `collection`. + */ + function baseEach(collection, iteratee) { + var length = collection ? collection.length : 0; + if (!isLength(length)) { + return baseForOwn(collection, iteratee); } - while (++argsIndex < argsLength) { - iterable = args[argsIndex]; - if (iterable && objectTypes[typeof iterable]) { - var ownIndex = -1, - ownProps = objectTypes[typeof iterable] && keys(iterable), - length = ownProps ? ownProps.length : 0; - - while (++ownIndex < length) { - index = ownProps[ownIndex]; - result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]; - } + var index = -1, + iterable = toObject(collection); + + while (++index < length) { + if (iteratee(iterable[index], index, iterable) === false) { + break; } } - return result - }; + return collection; + } /** - * Creates a clone of `value`. If `isDeep` is `true` nested objects will also - * be cloned, otherwise they will be assigned by reference. If a callback - * is provided it will be executed to produce the cloned values. If the - * callback returns `undefined` cloning will be handled by the method instead. - * The callback is bound to `thisArg` and invoked with one argument; (value). - * - * @static - * @memberOf _ - * @category Objects - * @param {*} value The value to clone. - * @param {boolean} [isDeep=false] Specify a deep clone. - * @param {Function} [callback] The function to customize cloning values. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the cloned value. - * @example + * The base implementation of `_.forEachRight` without support for callback + * shorthands and `this` binding. * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } - * ]; + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object|string} Returns `collection`. + */ + function baseEachRight(collection, iteratee) { + var length = collection ? collection.length : 0; + if (!isLength(length)) { + return baseForOwnRight(collection, iteratee); + } + var iterable = toObject(collection); + while (length--) { + if (iteratee(iterable[length], length, iterable) === false) { + break; + } + } + return collection; + } + + /** + * The base implementation of `_.every` without support for callback + * shorthands or `this` binding. + * + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false` + */ + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + + /** + * The base implementation of `_.fill` without an iteratee call guard. + * + * @private + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + */ + function baseFill(array, value, start, end) { + var length = array.length; + + start = start == null ? 0 : (+start || 0); + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = (typeof end == 'undefined' || end > length) ? length : (+end || 0); + if (end < 0) { + end += length; + } + length = start > end ? 0 : end >>> 0; + start >>>= 0; + + while (start < length) { + array[start++] = value; + } + return array; + } + + /** + * The base implementation of `_.filter` without support for callback + * shorthands or `this` binding. + * + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + + /** + * The base implementation of `_.find`, `_.findLast`, `_.findKey`, and `_.findLastKey`, + * without support for callback shorthands and `this` binding, which iterates + * over `collection` using the provided `eachFunc`. + * + * @private + * @param {Array|Object|string} collection The collection to search. + * @param {Function} predicate The function invoked per iteration. + * @param {Function} eachFunc The function to iterate over `collection`. + * @param {boolean} [retKey] Specify returning the key of the found element + * instead of the element itself. + * @returns {*} Returns the found element or its key, else `undefined`. + */ + function baseFind(collection, predicate, eachFunc, retKey) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = retKey ? key : value; + return false; + } + }); + return result; + } + + /** + * The base implementation of `_.flatten` with added support for restricting + * flattening and specifying the start index. + * + * @private + * @param {Array} array The array to flatten. + * @param {boolean} [isDeep] Specify a deep flatten. + * @param {boolean} [isStrict] Restrict flattening to arrays and `arguments` objects. + * @param {number} [fromIndex=0] The index to start from. + * @returns {Array} Returns the new flattened array. + */ + function baseFlatten(array, isDeep, isStrict, fromIndex) { + var index = (fromIndex || 0) - 1, + length = array.length, + resIndex = -1, + result = []; + + while (++index < length) { + var value = array[index]; + + if (isObjectLike(value) && isLength(value.length) && (isArray(value) || isArguments(value))) { + if (isDeep) { + // Recursively flatten arrays (susceptible to call stack limits). + value = baseFlatten(value, isDeep, isStrict); + } + var valIndex = -1, + valLength = value.length; + + result.length += valLength; + while (++valIndex < valLength) { + result[++resIndex] = value[valIndex]; + } + } else if (!isStrict) { + result[++resIndex] = value; + } + } + return result; + } + + /** + * The base implementation of `baseForIn` and `baseForOwn` which iterates + * over `object` properties returned by `keysFunc` invoking `iteratee` for + * each property. Iterator functions may exit iteration early by explicitly + * returning `false`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + function baseFor(object, iteratee, keysFunc) { + var index = -1, + iterable = toObject(object), + props = keysFunc(object), + length = props.length; + + while (++index < length) { + var key = props[index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + } + + /** + * This function is like `baseFor` except that it iterates over properties + * in the opposite order. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ + function baseForRight(object, iteratee, keysFunc) { + var iterable = toObject(object), + props = keysFunc(object), + length = props.length; + + while (length--) { + var key = props[length]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + } + + /** + * The base implementation of `_.forIn` without support for callback + * shorthands and `this` binding. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForIn(object, iteratee) { + return baseFor(object, iteratee, keysIn); + } + + /** + * The base implementation of `_.forOwn` without support for callback + * shorthands and `this` binding. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwn(object, iteratee) { + return baseFor(object, iteratee, keys); + } + + /** + * The base implementation of `_.forOwnRight` without support for callback + * shorthands and `this` binding. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ + function baseForOwnRight(object, iteratee) { + return baseForRight(object, iteratee, keys); + } + + /** + * The base implementation of `_.functions` which creates an array of + * `object` function property names filtered from those provided. + * + * @private + * @param {Object} object The object to inspect. + * @param {Array} props The property names to filter. + * @returns {Array} Returns the new array of filtered property names. + */ + function baseFunctions(object, props) { + var index = -1, + length = props.length, + resIndex = -1, + result = []; + + while (++index < length) { + var key = props[index]; + if (isFunction(object[key])) { + result[++resIndex] = key; + } + } + return result; + } + + /** + * The base implementation of `_.invoke` which requires additional arguments + * to be provided as an array of arguments rather than individually. + * + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function|string} methodName The name of the method to invoke or + * the function invoked per iteration. + * @param {Array} [args] The arguments to invoke the method with. + * @returns {Array} Returns the array of results. + */ + function baseInvoke(collection, methodName, args) { + var index = -1, + isFunc = typeof methodName == 'function', + length = collection ? collection.length : 0, + result = isLength(length) ? Array(length) : []; + + baseEach(collection, function(value) { + var func = isFunc ? methodName : (value != null && value[methodName]); + result[++index] = func ? func.apply(value, args) : undefined; + }); + return result; + } + + /** + * The base implementation of `_.isEqual` without support for `this` binding + * `customizer` functions. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {Function} [customizer] The function to customize comparing values. + * @param {boolean} [isWhere] Specify performing partial comparisons. + * @param {Array} [stackA] Tracks traversed `value` objects. + * @param {Array} [stackB] Tracks traversed `other` objects. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + */ + function baseIsEqual(value, other, customizer, isWhere, stackA, stackB) { + // Exit early for identical values. + if (value === other) { + // Treat `+0` vs. `-0` as not equal. + return value !== 0 || (1 / value == 1 / other); + } + var valType = typeof value, + othType = typeof other; + + // Exit early for unlike primitive values. + if ((valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object') || + value == null || other == null) { + // Return `false` unless both values are `NaN`. + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, baseIsEqual, customizer, isWhere, stackA, stackB); + } + + /** + * A specialized version of `baseIsEqual` for arrays and objects which performs + * deep comparisons and tracks traversed objects enabling objects with circular + * references to be compared. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Function} [customizer] The function to customize comparing objects. + * @param {boolean} [isWhere] Specify performing partial comparisons. + * @param {Array} [stackA=[]] Tracks traversed `value` objects. + * @param {Array} [stackB=[]] Tracks traversed `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function baseIsEqualDeep(object, other, equalFunc, customizer, isWhere, stackA, stackB) { + var objIsArr = isArray(object), + othIsArr = isArray(other), + objTag = arrayTag, + othTag = arrayTag; + + if (!objIsArr) { + objTag = objToString.call(object); + if (objTag == argsTag) { + objTag = objectTag; + } else if (objTag != objectTag) { + objIsArr = isTypedArray(object); + } + } + if (!othIsArr) { + othTag = objToString.call(other); + if (othTag == argsTag) { + othTag = objectTag; + } else if (othTag != objectTag) { + othIsArr = isTypedArray(other); + } + } + var objIsObj = objTag == objectTag, + othIsObj = othTag == objectTag, + isSameTag = objTag == othTag; + + if (isSameTag && !(objIsArr || objIsObj)) { + return equalByTag(object, other, objTag); + } + var valWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); + + if (valWrapped || othWrapped) { + return equalFunc(valWrapped ? object.value() : object, othWrapped ? other.value() : other, customizer, isWhere, stackA, stackB); + } + if (!isSameTag) { + return false; + } + // Assume cyclic values are equal. + // For more information on detecting circular references see https://es5.github.io/#JO. + stackA || (stackA = []); + stackB || (stackB = []); + + var length = stackA.length; + while (length--) { + if (stackA[length] == object) { + return stackB[length] == other; + } + } + // Add `object` and `other` to the stack of traversed objects. + stackA.push(object); + stackB.push(other); + + var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isWhere, stackA, stackB); + + stackA.pop(); + stackB.pop(); + + return result; + } + + /** + * The base implementation of `_.isMatch` without support for callback + * shorthands or `this` binding. + * + * @private + * @param {Object} object The object to inspect. + * @param {Array} props The source property names to match. + * @param {Array} values The source values to match. + * @param {Array} strictCompareFlags Strict comparison flags for source values. + * @param {Function} [customizer] The function to customize comparing objects. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + */ + function baseIsMatch(object, props, values, strictCompareFlags, customizer) { + var length = props.length; + if (object == null) { + return !length; + } + var index = -1, + noCustomizer = !customizer; + + while (++index < length) { + if ((noCustomizer && strictCompareFlags[index]) + ? values[index] !== object[props[index]] + : !hasOwnProperty.call(object, props[index]) + ) { + return false; + } + } + index = -1; + while (++index < length) { + var key = props[index]; + if (noCustomizer && strictCompareFlags[index]) { + var result = hasOwnProperty.call(object, key); + } else { + var objValue = object[key], + srcValue = values[index]; + + result = customizer ? customizer(objValue, srcValue, key) : undefined; + if (typeof result == 'undefined') { + result = baseIsEqual(srcValue, objValue, customizer, true); + } + } + if (!result) { + return false; + } + } + return true; + } + + /** + * The base implementation of `_.map` without support for callback shorthands + * or `this` binding. + * + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ + function baseMap(collection, iteratee) { + var result = []; + baseEach(collection, function(value, key, collection) { + result.push(iteratee(value, key, collection)); + }); + return result; + } + + /** + * The base implementation of `_.matches` which does not clone `source`. + * + * @private + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new function. + */ + function baseMatches(source) { + var props = keys(source), + length = props.length; + + if (length == 1) { + var key = props[0], + value = source[key]; + + if (isStrictComparable(value)) { + return function(object) { + return object != null && object[key] === value && hasOwnProperty.call(object, key); + }; + } + } + var values = Array(length), + strictCompareFlags = Array(length); + + while (length--) { + value = source[props[length]]; + values[length] = value; + strictCompareFlags[length] = isStrictComparable(value); + } + return function(object) { + return baseIsMatch(object, props, values, strictCompareFlags); + }; + } + + /** + * The base implementation of `_.matchesProperty` which does not coerce `key` + * to a string. + * + * @private + * @param {string} key The key of the property to get. + * @param {*} value The value to compare. + * @returns {Function} Returns the new function. + */ + function baseMatchesProperty(key, value) { + if (isStrictComparable(value)) { + return function(object) { + return object != null && object[key] === value; + }; + } + return function(object) { + return object != null && baseIsEqual(value, object[key], null, true); + }; + } + + /** + * The base implementation of `_.merge` without support for argument juggling, + * multiple sources, and `this` binding `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {Function} [customizer] The function to customize merging properties. + * @param {Array} [stackA=[]] Tracks traversed source objects. + * @param {Array} [stackB=[]] Associates values with source counterparts. + * @returns {Object} Returns the destination object. + */ + function baseMerge(object, source, customizer, stackA, stackB) { + if (!isObject(object)) { + return object; + } + var isSrcArr = isLength(source.length) && (isArray(source) || isTypedArray(source)); + (isSrcArr ? arrayEach : baseForOwn)(source, function(srcValue, key, source) { + if (isObjectLike(srcValue)) { + stackA || (stackA = []); + stackB || (stackB = []); + return baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB); + } + var value = object[key], + result = customizer ? customizer(value, srcValue, key, object, source) : undefined, + isCommon = typeof result == 'undefined'; + + if (isCommon) { + result = srcValue; + } + if ((isSrcArr || typeof result != 'undefined') && + (isCommon || (result === result ? result !== value : value === value))) { + object[key] = result; + } + }); + return object; + } + + /** + * A specialized version of `baseMerge` for arrays and objects which performs + * deep merges and tracks traversed objects enabling objects with circular + * references to be merged. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {string} key The key of the value to merge. + * @param {Function} mergeFunc The function to merge values. + * @param {Function} [customizer] The function to customize merging properties. + * @param {Array} [stackA=[]] Tracks traversed source objects. + * @param {Array} [stackB=[]] Associates values with source counterparts. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) { + var length = stackA.length, + srcValue = source[key]; + + while (length--) { + if (stackA[length] == srcValue) { + object[key] = stackB[length]; + return; + } + } + var value = object[key], + result = customizer ? customizer(value, srcValue, key, object, source) : undefined, + isCommon = typeof result == 'undefined'; + + if (isCommon) { + result = srcValue; + if (isLength(srcValue.length) && (isArray(srcValue) || isTypedArray(srcValue))) { + result = isArray(value) + ? value + : (value ? arrayCopy(value) : []); + } + else if (isPlainObject(srcValue) || isArguments(srcValue)) { + result = isArguments(value) + ? toPlainObject(value) + : (isPlainObject(value) ? value : {}); + } + else { + isCommon = false; + } + } + // Add the source value to the stack of traversed objects and associate + // it with its merged value. + stackA.push(srcValue); + stackB.push(result); + + if (isCommon) { + // Recursively merge objects and arrays (susceptible to call stack limits). + object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB); + } else if (result === result ? result !== value : value === value) { + object[key] = result; + } + } + + /** + * The base implementation of `_.property` which does not coerce `key` to a string. + * + * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new function. + */ + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + + /** + * The base implementation of `_.pullAt` without support for individual + * index arguments. + * + * @private + * @param {Array} array The array to modify. + * @param {number[]} indexes The indexes of elements to remove. + * @returns {Array} Returns the new array of removed elements. + */ + function basePullAt(array, indexes) { + var length = indexes.length, + result = baseAt(array, indexes); + + indexes.sort(baseCompareAscending); + while (length--) { + var index = parseFloat(indexes[length]); + if (index != previous && isIndex(index)) { + var previous = index; + splice.call(array, index, 1); + } + } + return result; + } + + /** + * The base implementation of `_.random` without support for argument juggling + * and returning floating-point numbers. + * + * @private + * @param {number} min The minimum possible value. + * @param {number} max The maximum possible value. + * @returns {number} Returns the random number. + */ + function baseRandom(min, max) { + return min + floor(nativeRandom() * (max - min + 1)); + } + + /** + * The base implementation of `_.reduce` and `_.reduceRight` without support + * for callback shorthands or `this` binding, which iterates over `collection` + * using the provided `eachFunc`. + * + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {*} accumulator The initial value. + * @param {boolean} initFromCollection Specify using the first or last element + * of `collection` as the initial value. + * @param {Function} eachFunc The function to iterate over `collection`. + * @returns {*} Returns the accumulated value. + */ + function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initFromCollection + ? (initFromCollection = false, value) + : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + + /** + * The base implementation of `setData` without support for hot loop detection. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + + /** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function baseSlice(array, start, end) { + var index = -1, + length = array.length; + + start = start == null ? 0 : (+start || 0); + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = (typeof end == 'undefined' || end > length) ? length : (+end || 0); + if (end < 0) { + end += length; + } + length = start > end ? 0 : (end - start) >>> 0; + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + + /** + * The base implementation of `_.some` without support for callback shorthands + * or `this` binding. + * + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ + function baseSome(collection, predicate) { + var result; + + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + + /** + * The base implementation of `_.uniq` without support for callback shorthands + * and `this` binding. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The function invoked per iteration. + * @returns {Array} Returns the new duplicate-value-free array. + */ + function baseUniq(array, iteratee) { + var index = -1, + indexOf = getIndexOf(), + length = array.length, + isCommon = indexOf == baseIndexOf, + isLarge = isCommon && length >= 200, + seen = isLarge ? createCache() : null, + result = []; + + if (seen) { + indexOf = cacheIndexOf; + isCommon = false; + } else { + isLarge = false; + seen = iteratee ? [] : result; + } + outer: + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value, index, array) : value; + + if (isCommon && value === value) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } + else if (indexOf(seen, computed) < 0) { + if (iteratee || isLarge) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + + /** + * The base implementation of `_.values` and `_.valuesIn` which creates an + * array of `object` property values corresponding to the property names + * returned by `keysFunc`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the array of property values. + */ + function baseValues(object, props) { + var index = -1, + length = props.length, + result = Array(length); + + while (++index < length) { + result[index] = object[props[index]]; + } + return result; + } + + /** + * The base implementation of `wrapperValue` which returns the result of + * performing a sequence of actions on the unwrapped `value`, where each + * successive action is supplied the return value of the previous. + * + * @private + * @param {*} value The unwrapped value. + * @param {Array} actions Actions to peform to resolve the unwrapped value. + * @returns {*} Returns the resolved unwrapped value. + */ + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + var index = -1, + length = actions.length; + + while (++index < length) { + var args = [result], + action = actions[index]; + + push.apply(args, action.args); + result = action.func.apply(action.thisArg, args); + } + return result; + } + + /** + * Performs a binary search of `array` to determine the index at which `value` + * should be inserted into `array` in order to maintain its sort order. + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {boolean} [retHighest] Specify returning the highest, instead + * of the lowest, index at which a value should be inserted into `array`. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ + function binaryIndex(array, value, retHighest) { + var low = 0, + high = array ? array.length : low; + + if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = (low + high) >>> 1, + computed = array[mid]; + + if (retHighest ? (computed <= value) : (computed < value)) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return binaryIndexBy(array, value, identity, retHighest); + } + + /** + * This function is like `binaryIndex` except that it invokes `iteratee` for + * `value` and each element of `array` to compute their sort ranking. The + * iteratee is invoked with one argument; (value). + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} iteratee The function invoked per iteration. + * @param {boolean} [retHighest] Specify returning the highest, instead + * of the lowest, index at which a value should be inserted into `array`. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ + function binaryIndexBy(array, value, iteratee, retHighest) { + value = iteratee(value); + + var low = 0, + high = array ? array.length : 0, + valIsNaN = value !== value, + valIsUndef = typeof value == 'undefined'; + + while (low < high) { + var mid = floor((low + high) / 2), + computed = iteratee(array[mid]), + isReflexive = computed === computed; + + if (valIsNaN) { + var setLow = isReflexive || retHighest; + } else if (valIsUndef) { + setLow = isReflexive && (retHighest || typeof computed != 'undefined'); + } else { + setLow = retHighest ? (computed <= value) : (computed < value); + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + + /** + * A specialized version of `baseCallback` which only supports `this` binding + * and specifying the number of arguments to provide to `func`. + * + * @private + * @param {Function} func The function to bind. + * @param {*} thisArg The `this` binding of `func`. + * @param {number} [argCount] The number of arguments to provide to `func`. + * @returns {Function} Returns the callback. + */ + function bindCallback(func, thisArg, argCount) { + if (typeof func != 'function') { + return identity; + } + if (typeof thisArg == 'undefined') { + return func; + } + switch (argCount) { + case 1: return function(value) { + return func.call(thisArg, value); + }; + case 3: return function(value, index, collection) { + return func.call(thisArg, value, index, collection); + }; + case 4: return function(accumulator, value, index, collection) { + return func.call(thisArg, accumulator, value, index, collection); + }; + case 5: return function(value, other, key, object, source) { + return func.call(thisArg, value, other, key, object, source); + }; + } + return function() { + return func.apply(thisArg, arguments); + }; + } + + /** + * Creates a clone of the given array buffer. + * + * @private + * @param {ArrayBuffer} buffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ + function bufferClone(buffer) { + return bufferSlice.call(buffer, 0); + } + if (!bufferSlice) { + // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array`. + bufferClone = !(ArrayBuffer && Uint8Array) ? constant(null) : function(buffer) { + var byteLength = buffer.byteLength, + floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0, + offset = floatLength * FLOAT64_BYTES_PER_ELEMENT, + result = new ArrayBuffer(byteLength); + + if (floatLength) { + var view = new Float64Array(result, 0, floatLength); + view.set(new Float64Array(buffer, 0, floatLength)); + } + if (byteLength != offset) { + view = new Uint8Array(result, offset); + view.set(new Uint8Array(buffer, offset)); + } + return result; + }; + } + + /** + * Creates an array that is the composition of partially applied arguments, + * placeholders, and provided arguments into a single array of arguments. + * + * @private + * @param {Array|Object} args The provided arguments. + * @param {Array} partials The arguments to prepend to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @returns {Array} Returns the new array of composed arguments. + */ + function composeArgs(args, partials, holders) { + var holdersLength = holders.length, + argsIndex = -1, + argsLength = nativeMax(args.length - holdersLength, 0), + leftIndex = -1, + leftLength = partials.length, + result = Array(argsLength + leftLength); + + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + while (argsLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + + /** + * This function is like `composeArgs` except that the arguments composition + * is tailored for `_.partialRight`. + * + * @private + * @param {Array|Object} args The provided arguments. + * @param {Array} partials The arguments to append to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @returns {Array} Returns the new array of composed arguments. + */ + function composeArgsRight(args, partials, holders) { + var holdersIndex = -1, + holdersLength = holders.length, + argsIndex = -1, + argsLength = nativeMax(args.length - holdersLength, 0), + rightIndex = -1, + rightLength = partials.length, + result = Array(argsLength + rightLength); + + while (++argsIndex < argsLength) { + result[argsIndex] = args[argsIndex]; + } + var pad = argsIndex; + while (++rightIndex < rightLength) { + result[pad + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + result[pad + holders[holdersIndex]] = args[argsIndex++]; + } + return result; + } + + /** + * Creates a function that aggregates a collection, creating an accumulator + * object composed from the results of running each element in the collection + * through an iteratee. + * + * @private + * @param {Function} setter The function to set keys and values of the accumulator object. + * @param {Function} [initializer] The function to initialize the accumulator object. + * @returns {Function} Returns the new aggregator function. + */ + function createAggregator(setter, initializer) { + return function(collection, iteratee, thisArg) { + var result = initializer ? initializer() : {}; + iteratee = getCallback(iteratee, thisArg, 3); + + if (isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + var value = collection[index]; + setter(result, value, iteratee(value, index, collection), collection); + } + } else { + baseEach(collection, function(value, key, collection) { + setter(result, value, iteratee(value, key, collection), collection); + }); + } + return result; + }; + } + + /** + * Creates a function that assigns properties of source object(s) to a given + * destination object. + * + * @private + * @param {Function} assigner The function to assign values. + * @returns {Function} Returns the new assigner function. + */ + function createAssigner(assigner) { + return function() { + var length = arguments.length, + object = arguments[0]; + + if (length < 2 || object == null) { + return object; + } + if (length > 3 && isIterateeCall(arguments[1], arguments[2], arguments[3])) { + length = 2; + } + // Juggle arguments. + if (length > 3 && typeof arguments[length - 2] == 'function') { + var customizer = bindCallback(arguments[--length - 1], arguments[length--], 5); + } else if (length > 2 && typeof arguments[length - 1] == 'function') { + customizer = arguments[--length]; + } + var index = 0; + while (++index < length) { + var source = arguments[index]; + if (source) { + assigner(object, source, customizer); + } + } + return object; + }; + } + + /** + * Creates a function that wraps `func` and invokes it with the `this` + * binding of `thisArg`. + * + * @private + * @param {Function} func The function to bind. + * @param {*} [thisArg] The `this` binding of `func`. + * @returns {Function} Returns the new bound function. + */ + function createBindWrapper(func, thisArg) { + var Ctor = createCtorWrapper(func); + + function wrapper() { + return (this instanceof wrapper ? Ctor : func).apply(thisArg, arguments); + } + return wrapper; + } + + /** + * Creates a `Set` cache object to optimize linear searches of large arrays. + * + * @private + * @param {Array} [values] The values to cache. + * @returns {null|Object} Returns the new cache object if `Set` is supported, else `null`. + */ + var createCache = !(nativeCreate && Set) ? constant(null) : function(values) { + return new SetCache(values); + }; + + /** + * Creates a function that produces compound words out of the words in a + * given string. + * + * @private + * @param {Function} callback The function to combine each word. + * @returns {Function} Returns the new compounder function. + */ + function createCompounder(callback) { + return function(string) { + var index = -1, + array = words(deburr(string)), + length = array.length, + result = ''; + + while (++index < length) { + result = callback(result, array[index], index); + } + return result; + }; + } + + /** + * Creates a function that produces an instance of `Ctor` regardless of + * whether it was invoked as part of a `new` expression or by `call` or `apply`. + * + * @private + * @param {Function} Ctor The constructor to wrap. + * @returns {Function} Returns the new wrapped function. + */ + function createCtorWrapper(Ctor) { + return function() { + var thisBinding = baseCreate(Ctor.prototype), + result = Ctor.apply(thisBinding, arguments); + + // Mimic the constructor's `return` behavior. + // See https://es5.github.io/#x13.2.2 for more details. + return isObject(result) ? result : thisBinding; + }; + } + + /** + * Creates a function that gets the extremum value of a collection. + * + * @private + * @param {Function} arrayFunc The function to get the extremum value from an array. + * @param {boolean} [isMin] Specify returning the minimum, instead of the maximum, + * extremum value. + * @returns {Function} Returns the new extremum function. + */ + function createExtremum(arrayFunc, isMin) { + return function(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = null; + } + var func = getCallback(), + noIteratee = iteratee == null; + + if (!(func === baseCallback && noIteratee)) { + noIteratee = false; + iteratee = func(iteratee, thisArg, 3); + } + if (noIteratee) { + var isArr = isArray(collection); + if (!isArr && isString(collection)) { + iteratee = charAtCallback; + } else { + return arrayFunc(isArr ? collection : toIterable(collection)); + } + } + return extremumBy(collection, iteratee, isMin); + }; + } + + /** + * Creates a function that wraps `func` and invokes it with optional `this` + * binding of, partial application, and currying. + * + * @private + * @param {Function|string} func The function or method name to reference. + * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [partialsRight] The arguments to append to those provided to the new function. + * @param {Array} [holdersRight] The `partialsRight` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & ARY_FLAG, + isBind = bitmask & BIND_FLAG, + isBindKey = bitmask & BIND_KEY_FLAG, + isCurry = bitmask & CURRY_FLAG, + isCurryBound = bitmask & CURRY_BOUND_FLAG, + isCurryRight = bitmask & CURRY_RIGHT_FLAG; + + var Ctor = !isBindKey && createCtorWrapper(func), + key = func; + + function wrapper() { + // Avoid `arguments` object use disqualifying optimizations by + // converting it to an array before providing it to other functions. + var length = arguments.length, + index = length, + args = Array(length); + + while (index--) { + args[index] = arguments[index]; + } + if (partials) { + args = composeArgs(args, partials, holders); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight); + } + if (isCurry || isCurryRight) { + var placeholder = wrapper.placeholder, + argsHolders = replaceHolders(args, placeholder); + + length -= argsHolders.length; + if (length < arity) { + var newArgPos = argPos ? arrayCopy(argPos) : null, + newArity = nativeMax(arity - length, 0), + newsHolders = isCurry ? argsHolders : null, + newHoldersRight = isCurry ? null : argsHolders, + newPartials = isCurry ? args : null, + newPartialsRight = isCurry ? null : args; + + bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var result = createHybridWrapper(func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity); + result.placeholder = placeholder; + return result; + } + } + var thisBinding = isBind ? thisArg : this; + if (isBindKey) { + func = thisBinding[key]; + } + if (argPos) { + args = reorder(args, argPos); + } + if (isAry && ary < args.length) { + args.length = ary; + } + return (this instanceof wrapper ? (Ctor || createCtorWrapper(func)) : func).apply(thisBinding, args); + } + return wrapper; + } + + /** + * Creates the pad required for `string` based on the given padding length. + * The `chars` string may be truncated if the number of padding characters + * exceeds the padding length. + * + * @private + * @param {string} string The string to create padding for. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the pad for `string`. + */ + function createPad(string, length, chars) { + var strLength = string.length; + length = +length; + + if (strLength >= length || !nativeIsFinite(length)) { + return ''; + } + var padLength = length - strLength; + chars = chars == null ? ' ' : (chars + ''); + return repeat(chars, ceil(padLength / chars.length)).slice(0, padLength); + } + + /** + * Creates a function that wraps `func` and invokes it with the optional `this` + * binding of `thisArg` and the `partials` prepended to those provided to + * the wrapper. + * + * @private + * @param {Function} func The function to partially apply arguments to. + * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} partials The arguments to prepend to those provided to the new function. + * @returns {Function} Returns the new bound function. + */ + function createPartialWrapper(func, bitmask, thisArg, partials) { + var isBind = bitmask & BIND_FLAG, + Ctor = createCtorWrapper(func); + + function wrapper() { + // Avoid `arguments` object use disqualifying optimizations by + // converting it to an array before providing it `func`. + var argsIndex = -1, + argsLength = arguments.length, + leftIndex = -1, + leftLength = partials.length, + args = Array(argsLength + leftLength); + + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + return (this instanceof wrapper ? Ctor : func).apply(isBind ? thisArg : this, args); + } + return wrapper; + } + + /** + * Creates a function that either curries or invokes `func` with optional + * `this` binding and partially applied arguments. + * + * @private + * @param {Function|string} func The function or method name to reference. + * @param {number} bitmask The bitmask of flags. + * The bitmask may be composed of the following flags: + * 1 - `_.bind` + * 2 - `_.bindKey` + * 4 - `_.curry` or `_.curryRight` of a bound function + * 8 - `_.curry` + * 16 - `_.curryRight` + * 32 - `_.partial` + * 64 - `_.partialRight` + * 128 - `_.rearg` + * 256 - `_.ary` + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to be partially applied. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ + function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & BIND_KEY_FLAG; + if (!isBindKey && typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); + partials = holders = null; + } + length -= (holders ? holders.length : 0); + if (bitmask & PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, + holdersRight = holders; + + partials = holders = null; + } + var data = !isBindKey && getData(func), + newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity]; + + if (data && data !== true) { + mergeData(newData, data); + bitmask = newData[1]; + arity = newData[9]; + } + newData[9] = arity == null + ? (isBindKey ? 0 : func.length) + : (nativeMax(arity - length, 0) || 0); + + if (bitmask == BIND_FLAG) { + var result = createBindWrapper(newData[0], newData[2]); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { + result = createPartialWrapper.apply(undefined, newData); + } else { + result = createHybridWrapper.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setter(result, newData); + } + + /** + * A specialized version of `baseIsEqualDeep` for arrays with support for + * partial deep comparisons. + * + * @private + * @param {Array} array The array to compare. + * @param {Array} other The other array to compare. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Function} [customizer] The function to customize comparing arrays. + * @param {boolean} [isWhere] Specify performing partial comparisons. + * @param {Array} [stackA] Tracks traversed `value` objects. + * @param {Array} [stackB] Tracks traversed `other` objects. + * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. + */ + function equalArrays(array, other, equalFunc, customizer, isWhere, stackA, stackB) { + var index = -1, + arrLength = array.length, + othLength = other.length, + result = true; + + if (arrLength != othLength && !(isWhere && othLength > arrLength)) { + return false; + } + // Deep compare the contents, ignoring non-numeric properties. + while (result && ++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; + + result = undefined; + if (customizer) { + result = isWhere + ? customizer(othValue, arrValue, index) + : customizer(arrValue, othValue, index); + } + if (typeof result == 'undefined') { + // Recursively compare arrays (susceptible to call stack limits). + if (isWhere) { + var othIndex = othLength; + while (othIndex--) { + othValue = other[othIndex]; + result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isWhere, stackA, stackB); + if (result) { + break; + } + } + } else { + result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isWhere, stackA, stackB); + } + } + } + return !!result; + } + + /** + * A specialized version of `baseIsEqualDeep` for comparing objects of + * the same `toStringTag`. + * + * **Note:** This function only supports comparing values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} value The object to compare. + * @param {Object} other The other object to compare. + * @param {string} tag The `toStringTag` of the objects to compare. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalByTag(object, other, tag) { + switch (tag) { + case boolTag: + case dateTag: + // Coerce dates and booleans to numbers, dates to milliseconds and booleans + // to `1` or `0` treating invalid dates coerced to `NaN` as not equal. + return +object == +other; + + case errorTag: + return object.name == other.name && object.message == other.message; + + case numberTag: + // Treat `NaN` vs. `NaN` as equal. + return (object != +object) + ? other != +other + // But, treat `-0` vs. `+0` as not equal. + : (object == 0 ? ((1 / object) == (1 / other)) : object == +other); + + case regexpTag: + case stringTag: + // Coerce regexes to strings and treat strings primitives and string + // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details. + return object == (other + ''); + } + return false; + } + + /** + * A specialized version of `baseIsEqualDeep` for objects with support for + * partial deep comparisons. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Function} [customizer] The function to customize comparing values. + * @param {boolean} [isWhere] Specify performing partial comparisons. + * @param {Array} [stackA] Tracks traversed `value` objects. + * @param {Array} [stackB] Tracks traversed `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ + function equalObjects(object, other, equalFunc, customizer, isWhere, stackA, stackB) { + var objProps = keys(object), + objLength = objProps.length, + othProps = keys(other), + othLength = othProps.length; + + if (objLength != othLength && !isWhere) { + return false; + } + var hasCtor, + index = -1; + + while (++index < objLength) { + var key = objProps[index], + result = hasOwnProperty.call(other, key); + + if (result) { + var objValue = object[key], + othValue = other[key]; + + result = undefined; + if (customizer) { + result = isWhere + ? customizer(othValue, objValue, key) + : customizer(objValue, othValue, key); + } + if (typeof result == 'undefined') { + // Recursively compare objects (susceptible to call stack limits). + result = (objValue && objValue === othValue) || equalFunc(objValue, othValue, customizer, isWhere, stackA, stackB); + } + } + if (!result) { + return false; + } + hasCtor || (hasCtor = key == 'constructor'); + } + if (!hasCtor) { + var objCtor = object.constructor, + othCtor = other.constructor; + + // Non `Object` object instances with different constructors are not equal. + if (objCtor != othCtor && ('constructor' in object && 'constructor' in other) && + !(typeof objCtor == 'function' && objCtor instanceof objCtor && typeof othCtor == 'function' && othCtor instanceof othCtor)) { + return false; + } + } + return true; + } + + /** + * Gets the extremum value of `collection` invoking `iteratee` for each value + * in `collection` to generate the criterion by which the value is ranked. + * The `iteratee` is invoked with three arguments; (value, index, collection). + * + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {boolean} [isMin] Specify returning the minimum, instead of the + * maximum, extremum value. + * @returns {*} Returns the extremum value. + */ + function extremumBy(collection, iteratee, isMin) { + var exValue = isMin ? POSITIVE_INFINITY : NEGATIVE_INFINITY, + computed = exValue, + result = computed; + + baseEach(collection, function(value, index, collection) { + var current = iteratee(value, index, collection); + if ((isMin ? current < computed : current > computed) || (current === exValue && current === result)) { + computed = current; + result = value; + } + }); + return result; + } + + /** + * Gets the appropriate "callback" function. If the `_.callback` method is + * customized this function returns the custom method, otherwise it returns + * the `baseCallback` function. If arguments are provided the chosen function + * is invoked with them and its result is returned. + * + * @private + * @returns {Function} Returns the chosen function or its result. + */ + function getCallback(func, thisArg, argCount) { + var result = lodash.callback || callback; + result = result === callback ? baseCallback : result; + return argCount ? result(func, thisArg, argCount) : result; + } + + /** + * Gets metadata for `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {*} Returns the metadata for `func`. + */ + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + + /** + * Gets the appropriate "indexOf" function. If the `_.indexOf` method is + * customized this function returns the custom method, otherwise it returns + * the `baseIndexOf` function. If arguments are provided the chosen function + * is invoked with them and its result is returned. + * + * @private + * @returns {Function|number} Returns the chosen function or its result. + */ + function getIndexOf(collection, target, fromIndex) { + var result = lodash.indexOf || indexOf; + result = result === indexOf ? baseIndexOf : result; + return collection ? result(collection, target, fromIndex) : result; + } + + /** + * Gets the view, applying any `transforms` to the `start` and `end` positions. + * + * @private + * @param {number} start The start of the view. + * @param {number} end The end of the view. + * @param {Array} [transforms] The transformations to apply to the view. + * @returns {Object} Returns an object containing the `start` and `end` + * positions of the view. + */ + function getView(start, end, transforms) { + var index = -1, + length = transforms ? transforms.length : 0; + + while (++index < length) { + var data = transforms[index], + size = data.size; + + switch (data.type) { + case 'drop': start += size; break; + case 'dropRight': end -= size; break; + case 'take': end = nativeMin(end, start + size); break; + case 'takeRight': start = nativeMax(start, end - size); break; + } + } + return { 'start': start, 'end': end }; + } + + /** + * Initializes an array clone. + * + * @private + * @param {Array} array The array to clone. + * @returns {Array} Returns the initialized clone. + */ + function initCloneArray(array) { + var length = array.length, + result = new array.constructor(length); + + // Add array properties assigned by `RegExp#exec`. + if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { + result.index = array.index; + result.input = array.input; + } + return result; + } + + /** + * Initializes an object clone. + * + * @private + * @param {Object} object The object to clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneObject(object) { + var Ctor = object.constructor; + if (!(typeof Ctor == 'function' && Ctor instanceof Ctor)) { + Ctor = Object; + } + return new Ctor; + } + + /** + * Initializes an object clone based on its `toStringTag`. + * + * **Note:** This function only supports cloning values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * + * @private + * @param {Object} object The object to clone. + * @param {string} tag The `toStringTag` of the object to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the initialized clone. + */ + function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return bufferClone(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case float32Tag: case float64Tag: + case int8Tag: case int16Tag: case int32Tag: + case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: + var buffer = object.buffer; + return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + var result = new Ctor(object.source, reFlags.exec(object)); + result.lastIndex = object.lastIndex; + } + return result; + } + + /** + * Checks if `func` is eligible for `this` binding. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is eligible, else `false`. + */ + function isBindable(func) { + var support = lodash.support, + result = !(support.funcNames ? func.name : support.funcDecomp); + + if (!result) { + var source = fnToString.call(func); + if (!support.funcNames) { + result = !reFuncName.test(source); + } + if (!result) { + // Check if `func` references the `this` keyword and store the result. + result = reThis.test(source) || isNative(func); + baseSetData(func, result); + } + } + return result; + } + + /** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ + function isIndex(value, length) { + value = +value; + length = length == null ? MAX_SAFE_INTEGER : length; + return value > -1 && value % 1 == 0 && value < length; + } + + /** + * Checks if the provided arguments are from an iteratee call. + * + * @private + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`. + */ + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == 'number') { + var length = object.length, + prereq = isLength(length) && isIndex(index, length); + } else { + prereq = type == 'string' && index in object; + } + if (prereq) { + var other = object[index]; + return value === value ? value === other : other !== other; + } + return false; + } + + /** + * Checks if `value` is a valid array-like length. + * + * **Note:** This function is based on ES `ToLength`. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength) + * for more details. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + */ + function isLength(value) { + return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + + /** + * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` if suitable for strict + * equality comparisons, else `false`. + */ + function isStrictComparable(value) { + return value === value && (value === 0 ? ((1 / value) > 0) : !isObject(value)); + } + + /** + * Merges the function metadata of `source` into `data`. + * + * Merging metadata reduces the number of wrappers required to invoke a function. + * This is possible because methods like `_.bind`, `_.curry`, and `_.partial` + * may be applied regardless of execution order. Methods like `_.ary` and `_.rearg` + * augment function arguments, making the order in which they are executed important, + * preventing the merging of metadata. However, we make an exception for a safe + * common case where curried functions have `_.ary` and or `_.rearg` applied. + * + * @private + * @param {Array} data The destination metadata. + * @param {Array} source The source metadata. + * @returns {Array} Returns `data`. + */ + function mergeData(data, source) { + var bitmask = data[1], + srcBitmask = source[1], + newBitmask = bitmask | srcBitmask; + + var arityFlags = ARY_FLAG | REARG_FLAG, + bindFlags = BIND_FLAG | BIND_KEY_FLAG, + comboFlags = arityFlags | bindFlags | CURRY_BOUND_FLAG | CURRY_RIGHT_FLAG; + + var isAry = bitmask & ARY_FLAG && !(srcBitmask & ARY_FLAG), + isRearg = bitmask & REARG_FLAG && !(srcBitmask & REARG_FLAG), + argPos = (isRearg ? data : source)[7], + ary = (isAry ? data : source)[8]; + + var isCommon = !(bitmask >= REARG_FLAG && srcBitmask > bindFlags) && + !(bitmask > bindFlags && srcBitmask >= REARG_FLAG); + + var isCombo = (newBitmask >= arityFlags && newBitmask <= comboFlags) && + (bitmask < REARG_FLAG || ((isRearg || isAry) && argPos.length <= ary)); + + // Exit early if metadata can't be merged. + if (!(isCommon || isCombo)) { + return data; + } + // Use source `thisArg` if available. + if (srcBitmask & BIND_FLAG) { + data[2] = source[2]; + // Set when currying a bound function. + newBitmask |= (bitmask & BIND_FLAG) ? 0 : CURRY_BOUND_FLAG; + } + // Compose partial arguments. + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value); + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]); + } + // Compose partial right arguments. + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value); + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]); + } + // Use source `argPos` if available. + value = source[7]; + if (value) { + data[7] = arrayCopy(value); + } + // Use source `ary` if it's smaller. + if (srcBitmask & ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + // Use source `arity` if one is not provided. + if (data[9] == null) { + data[9] = source[9]; + } + // Use source `func` and merge bitmasks. + data[0] = source[0]; + data[1] = newBitmask; + + return data; + } + + /** + * A specialized version of `_.pick` that picks `object` properties specified + * by the `props` array. + * + * @private + * @param {Object} object The source object. + * @param {string[]} props The property names to pick. + * @returns {Object} Returns the new object. + */ + function pickByArray(object, props) { + object = toObject(object); + + var index = -1, + length = props.length, + result = {}; + + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + return result; + } + + /** + * A specialized version of `_.pick` that picks `object` properties `predicate` + * returns truthy for. + * + * @private + * @param {Object} object The source object. + * @param {Function} predicate The function invoked per iteration. + * @returns {Object} Returns the new object. + */ + function pickByCallback(object, predicate) { + var result = {}; + baseForIn(object, function(value, key, object) { + if (predicate(value, key, object)) { + result[key] = value; + } + }); + return result; + } + + /** + * Reorder `array` according to the specified indexes where the element at + * the first index is assigned as the first element, the element at + * the second index is assigned as the second element, and so on. + * + * @private + * @param {Array} array The array to reorder. + * @param {Array} indexes The arranged array indexes. + * @returns {Array} Returns `array`. + */ + function reorder(array, indexes) { + var arrLength = array.length, + length = nativeMin(indexes.length, arrLength), + oldArray = arrayCopy(array); + + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + + /** + * Sets metadata for `func`. + * + * **Note:** If this function becomes hot, i.e. is invoked a lot in a short + * period of time, it will trip its breaker and transition to an identity function + * to avoid garbage collection pauses in V8. See [V8 issue 2070](https://code.google.com/p/v8/issues/detail?id=2070) + * for more details. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ + var setData = (function() { + var count = 0, + lastCalled = 0; + + return function(key, value) { + var stamp = now(), + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return key; + } + } else { + count = 0; + } + return baseSetData(key, value); + }; + }()); + + /** + * A fallback implementation of `_.isPlainObject` which checks if `value` + * is an object created by the `Object` constructor or has a `[[Prototype]]` + * of `null`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + */ + function shimIsPlainObject(value) { + var Ctor, + support = lodash.support; + + // Exit early for non `Object` objects. + if (!(isObjectLike(value) && objToString.call(value) == objectTag) || + (!hasOwnProperty.call(value, 'constructor') && + (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) { + return false; + } + // IE < 9 iterates inherited properties before own properties. If the first + // iterated property is an object's own property then there are no inherited + // enumerable properties. + var result; + // In most environments an object's own properties are iterated before + // its inherited properties. If the last iterated property is an object's + // own property then there are no inherited enumerable properties. + baseForIn(value, function(subValue, key) { + result = key; + }); + return typeof result == 'undefined' || hasOwnProperty.call(value, result); + } + + /** + * A fallback implementation of `Object.keys` which creates an array of the + * own enumerable property names of `object`. + * + * @private + * @param {Object} object The object to inspect. + * @returns {Array} Returns the array of property names. + */ + function shimKeys(object) { + var props = keysIn(object), + propsLength = props.length, + length = propsLength && object.length, + support = lodash.support; + + var allowIndexes = length && isLength(length) && + (isArray(object) || (support.nonEnumArgs && isArguments(object))); + + var index = -1, + result = []; + + while (++index < propsLength) { + var key = props[index]; + if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) { + result.push(key); + } + } + return result; + } + + /** + * Converts `value` to an array-like object if it is not one. + * + * @private + * @param {*} value The value to process. + * @returns {Array|Object} Returns the array-like object. + */ + function toIterable(value) { + if (value == null) { + return []; + } + if (!isLength(value.length)) { + return values(value); + } + return isObject(value) ? value : Object(value); + } + + /** + * Converts `value` to an object if it is not one. + * + * @private + * @param {*} value The value to process. + * @returns {Object} Returns the object. + */ + function toObject(value) { + return isObject(value) ? value : Object(value); + } + + /** + * Creates a clone of `wrapper`. + * + * @private + * @param {Object} wrapper The wrapper to clone. + * @returns {Object} Returns the cloned wrapper. + */ + function wrapperClone(wrapper) { + return wrapper instanceof LazyWrapper + ? wrapper.clone() + : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__)); + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates an array of elements split into groups the length of `size`. + * If `collection` can't be split evenly, the final chunk will be the remaining + * elements. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to process. + * @param {number} [size=1] The length of each chunk. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Array} Returns the new array containing chunks. + * @example + * + * _.chunk(['a', 'b', 'c', 'd'], 2); + * // => [['a', 'b'], ['c', 'd']] + * + * _.chunk(['a', 'b', 'c', 'd'], 3); + * // => [['a', 'b', 'c'], ['d']] + */ + function chunk(array, size, guard) { + if (guard ? isIterateeCall(array, size, guard) : size == null) { + size = 1; + } else { + size = nativeMax(+size || 1, 1); + } + var index = 0, + length = array ? array.length : 0, + resIndex = -1, + result = Array(ceil(length / size)); + + while (index < length) { + result[++resIndex] = baseSlice(array, index, (index += size)); + } + return result; + } + + /** + * Creates an array with all falsey values removed. The values `false`, `null`, + * `0`, `""`, `undefined`, and `NaN` are falsey. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to compact. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.compact([0, 1, false, 2, '', 3]); + * // => [1, 2, 3] + */ + function compact(array) { + var index = -1, + length = array ? array.length : 0, + resIndex = -1, + result = []; + + while (++index < length) { + var value = array[index]; + if (value) { + result[++resIndex] = value; + } + } + return result; + } + + /** + * Creates an array excluding all values of the provided arrays using + * `SameValueZero` for equality comparisons. + * + * **Note:** `SameValueZero` comparisons are like strict equality comparisons, + * e.g. `===`, except that `NaN` matches `NaN`. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The arrays of values to exclude. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.difference([1, 2, 3], [4, 2]); + * // => [1, 3] + */ + function difference() { + var index = -1, + length = arguments.length; + + while (++index < length) { + var value = arguments[index]; + if (isArray(value) || isArguments(value)) { + break; + } + } + return baseDifference(value, baseFlatten(arguments, false, true, ++index)); + } + + /** + * Creates a slice of `array` with `n` elements dropped from the beginning. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.drop([1, 2, 3]); + * // => [2, 3] + * + * _.drop([1, 2, 3], 2); + * // => [3] + * + * _.drop([1, 2, 3], 5); + * // => [] + * + * _.drop([1, 2, 3], 0); + * // => [1, 2, 3] + */ + function drop(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, n < 0 ? 0 : n); + } + + /** + * Creates a slice of `array` with `n` elements dropped from the end. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to drop. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.dropRight([1, 2, 3]); + * // => [1, 2] + * + * _.dropRight([1, 2, 3], 2); + * // => [1] + * + * _.dropRight([1, 2, 3], 5); + * // => [] + * + * _.dropRight([1, 2, 3], 0); + * // => [1, 2, 3] + */ + function dropRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + + /** + * Creates a slice of `array` excluding elements dropped from the end. + * Elements are dropped until `predicate` returns falsey. The predicate is + * bound to `thisArg` and invoked with three arguments; (value, index, array). + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that match the properties of the given + * object, else `false`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to query. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.dropRightWhile([1, 2, 3], function(n) { + * return n > 1; + * }); + * // => [1] + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * // using the `_.matches` callback shorthand + * _.pluck(_.dropRightWhile(users, { 'user': pebbles, 'active': false }), 'user'); + * // => ['barney', 'fred'] + * + * // using the `_.matchesProperty` callback shorthand + * _.pluck(_.dropRightWhile(users, 'active', false), 'user'); + * // => ['barney'] + * + * // using the `_.property` callback shorthand + * _.pluck(_.dropRightWhile(users, 'active'), 'user'); + * // => ['barney', 'fred', 'pebbles'] + */ + function dropRightWhile(array, predicate, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + predicate = getCallback(predicate, thisArg, 3); + while (length-- && predicate(array[length], length, array)) {} + return baseSlice(array, 0, length + 1); + } + + /** + * Creates a slice of `array` excluding elements dropped from the beginning. + * Elements are dropped until `predicate` returns falsey. The predicate is + * bound to `thisArg` and invoked with three arguments; (value, index, array). + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to query. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.dropWhile([1, 2, 3], function(n) { + * return n < 3; + * }); + * // => [3] + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * // using the `_.matches` callback shorthand + * _.pluck(_.dropWhile(users, { 'user': 'barney', 'active': false }), 'user'); + * // => ['fred', 'pebbles'] + * + * // using the `_.matchesProperty` callback shorthand + * _.pluck(_.dropWhile(users, 'active', false), 'user'); + * // => ['pebbles'] + * + * // using the `_.property` callback shorthand + * _.pluck(_.dropWhile(users, 'active'), 'user'); + * // => ['barney', 'fred', 'pebbles'] + */ + function dropWhile(array, predicate, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + var index = -1; + predicate = getCallback(predicate, thisArg, 3); + while (++index < length && predicate(array[index], index, array)) {} + return baseSlice(array, index); + } + + /** + * Fills elements of `array` with `value` from `start` up to, but not + * including, `end`. + * + * **Note:** This method mutates `array`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to fill. + * @param {*} value The value to fill `array` with. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns `array`. + */ + function fill(array, value, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (start && typeof start != 'number' && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + + /** + * This method is like `_.find` except that it returns the index of the first + * element `predicate` returns truthy for, instead of the element itself. + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to search. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.findIndex(users, function(chr) { + * return chr.user == 'barney'; + * }); + * // => 0 + * + * // using the `_.matches` callback shorthand + * _.findIndex(users, { 'user': 'fred', 'active': false }); + * // => 1 + * + * // using the `_.matchesProperty` callback shorthand + * _.findIndex(users, 'active', false); + * // => 0 + * + * // using the `_.property` callback shorthand + * _.findIndex(users, 'active'); + * // => 2 + */ + function findIndex(array, predicate, thisArg) { + var index = -1, + length = array ? array.length : 0; + + predicate = getCallback(predicate, thisArg, 3); + while (++index < length) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + + /** + * This method is like `_.findIndex` except that it iterates over elements + * of `collection` from right to left. + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to search. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * _.findLastIndex(users, function(chr) { + * return chr.user == 'pebbles'; + * }); + * // => 2 + * + * // using the `_.matches` callback shorthand + * _.findLastIndex(users, { 'user': 'barney', 'active': true }); + * // => 0 + * + * // using the `_.matchesProperty` callback shorthand + * _.findLastIndex(users, 'active', false); + * // => 1 + * + * // using the `_.property` callback shorthand + * _.findLastIndex(users, 'active'); + * // => 0 + */ + function findLastIndex(array, predicate, thisArg) { + var length = array ? array.length : 0; + predicate = getCallback(predicate, thisArg, 3); + while (length--) { + if (predicate(array[length], length, array)) { + return length; + } + } + return -1; + } + + /** + * Gets the first element of `array`. + * + * @static + * @memberOf _ + * @alias head + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the first element of `array`. + * @example + * + * _.first([1, 2, 3]); + * // => 1 + * + * _.first([]); + * // => undefined + */ + function first(array) { + return array ? array[0] : undefined; + } + + /** + * Flattens a nested array. If `isDeep` is `true` the array is recursively + * flattened, otherwise it is only flattened a single level. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to flatten. + * @param {boolean} [isDeep] Specify a deep flatten. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flatten([1, [2, 3, [4]]]); + * // => [1, 2, 3, [4]]; + * + * // using `isDeep` + * _.flatten([1, [2, 3, [4]]], true); + * // => [1, 2, 3, 4]; + */ + function flatten(array, isDeep, guard) { + var length = array ? array.length : 0; + if (guard && isIterateeCall(array, isDeep, guard)) { + isDeep = false; + } + return length ? baseFlatten(array, isDeep) : []; + } + + /** + * Recursively flattens a nested array. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to recursively flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flattenDeep([1, [2, 3, [4]]]); + * // => [1, 2, 3, 4]; + */ + function flattenDeep(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, true) : []; + } + + /** + * Gets the index at which the first occurrence of `value` is found in `array` + * using `SameValueZero` for equality comparisons. If `fromIndex` is negative, + * it is used as the offset from the end of `array`. If `array` is sorted + * providing `true` for `fromIndex` performs a faster binary search. + * + * **Note:** `SameValueZero` comparisons are like strict equality comparisons, + * e.g. `===`, except that `NaN` matches `NaN`. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to search. + * @param {*} value The value to search for. + * @param {boolean|number} [fromIndex=0] The index to search from or `true` + * to perform a binary search on a sorted array. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.indexOf([1, 2, 1, 2], 2); + * // => 1 + * + * // using `fromIndex` + * _.indexOf([1, 2, 1, 2], 2, 2); + * // => 3 + * + * // performing a binary search + * _.indexOf([1, 1, 2, 2], 2, true); + * // => 2 + */ + function indexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + if (typeof fromIndex == 'number') { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); + } else if (fromIndex) { + var index = binaryIndex(array, value), + other = array[index]; + + return (value === value ? value === other : other !== other) ? index : -1; + } + return baseIndexOf(array, value, fromIndex); + } + + /** + * Gets all but the last element of `array`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to query. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.initial([1, 2, 3]); + * // => [1, 2] + */ + function initial(array) { + return dropRight(array, 1); + } + + /** + * Creates an array of unique values in all provided arrays using `SameValueZero` + * for equality comparisons. + * + * **Note:** `SameValueZero` comparisons are like strict equality comparisons, + * e.g. `===`, except that `NaN` matches `NaN`. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * + * @static + * @memberOf _ + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of shared values. + * @example + * _.intersection([1, 2], [4, 2], [2, 1]); + * // => [2] + */ + function intersection() { + var args = [], + argsIndex = -1, + argsLength = arguments.length, + caches = [], + indexOf = getIndexOf(), + isCommon = indexOf == baseIndexOf; + + while (++argsIndex < argsLength) { + var value = arguments[argsIndex]; + if (isArray(value) || isArguments(value)) { + args.push(value); + caches.push((isCommon && value.length >= 120) ? createCache(argsIndex && value) : null); + } + } + argsLength = args.length; + var array = args[0], + index = -1, + length = array ? array.length : 0, + result = [], + seen = caches[0]; + + outer: + while (++index < length) { + value = array[index]; + if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value)) < 0) { + argsIndex = argsLength; + while (--argsIndex) { + var cache = caches[argsIndex]; + if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) { + continue outer; + } + } + if (seen) { + seen.push(value); + } + result.push(value); + } + } + return result; + } + + /** + * Gets the last element of `array`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the last element of `array`. + * @example + * + * _.last([1, 2, 3]); + * // => 3 + */ + function last(array) { + var length = array ? array.length : 0; + return length ? array[length - 1] : undefined; + } + + /** + * This method is like `_.indexOf` except that it iterates over elements of + * `array` from right to left. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to search. + * @param {*} value The value to search for. + * @param {boolean|number} [fromIndex=array.length-1] The index to search from + * or `true` to perform a binary search on a sorted array. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.lastIndexOf([1, 2, 1, 2], 2); + * // => 3 + * + * // using `fromIndex` + * _.lastIndexOf([1, 2, 1, 2], 2, 2); + * // => 1 + * + * // performing a binary search + * _.lastIndexOf([1, 1, 2, 2], 2, true); + * // => 3 + */ + function lastIndexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = length; + if (typeof fromIndex == 'number') { + index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1; + } else if (fromIndex) { + index = binaryIndex(array, value, true) - 1; + var other = array[index]; + return (value === value ? value === other : other !== other) ? index : -1; + } + if (value !== value) { + return indexOfNaN(array, index, true); + } + while (index--) { + if (array[index] === value) { + return index; + } + } + return -1; + } + + /** + * Removes all provided values from `array` using `SameValueZero` for equality + * comparisons. + * + * **Notes:** + * - Unlike `_.without`, this method mutates `array`. + * - `SameValueZero` comparisons are like strict equality comparisons, e.g. `===`, + * except that `NaN` matches `NaN`. See the [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to modify. + * @param {...*} [values] The values to remove. + * @returns {Array} Returns `array`. + * @example + * + * var array = [1, 2, 3, 1, 2, 3]; + * + * _.pull(array, 2, 3); + * console.log(array); + * // => [1, 1] + */ + function pull() { + var array = arguments[0]; + if (!(array && array.length)) { + return array; + } + var index = 0, + indexOf = getIndexOf(), + length = arguments.length; + + while (++index < length) { + var fromIndex = 0, + value = arguments[index]; + + while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { + splice.call(array, fromIndex, 1); + } + } + return array; + } + + /** + * Removes elements from `array` corresponding to the given indexes and returns + * an array of the removed elements. Indexes may be specified as an array of + * indexes or as individual arguments. + * + * **Note:** Unlike `_.at`, this method mutates `array`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to modify. + * @param {...(number|number[])} [indexes] The indexes of elements to remove, + * specified as individual indexes or arrays of indexes. + * @returns {Array} Returns the new array of removed elements. + * @example + * + * var array = [5, 10, 15, 20]; + * var evens = _.pullAt(array, 1, 3); + * + * console.log(array); + * // => [5, 15] + * + * console.log(evens); + * // => [10, 20] + */ + function pullAt(array) { + return basePullAt(array || [], baseFlatten(arguments, false, false, 1)); + } + + /** + * Removes all elements from `array` that `predicate` returns truthy for + * and returns an array of the removed elements. The predicate is bound to + * `thisArg` and invoked with three arguments; (value, index, array). + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * **Note:** Unlike `_.filter`, this method mutates `array`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to modify. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Array} Returns the new array of removed elements. + * @example + * + * var array = [1, 2, 3, 4]; + * var evens = _.remove(array, function(n) { + * return n % 2 == 0; + * }); + * + * console.log(array); + * // => [1, 3] + * + * console.log(evens); + * // => [2, 4] + */ + function remove(array, predicate, thisArg) { + var index = -1, + length = array ? array.length : 0, + result = []; + + predicate = getCallback(predicate, thisArg, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + splice.call(array, index--, 1); + length--; + } + } + return result; + } + + /** + * Gets all but the first element of `array`. + * + * @static + * @memberOf _ + * @alias tail + * @category Array + * @param {Array} array The array to query. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.rest([1, 2, 3]); + * // => [2, 3] + */ + function rest(array) { + return drop(array, 1); + } + + /** + * Creates a slice of `array` from `start` up to, but not including, `end`. + * + * **Note:** This function is used instead of `Array#slice` to support node + * lists in IE < 9 and to ensure dense arrays are returned. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ + function slice(array, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (end && typeof end != 'number' && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } + return baseSlice(array, start, end); + } + + /** + * Uses a binary search to determine the lowest index at which `value` should + * be inserted into `array` in order to maintain its sort order. If an iteratee + * function is provided it is invoked for `value` and each element of `array` + * to compute their sort ranking. The iteratee is bound to `thisArg` and + * invoked with one argument; (value). + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function|Object|string} [iteratee=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * _.sortedIndex([30, 50], 40); + * // => 1 + * + * _.sortedIndex([4, 4, 5, 5], 5); + * // => 2 + * + * var dict = { 'data': { 'thirty': 30, 'forty': 40, 'fifty': 50 } }; + * + * // using an iteratee function + * _.sortedIndex(['thirty', 'fifty'], 'forty', function(word) { + * return this.data[word]; + * }, dict); + * // => 1 + * + * // using the `_.property` callback shorthand + * _.sortedIndex([{ 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); + * // => 1 + */ + function sortedIndex(array, value, iteratee, thisArg) { + var func = getCallback(iteratee); + return (func === baseCallback && iteratee == null) + ? binaryIndex(array, value) + : binaryIndexBy(array, value, func(iteratee, thisArg, 1)); + } + + /** + * This method is like `_.sortedIndex` except that it returns the highest + * index at which `value` should be inserted into `array` in order to + * maintain its sort order. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function|Object|string} [iteratee=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + * @example + * + * _.sortedLastIndex([4, 4, 5, 5], 5); + * // => 4 + */ + function sortedLastIndex(array, value, iteratee, thisArg) { + var func = getCallback(iteratee); + return (func === baseCallback && iteratee == null) + ? binaryIndex(array, value, true) + : binaryIndexBy(array, value, func(iteratee, thisArg, 1), true); + } + + /** + * Creates a slice of `array` with `n` elements taken from the beginning. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to take. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.take([1, 2, 3]); + * // => [1] + * + * _.take([1, 2, 3], 2); + * // => [1, 2] + * + * _.take([1, 2, 3], 5); + * // => [1, 2, 3] + * + * _.take([1, 2, 3], 0); + * // => [] + */ + function take(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, 0, n < 0 ? 0 : n); + } + + /** + * Creates a slice of `array` with `n` elements taken from the end. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to query. + * @param {number} [n=1] The number of elements to take. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.takeRight([1, 2, 3]); + * // => [3] + * + * _.takeRight([1, 2, 3], 2); + * // => [2, 3] + * + * _.takeRight([1, 2, 3], 5); + * // => [1, 2, 3] + * + * _.takeRight([1, 2, 3], 0); + * // => [] + */ + function takeRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, n < 0 ? 0 : n); + } + + /** + * Creates a slice of `array` with elements taken from the end. Elements are + * taken until `predicate` returns falsey. The predicate is bound to `thisArg` + * and invoked with three arguments; (value, index, array). + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to query. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.takeRightWhile([1, 2, 3], function(n) { + * return n > 1; + * }); + * // => [2, 3] + * + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': false } + * ]; + * + * // using the `_.matches` callback shorthand + * _.pluck(_.takeRightWhile(users, { 'user': 'pebbles', 'active': false }), 'user'); + * // => ['pebbles'] + * + * // using the `_.matchesProperty` callback shorthand + * _.pluck(_.takeRightWhile(users, 'active', false), 'user'); + * // => ['fred', 'pebbles'] + * + * // using the `_.property` callback shorthand + * _.pluck(_.takeRightWhile(users, 'active'), 'user'); + * // => [] + */ + function takeRightWhile(array, predicate, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + predicate = getCallback(predicate, thisArg, 3); + while (length-- && predicate(array[length], length, array)) {} + return baseSlice(array, length + 1); + } + + /** + * Creates a slice of `array` with elements taken from the beginning. Elements + * are taken until `predicate` returns falsey. The predicate is bound to + * `thisArg` and invoked with three arguments; (value, index, array). + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to query. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Array} Returns the slice of `array`. + * @example + * + * _.takeWhile([1, 2, 3], function(n) { + * return n < 3; + * }); + * // => [1, 2] + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false}, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * // using the `_.matches` callback shorthand + * _.pluck(_.takeWhile(users, { 'user': 'barney', 'active': false }), 'user'); + * // => ['barney'] + * + * // using the `_.matchesProperty` callback shorthand + * _.pluck(_.takeWhile(users, 'active', false), 'user'); + * // => ['barney', 'fred'] + * + * // using the `_.property` callback shorthand + * _.pluck(_.takeWhile(users, 'active'), 'user'); + * // => [] + */ + function takeWhile(array, predicate, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + var index = -1; + predicate = getCallback(predicate, thisArg, 3); + while (++index < length && predicate(array[index], index, array)) {} + return baseSlice(array, 0, index); + } + + /** + * Creates an array of unique values, in order, of the provided arrays using + * `SameValueZero` for equality comparisons. + * + * **Note:** `SameValueZero` comparisons are like strict equality comparisons, + * e.g. `===`, except that `NaN` matches `NaN`. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * + * @static + * @memberOf _ + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of combined values. + * @example + * + * _.union([1, 2], [4, 2], [2, 1]); + * // => [1, 2, 4] + */ + function union() { + return baseUniq(baseFlatten(arguments, false, true)); + } + + /** + * Creates a duplicate-value-free version of an array using `SameValueZero` + * for equality comparisons. Providing `true` for `isSorted` performs a faster + * search algorithm for sorted arrays. If an iteratee function is provided it + * is invoked for each value in the array to generate the criterion by which + * uniqueness is computed. The `iteratee` is bound to `thisArg` and invoked + * with three arguments; (value, index, array). + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * **Note:** `SameValueZero` comparisons are like strict equality comparisons, + * e.g. `===`, except that `NaN` matches `NaN`. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * + * @static + * @memberOf _ + * @alias unique + * @category Array + * @param {Array} array The array to inspect. + * @param {boolean} [isSorted] Specify the array is sorted. + * @param {Function|Object|string} [iteratee] The function invoked per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Array} Returns the new duplicate-value-free array. + * @example + * + * _.uniq([1, 2, 1]); + * // => [1, 2] + * + * // using `isSorted` + * _.uniq([1, 1, 2], true); + * // => [1, 2] + * + * // using an iteratee function + * _.uniq([1, 2.5, 1.5, 2], function(n) { + * return this.floor(n); + * }, Math); + * // => [1, 2.5] + * + * // using the `_.property` callback shorthand + * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ + function uniq(array, isSorted, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (isSorted != null && typeof isSorted != 'boolean') { + thisArg = iteratee; + iteratee = isIterateeCall(array, isSorted, thisArg) ? null : isSorted; + isSorted = false; + } + var func = getCallback(); + if (!(func === baseCallback && iteratee == null)) { + iteratee = func(iteratee, thisArg, 3); + } + return (isSorted && getIndexOf() == baseIndexOf) + ? sortedUniq(array, iteratee) + : baseUniq(array, iteratee); + } + + /** + * This method is like `_.zip` except that it accepts an array of grouped + * elements and creates an array regrouping the elements to their pre-`_.zip` + * configuration. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array of grouped elements to process. + * @returns {Array} Returns the new array of regrouped elements. + * @example + * + * var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]); + * // => [['fred', 30, true], ['barney', 40, false]] + * + * _.unzip(zipped); + * // => [['fred', 'barney'], [30, 40], [true, false]] + */ + function unzip(array) { + var index = -1, + length = (array && array.length && arrayMax(arrayMap(array, getLength))) >>> 0, + result = Array(length); + + while (++index < length) { + result[index] = arrayMap(array, baseProperty(index)); + } + return result; + } + + /** + * Creates an array excluding all provided values using `SameValueZero` for + * equality comparisons. + * + * **Note:** `SameValueZero` comparisons are like strict equality comparisons, + * e.g. `===`, except that `NaN` matches `NaN`. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to filter. + * @param {...*} [values] The values to exclude. + * @returns {Array} Returns the new array of filtered values. + * @example + * + * _.without([1, 2, 1, 3], 1, 2); + * // => [3] + */ + function without(array) { + return baseDifference(array, baseSlice(arguments, 1)); + } + + /** + * Creates an array that is the symmetric difference of the provided arrays. + * See [Wikipedia](https://en.wikipedia.org/wiki/Symmetric_difference) for + * more details. + * + * @static + * @memberOf _ + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of values. + * @example + * + * _.xor([1, 2], [4, 2]); + * // => [1, 4] + */ + function xor() { + var index = -1, + length = arguments.length; + + while (++index < length) { + var array = arguments[index]; + if (isArray(array) || isArguments(array)) { + var result = result + ? baseDifference(result, array).concat(baseDifference(array, result)) + : array; + } + } + return result ? baseUniq(result) : []; + } + + /** + * Creates an array of grouped elements, the first of which contains the first + * elements of the given arrays, the second of which contains the second elements + * of the given arrays, and so on. + * + * @static + * @memberOf _ + * @category Array + * @param {...Array} [arrays] The arrays to process. + * @returns {Array} Returns the new array of grouped elements. + * @example + * + * _.zip(['fred', 'barney'], [30, 40], [true, false]); + * // => [['fred', 30, true], ['barney', 40, false]] + */ + function zip() { + var length = arguments.length, + array = Array(length); + + while (length--) { + array[length] = arguments[length]; + } + return unzip(array); + } + + /** + * Creates an object composed from arrays of property names and values. Provide + * either a single two dimensional array, e.g. `[[key1, value1], [key2, value2]]` + * or two arrays, one of property names and one of corresponding values. + * + * @static + * @memberOf _ + * @alias object + * @category Array + * @param {Array} props The property names. + * @param {Array} [values=[]] The property values. + * @returns {Object} Returns the new object. + * @example + * + * _.zipObject(['fred', 'barney'], [30, 40]); + * // => { 'fred': 30, 'barney': 40 } + */ + function zipObject(props, values) { + var index = -1, + length = props ? props.length : 0, + result = {}; + + if (length && !values && !isArray(props[0])) { + values = []; + } + while (++index < length) { + var key = props[index]; + if (values) { + result[key] = values[index]; + } else if (key) { + result[key[0]] = key[1]; + } + } + return result; + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` object that wraps `value` with explicit method + * chaining enabled. + * + * @static + * @memberOf _ + * @category Chain + * @param {*} value The value to wrap. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'pebbles', 'age': 1 } + * ]; + * + * var youngest = _.chain(users) + * .sortBy('age') + * .map(function(chr) { + * return chr.user + ' is ' + chr.age; + * }) + * .first() + * .value(); + * // => 'pebbles is 1' + */ + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + + /** + * This method invokes `interceptor` and returns `value`. The interceptor is + * bound to `thisArg` and invoked with one argument; (value). The purpose of + * this method is to "tap into" a method chain in order to perform operations + * on intermediate results within the chain. + * + * @static + * @memberOf _ + * @category Chain + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @param {*} [thisArg] The `this` binding of `interceptor`. + * @returns {*} Returns `value`. + * @example + * + * _([1, 2, 3]) + * .tap(function(array) { + * array.pop(); + * }) + * .reverse() + * .value(); + * // => [2, 1] + */ + function tap(value, interceptor, thisArg) { + interceptor.call(thisArg, value); + return value; + } + + /** + * This method is like `_.tap` except that it returns the result of `interceptor`. + * + * @static + * @memberOf _ + * @category Chain + * @param {*} value The value to provide to `interceptor`. + * @param {Function} interceptor The function to invoke. + * @param {*} [thisArg] The `this` binding of `interceptor`. + * @returns {*} Returns the result of `interceptor`. + * @example + * + * _([1, 2, 3]) + * .last() + * .thru(function(value) { + * return [value]; + * }) + * .value(); + * // => [3] + */ + function thru(value, interceptor, thisArg) { + return interceptor.call(thisArg, value); + } + + /** + * Enables explicit method chaining on the wrapper object. + * + * @name chain + * @memberOf _ + * @category Chain + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } + * ]; + * + * // without explicit chaining + * _(users).first(); + * // => { 'user': 'barney', 'age': 36 } + * + * // with explicit chaining + * _(users).chain() + * .first() + * .pick('user') + * .value(); + * // => { 'user': 'barney' } + */ + function wrapperChain() { + return chain(this); + } + + /** + * Executes the chained sequence and returns the wrapped result. + * + * @name commit + * @memberOf _ + * @category Chain + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2]; + * var wrapper = _(array).push(3); + * + * console.log(array); + * // => [1, 2] + * + * wrapper = wrapper.commit(); + * console.log(array); + * // => [1, 2, 3] + * + * wrapper.last(); + * // => 3 + * + * console.log(array); + * // => [1, 2, 3] + */ + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + + /** + * Creates a clone of the chained sequence planting `value` as the wrapped value. + * + * @name plant + * @memberOf _ + * @category Chain + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var array = [1, 2]; + * var wrapper = _(array).map(function(value) { + * return Math.pow(value, 2); + * }); + * + * var other = [3, 4]; + * var otherWrapper = wrapper.plant(other); + * + * otherWrapper.value(); + * // => [9, 16] + * + * wrapper.value(); + * // => [1, 4] + */ + function wrapperPlant(value) { + var result, + parent = this; + + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + + /** + * Reverses the wrapped array so the first element becomes the last, the + * second element becomes the second to last, and so on. + * + * **Note:** This method mutates the wrapped array. + * + * @name reverse + * @memberOf _ + * @category Chain + * @returns {Object} Returns the new reversed `lodash` wrapper instance. + * @example + * + * var array = [1, 2, 3]; + * + * _(array).reverse().value() + * // => [3, 2, 1] + * + * console.log(array); + * // => [3, 2, 1] + */ + function wrapperReverse() { + var value = this.__wrapped__; + if (value instanceof LazyWrapper) { + if (this.__actions__.length) { + value = new LazyWrapper(this); + } + return new LodashWrapper(value.reverse(), this.__chain__); + } + return this.thru(function(value) { + return value.reverse(); + }); + } + + /** + * Produces the result of coercing the unwrapped value to a string. + * + * @name toString + * @memberOf _ + * @category Chain + * @returns {string} Returns the coerced string value. + * @example + * + * _([1, 2, 3]).toString(); + * // => '1,2,3' + */ + function wrapperToString() { + return (this.value() + ''); + } + + /** + * Executes the chained sequence to extract the unwrapped value. + * + * @name value + * @memberOf _ + * @alias run, toJSON, valueOf + * @category Chain + * @returns {*} Returns the resolved unwrapped value. + * @example + * + * _([1, 2, 3]).value(); + * // => [1, 2, 3] + */ + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + + /*------------------------------------------------------------------------*/ + + /** + * Creates an array of elements corresponding to the given keys, or indexes, + * of `collection`. Keys may be specified as individual arguments or as arrays + * of keys. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {...(number|number[]|string|string[])} [props] The property names + * or indexes of elements to pick, specified individually or in arrays. + * @returns {Array} Returns the new array of picked elements. + * @example + * + * _.at(['a', 'b', 'c'], [0, 2]); + * // => ['a', 'c'] + * + * _.at(['fred', 'barney', 'pebbles'], 0, 2); + * // => ['fred', 'pebbles'] + */ + function at(collection) { + var length = collection ? collection.length : 0; + if (isLength(length)) { + collection = toIterable(collection); + } + return baseAt(collection, baseFlatten(arguments, false, false, 1)); + } + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` through `iteratee`. The corresponding value + * of each key is the number of times the key was returned by `iteratee`. + * The `iteratee` is bound to `thisArg` and invoked with three arguments; + * (value, index|key, collection). + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function|Object|string} [iteratee=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.countBy([4.3, 6.1, 6.4], function(n) { + * return Math.floor(n); + * }); + * // => { '4': 1, '6': 2 } + * + * _.countBy([4.3, 6.1, 6.4], function(n) { + * return this.floor(n); + * }, Math); + * // => { '4': 1, '6': 2 } + * + * _.countBy(['one', 'two', 'three'], 'length'); + * // => { '3': 2, '5': 1 } + */ + var countBy = createAggregator(function(result, value, key) { + hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1); + }); + + /** + * Checks if `predicate` returns truthy for **all** elements of `collection`. + * The predicate is bound to `thisArg` and invoked with three arguments; + * (value, index|key, collection). + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * @static + * @memberOf _ + * @alias all + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + * @example + * + * _.every([true, 1, null, 'yes'], Boolean); + * // => false + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false } + * ]; + * + * // using the `_.matches` callback shorthand + * _.every(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // using the `_.matchesProperty` callback shorthand + * _.every(users, 'active', false); + * // => true + * + * // using the `_.property` callback shorthand + * _.every(users, 'active'); + * // => false + */ + function every(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (typeof predicate != 'function' || typeof thisArg != 'undefined') { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + + /** + * Iterates over elements of `collection`, returning an array of all elements + * `predicate` returns truthy for. The predicate is bound to `thisArg` and + * invoked with three arguments; (value, index|key, collection). + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * @static + * @memberOf _ + * @alias select + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Array} Returns the new filtered array. + * @example + * + * _.filter([4, 5, 6], function(n) { + * return n % 2 == 0; + * }); + * // => [4, 6] + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * // using the `_.matches` callback shorthand + * _.pluck(_.filter(users, { 'age': 36, 'active': true }), 'user'); + * // => ['barney'] + * + * // using the `_.matchesProperty` callback shorthand + * _.pluck(_.filter(users, 'active', false), 'user'); + * // => ['fred'] + * + * // using the `_.property` callback shorthand + * _.pluck(_.filter(users, 'active'), 'user'); + * // => ['barney'] + */ + function filter(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, predicate); + } + + /** + * Iterates over elements of `collection`, returning the first element + * `predicate` returns truthy for. The predicate is bound to `thisArg` and + * invoked with three arguments; (value, index|key, collection). + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * @static + * @memberOf _ + * @alias detect + * @category Collection + * @param {Array|Object|string} collection The collection to search. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false }, + * { 'user': 'pebbles', 'age': 1, 'active': true } + * ]; + * + * _.result(_.find(users, function(chr) { + * return chr.age < 40; + * }), 'user'); + * // => 'barney' + * + * // using the `_.matches` callback shorthand + * _.result(_.find(users, { 'age': 1, 'active': true }), 'user'); + * // => 'pebbles' + * + * // using the `_.matchesProperty` callback shorthand + * _.result(_.find(users, 'active', false), 'user'); + * // => 'fred' + * + * // using the `_.property` callback shorthand + * _.result(_.find(users, 'active'), 'user'); + * // => 'barney' + */ + function find(collection, predicate, thisArg) { + if (isArray(collection)) { + var index = findIndex(collection, predicate, thisArg); + return index > -1 ? collection[index] : undefined; + } + predicate = getCallback(predicate, thisArg, 3); + return baseFind(collection, predicate, baseEach); + } + + /** + * This method is like `_.find` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object|string} collection The collection to search. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * _.findLast([1, 2, 3, 4], function(n) { + * return n % 2 == 1; + * }); + * // => 3 + */ + function findLast(collection, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + return baseFind(collection, predicate, baseEachRight); + } + + /** + * Performs a deep comparison between each element in `collection` and the + * source object, returning the first element that has equivalent property + * values. + * + * **Note:** This method supports comparing arrays, booleans, `Date` objects, + * numbers, `Object` objects, regexes, and strings. Objects are compared by + * their own, not inherited, enumerable properties. For comparing a single + * own or inherited property value see `_.matchesProperty`. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object|string} collection The collection to search. + * @param {Object} source The object of property values to match. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * _.result(_.findWhere(users, { 'age': 36, 'active': true }), 'user'); + * // => 'barney' + * + * _.result(_.findWhere(users, { 'age': 40, 'active': false }), 'user'); + * // => 'fred' + */ + function findWhere(collection, source) { + return find(collection, baseMatches(source)); + } + + /** + * Iterates over elements of `collection` invoking `iteratee` for each element. + * The `iteratee` is bound to `thisArg` and invoked with three arguments; + * (value, index|key, collection). Iterator functions may exit iteration early + * by explicitly returning `false`. + * + * **Note:** As with other "Collections" methods, objects with a `length` property + * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn` + * may be used for object iteration. + * + * @static + * @memberOf _ + * @alias each + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Array|Object|string} Returns `collection`. + * @example + * + * _([1, 2]).forEach(function(n) { + * console.log(n); + * }).value(); + * // => logs each value from left to right and returns the array + * + * _.forEach({ 'a': 1, 'b': 2 }, function(n, key) { + * console.log(n, key); + * }); + * // => logs each value-key pair and returns the object (iteration order is not guaranteed) + */ + function forEach(collection, iteratee, thisArg) { + return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) + ? arrayEach(collection, iteratee) + : baseEach(collection, bindCallback(iteratee, thisArg, 3)); + } + + /** + * This method is like `_.forEach` except that it iterates over elements of + * `collection` from right to left. + * + * @static + * @memberOf _ + * @alias eachRight + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Array|Object|string} Returns `collection`. + * @example + * + * _([1, 2]).forEachRight(function(n) { + * console.log(n); + * }).join(','); + * // => logs each value from right to left and returns the array + */ + function forEachRight(collection, iteratee, thisArg) { + return (typeof iteratee == 'function' && typeof thisArg == 'undefined' && isArray(collection)) + ? arrayEachRight(collection, iteratee) + : baseEachRight(collection, bindCallback(iteratee, thisArg, 3)); + } + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` through `iteratee`. The corresponding value + * of each key is an array of the elements responsible for generating the key. + * The `iteratee` is bound to `thisArg` and invoked with three arguments; + * (value, index|key, collection). + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function|Object|string} [iteratee=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.groupBy([4.2, 6.1, 6.4], function(n) { + * return Math.floor(n); + * }); + * // => { '4': [4.2], '6': [6.1, 6.4] } + * + * _.groupBy([4.2, 6.1, 6.4], function(n) { + * return this.floor(n); + * }, Math); + * // => { '4': [4.2], '6': [6.1, 6.4] } + * + * // using the `_.property` callback shorthand + * _.groupBy(['one', 'two', 'three'], 'length'); + * // => { '3': ['one', 'two'], '5': ['three'] } + */ + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + result[key] = [value]; + } + }); + + /** + * Checks if `value` is in `collection` using `SameValueZero` for equality + * comparisons. If `fromIndex` is negative, it is used as the offset from + * the end of `collection`. + * + * **Note:** `SameValueZero` comparisons are like strict equality comparisons, + * e.g. `===`, except that `NaN` matches `NaN`. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero) + * for more details. + * + * @static + * @memberOf _ + * @alias contains, include + * @category Collection + * @param {Array|Object|string} collection The collection to search. + * @param {*} target The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @returns {boolean} Returns `true` if a matching element is found, else `false`. + * @example * - * var shallow = _.clone(characters); - * shallow[0] === characters[0]; + * _.includes([1, 2, 3], 1); * // => true * - * var deep = _.clone(characters, true); - * deep[0] === characters[0]; + * _.includes([1, 2, 3], 1, 2); * // => false * - * _.mixin({ - * 'clone': _.partialRight(_.clone, function(value) { - * return _.isElement(value) ? value.cloneNode(false) : undefined; - * }) - * }); + * _.includes({ 'user': 'fred', 'age': 40 }, 'fred'); + * // => true * - * var clone = _.clone(document.body); - * clone.childNodes.length; - * // => 0 + * _.includes('pebbles', 'eb'); + * // => true */ - function clone(value, isDeep, callback, thisArg) { - // allows working with "Collections" methods without using their `index` - // and `collection` arguments for `isDeep` and `callback` - if (typeof isDeep != 'boolean' && isDeep != null) { - thisArg = callback; - callback = isDeep; - isDeep = false; + function includes(collection, target, fromIndex) { + var length = collection ? collection.length : 0; + if (!isLength(length)) { + collection = values(collection); + length = collection.length; + } + if (!length) { + return false; + } + if (typeof fromIndex == 'number') { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); + } else { + fromIndex = 0; } - return baseClone(value, isDeep, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1)); + return (typeof collection == 'string' || !isArray(collection) && isString(collection)) + ? (fromIndex < length && collection.indexOf(target, fromIndex) > -1) + : (getIndexOf(collection, target, fromIndex) > -1); + } + + /** + * Creates an object composed of keys generated from the results of running + * each element of `collection` through `iteratee`. The corresponding value + * of each key is the last element responsible for generating the key. The + * iteratee function is bound to `thisArg` and invoked with three arguments; + * (value, index|key, collection). + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function|Object|string} [iteratee=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * var keyData = [ + * { 'dir': 'left', 'code': 97 }, + * { 'dir': 'right', 'code': 100 } + * ]; + * + * _.indexBy(keyData, 'dir'); + * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } + * + * _.indexBy(keyData, function(object) { + * return String.fromCharCode(object.code); + * }); + * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } + * + * _.indexBy(keyData, function(object) { + * return this.fromCharCode(object.code); + * }, String); + * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } + */ + var indexBy = createAggregator(function(result, value, key) { + result[key] = value; + }); + + /** + * Invokes the method named by `methodName` on each element in `collection`, + * returning an array of the results of each invoked method. Any additional + * arguments are provided to each invoked method. If `methodName` is a function + * it is invoked for, and `this` bound to, each element in `collection`. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function|string} methodName The name of the method to invoke or + * the function invoked per iteration. + * @param {...*} [args] The arguments to invoke the method with. + * @returns {Array} Returns the array of results. + * @example + * + * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort'); + * // => [[1, 5, 7], [1, 2, 3]] + * + * _.invoke([123, 456], String.prototype.split, ''); + * // => [['1', '2', '3'], ['4', '5', '6']] + */ + function invoke(collection, methodName) { + return baseInvoke(collection, methodName, baseSlice(arguments, 2)); } /** - * Creates a deep clone of `value`. If a callback is provided it will be - * executed to produce the cloned values. If the callback returns `undefined` - * cloning will be handled by the method instead. The callback is bound to - * `thisArg` and invoked with one argument; (value). + * Creates an array of values by running each element in `collection` through + * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three + * arguments; (value, index|key, collection). + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. * - * Note: This method is loosely based on the structured clone algorithm. Functions - * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and - * objects created by constructors other than `Object` are cloned to plain `Object` objects. - * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm. + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * Many lodash methods are guarded to work as interatees for methods like + * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. + * + * The guarded methods are: + * `ary`, `callback`, `chunk`, `clone`, `create`, `curry`, `curryRight`, `drop`, + * `dropRight`, `fill`, `flatten`, `invert`, `max`, `min`, `parseInt`, `slice`, + * `sortBy`, `take`, `takeRight`, `template`, `trim`, `trimLeft`, `trimRight`, + * `trunc`, `random`, `range`, `sample`, `uniq`, and `words` * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to deep clone. - * @param {Function} [callback] The function to customize cloning values. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the deep cloned value. + * @alias collect + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function|Object|string} [iteratee=_.identity] The function invoked + * per iteration. + * create a `_.property` or `_.matches` style callback respectively. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Array} Returns the new mapped array. * @example * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } + * function timesThree(n) { + * return n * 3; + * } + * + * _.map([1, 2], timesThree); + * // => [3, 6] + * + * _.map({ 'a': 1, 'b': 2 }, timesThree); + * // => [3, 6] (iteration order is not guaranteed) + * + * var users = [ + * { 'user': 'barney' }, + * { 'user': 'fred' } * ]; * - * var deep = _.cloneDeep(characters); - * deep[0] === characters[0]; - * // => false + * // using the `_.property` callback shorthand + * _.map(users, 'user'); + * // => ['barney', 'fred'] + */ + function map(collection, iteratee, thisArg) { + var func = isArray(collection) ? arrayMap : baseMap; + iteratee = getCallback(iteratee, thisArg, 3); + return func(collection, iteratee); + } + + /** + * Gets the maximum value of `collection`. If `collection` is empty or falsey + * `-Infinity` is returned. If an iteratee function is provided it is invoked + * for each value in `collection` to generate the criterion by which the value + * is ranked. The `iteratee` is bound to `thisArg` and invoked with three + * arguments; (value, index, collection). * - * var view = { - * 'label': 'docs', - * 'node': element + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function|Object|string} [iteratee] The function invoked per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {*} Returns the maximum value. + * @example + * + * _.max([4, 2, 8, 6]); + * // => 8 + * + * _.max([]); + * // => -Infinity + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } + * ]; + * + * _.max(users, function(chr) { + * return chr.age; + * }); + * // => { 'user': 'fred', 'age': 40 }; + * + * // using the `_.property` callback shorthand + * _.max(users, 'age'); + * // => { 'user': 'fred', 'age': 40 }; + */ + var max = createExtremum(arrayMax); + + /** + * Gets the minimum value of `collection`. If `collection` is empty or falsey + * `Infinity` is returned. If an iteratee function is provided it is invoked + * for each value in `collection` to generate the criterion by which the value + * is ranked. The `iteratee` is bound to `thisArg` and invoked with three + * arguments; (value, index, collection). + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function|Object|string} [iteratee] The function invoked per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {*} Returns the minimum value. + * @example + * + * _.min([4, 2, 8, 6]); + * // => 2 + * + * _.min([]); + * // => Infinity + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } + * ]; + * + * _.min(users, function(chr) { + * return chr.age; + * }); + * // => { 'user': 'barney', 'age': 36 }; + * + * // using the `_.property` callback shorthand + * _.min(users, 'age'); + * // => { 'user': 'barney', 'age': 36 }; + */ + var min = createExtremum(arrayMin, true); + + /** + * Creates an array of elements split into two groups, the first of which + * contains elements `predicate` returns truthy for, while the second of which + * contains elements `predicate` returns falsey for. The predicate is bound + * to `thisArg` and invoked with three arguments; (value, index|key, collection). + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Array} Returns the array of grouped elements. + * @example + * + * _.partition([1, 2, 3], function(n) { + * return n % 2; + * }); + * // => [[1, 3], [2]] + * + * _.partition([1.2, 2.3, 3.4], function(n) { + * return this.floor(n) % 2; + * }, Math); + * // => [[1, 3], [2]] + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true }, + * { 'user': 'pebbles', 'age': 1, 'active': false } + * ]; + * + * var mapper = function(array) { + * return _.pluck(array, 'user'); * }; * - * var clone = _.cloneDeep(view, function(value) { - * return _.isElement(value) ? value.cloneNode(true) : undefined; + * // using the `_.matches` callback shorthand + * _.map(_.partition(users, { 'age': 1, 'active': false }), mapper); + * // => [['pebbles'], ['barney', 'fred']] + * + * // using the `_.matchesProperty` callback shorthand + * _.map(_.partition(users, 'active', false), mapper); + * // => [['barney', 'pebbles'], ['fred']] + * + * // using the `_.property` callback shorthand + * _.map(_.partition(users, 'active'), mapper); + * // => [['fred'], ['barney', 'pebbles']] + */ + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { return [[], []]; }); + + /** + * Gets the value of `key` from all elements in `collection`. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {string} key The key of the property to pluck. + * @returns {Array} Returns the property values. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 } + * ]; + * + * _.pluck(users, 'user'); + * // => ['barney', 'fred'] + * + * var userIndex = _.indexBy(users, 'user'); + * _.pluck(userIndex, 'age'); + * // => [36, 40] (iteration order is not guaranteed) + */ + function pluck(collection, key) { + return map(collection, baseProperty(key)); + } + + /** + * Reduces `collection` to a value which is the accumulated result of running + * each element in `collection` through `iteratee`, where each successive + * invocation is supplied the return value of the previous. If `accumulator` + * is not provided the first element of `collection` is used as the initial + * value. The `iteratee` is bound to `thisArg`and invoked with four arguments; + * (accumulator, value, index|key, collection). + * + * Many lodash methods are guarded to work as interatees for methods like + * `_.reduce`, `_.reduceRight`, and `_.transform`. + * + * The guarded methods are: + * `assign`, `defaults`, `merge`, and `sortAllBy` + * + * @static + * @memberOf _ + * @alias foldl, inject + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {*} Returns the accumulated value. + * @example + * + * _.reduce([1, 2], function(sum, n) { + * return sum + n; * }); + * // => 3 * - * clone.node == view.node; - * // => false + * _.reduce({ 'a': 1, 'b': 2 }, function(result, n, key) { + * result[key] = n * 3; + * return result; + * }, {}); + * // => { 'a': 3, 'b': 6 } (iteration order is not guaranteed) */ - function cloneDeep(value, callback, thisArg) { - return baseClone(value, true, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1)); + function reduce(collection, iteratee, accumulator, thisArg) { + var func = isArray(collection) ? arrayReduce : baseReduce; + return func(collection, getCallback(iteratee, thisArg, 4), accumulator, arguments.length < 3, baseEach); } /** - * Creates an object that inherits from the given `prototype` object. If a - * `properties` object is provided its own enumerable properties are assigned - * to the created object. + * This method is like `_.reduce` except that it iterates over elements of + * `collection` from right to left. * * @static * @memberOf _ - * @category Objects - * @param {Object} prototype The object to inherit from. - * @param {Object} [properties] The properties to assign to the object. - * @returns {Object} Returns the new object. + * @alias foldr + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The initial value. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {*} Returns the accumulated value. * @example * - * function Shape() { - * this.x = 0; - * this.y = 0; - * } + * var array = [[0, 1], [2, 3], [4, 5]]; * - * function Circle() { - * Shape.call(this); - * } + * _.reduceRight(array, function(flattened, other) { + * return flattened.concat(other); + * }, []); + * // => [4, 5, 2, 3, 0, 1] + */ + function reduceRight(collection, iteratee, accumulator, thisArg) { + var func = isArray(collection) ? arrayReduceRight : baseReduce; + return func(collection, getCallback(iteratee, thisArg, 4), accumulator, arguments.length < 3, baseEachRight); + } + + /** + * The opposite of `_.filter`; this method returns the elements of `collection` + * that `predicate` does **not** return truthy for. * - * Circle.prototype = _.create(Shape.prototype, { 'constructor': Circle }); + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. * - * var circle = new Circle; - * circle instanceof Circle; + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Array} Returns the new filtered array. + * @example + * + * _.reject([1, 2, 3, 4], function(n) { + * return n % 2 == 0; + * }); + * // => [1, 3] + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': true } + * ]; + * + * // using the `_.matches` callback shorthand + * _.pluck(_.reject(users, { 'age': 40, 'active': true }), 'user'); + * // => ['barney'] + * + * // using the `_.matchesProperty` callback shorthand + * _.pluck(_.reject(users, 'active', false), 'user'); + * // => ['fred'] + * + * // using the `_.property` callback shorthand + * _.pluck(_.reject(users, 'active'), 'user'); + * // => ['barney'] + */ + function reject(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, function(value, index, collection) { + return !predicate(value, index, collection); + }); + } + + /** + * Gets a random element or `n` random elements from a collection. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object|string} collection The collection to sample. + * @param {number} [n] The number of elements to sample. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {*} Returns the random sample(s). + * @example + * + * _.sample([1, 2, 3, 4]); + * // => 2 + * + * _.sample([1, 2, 3, 4], 2); + * // => [3, 1] + */ + function sample(collection, n, guard) { + if (guard ? isIterateeCall(collection, n, guard) : n == null) { + collection = toIterable(collection); + var length = collection.length; + return length > 0 ? collection[baseRandom(0, length - 1)] : undefined; + } + var result = shuffle(collection); + result.length = nativeMin(n < 0 ? 0 : (+n || 0), result.length); + return result; + } + + /** + * Creates an array of shuffled values, using a version of the Fisher-Yates + * shuffle. See [Wikipedia](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle) + * for more details. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object|string} collection The collection to shuffle. + * @returns {Array} Returns the new shuffled array. + * @example + * + * _.shuffle([1, 2, 3, 4]); + * // => [4, 1, 3, 2] + */ + function shuffle(collection) { + collection = toIterable(collection); + + var index = -1, + length = collection.length, + result = Array(length); + + while (++index < length) { + var rand = baseRandom(0, index); + if (index != rand) { + result[index] = result[rand]; + } + result[rand] = collection[index]; + } + return result; + } + + /** + * Gets the size of `collection` by returning `collection.length` for + * array-like values or the number of own enumerable properties for objects. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object|string} collection The collection to inspect. + * @returns {number} Returns the size of `collection`. + * @example + * + * _.size([1, 2, 3]); + * // => 3 + * + * _.size({ 'a': 1, 'b': 2 }); + * // => 2 + * + * _.size('pebbles'); + * // => 7 + */ + function size(collection) { + var length = collection ? collection.length : 0; + return isLength(length) ? length : keys(collection).length; + } + + /** + * Checks if `predicate` returns truthy for **any** element of `collection`. + * The function returns as soon as it finds a passing value and does not iterate + * over the entire collection. The predicate is bound to `thisArg` and invoked + * with three arguments; (value, index|key, collection). + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * @static + * @memberOf _ + * @alias any + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + * @example + * + * _.some([null, 0, 'yes', false], Boolean); * // => true * - * circle instanceof Shape; + * var users = [ + * { 'user': 'barney', 'active': true }, + * { 'user': 'fred', 'active': false } + * ]; + * + * // using the `_.matches` callback shorthand + * _.some(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // using the `_.matchesProperty` callback shorthand + * _.some(users, 'active', false); + * // => true + * + * // using the `_.property` callback shorthand + * _.some(users, 'active'); * // => true */ - function create(prototype, properties) { - var result = baseCreate(prototype); - return properties ? assign(result, properties) : result; + function some(collection, predicate, thisArg) { + var func = isArray(collection) ? arraySome : baseSome; + if (typeof predicate != 'function' || typeof thisArg != 'undefined') { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); } /** - * Assigns own enumerable properties of source object(s) to the destination - * object for all destination properties that resolve to `undefined`. Once a - * property is set, additional defaults of the same property will be ignored. + * Creates an array of elements, sorted in ascending order by the results of + * running each element in a collection through `iteratee`. This method performs + * a stable sort, that is, it preserves the original sort order of equal elements. + * The `iteratee` is bound to `thisArg` and invoked with three arguments; + * (value, index|key, collection). + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. * * @static * @memberOf _ - * @type Function - * @category Objects - * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. - * @param- {Object} [guard] Allows working with `_.reduce` without using its - * `key` and `object` arguments as sources. - * @returns {Object} Returns the destination object. + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Array|Function|Object|string} [iteratee=_.identity] The function + * invoked per iteration. If a property name or an object is provided it is + * used to create a `_.property` or `_.matches` style callback respectively. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Array} Returns the new sorted array. * @example * - * var object = { 'name': 'barney' }; - * _.defaults(object, { 'name': 'fred', 'employer': 'slate' }); - * // => { 'name': 'barney', 'employer': 'slate' } + * _.sortBy([1, 2, 3], function(n) { + * return Math.sin(n); + * }); + * // => [3, 1, 2] + * + * _.sortBy([1, 2, 3], function(n) { + * return this.sin(n); + * }, Math); + * // => [3, 1, 2] + * + * var users = [ + * { 'user': 'fred' }, + * { 'user': 'pebbles' }, + * { 'user': 'barney' } + * ]; + * + * // using the `_.property` callback shorthand + * _.pluck(_.sortBy(users, 'user'), 'user'); + * // => ['barney', 'fred', 'pebbles'] */ - var defaults = function(object, source, guard) { - var index, iterable = object, result = iterable; - if (!iterable) return result; - var args = arguments, - argsIndex = 0, - argsLength = typeof guard == 'number' ? 2 : args.length; - while (++argsIndex < argsLength) { - iterable = args[argsIndex]; - if (iterable && objectTypes[typeof iterable]) { - var ownIndex = -1, - ownProps = objectTypes[typeof iterable] && keys(iterable), - length = ownProps ? ownProps.length : 0; - - while (++ownIndex < length) { - index = ownProps[ownIndex]; - if (typeof result[index] == 'undefined') result[index] = iterable[index]; - } - } + function sortBy(collection, iteratee, thisArg) { + var index = -1, + length = collection ? collection.length : 0, + result = isLength(length) ? Array(length) : []; + + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = null; } - return result - }; + iteratee = getCallback(iteratee, thisArg, 3); + baseEach(collection, function(value, key, collection) { + result[++index] = { 'criteria': iteratee(value, key, collection), 'index': index, 'value': value }; + }); + return baseSortBy(result, compareAscending); + } /** - * This method is like `_.findIndex` except that it returns the key of the - * first element that passes the callback check, instead of the element itself. + * This method is like `_.sortBy` except that it sorts by property names + * instead of an iteratee function. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {...(string|string[])} props The property names to sort by, + * specified as individual property names or arrays of property names. + * @returns {Array} Returns the new sorted array. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36 }, + * { 'user': 'fred', 'age': 40 }, + * { 'user': 'barney', 'age': 26 }, + * { 'user': 'fred', 'age': 30 } + * ]; + * + * _.map(_.sortByAll(users, ['user', 'age']), _.values); + * // => [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]] + */ + function sortByAll(collection) { + var args = arguments; + if (args.length > 3 && isIterateeCall(args[1], args[2], args[3])) { + args = [collection, args[1]]; + } + var index = -1, + length = collection ? collection.length : 0, + props = baseFlatten(args, false, false, 1), + result = isLength(length) ? Array(length) : []; + + baseEach(collection, function(value) { + var length = props.length, + criteria = Array(length); + + while (length--) { + criteria[length] = value == null ? undefined : value[props[length]]; + } + result[++index] = { 'criteria': criteria, 'index': index, 'value': value }; + }); + return baseSortBy(result, compareMultipleAscending); + } + + /** + * Performs a deep comparison between each element in `collection` and the + * source object, returning an array of all elements that have equivalent + * property values. + * + * **Note:** This method supports comparing arrays, booleans, `Date` objects, + * numbers, `Object` objects, regexes, and strings. Objects are compared by + * their own, not inherited, enumerable properties. For comparing a single + * own or inherited property value see `_.matchesProperty`. + * + * @static + * @memberOf _ + * @category Collection + * @param {Array|Object|string} collection The collection to search. + * @param {Object} source The object of property values to match. + * @returns {Array} Returns the new filtered array. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false, 'pets': ['hoppy'] }, + * { 'user': 'fred', 'age': 40, 'active': true, 'pets': ['baby puss', 'dino'] } + * ]; * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * _.pluck(_.where(users, { 'age': 36, 'active': false }), 'user'); + * // => ['barney'] * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * _.pluck(_.where(users, { 'pets': ['dino'] }), 'user'); + * // => ['fred'] + */ + function where(collection, source) { + return filter(collection, baseMatches(source)); + } + + /*------------------------------------------------------------------------*/ + + /** + * Gets the number of milliseconds that have elapsed since the Unix epoch + * (1 January 1970 00:00:00 UTC). * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to search. - * @param {Function|Object|string} [callback=identity] The function called per - * iteration. If a property name or object is provided it will be used to - * create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {string|undefined} Returns the key of the found element, else `undefined`. + * @category Date * @example * - * var characters = { - * 'barney': { 'age': 36, 'blocked': false }, - * 'fred': { 'age': 40, 'blocked': true }, - * 'pebbles': { 'age': 1, 'blocked': false } - * }; + * _.defer(function(stamp) { + * console.log(_.now() - stamp); + * }, _.now()); + * // => logs the number of milliseconds it took for the deferred function to be invoked + */ + var now = nativeNow || function() { + return new Date().getTime(); + }; + + /*------------------------------------------------------------------------*/ + + /** + * The opposite of `_.before`; this method creates a function that invokes + * `func` once it is called `n` or more times. * - * _.findKey(characters, function(chr) { - * return chr.age < 40; + * @static + * @memberOf _ + * @category Function + * @param {number} n The number of calls before `func` is invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var saves = ['profile', 'settings']; + * + * var done = _.after(saves.length, function() { + * console.log('done saving!'); * }); - * // => 'barney' (property order is not guaranteed across environments) * - * // using "_.where" callback shorthand - * _.findKey(characters, { 'age': 1 }); - * // => 'pebbles' + * _.forEach(saves, function(type) { + * asyncSave({ 'type': type, 'complete': done }); + * }); + * // => logs 'done saving!' after the two async saves have completed + */ + function after(n, func) { + if (typeof func != 'function') { + if (typeof n == 'function') { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + n = nativeIsFinite(n = +n) ? n : 0; + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + + /** + * Creates a function that accepts up to `n` arguments ignoring any + * additional arguments. + * + * @static + * @memberOf _ + * @category Function + * @param {Function} func The function to cap arguments for. + * @param {number} [n=func.length] The arity cap. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Function} Returns the new function. + * @example + * + * _.map(['6', '8', '10'], _.ary(parseInt, 1)); + * // => [6, 8, 10] + */ + function ary(func, n, guard) { + if (guard && isIterateeCall(func, n, guard)) { + n = null; + } + n = (func && n == null) ? func.length : nativeMax(+n || 0, 0); + return createWrapper(func, ARY_FLAG, null, null, null, null, n); + } + + /** + * Creates a function that invokes `func`, with the `this` binding and arguments + * of the created function, while it is called less than `n` times. Subsequent + * calls to the created function return the result of the last `func` invocation. + * + * @static + * @memberOf _ + * @category Function + * @param {number} n The number of calls at which `func` is no longer invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example * - * // using "_.pluck" callback shorthand - * _.findKey(characters, 'blocked'); - * // => 'fred' + * jQuery('#add').on('click', _.before(5, addContactToList)); + * // => allows adding up to 4 contacts to the list */ - function findKey(object, callback, thisArg) { + function before(n, func) { var result; - callback = lodash.createCallback(callback, thisArg, 3); - forOwn(object, function(value, key, object) { - if (callback(value, key, object)) { - result = key; - return false; + if (typeof func != 'function') { + if (typeof n == 'function') { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); } - }); - return result; + } + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } else { + func = null; + } + return result; + }; } /** - * This method is like `_.findKey` except that it iterates over elements - * of a `collection` in the opposite order. + * Creates a function that invokes `func` with the `this` binding of `thisArg` + * and prepends any additional `_.bind` arguments to those provided to the + * bound function. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for partially applied arguments. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * **Note:** Unlike native `Function#bind` this method does not set the `length` + * property of bound functions. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to search. - * @param {Function|Object|string} [callback=identity] The function called per - * iteration. If a property name or object is provided it will be used to - * create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {string|undefined} Returns the key of the found element, else `undefined`. + * @category Function + * @param {Function} func The function to bind. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} [args] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. * @example * - * var characters = { - * 'barney': { 'age': 36, 'blocked': true }, - * 'fred': { 'age': 40, 'blocked': false }, - * 'pebbles': { 'age': 1, 'blocked': true } + * var greet = function(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; * }; * - * _.findLastKey(characters, function(chr) { - * return chr.age < 40; - * }); - * // => returns `pebbles`, assuming `_.findKey` returns `barney` + * var object = { 'user': 'fred' }; * - * // using "_.where" callback shorthand - * _.findLastKey(characters, { 'age': 40 }); - * // => 'fred' + * var bound = _.bind(greet, object, 'hi'); + * bound('!'); + * // => 'hi fred!' * - * // using "_.pluck" callback shorthand - * _.findLastKey(characters, 'blocked'); - * // => 'pebbles' + * // using placeholders + * var bound = _.bind(greet, object, _, '!'); + * bound('hi'); + * // => 'hi fred!' */ - function findLastKey(object, callback, thisArg) { - var result; - callback = lodash.createCallback(callback, thisArg, 3); - forOwnRight(object, function(value, key, object) { - if (callback(value, key, object)) { - result = key; - return false; - } - }); - return result; + function bind(func, thisArg) { + var bitmask = BIND_FLAG; + if (arguments.length > 2) { + var partials = baseSlice(arguments, 2), + holders = replaceHolders(partials, bind.placeholder); + + bitmask |= PARTIAL_FLAG; + } + return createWrapper(func, bitmask, thisArg, partials, holders); } /** - * Iterates over own and inherited enumerable properties of an object, - * executing the callback for each property. The callback is bound to `thisArg` - * and invoked with three arguments; (value, key, object). Callbacks may exit - * iteration early by explicitly returning `false`. + * Binds methods of an object to the object itself, overwriting the existing + * method. Method names may be specified as individual arguments or as arrays + * of method names. If no method names are provided all enumerable function + * properties, own and inherited, of `object` are bound. + * + * **Note:** This method does not set the `length` property of bound functions. * * @static * @memberOf _ - * @type Function - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. + * @category Function + * @param {Object} object The object to bind and assign the bound methods to. + * @param {...(string|string[])} [methodNames] The object method names to bind, + * specified as individual method names or arrays of method names. * @returns {Object} Returns `object`. * @example * - * function Shape() { - * this.x = 0; - * this.y = 0; - * } - * - * Shape.prototype.move = function(x, y) { - * this.x += x; - * this.y += y; + * var view = { + * 'label': 'docs', + * 'onClick': function() { + * console.log('clicked ' + this.label); + * } * }; * - * _.forIn(new Shape, function(value, key) { - * console.log(key); - * }); - * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments) - */ - var forIn = function(collection, callback, thisArg) { - var index, iterable = collection, result = iterable; - if (!iterable) return result; - if (!objectTypes[typeof iterable]) return result; - callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3); - for (index in iterable) { - if (callback(iterable[index], index, collection) === false) return result; - } - return result - }; + * _.bindAll(view); + * jQuery('#docs').on('click', view.onClick); + * // => logs 'clicked docs' when the element is clicked + */ + function bindAll(object) { + return baseBindAll(object, + arguments.length > 1 + ? baseFlatten(arguments, false, false, 1) + : functions(object) + ); + } /** - * This method is like `_.forIn` except that it iterates over elements - * of a `collection` in the opposite order. + * Creates a function that invokes the method at `object[key]` and prepends + * any additional `_.bindKey` arguments to those provided to the bound function. + * + * This method differs from `_.bind` by allowing bound functions to reference + * methods that may be redefined or don't yet exist. + * See [Peter Michaux's article](http://michaux.ca/articles/lazy-function-definition-pattern) + * for more details. + * + * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns `object`. + * @category Function + * @param {Object} object The object the method belongs to. + * @param {string} key The key of the method. + * @param {...*} [args] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. * @example * - * function Shape() { - * this.x = 0; - * this.y = 0; - * } + * var object = { + * 'user': 'fred', + * 'greet': function(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * } + * }; * - * Shape.prototype.move = function(x, y) { - * this.x += x; - * this.y += y; + * var bound = _.bindKey(object, 'greet', 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * object.greet = function(greeting, punctuation) { + * return greeting + 'ya ' + this.user + punctuation; * }; * - * _.forInRight(new Shape, function(value, key) { - * console.log(key); - * }); - * // => logs 'move', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'move' + * bound('!'); + * // => 'hiya fred!' + * + * // using placeholders + * var bound = _.bindKey(object, 'greet', _, '!'); + * bound('hi'); + * // => 'hiya fred!' */ - function forInRight(object, callback, thisArg) { - var pairs = []; - - forIn(object, function(value, key) { - pairs.push(key, value); - }); + function bindKey(object, key) { + var bitmask = BIND_FLAG | BIND_KEY_FLAG; + if (arguments.length > 2) { + var partials = baseSlice(arguments, 2), + holders = replaceHolders(partials, bindKey.placeholder); - var length = pairs.length; - callback = baseCreateCallback(callback, thisArg, 3); - while (length--) { - if (callback(pairs[length--], pairs[length], object) === false) { - break; - } + bitmask |= PARTIAL_FLAG; } - return object; + return createWrapper(key, bitmask, object, partials, holders); } /** - * Iterates over own enumerable properties of an object, executing the callback - * for each property. The callback is bound to `thisArg` and invoked with three - * arguments; (value, key, object). Callbacks may exit iteration early by - * explicitly returning `false`. + * Creates a function that accepts one or more arguments of `func` that when + * called either invokes `func` returning its result, if all `func` arguments + * have been provided, or returns a function that accepts one or more of the + * remaining `func` arguments, and so on. The arity of `func` may be specified + * if `func.length` is not sufficient. * - * @static - * @memberOf _ - * @type Function - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns `object`. - * @example + * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for provided arguments. * - * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { - * console.log(key); - * }); - * // => logs '0', '1', and 'length' (property order is not guaranteed across environments) - */ - var forOwn = function(collection, callback, thisArg) { - var index, iterable = collection, result = iterable; - if (!iterable) return result; - if (!objectTypes[typeof iterable]) return result; - callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3); - var ownIndex = -1, - ownProps = objectTypes[typeof iterable] && keys(iterable), - length = ownProps ? ownProps.length : 0; - - while (++ownIndex < length) { - index = ownProps[ownIndex]; - if (callback(iterable[index], index, collection) === false) return result; - } - return result - }; - - /** - * This method is like `_.forOwn` except that it iterates over elements - * of a `collection` in the opposite order. + * **Note:** This method does not set the `length` property of curried functions. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns `object`. + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Function} Returns the new curried function. * @example * - * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { - * console.log(key); - * }); - * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length' + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; + * + * var curried = _.curry(abc); + * + * curried(1)(2)(3); + * // => [1, 2, 3] + * + * curried(1, 2)(3); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // using placeholders + * curried(1)(_, 3)(2); + * // => [1, 2, 3] */ - function forOwnRight(object, callback, thisArg) { - var props = keys(object), - length = props.length; - - callback = baseCreateCallback(callback, thisArg, 3); - while (length--) { - var key = props[length]; - if (callback(object[key], key, object) === false) { - break; - } + function curry(func, arity, guard) { + if (guard && isIterateeCall(func, arity, guard)) { + arity = null; } - return object; + var result = createWrapper(func, CURRY_FLAG, null, null, null, null, null, arity); + result.placeholder = curry.placeholder; + return result; } /** - * Creates a sorted array of property names of all enumerable properties, - * own and inherited, of `object` that have function values. + * This method is like `_.curry` except that arguments are applied to `func` + * in the manner of `_.partialRight` instead of `_.partial`. * - * @static - * @memberOf _ - * @alias methods - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property names that have function values. - * @example + * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for provided arguments. * - * _.functions(_); - * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] - */ - function functions(object) { - var result = []; - forIn(object, function(value, key) { - if (isFunction(value)) { - result.push(key); - } - }); - return result.sort(); - } - - /** - * Checks if the specified property name exists as a direct property of `object`, - * instead of an inherited property. + * **Note:** This method does not set the `length` property of curried functions. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @param {string} key The name of the property to check. - * @returns {boolean} Returns `true` if key is a direct property, else `false`. + * @category Function + * @param {Function} func The function to curry. + * @param {number} [arity=func.length] The arity of `func`. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Function} Returns the new curried function. * @example * - * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b'); - * // => true + * var abc = function(a, b, c) { + * return [a, b, c]; + * }; + * + * var curried = _.curryRight(abc); + * + * curried(3)(2)(1); + * // => [1, 2, 3] + * + * curried(2, 3)(1); + * // => [1, 2, 3] + * + * curried(1, 2, 3); + * // => [1, 2, 3] + * + * // using placeholders + * curried(3)(1, _)(2); + * // => [1, 2, 3] */ - function has(object, key) { - return object ? hasOwnProperty.call(object, key) : false; + function curryRight(func, arity, guard) { + if (guard && isIterateeCall(func, arity, guard)) { + arity = null; + } + var result = createWrapper(func, CURRY_RIGHT_FLAG, null, null, null, null, null, arity); + result.placeholder = curryRight.placeholder; + return result; } /** - * Creates an object composed of the inverted keys and values of the given object. + * Creates a function that delays invoking `func` until after `wait` milliseconds + * have elapsed since the last time it was invoked. The created function comes + * with a `cancel` method to cancel delayed invocations. Provide an options + * object to indicate that `func` should be invoked on the leading and/or + * trailing edge of the `wait` timeout. Subsequent calls to the debounced + * function return the result of the last `func` invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked + * on the trailing edge of the timeout only if the the debounced function is + * invoked more than once during the `wait` timeout. + * + * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation) + * for details over the differences between `_.debounce` and `_.throttle`. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to invert. - * @returns {Object} Returns the created inverted object. + * @category Function + * @param {Function} func The function to debounce. + * @param {number} [wait=0] The number of milliseconds to delay. + * @param {Object} [options] The options object. + * @param {boolean} [options.leading=false] Specify invoking on the leading + * edge of the timeout. + * @param {number} [options.maxWait] The maximum time `func` is allowed to be + * delayed before it is invoked. + * @param {boolean} [options.trailing=true] Specify invoking on the trailing + * edge of the timeout. + * @returns {Function} Returns the new debounced function. * @example * - * _.invert({ 'first': 'fred', 'second': 'barney' }); - * // => { 'fred': 'first', 'barney': 'second' } + * // avoid costly calculations while the window size is in flux + * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); + * + * // invoke `sendMail` when the click event is fired, debouncing subsequent calls + * jQuery('#postbox').on('click', _.debounce(sendMail, 300, { + * 'leading': true, + * 'trailing': false + * })); + * + * // ensure `batchLog` is invoked once after 1 second of debounced calls + * var source = new EventSource('/stream'); + * jQuery(source).on('message', _.debounce(batchLog, 250, { + * 'maxWait': 1000 + * })); + * + * // cancel a debounced call + * var todoChanges = _.debounce(batchLog, 1000); + * Object.observe(models.todo, todoChanges); + * + * Object.observe(models, function(changes) { + * if (_.find(changes, { 'user': 'todo', 'type': 'delete'})) { + * todoChanges.cancel(); + * } + * }, ['delete']); + * + * // ...at some point `models.todo` is changed + * models.todo.completed = true; + * + * // ...before 1 second has passed `models.todo` is deleted + * // which cancels the debounced `todoChanges` call + * delete models.todo; */ - function invert(object) { - var index = -1, - props = keys(object), - length = props.length, - result = {}; + function debounce(func, wait, options) { + var args, + maxTimeoutId, + result, + stamp, + thisArg, + timeoutId, + trailingCall, + lastCalled = 0, + maxWait = false, + trailing = true; - while (++index < length) { - var key = props[index]; - result[object[key]] = key; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); } - return result; + wait = wait < 0 ? 0 : (+wait || 0); + if (options === true) { + var leading = true; + trailing = false; + } else if (isObject(options)) { + leading = options.leading; + maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait); + trailing = 'trailing' in options ? options.trailing : trailing; + } + + function cancel() { + if (timeoutId) { + clearTimeout(timeoutId); + } + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + } + + function delayed() { + var remaining = wait - (now() - stamp); + if (remaining <= 0 || remaining > wait) { + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + var isCalled = trailingCall; + maxTimeoutId = timeoutId = trailingCall = undefined; + if (isCalled) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = null; + } + } + } else { + timeoutId = setTimeout(delayed, remaining); + } + } + + function maxDelayed() { + if (timeoutId) { + clearTimeout(timeoutId); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + if (trailing || (maxWait !== wait)) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = null; + } + } + } + + function debounced() { + args = arguments; + stamp = now(); + thisArg = this; + trailingCall = trailing && (timeoutId || !leading); + + if (maxWait === false) { + var leadingCall = leading && !timeoutId; + } else { + if (!maxTimeoutId && !leading) { + lastCalled = stamp; + } + var remaining = maxWait - (stamp - lastCalled), + isCalled = remaining <= 0 || remaining > maxWait; + + if (isCalled) { + if (maxTimeoutId) { + maxTimeoutId = clearTimeout(maxTimeoutId); + } + lastCalled = stamp; + result = func.apply(thisArg, args); + } + else if (!maxTimeoutId) { + maxTimeoutId = setTimeout(maxDelayed, remaining); + } + } + if (isCalled && timeoutId) { + timeoutId = clearTimeout(timeoutId); + } + else if (!timeoutId && wait !== maxWait) { + timeoutId = setTimeout(delayed, wait); + } + if (leadingCall) { + isCalled = true; + result = func.apply(thisArg, args); + } + if (isCalled && !timeoutId && !maxTimeoutId) { + args = thisArg = null; + } + return result; + } + debounced.cancel = cancel; + return debounced; } /** - * Checks if `value` is a boolean value. + * Defers invoking the `func` until the current call stack has cleared. Any + * additional arguments are provided to `func` when it is invoked. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a boolean value, else `false`. + * @category Function + * @param {Function} func The function to defer. + * @param {...*} [args] The arguments to invoke the function with. + * @returns {number} Returns the timer id. * @example * - * _.isBoolean(null); - * // => false + * _.defer(function(text) { + * console.log(text); + * }, 'deferred'); + * // logs 'deferred' after one or more milliseconds */ - function isBoolean(value) { - return value === true || value === false || - value && typeof value == 'object' && toString.call(value) == boolClass || false; + function defer(func) { + return baseDelay(func, 1, arguments, 1); } /** - * Checks if `value` is a date. + * Invokes `func` after `wait` milliseconds. Any additional arguments are + * provided to `func` when it is invoked. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a date, else `false`. + * @category Function + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @param {...*} [args] The arguments to invoke the function with. + * @returns {number} Returns the timer id. * @example * - * _.isDate(new Date); - * // => true + * _.delay(function(text) { + * console.log(text); + * }, 1000, 'later'); + * // => logs 'later' after one second */ - function isDate(value) { - return value && typeof value == 'object' && toString.call(value) == dateClass || false; + function delay(func, wait) { + return baseDelay(func, wait, arguments, 2); } /** - * Checks if `value` is a DOM element. + * Creates a function that returns the result of invoking the provided + * functions with the `this` binding of the created function, where each + * successive invocation is supplied the return value of the previous. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a DOM element, else `false`. + * @category Function + * @param {...Function} [funcs] Functions to invoke. + * @returns {Function} Returns the new function. * @example * - * _.isElement(document.body); - * // => true + * function add(x, y) { + * return x + y; + * } + * + * function square(n) { + * return n * n; + * } + * + * var addSquare = _.flow(add, square); + * addSquare(1, 2); + * // => 9 */ - function isElement(value) { - return value && value.nodeType === 1 || false; + function flow() { + var funcs = arguments, + length = funcs.length; + + if (!length) { + return function() { return arguments[0]; }; + } + if (!arrayEvery(funcs, baseIsFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var index = 0, + result = funcs[index].apply(this, arguments); + + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; } /** - * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a - * length of `0` and objects with no own enumerable properties are considered - * "empty". + * This method is like `_.flow` except that it creates a function that + * invokes the provided functions from right to left. * * @static * @memberOf _ - * @category Objects - * @param {Array|Object|string} value The value to inspect. - * @returns {boolean} Returns `true` if the `value` is empty, else `false`. + * @alias backflow, compose + * @category Function + * @param {...Function} [funcs] Functions to invoke. + * @returns {Function} Returns the new function. * @example * - * _.isEmpty([1, 2, 3]); - * // => false + * function add(x, y) { + * return x + y; + * } * - * _.isEmpty({}); - * // => true + * function square(n) { + * return n * n; + * } * - * _.isEmpty(''); - * // => true + * var addSquare = _.flowRight(square, add); + * addSquare(1, 2); + * // => 9 */ - function isEmpty(value) { - var result = true; - if (!value) { - return result; - } - var className = toString.call(value), - length = value.length; + function flowRight() { + var funcs = arguments, + fromIndex = funcs.length - 1; - if ((className == arrayClass || className == stringClass || className == argsClass ) || - (className == objectClass && typeof length == 'number' && isFunction(value.splice))) { - return !length; + if (fromIndex < 0) { + return function() { return arguments[0]; }; } - forOwn(value, function() { - return (result = false); - }); - return result; + if (!arrayEvery(funcs, baseIsFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + var index = fromIndex, + result = funcs[index].apply(this, arguments); + + while (index--) { + result = funcs[index].call(this, result); + } + return result; + }; } /** - * Performs a deep comparison between two values to determine if they are - * equivalent to each other. If a callback is provided it will be executed - * to compare values. If the callback returns `undefined` comparisons will - * be handled by the method instead. The callback is bound to `thisArg` and - * invoked with two arguments; (a, b). + * Creates a function that memoizes the result of `func`. If `resolver` is + * provided it determines the cache key for storing the result based on the + * arguments provided to the memoized function. By default, the first argument + * provided to the memoized function is coerced to a string and used as the + * cache key. The `func` is invoked with the `this` binding of the memoized + * function. + * + * **Note:** The cache is exposed as the `cache` property on the memoized + * function. Its creation may be customized by replacing the `_.memoize.Cache` + * constructor with one whose instances implement the ES `Map` method interface + * of `get`, `has`, and `set`. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-properties-of-the-map-prototype-object) + * for more details. * * @static * @memberOf _ - * @category Objects - * @param {*} a The value to compare. - * @param {*} b The other value to compare. - * @param {Function} [callback] The function to customize comparing values. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @category Function + * @param {Function} func The function to have its output memoized. + * @param {Function} [resolver] The function to resolve the cache key. + * @returns {Function} Returns the new memoizing function. * @example * - * var object = { 'name': 'fred' }; - * var copy = { 'name': 'fred' }; - * - * object == copy; - * // => false - * - * _.isEqual(object, copy); - * // => true - * - * var words = ['hello', 'goodbye']; - * var otherWords = ['hi', 'goodbye']; + * var upperCase = _.memoize(function(string) { + * return string.toUpperCase(); + * }); * - * _.isEqual(words, otherWords, function(a, b) { - * var reGreet = /^(?:hello|hi)$/i, - * aGreet = _.isString(a) && reGreet.test(a), - * bGreet = _.isString(b) && reGreet.test(b); + * upperCase('fred'); + * // => 'FRED' * - * return (aGreet || bGreet) ? (aGreet == bGreet) : undefined; - * }); - * // => true + * // modifying the result cache + * upperCase.cache.set('fred', 'BARNEY'); + * upperCase('fred'); + * // => 'BARNEY' + * + * // replacing `_.memoize.Cache` + * var object = { 'user': 'fred' }; + * var other = { 'user': 'barney' }; + * var identity = _.memoize(_.identity); + * + * identity(object); + * // => { 'user': 'fred' } + * identity(other); + * // => { 'user': 'fred' } + * + * _.memoize.Cache = WeakMap; + * var identity = _.memoize(_.identity); + * + * identity(object); + * // => { 'user': 'fred' } + * identity(other); + * // => { 'user': 'barney' } */ - function isEqual(a, b, callback, thisArg) { - return baseIsEqual(a, b, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2)); + function memoize(func, resolver) { + if (typeof func != 'function' || (resolver && typeof resolver != 'function')) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var cache = memoized.cache, + key = resolver ? resolver.apply(this, arguments) : arguments[0]; + + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, arguments); + cache.set(key, result); + return result; + }; + memoized.cache = new memoize.Cache; + return memoized; } /** - * Checks if `value` is, or can be coerced to, a finite number. - * - * Note: This is not the same as native `isFinite` which will return true for - * booleans and empty strings. See http://es5.github.io/#x15.1.2.5. + * Creates a function that negates the result of the predicate `func`. The + * `func` predicate is invoked with the `this` binding and arguments of the + * created function. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is finite, else `false`. + * @category Function + * @param {Function} predicate The predicate to negate. + * @returns {Function} Returns the new function. * @example * - * _.isFinite(-101); - * // => true - * - * _.isFinite('10'); - * // => true - * - * _.isFinite(true); - * // => false - * - * _.isFinite(''); - * // => false + * function isEven(n) { + * return n % 2 == 0; + * } * - * _.isFinite(Infinity); - * // => false + * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); + * // => [1, 3, 5] */ - function isFinite(value) { - return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value)); + function negate(predicate) { + if (typeof predicate != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + return !predicate.apply(this, arguments); + }; } /** - * Checks if `value` is a function. + * Creates a function that is restricted to invoking `func` once. Repeat calls + * to the function return the value of the first call. The `func` is invoked + * with the `this` binding of the created function. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a function, else `false`. + * @category Function + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. * @example * - * _.isFunction(_); - * // => true + * var initialize = _.once(createApplication); + * initialize(); + * initialize(); + * // `initialize` invokes `createApplication` once */ - function isFunction(value) { - return typeof value == 'function'; + function once(func) { + return before(func, 2); } /** - * Checks if `value` is the language type of Object. - * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * Creates a function that invokes `func` with `partial` arguments prepended + * to those provided to the new function. This method is like `_.bind` except + * it does **not** alter the `this` binding. + * + * The `_.partial.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. + * + * **Note:** This method does not set the `length` property of partially + * applied functions. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is an object, else `false`. + * @category Function + * @param {Function} func The function to partially apply arguments to. + * @param {...*} [args] The arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. * @example * - * _.isObject({}); - * // => true + * var greet = function(greeting, name) { + * return greeting + ' ' + name; + * }; * - * _.isObject([1, 2, 3]); - * // => true + * var sayHelloTo = _.partial(greet, 'hello'); + * sayHelloTo('fred'); + * // => 'hello fred' * - * _.isObject(1); - * // => false + * // using placeholders + * var greetFred = _.partial(greet, _, 'fred'); + * greetFred('hi'); + * // => 'hi fred' */ - function isObject(value) { - // check if the value is the ECMAScript language type of Object - // http://es5.github.io/#x8 - // and avoid a V8 bug - // http://code.google.com/p/v8/issues/detail?id=2291 - return !!(value && objectTypes[typeof value]); + function partial(func) { + var partials = baseSlice(arguments, 1), + holders = replaceHolders(partials, partial.placeholder); + + return createWrapper(func, PARTIAL_FLAG, null, partials, holders); } /** - * Checks if `value` is `NaN`. + * This method is like `_.partial` except that partially applied arguments + * are appended to those provided to the new function. + * + * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic + * builds, may be used as a placeholder for partially applied arguments. * - * Note: This is not the same as native `isNaN` which will return `true` for - * `undefined` and other non-numeric values. See http://es5.github.io/#x15.1.2.4. + * **Note:** This method does not set the `length` property of partially + * applied functions. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`. + * @category Function + * @param {Function} func The function to partially apply arguments to. + * @param {...*} [args] The arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. * @example * - * _.isNaN(NaN); - * // => true - * - * _.isNaN(new Number(NaN)); - * // => true + * var greet = function(greeting, name) { + * return greeting + ' ' + name; + * }; * - * isNaN(undefined); - * // => true + * var greetFred = _.partialRight(greet, 'fred'); + * greetFred('hi'); + * // => 'hi fred' * - * _.isNaN(undefined); - * // => false + * // using placeholders + * var sayHelloTo = _.partialRight(greet, 'hello', _); + * sayHelloTo('fred'); + * // => 'hello fred' */ - function isNaN(value) { - // `NaN` as a primitive is the only value that is not equal to itself - // (perform the [[Class]] check first to avoid errors with some host objects in IE) - return isNumber(value) && value != +value; + function partialRight(func) { + var partials = baseSlice(arguments, 1), + holders = replaceHolders(partials, partialRight.placeholder); + + return createWrapper(func, PARTIAL_RIGHT_FLAG, null, partials, holders); } /** - * Checks if `value` is `null`. + * Creates a function that invokes `func` with arguments arranged according + * to the specified indexes where the argument value at the first index is + * provided as the first argument, the argument value at the second index is + * provided as the second argument, and so on. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is `null`, else `false`. + * @category Function + * @param {Function} func The function to rearrange arguments for. + * @param {...(number|number[])} indexes The arranged argument indexes, + * specified as individual indexes or arrays of indexes. + * @returns {Function} Returns the new function. * @example * - * _.isNull(null); - * // => true + * var rearged = _.rearg(function(a, b, c) { + * return [a, b, c]; + * }, 2, 0, 1); * - * _.isNull(undefined); - * // => false + * rearged('b', 'c', 'a') + * // => ['a', 'b', 'c'] + * + * var map = _.rearg(_.map, [1, 0]); + * map(function(n) { + * return n * 3; + * }, [1, 2, 3]); + * // => [3, 6, 9] */ - function isNull(value) { - return value === null; + function rearg(func) { + var indexes = baseFlatten(arguments, false, false, 1); + return createWrapper(func, REARG_FLAG, null, null, null, indexes); } /** - * Checks if `value` is a number. - * - * Note: `NaN` is considered a number. See http://es5.github.io/#x8.5. + * Creates a function that invokes `func` with the `this` binding of the + * created function and the array of arguments provided to the created + * function much like [Function#apply](http://es5.github.io/#x15.3.4.3). * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a number, else `false`. + * @category Function + * @param {Function} func The function to spread arguments over. + * @returns {*} Returns the new function. * @example * - * _.isNumber(8.4 * 5); - * // => true + * var spread = _.spread(function(who, what) { + * return who + ' says ' + what; + * }); + * + * spread(['Fred', 'hello']); + * // => 'Fred says hello' + * + * // with a Promise + * var numbers = Promise.all([ + * Promise.resolve(40), + * Promise.resolve(36) + * ]); + * + * numbers.then(_.spread(function(x, y) { + * return x + y; + * })); + * // => a Promise of 76 */ - function isNumber(value) { - return typeof value == 'number' || - value && typeof value == 'object' && toString.call(value) == numberClass || false; + function spread(func) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function(array) { + return func.apply(this, array); + }; } /** - * Checks if `value` is an object created by the `Object` constructor. + * Creates a function that only invokes `func` at most once per every `wait` + * milliseconds. The created function comes with a `cancel` method to cancel + * delayed invocations. Provide an options object to indicate that `func` + * should be invoked on the leading and/or trailing edge of the `wait` timeout. + * Subsequent calls to the throttled function return the result of the last + * `func` call. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked + * on the trailing edge of the timeout only if the the throttled function is + * invoked more than once during the `wait` timeout. + * + * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation) + * for details over the differences between `_.throttle` and `_.debounce`. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @category Function + * @param {Function} func The function to throttle. + * @param {number} [wait=0] The number of milliseconds to throttle invocations to. + * @param {Object} [options] The options object. + * @param {boolean} [options.leading=true] Specify invoking on the leading + * edge of the timeout. + * @param {boolean} [options.trailing=true] Specify invoking on the trailing + * edge of the timeout. + * @returns {Function} Returns the new throttled function. * @example * - * function Shape() { - * this.x = 0; - * this.y = 0; - * } - * - * _.isPlainObject(new Shape); - * // => false + * // avoid excessively updating the position while scrolling + * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); * - * _.isPlainObject([1, 2, 3]); - * // => false + * // invoke `renewToken` when the click event is fired, but not more than once every 5 minutes + * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, { + * 'trailing': false + * })); * - * _.isPlainObject({ 'x': 0, 'y': 0 }); - * // => true + * // cancel a trailing throttled call + * jQuery(window).on('popstate', throttled.cancel); */ - var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { - if (!(value && toString.call(value) == objectClass)) { - return false; - } - var valueOf = value.valueOf, - objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); + function throttle(func, wait, options) { + var leading = true, + trailing = true; - return objProto - ? (value == objProto || getPrototypeOf(value) == objProto) - : shimIsPlainObject(value); - }; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (options === false) { + leading = false; + } else if (isObject(options)) { + leading = 'leading' in options ? !!options.leading : leading; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + debounceOptions.leading = leading; + debounceOptions.maxWait = +wait; + debounceOptions.trailing = trailing; + return debounce(func, wait, debounceOptions); + } /** - * Checks if `value` is a regular expression. + * Creates a function that provides `value` to the wrapper function as its + * first argument. Any additional arguments provided to the function are + * appended to those provided to the wrapper function. The wrapper is invoked + * with the `this` binding of the created function. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`. + * @category Function + * @param {*} value The value to wrap. + * @param {Function} wrapper The wrapper function. + * @returns {Function} Returns the new function. * @example * - * _.isRegExp(/fred/); - * // => true + * var p = _.wrap(_.escape, function(func, text) { + * return '

' + func(text) + '

'; + * }); + * + * p('fred, barney, & pebbles'); + * // => '

fred, barney, & pebbles

' */ - function isRegExp(value) { - return value && typeof value == 'object' && toString.call(value) == regexpClass || false; + function wrap(value, wrapper) { + wrapper = wrapper == null ? identity : wrapper; + return createWrapper(wrapper, PARTIAL_FLAG, null, [value], []); } + /*------------------------------------------------------------------------*/ + /** - * Checks if `value` is a string. + * Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned, + * otherwise they are assigned by reference. If `customizer` is provided it is + * invoked to produce the cloned values. If `customizer` returns `undefined` + * cloning is handled by the method instead. The `customizer` is bound to + * `thisArg` and invoked with two argument; (value [, index|key, object]). + * + * **Note:** This method is loosely based on the structured clone algorithm. + * The enumerable properties of `arguments` objects and objects created by + * constructors other than `Object` are cloned to plain `Object` objects. An + * empty object is returned for uncloneable values such as functions, DOM nodes, + * Maps, Sets, and WeakMaps. See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) + * for more details. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a string, else `false`. + * @category Lang + * @param {*} value The value to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @param {Function} [customizer] The function to customize cloning values. + * @param {*} [thisArg] The `this` binding of `customizer`. + * @returns {*} Returns the cloned value. * @example * - * _.isString('fred'); + * var users = [ + * { 'user': 'barney' }, + * { 'user': 'fred' } + * ]; + * + * var shallow = _.clone(users); + * shallow[0] === users[0]; * // => true + * + * var deep = _.clone(users, true); + * deep[0] === users[0]; + * // => false + * + * // using a customizer callback + * var el = _.clone(document.body, function(value) { + * if (_.isElement(value)) { + * return value.cloneNode(false); + * } + * }); + * + * el === document.body + * // => false + * el.nodeName + * // => BODY + * el.childNodes.length; + * // => 0 */ - function isString(value) { - return typeof value == 'string' || - value && typeof value == 'object' && toString.call(value) == stringClass || false; + function clone(value, isDeep, customizer, thisArg) { + if (isDeep && typeof isDeep != 'boolean' && isIterateeCall(value, isDeep, customizer)) { + isDeep = false; + } + else if (typeof isDeep == 'function') { + thisArg = customizer; + customizer = isDeep; + isDeep = false; + } + customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 1); + return baseClone(value, isDeep, customizer); } /** - * Checks if `value` is `undefined`. + * Creates a deep clone of `value`. If `customizer` is provided it is invoked + * to produce the cloned values. If `customizer` returns `undefined` cloning + * is handled by the method instead. The `customizer` is bound to `thisArg` + * and invoked with two argument; (value [, index|key, object]). + * + * **Note:** This method is loosely based on the structured clone algorithm. + * The enumerable properties of `arguments` objects and objects created by + * constructors other than `Object` are cloned to plain `Object` objects. An + * empty object is returned for uncloneable values such as functions, DOM nodes, + * Maps, Sets, and WeakMaps. See the [HTML5 specification](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm) + * for more details. * * @static * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`. + * @category Lang + * @param {*} value The value to deep clone. + * @param {Function} [customizer] The function to customize cloning values. + * @param {*} [thisArg] The `this` binding of `customizer`. + * @returns {*} Returns the deep cloned value. * @example * - * _.isUndefined(void 0); - * // => true + * var users = [ + * { 'user': 'barney' }, + * { 'user': 'fred' } + * ]; + * + * var deep = _.cloneDeep(users); + * deep[0] === users[0]; + * // => false + * + * // using a customizer callback + * var el = _.cloneDeep(document.body, function(value) { + * if (_.isElement(value)) { + * return value.cloneNode(true); + * } + * }); + * + * el === document.body + * // => false + * el.nodeName + * // => BODY + * el.childNodes.length; + * // => 20 */ - function isUndefined(value) { - return typeof value == 'undefined'; + function cloneDeep(value, customizer, thisArg) { + customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 1); + return baseClone(value, true, customizer); } /** - * Creates an object with the same keys as `object` and values generated by - * running each own enumerable property of `object` through the callback. - * The callback is bound to `thisArg` and invoked with three arguments; - * (value, key, object). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Checks if `value` is classified as an `arguments` object. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new object with values of the results of each `callback` execution. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * - * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; }); - * // => { 'a': 3, 'b': 6, 'c': 9 } - * - * var characters = { - * 'fred': { 'name': 'fred', 'age': 40 }, - * 'pebbles': { 'name': 'pebbles', 'age': 1 } - * }; + * _.isArguments(function() { return arguments; }()); + * // => true * - * // using "_.pluck" callback shorthand - * _.mapValues(characters, 'age'); - * // => { 'fred': 40, 'pebbles': 1 } + * _.isArguments([1, 2, 3]); + * // => false */ - function mapValues(object, callback, thisArg) { - var result = {}; - callback = lodash.createCallback(callback, thisArg, 3); - - forOwn(object, function(value, key, object) { - result[key] = callback(value, key, object); - }); - return result; + function isArguments(value) { + var length = isObjectLike(value) ? value.length : undefined; + return (isLength(length) && objToString.call(value) == argsTag) || false; } /** - * Recursively merges own enumerable properties of the source object(s), that - * don't resolve to `undefined` into the destination object. Subsequent sources - * will overwrite property assignments of previous sources. If a callback is - * provided it will be executed to produce the merged values of the destination - * and source properties. If the callback returns `undefined` merging will - * be handled by the method instead. The callback is bound to `thisArg` and - * invoked with two arguments; (objectValue, sourceValue). + * Checks if `value` is classified as an `Array` object. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. - * @param {Function} [callback] The function to customize merging properties. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns the destination object. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * - * var names = { - * 'characters': [ - * { 'name': 'barney' }, - * { 'name': 'fred' } - * ] - * }; - * - * var ages = { - * 'characters': [ - * { 'age': 36 }, - * { 'age': 40 } - * ] - * }; - * - * _.merge(names, ages); - * // => { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] } - * - * var food = { - * 'fruits': ['apple'], - * 'vegetables': ['beet'] - * }; - * - * var otherFood = { - * 'fruits': ['banana'], - * 'vegetables': ['carrot'] - * }; + * _.isArray([1, 2, 3]); + * // => true * - * _.merge(food, otherFood, function(a, b) { - * return _.isArray(a) ? a.concat(b) : undefined; - * }); - * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] } + * _.isArray(function() { return arguments; }()); + * // => false */ - function merge(object) { - var args = arguments, - length = 2; - - if (!isObject(object)) { - return object; - } - // allows working with `_.reduce` and `_.reduceRight` without using - // their `index` and `collection` arguments - if (typeof args[2] != 'number') { - length = args.length; - } - if (length > 3 && typeof args[length - 2] == 'function') { - var callback = baseCreateCallback(args[--length - 1], args[length--], 2); - } else if (length > 2 && typeof args[length - 1] == 'function') { - callback = args[--length]; - } - var sources = slice(arguments, 1, length), - index = -1, - stackA = getArray(), - stackB = getArray(); - - while (++index < length) { - baseMerge(object, sources[index], callback, stackA, stackB); - } - releaseArray(stackA); - releaseArray(stackB); - return object; - } + var isArray = nativeIsArray || function(value) { + return (isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag) || false; + }; /** - * Creates a shallow clone of `object` excluding the specified properties. - * Property names may be specified as individual arguments or as arrays of - * property names. If a callback is provided it will be executed for each - * property of `object` omitting the properties the callback returns truey - * for. The callback is bound to `thisArg` and invoked with three arguments; - * (value, key, object). + * Checks if `value` is classified as a boolean primitive or object. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The source object. - * @param {Function|...string|string[]} [callback] The properties to omit or the - * function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns an object without the omitted properties. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * - * _.omit({ 'name': 'fred', 'age': 40 }, 'age'); - * // => { 'name': 'fred' } + * _.isBoolean(false); + * // => true * - * _.omit({ 'name': 'fred', 'age': 40 }, function(value) { - * return typeof value == 'number'; - * }); - * // => { 'name': 'fred' } + * _.isBoolean(null); + * // => false */ - function omit(object, callback, thisArg) { - var result = {}; - if (typeof callback != 'function') { - var props = []; - forIn(object, function(value, key) { - props.push(key); - }); - props = baseDifference(props, baseFlatten(arguments, true, false, 1)); - - var index = -1, - length = props.length; - - while (++index < length) { - var key = props[index]; - result[key] = object[key]; - } - } else { - callback = lodash.createCallback(callback, thisArg, 3); - forIn(object, function(value, key, object) { - if (!callback(value, key, object)) { - result[key] = value; - } - }); - } - return result; + function isBoolean(value) { + return (value === true || value === false || isObjectLike(value) && objToString.call(value) == boolTag) || false; } /** - * Creates a two dimensional array of an object's key-value pairs, - * i.e. `[[key1, value1], [key2, value2]]`. + * Checks if `value` is classified as a `Date` object. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns new array of key-value pairs. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * - * _.pairs({ 'barney': 36, 'fred': 40 }); - * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments) + * _.isDate(new Date); + * // => true + * + * _.isDate('Mon April 23 2012'); + * // => false */ - function pairs(object) { - var index = -1, - props = keys(object), - length = props.length, - result = Array(length); - - while (++index < length) { - var key = props[index]; - result[index] = [key, object[key]]; - } - return result; + function isDate(value) { + return (isObjectLike(value) && objToString.call(value) == dateTag) || false; } /** - * Creates a shallow clone of `object` composed of the specified properties. - * Property names may be specified as individual arguments or as arrays of - * property names. If a callback is provided it will be executed for each - * property of `object` picking the properties the callback returns truey - * for. The callback is bound to `thisArg` and invoked with three arguments; - * (value, key, object). + * Checks if `value` is a DOM element. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The source object. - * @param {Function|...string|string[]} [callback] The function called per - * iteration or property names to pick, specified as individual property - * names or arrays of property names. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns an object composed of the picked properties. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`. * @example * - * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name'); - * // => { 'name': 'fred' } + * _.isElement(document.body); + * // => true * - * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) { - * return key.charAt(0) != '_'; - * }); - * // => { 'name': 'fred' } + * _.isElement(''); + * // => false */ - function pick(object, callback, thisArg) { - var result = {}; - if (typeof callback != 'function') { - var index = -1, - props = baseFlatten(arguments, true, false, 1), - length = isObject(object) ? props.length : 0; - - while (++index < length) { - var key = props[index]; - if (key in object) { - result[key] = object[key]; - } - } - } else { - callback = lodash.createCallback(callback, thisArg, 3); - forIn(object, function(value, key, object) { - if (callback(value, key, object)) { - result[key] = value; - } - }); - } - return result; + function isElement(value) { + return (value && value.nodeType === 1 && isObjectLike(value) && + objToString.call(value).indexOf('Element') > -1) || false; + } + // Fallback for environments without DOM support. + if (!support.dom) { + isElement = function(value) { + return (value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value)) || false; + }; } /** - * An alternative to `_.reduce` this method transforms `object` to a new - * `accumulator` object which is the result of running each of its own - * enumerable properties through a callback, with each callback execution - * potentially mutating the `accumulator` object. The callback is bound to - * `thisArg` and invoked with four arguments; (accumulator, value, key, object). - * Callbacks may exit iteration early by explicitly returning `false`. + * Checks if a value is empty. A value is considered empty unless it is an + * `arguments` object, array, string, or jQuery-like collection with a length + * greater than `0` or an object with own enumerable properties. * * @static * @memberOf _ - * @category Objects - * @param {Array|Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [accumulator] The custom accumulator value. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the accumulated value. + * @category Lang + * @param {Array|Object|string} value The value to inspect. + * @returns {boolean} Returns `true` if `value` is empty, else `false`. * @example * - * var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(result, num) { - * num *= num; - * if (num % 2) { - * return result.push(num) < 3; - * } - * }); - * // => [1, 9, 25] + * _.isEmpty(null); + * // => true * - * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { - * result[key] = num * 3; - * }); - * // => { 'a': 3, 'b': 6, 'c': 9 } + * _.isEmpty(true); + * // => true + * + * _.isEmpty(1); + * // => true + * + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({ 'a': 1 }); + * // => false */ - function transform(object, callback, accumulator, thisArg) { - var isArr = isArray(object); - if (accumulator == null) { - if (isArr) { - accumulator = []; - } else { - var ctor = object && object.constructor, - proto = ctor && ctor.prototype; - - accumulator = baseCreate(proto); - } + function isEmpty(value) { + if (value == null) { + return true; } - if (callback) { - callback = lodash.createCallback(callback, thisArg, 4); - (isArr ? forEach : forOwn)(object, function(value, index, object) { - return callback(accumulator, value, index, object); - }); + var length = value.length; + if (isLength(length) && (isArray(value) || isString(value) || isArguments(value) || + (isObjectLike(value) && isFunction(value.splice)))) { + return !length; } - return accumulator; + return !keys(value).length; } /** - * Creates an array composed of the own enumerable property values of `object`. + * Performs a deep comparison between two values to determine if they are + * equivalent. If `customizer` is provided it is invoked to compare values. + * If `customizer` returns `undefined` comparisons are handled by the method + * instead. The `customizer` is bound to `thisArg` and invoked with three + * arguments; (value, other [, index|key]). + * + * **Note:** This method supports comparing arrays, booleans, `Date` objects, + * numbers, `Object` objects, regexes, and strings. Objects are compared by + * their own, not inherited, enumerable properties. Functions and DOM nodes + * are **not** supported. Provide a customizer function to extend support + * for comparing other values. * * @static * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property values. + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {Function} [customizer] The function to customize comparing values. + * @param {*} [thisArg] The `this` binding of `customizer`. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @example * - * _.values({ 'one': 1, 'two': 2, 'three': 3 }); - * // => [1, 2, 3] (property order is not guaranteed across environments) + * var object = { 'user': 'fred' }; + * var other = { 'user': 'fred' }; + * + * object == other; + * // => false + * + * _.isEqual(object, other); + * // => true + * + * // using a customizer callback + * var array = ['hello', 'goodbye']; + * var other = ['hi', 'goodbye']; + * + * _.isEqual(array, other, function(value, other) { + * if (_.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/)) { + * return true; + * } + * }); + * // => true */ - function values(object) { - var index = -1, - props = keys(object), - length = props.length, - result = Array(length); - - while (++index < length) { - result[index] = object[props[index]]; + function isEqual(value, other, customizer, thisArg) { + customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 3); + if (!customizer && isStrictComparable(value) && isStrictComparable(other)) { + return value === other; } - return result; + var result = customizer ? customizer(value, other) : undefined; + return typeof result == 'undefined' ? baseIsEqual(value, other, customizer) : !!result; } - /*--------------------------------------------------------------------------*/ - /** - * Creates an array of elements from the specified indexes, or keys, of the - * `collection`. Indexes may be specified as individual arguments or as arrays - * of indexes. + * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`, + * `SyntaxError`, `TypeError`, or `URIError` object. * * @static * @memberOf _ - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {...(number|number[]|string|string[])} [index] The indexes of `collection` - * to retrieve, specified as individual indexes or arrays of indexes. - * @returns {Array} Returns a new array of elements corresponding to the - * provided indexes. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an error object, else `false`. * @example * - * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]); - * // => ['a', 'c', 'e'] + * _.isError(new Error); + * // => true * - * _.at(['fred', 'barney', 'pebbles'], 0, 2); - * // => ['fred', 'pebbles'] + * _.isError(Error); + * // => false */ - function at(collection) { - var args = arguments, - index = -1, - props = baseFlatten(args, true, false, 1), - length = (args[2] && args[2][args[1]] === collection) ? 1 : props.length, - result = Array(length); - - while(++index < length) { - result[index] = collection[props[index]]; - } - return result; + function isError(value) { + return (isObjectLike(value) && typeof value.message == 'string' && objToString.call(value) == errorTag) || false; } /** - * Checks if a given value is present in a collection using strict equality - * for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the - * offset from the end of the collection. + * Checks if `value` is a finite primitive number. + * + * **Note:** This method is based on ES `Number.isFinite`. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.isfinite) + * for more details. * * @static * @memberOf _ - * @alias include - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {*} target The value to check for. - * @param {number} [fromIndex=0] The index to search from. - * @returns {boolean} Returns `true` if the `target` element is found, else `false`. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. * @example * - * _.contains([1, 2, 3], 1); + * _.isFinite(10); * // => true * - * _.contains([1, 2, 3], 1, 2); + * _.isFinite('10'); * // => false * - * _.contains({ 'name': 'fred', 'age': 40 }, 'fred'); - * // => true + * _.isFinite(true); + * // => false * - * _.contains('pebbles', 'eb'); - * // => true + * _.isFinite(Object(10)); + * // => false + * + * _.isFinite(Infinity); + * // => false */ - function contains(collection, target, fromIndex) { - var index = -1, - indexOf = getIndexOf(), - length = collection ? collection.length : 0, - result = false; - - fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0; - if (isArray(collection)) { - result = indexOf(collection, target, fromIndex) > -1; - } else if (typeof length == 'number') { - result = (isString(collection) ? collection.indexOf(target, fromIndex) : indexOf(collection, target, fromIndex)) > -1; - } else { - forOwn(collection, function(value) { - if (++index >= fromIndex) { - return !(result = value === target); - } - }); - } - return result; - } + var isFinite = nativeNumIsFinite || function(value) { + return typeof value == 'number' && nativeIsFinite(value); + }; /** - * Creates an object composed of keys generated from the results of running - * each element of `collection` through the callback. The corresponding value - * of each key is the number of times the key was returned by the callback. - * The callback is bound to `thisArg` and invoked with three arguments; - * (value, index|key, collection). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Checks if `value` is classified as a `Function` object. * * @static * @memberOf _ - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns the composed aggregate object. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * - * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); }); - * // => { '4': 1, '6': 2 } - * - * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math); - * // => { '4': 1, '6': 2 } + * _.isFunction(_); + * // => true * - * _.countBy(['one', 'two', 'three'], 'length'); - * // => { '3': 2, '5': 1 } + * _.isFunction(/abc/); + * // => false */ - var countBy = createAggregator(function(result, value, key) { - (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1); - }); + var isFunction = !(baseIsFunction(/x/) || (Uint8Array && !baseIsFunction(Uint8Array))) ? baseIsFunction : function(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // in older versions of Chrome and Safari which return 'function' for regexes + // and Safari 8 equivalents which return 'object' for typed array constructors. + return objToString.call(value) == funcTag; + }; /** - * Checks if the given callback returns truey value for **all** elements of - * a collection. The callback is bound to `thisArg` and invoked with three - * arguments; (value, index|key, collection). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * Checks if `value` is the language type of `Object`. + * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * **Note:** See the [ES5 spec](https://es5.github.io/#x8) for more details. * * @static * @memberOf _ - * @alias all - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {boolean} Returns `true` if all elements passed the callback check, - * else `false`. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. * @example * - * _.every([true, 1, null, 'yes']); - * // => false - * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } - * ]; + * _.isObject({}); + * // => true * - * // using "_.pluck" callback shorthand - * _.every(characters, 'age'); + * _.isObject([1, 2, 3]); * // => true * - * // using "_.where" callback shorthand - * _.every(characters, { 'age': 36 }); + * _.isObject(1); * // => false */ - function every(collection, callback, thisArg) { - var result = true; - callback = lodash.createCallback(callback, thisArg, 3); - - var index = -1, - length = collection ? collection.length : 0; - - if (typeof length == 'number') { - while (++index < length) { - if (!(result = !!callback(collection[index], index, collection))) { - break; - } - } - } else { - forOwn(collection, function(value, index, collection) { - return (result = !!callback(value, index, collection)); - }); - } - return result; + function isObject(value) { + // Avoid a V8 JIT bug in Chrome 19-20. + // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. + var type = typeof value; + return type == 'function' || (value && type == 'object') || false; } /** - * Iterates over elements of a collection, returning an array of all elements - * the callback returns truey for. The callback is bound to `thisArg` and - * invoked with three arguments; (value, index|key, collection). + * Performs a deep comparison between `object` and `source` to determine if + * `object` contains equivalent property values. If `customizer` is provided + * it is invoked to compare values. If `customizer` returns `undefined` + * comparisons are handled by the method instead. The `customizer` is bound + * to `thisArg` and invoked with three arguments; (value, other, index|key). * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * **Note:** This method supports comparing properties of arrays, booleans, + * `Date` objects, numbers, `Object` objects, regexes, and strings. Functions + * and DOM nodes are **not** supported. Provide a customizer function to extend + * support for comparing other values. * * @static * @memberOf _ - * @alias select - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new array of elements that passed the callback check. + * @category Lang + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Function} [customizer] The function to customize comparing values. + * @param {*} [thisArg] The `this` binding of `customizer`. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. * @example * - * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; }); - * // => [2, 4, 6] + * var object = { 'user': 'fred', 'age': 40 }; * - * var characters = [ - * { 'name': 'barney', 'age': 36, 'blocked': false }, - * { 'name': 'fred', 'age': 40, 'blocked': true } - * ]; + * _.isMatch(object, { 'age': 40 }); + * // => true + * + * _.isMatch(object, { 'age': 36 }); + * // => false * - * // using "_.pluck" callback shorthand - * _.filter(characters, 'blocked'); - * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }] + * // using a customizer callback + * var object = { 'greeting': 'hello' }; + * var source = { 'greeting': 'hi' }; * - * // using "_.where" callback shorthand - * _.filter(characters, { 'age': 36 }); - * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }] + * _.isMatch(object, source, function(value, other) { + * return _.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/) || undefined; + * }); + * // => true */ - function filter(collection, callback, thisArg) { - var result = []; - callback = lodash.createCallback(callback, thisArg, 3); + function isMatch(object, source, customizer, thisArg) { + var props = keys(source), + length = props.length; - var index = -1, - length = collection ? collection.length : 0; + customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 3); + if (!customizer && length == 1) { + var key = props[0], + value = source[key]; - if (typeof length == 'number') { - while (++index < length) { - var value = collection[index]; - if (callback(value, index, collection)) { - result.push(value); - } + if (isStrictComparable(value)) { + return object != null && value === object[key] && hasOwnProperty.call(object, key); } - } else { - forOwn(collection, function(value, index, collection) { - if (callback(value, index, collection)) { - result.push(value); - } - }); } - return result; + var values = Array(length), + strictCompareFlags = Array(length); + + while (length--) { + value = values[length] = source[props[length]]; + strictCompareFlags[length] = isStrictComparable(value); + } + return baseIsMatch(object, props, values, strictCompareFlags, customizer); } /** - * Iterates over elements of a collection, returning the first element that - * the callback returns truey for. The callback is bound to `thisArg` and - * invoked with three arguments; (value, index|key, collection). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * Checks if `value` is `NaN`. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * **Note:** This method is not the same as native `isNaN` which returns `true` + * for `undefined` and other non-numeric values. See the [ES5 spec](https://es5.github.io/#x15.1.2.4) + * for more details. * * @static * @memberOf _ - * @alias detect, findWhere - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the found element, else `undefined`. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. * @example * - * var characters = [ - * { 'name': 'barney', 'age': 36, 'blocked': false }, - * { 'name': 'fred', 'age': 40, 'blocked': true }, - * { 'name': 'pebbles', 'age': 1, 'blocked': false } - * ]; + * _.isNaN(NaN); + * // => true * - * _.find(characters, function(chr) { - * return chr.age < 40; - * }); - * // => { 'name': 'barney', 'age': 36, 'blocked': false } + * _.isNaN(new Number(NaN)); + * // => true * - * // using "_.where" callback shorthand - * _.find(characters, { 'age': 1 }); - * // => { 'name': 'pebbles', 'age': 1, 'blocked': false } + * isNaN(undefined); + * // => true * - * // using "_.pluck" callback shorthand - * _.find(characters, 'blocked'); - * // => { 'name': 'fred', 'age': 40, 'blocked': true } + * _.isNaN(undefined); + * // => false */ - function find(collection, callback, thisArg) { - callback = lodash.createCallback(callback, thisArg, 3); - - var index = -1, - length = collection ? collection.length : 0; - - if (typeof length == 'number') { - while (++index < length) { - var value = collection[index]; - if (callback(value, index, collection)) { - return value; - } - } - } else { - var result; - forOwn(collection, function(value, index, collection) { - if (callback(value, index, collection)) { - result = value; - return false; - } - }); - return result; - } + function isNaN(value) { + // An `NaN` primitive is the only value that is not equal to itself. + // Perform the `toStringTag` check first to avoid errors with some host objects in IE. + return isNumber(value) && value != +value; } /** - * This method is like `_.find` except that it iterates over elements - * of a `collection` from right to left. + * Checks if `value` is a native function. * * @static * @memberOf _ - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the found element, else `undefined`. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, else `false`. * @example * - * _.findLast([1, 2, 3, 4], function(num) { - * return num % 2 == 1; - * }); - * // => 3 + * _.isNative(Array.prototype.push); + * // => true + * + * _.isNative(_); + * // => false */ - function findLast(collection, callback, thisArg) { - var result; - callback = lodash.createCallback(callback, thisArg, 3); - forEachRight(collection, function(value, index, collection) { - if (callback(value, index, collection)) { - result = value; - return false; - } - }); - return result; + function isNative(value) { + if (value == null) { + return false; + } + if (objToString.call(value) == funcTag) { + return reNative.test(fnToString.call(value)); + } + return (isObjectLike(value) && reHostCtor.test(value)) || false; } /** - * Iterates over elements of a collection, executing the callback for each - * element. The callback is bound to `thisArg` and invoked with three arguments; - * (value, index|key, collection). Callbacks may exit iteration early by - * explicitly returning `false`. - * - * Note: As with other "Collections" methods, objects with a `length` property - * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn` - * may be used for object iteration. + * Checks if `value` is `null`. * * @static * @memberOf _ - * @alias each - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array|Object|string} Returns `collection`. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `null`, else `false`. * @example * - * _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(','); - * // => logs each number and returns '1,2,3' + * _.isNull(null); + * // => true * - * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); }); - * // => logs each number and returns the object (property order is not guaranteed across environments) + * _.isNull(void 0); + * // => false */ - function forEach(collection, callback, thisArg) { - var index = -1, - length = collection ? collection.length : 0; - - callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3); - if (typeof length == 'number') { - while (++index < length) { - if (callback(collection[index], index, collection) === false) { - break; - } - } - } else { - forOwn(collection, callback); - } - return collection; + function isNull(value) { + return value === null; } /** - * This method is like `_.forEach` except that it iterates over elements - * of a `collection` from right to left. + * Checks if `value` is classified as a `Number` primitive or object. + * + * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified + * as numbers, use the `_.isFinite` method. * * @static * @memberOf _ - * @alias eachRight - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array|Object|string} Returns `collection`. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * - * _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(','); - * // => logs each number from right to left and returns '3,2,1' + * _.isNumber(8.4); + * // => true + * + * _.isNumber(NaN); + * // => true + * + * _.isNumber('8.4'); + * // => false */ - function forEachRight(collection, callback, thisArg) { - var length = collection ? collection.length : 0; - callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3); - if (typeof length == 'number') { - while (length--) { - if (callback(collection[length], length, collection) === false) { - break; - } - } - } else { - var props = keys(collection); - length = props.length; - forOwn(collection, function(value, key, collection) { - key = props ? props[--length] : --length; - return callback(collection[key], key, collection); - }); - } - return collection; + function isNumber(value) { + return typeof value == 'number' || (isObjectLike(value) && objToString.call(value) == numberTag) || false; } /** - * Creates an object composed of keys generated from the results of running - * each element of a collection through the callback. The corresponding value - * of each key is an array of the elements responsible for generating the key. - * The callback is bound to `thisArg` and invoked with three arguments; - * (value, index|key, collection). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * Checks if `value` is a plain object, that is, an object created by the + * `Object` constructor or one with a `[[Prototype]]` of `null`. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false` + * **Note:** This method assumes objects created by the `Object` constructor + * have no inherited enumerable properties. * * @static * @memberOf _ - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns the composed aggregate object. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. * @example * - * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); }); - * // => { '4': [4.2], '6': [6.1, 6.4] } + * function Foo() { + * this.a = 1; + * } * - * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math); - * // => { '4': [4.2], '6': [6.1, 6.4] } + * _.isPlainObject(new Foo); + * // => false * - * // using "_.pluck" callback shorthand - * _.groupBy(['one', 'two', 'three'], 'length'); - * // => { '3': ['one', 'two'], '5': ['three'] } + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'x': 0, 'y': 0 }); + * // => true + * + * _.isPlainObject(Object.create(null)); + * // => true */ - var groupBy = createAggregator(function(result, value, key) { - (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value); - }); + var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { + if (!(value && objToString.call(value) == objectTag)) { + return false; + } + var valueOf = value.valueOf, + objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); + + return objProto + ? (value == objProto || getPrototypeOf(value) == objProto) + : shimIsPlainObject(value); + }; /** - * Creates an object composed of keys generated from the results of running - * each element of the collection through the given callback. The corresponding - * value of each key is the last element responsible for generating the key. - * The callback is bound to `thisArg` and invoked with three arguments; - * (value, index|key, collection). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Checks if `value` is classified as a `RegExp` object. * * @static * @memberOf _ - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns the composed aggregate object. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * - * var keys = [ - * { 'dir': 'left', 'code': 97 }, - * { 'dir': 'right', 'code': 100 } - * ]; - * - * _.indexBy(keys, 'dir'); - * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } - * - * _.indexBy(keys, function(key) { return String.fromCharCode(key.code); }); - * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } + * _.isRegExp(/abc/); + * // => true * - * _.indexBy(characters, function(key) { this.fromCharCode(key.code); }, String); - * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } + * _.isRegExp('/abc/'); + * // => false */ - var indexBy = createAggregator(function(result, value, key) { - result[key] = value; - }); + function isRegExp(value) { + return (isObjectLike(value) && objToString.call(value) == regexpTag) || false; + } /** - * Invokes the method named by `methodName` on each element in the `collection` - * returning an array of the results of each invoked method. Additional arguments - * will be provided to each invoked method. If `methodName` is a function it - * will be invoked for, and `this` bound to, each element in the `collection`. + * Checks if `value` is classified as a `String` primitive or object. * * @static * @memberOf _ - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|string} methodName The name of the method to invoke or - * the function invoked per iteration. - * @param {...*} [arg] Arguments to invoke the method with. - * @returns {Array} Returns a new array of the results of each invoked method. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * - * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort'); - * // => [[1, 5, 7], [1, 2, 3]] + * _.isString('abc'); + * // => true * - * _.invoke([123, 456], String.prototype.split, ''); - * // => [['1', '2', '3'], ['4', '5', '6']] + * _.isString(1); + * // => false */ - function invoke(collection, methodName) { - var args = slice(arguments, 2), - index = -1, - isFunc = typeof methodName == 'function', - length = collection ? collection.length : 0, - result = Array(typeof length == 'number' ? length : 0); - - forEach(collection, function(value) { - result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args); - }); - return result; + function isString(value) { + return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag) || false; } /** - * Creates an array of values by running each element in the collection - * through the callback. The callback is bound to `thisArg` and invoked with - * three arguments; (value, index|key, collection). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Checks if `value` is classified as a typed array. * * @static * @memberOf _ - * @alias collect - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new array of the results of each `callback` execution. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. * @example * - * _.map([1, 2, 3], function(num) { return num * 3; }); - * // => [3, 6, 9] - * - * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; }); - * // => [3, 6, 9] (property order is not guaranteed across environments) - * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } - * ]; + * _.isTypedArray(new Uint8Array); + * // => true * - * // using "_.pluck" callback shorthand - * _.map(characters, 'name'); - * // => ['barney', 'fred'] + * _.isTypedArray([]); + * // => false */ - function map(collection, callback, thisArg) { - var index = -1, - length = collection ? collection.length : 0; - - callback = lodash.createCallback(callback, thisArg, 3); - if (typeof length == 'number') { - var result = Array(length); - while (++index < length) { - result[index] = callback(collection[index], index, collection); - } - } else { - result = []; - forOwn(collection, function(value, key, collection) { - result[++index] = callback(value, key, collection); - }); - } - return result; + function isTypedArray(value) { + return (isObjectLike(value) && isLength(value.length) && typedArrayTags[objToString.call(value)]) || false; } /** - * Retrieves the maximum value of a collection. If the collection is empty or - * falsey `-Infinity` is returned. If a callback is provided it will be executed - * for each value in the collection to generate the criterion by which the value - * is ranked. The callback is bound to `thisArg` and invoked with three - * arguments; (value, index, collection). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Checks if `value` is `undefined`. * * @static * @memberOf _ - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the maximum value. + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. * @example * - * _.max([4, 2, 8, 6]); - * // => 8 + * _.isUndefined(void 0); + * // => true * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } - * ]; + * _.isUndefined(null); + * // => false + */ + function isUndefined(value) { + return typeof value == 'undefined'; + } + + /** + * Converts `value` to an array. * - * _.max(characters, function(chr) { return chr.age; }); - * // => { 'name': 'fred', 'age': 40 }; + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to convert. + * @returns {Array} Returns the converted array. + * @example * - * // using "_.pluck" callback shorthand - * _.max(characters, 'age'); - * // => { 'name': 'fred', 'age': 40 }; + * (function() { + * return _.toArray(arguments).slice(1); + * }(1, 2, 3)); + * // => [2, 3] */ - function max(collection, callback, thisArg) { - var computed = -Infinity, - result = computed; - - // allows working with functions like `_.map` without using - // their `index` argument as a callback - if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) { - callback = null; + function toArray(value) { + var length = value ? value.length : 0; + if (!isLength(length)) { + return values(value); } - if (callback == null && isArray(collection)) { - var index = -1, - length = collection.length; - - while (++index < length) { - var value = collection[index]; - if (value > result) { - result = value; - } - } - } else { - callback = (callback == null && isString(collection)) - ? charAtCallback - : lodash.createCallback(callback, thisArg, 3); - - forEach(collection, function(value, index, collection) { - var current = callback(value, index, collection); - if (current > computed) { - computed = current; - result = value; - } - }); + if (!length) { + return []; } - return result; + return arrayCopy(value); } /** - * Retrieves the minimum value of a collection. If the collection is empty or - * falsey `Infinity` is returned. If a callback is provided it will be executed - * for each value in the collection to generate the criterion by which the value - * is ranked. The callback is bound to `thisArg` and invoked with three - * arguments; (value, index, collection). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Converts `value` to a plain object flattening inherited enumerable + * properties of `value` to own properties of the plain object. * * @static * @memberOf _ - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the minimum value. + * @category Lang + * @param {*} value The value to convert. + * @returns {Object} Returns the converted plain object. * @example * - * _.min([4, 2, 8, 6]); - * // => 2 + * function Foo() { + * this.b = 2; + * } * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } - * ]; + * Foo.prototype.c = 3; * - * _.min(characters, function(chr) { return chr.age; }); - * // => { 'name': 'barney', 'age': 36 }; + * _.assign({ 'a': 1 }, new Foo); + * // => { 'a': 1, 'b': 2 } * - * // using "_.pluck" callback shorthand - * _.min(characters, 'age'); - * // => { 'name': 'barney', 'age': 36 }; + * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); + * // => { 'a': 1, 'b': 2, 'c': 3 } */ - function min(collection, callback, thisArg) { - var computed = Infinity, - result = computed; - - // allows working with functions like `_.map` without using - // their `index` argument as a callback - if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) { - callback = null; - } - if (callback == null && isArray(collection)) { - var index = -1, - length = collection.length; - - while (++index < length) { - var value = collection[index]; - if (value < result) { - result = value; - } - } - } else { - callback = (callback == null && isString(collection)) - ? charAtCallback - : lodash.createCallback(callback, thisArg, 3); - - forEach(collection, function(value, index, collection) { - var current = callback(value, index, collection); - if (current < computed) { - computed = current; - result = value; - } - }); - } - return result; + function toPlainObject(value) { + return baseCopy(value, keysIn(value)); } + /*------------------------------------------------------------------------*/ + /** - * Retrieves the value of a specified property from all elements in the collection. + * Assigns own enumerable properties of source object(s) to the destination + * object. Subsequent sources overwrite property assignments of previous sources. + * If `customizer` is provided it is invoked to produce the assigned values. + * The `customizer` is bound to `thisArg` and invoked with five arguments; + * (objectValue, sourceValue, key, object, source). * * @static * @memberOf _ - * @type Function - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {string} property The name of the property to pluck. - * @returns {Array} Returns a new array of property values. + * @alias extend + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @param {Function} [customizer] The function to customize assigning values. + * @param {*} [thisArg] The `this` binding of `customizer`. + * @returns {Object} Returns `object`. * @example * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } - * ]; + * _.assign({ 'user': 'barney' }, { 'age': 40 }, { 'user': 'fred' }); + * // => { 'user': 'fred', 'age': 40 } * - * _.pluck(characters, 'name'); - * // => ['barney', 'fred'] + * // using a customizer callback + * var defaults = _.partialRight(_.assign, function(value, other) { + * return typeof value == 'undefined' ? other : value; + * }); + * + * defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); + * // => { 'user': 'barney', 'age': 36 } */ - var pluck = map; + var assign = createAssigner(baseAssign); /** - * Reduces a collection to a value which is the accumulated result of running - * each element in the collection through the callback, where each successive - * callback execution consumes the return value of the previous execution. If - * `accumulator` is not provided the first element of the collection will be - * used as the initial `accumulator` value. The callback is bound to `thisArg` - * and invoked with four arguments; (accumulator, value, index|key, collection). + * Creates an object that inherits from the given `prototype` object. If a + * `properties` object is provided its own enumerable properties are assigned + * to the created object. * * @static * @memberOf _ - * @alias foldl, inject - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [accumulator] Initial value of the accumulator. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the accumulated value. + * @category Object + * @param {Object} prototype The object to inherit from. + * @param {Object} [properties] The properties to assign to the object. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Object} Returns the new object. * @example * - * var sum = _.reduce([1, 2, 3], function(sum, num) { - * return sum + num; + * function Shape() { + * this.x = 0; + * this.y = 0; + * } + * + * function Circle() { + * Shape.call(this); + * } + * + * Circle.prototype = _.create(Shape.prototype, { + * 'constructor': Circle * }); - * // => 6 * - * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { - * result[key] = num * 3; - * return result; - * }, {}); - * // => { 'a': 3, 'b': 6, 'c': 9 } + * var circle = new Circle; + * circle instanceof Circle; + * // => true + * + * circle instanceof Shape; + * // => true */ - function reduce(collection, callback, accumulator, thisArg) { - if (!collection) return accumulator; - var noaccum = arguments.length < 3; - callback = lodash.createCallback(callback, thisArg, 4); - - var index = -1, - length = collection.length; - - if (typeof length == 'number') { - if (noaccum) { - accumulator = collection[++index]; - } - while (++index < length) { - accumulator = callback(accumulator, collection[index], index, collection); - } - } else { - forOwn(collection, function(value, index, collection) { - accumulator = noaccum - ? (noaccum = false, value) - : callback(accumulator, value, index, collection) - }); + function create(prototype, properties, guard) { + var result = baseCreate(prototype); + if (guard && isIterateeCall(prototype, properties, guard)) { + properties = null; } - return accumulator; + return properties ? baseCopy(properties, result, keys(properties)) : result; } /** - * This method is like `_.reduce` except that it iterates over elements - * of a `collection` from right to left. + * Assigns own enumerable properties of source object(s) to the destination + * object for all destination properties that resolve to `undefined`. Once a + * property is set, additional defaults of the same property are ignored. * * @static * @memberOf _ - * @alias foldr - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [accumulator] Initial value of the accumulator. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the accumulated value. + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. * @example * - * var list = [[0, 1], [2, 3], [4, 5]]; - * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []); - * // => [4, 5, 2, 3, 0, 1] + * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); + * // => { 'user': 'barney', 'age': 36 } */ - function reduceRight(collection, callback, accumulator, thisArg) { - var noaccum = arguments.length < 3; - callback = lodash.createCallback(callback, thisArg, 4); - forEachRight(collection, function(value, index, collection) { - accumulator = noaccum - ? (noaccum = false, value) - : callback(accumulator, value, index, collection); - }); - return accumulator; + function defaults(object) { + if (object == null) { + return object; + } + var args = arrayCopy(arguments); + args.push(assignDefaults); + return assign.apply(undefined, args); } /** - * The opposite of `_.filter` this method returns the elements of a - * collection that the callback does **not** return truey for. + * This method is like `_.findIndex` except that it returns the key of the + * first element `predicate` returns truthy for, instead of the element itself. + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. * * @static * @memberOf _ - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new array of elements that failed the callback check. + * @category Object + * @param {Object} object The object to search. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {string|undefined} Returns the key of the matched element, else `undefined`. * @example * - * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; }); - * // => [1, 3, 5] + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; * - * var characters = [ - * { 'name': 'barney', 'age': 36, 'blocked': false }, - * { 'name': 'fred', 'age': 40, 'blocked': true } - * ]; + * _.findKey(users, function(chr) { + * return chr.age < 40; + * }); + * // => 'barney' (iteration order is not guaranteed) + * + * // using the `_.matches` callback shorthand + * _.findKey(users, { 'age': 1, 'active': true }); + * // => 'pebbles' * - * // using "_.pluck" callback shorthand - * _.reject(characters, 'blocked'); - * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }] + * // using the `_.matchesProperty` callback shorthand + * _.findKey(users, 'active', false); + * // => 'fred' * - * // using "_.where" callback shorthand - * _.reject(characters, { 'age': 36 }); - * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }] + * // using the `_.property` callback shorthand + * _.findKey(users, 'active'); + * // => 'barney' */ - function reject(collection, callback, thisArg) { - callback = lodash.createCallback(callback, thisArg, 3); - return filter(collection, function(value, index, collection) { - return !callback(value, index, collection); - }); + function findKey(object, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + return baseFind(object, predicate, baseForOwn, true); } /** - * Retrieves a random element or `n` random elements from a collection. + * This method is like `_.findKey` except that it iterates over elements of + * a collection in the opposite order. + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. * * @static * @memberOf _ - * @category Collections - * @param {Array|Object|string} collection The collection to sample. - * @param {number} [n] The number of elements to sample. - * @param- {Object} [guard] Allows working with functions like `_.map` - * without using their `index` arguments as `n`. - * @returns {Array} Returns the random sample(s) of `collection`. + * @category Object + * @param {Object} object The object to search. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {string|undefined} Returns the key of the matched element, else `undefined`. * @example * - * _.sample([1, 2, 3, 4]); - * // => 2 + * var users = { + * 'barney': { 'age': 36, 'active': true }, + * 'fred': { 'age': 40, 'active': false }, + * 'pebbles': { 'age': 1, 'active': true } + * }; * - * _.sample([1, 2, 3, 4], 2); - * // => [3, 1] + * _.findLastKey(users, function(chr) { + * return chr.age < 40; + * }); + * // => returns `pebbles` assuming `_.findKey` returns `barney` + * + * // using the `_.matches` callback shorthand + * _.findLastKey(users, { 'age': 36, 'active': true }); + * // => 'barney' + * + * // using the `_.matchesProperty` callback shorthand + * _.findLastKey(users, 'active', false); + * // => 'fred' + * + * // using the `_.property` callback shorthand + * _.findLastKey(users, 'active'); + * // => 'pebbles' */ - function sample(collection, n, guard) { - if (collection && typeof collection.length != 'number') { - collection = values(collection); - } - if (n == null || guard) { - return collection ? collection[baseRandom(0, collection.length - 1)] : undefined; - } - var result = shuffle(collection); - result.length = nativeMin(nativeMax(0, n), result.length); - return result; + function findLastKey(object, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + return baseFind(object, predicate, baseForOwnRight, true); } /** - * Creates an array of shuffled values, using a version of the Fisher-Yates - * shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle. + * Iterates over own and inherited enumerable properties of an object invoking + * `iteratee` for each property. The `iteratee` is bound to `thisArg` and invoked + * with three arguments; (value, key, object). Iterator functions may exit + * iteration early by explicitly returning `false`. * * @static * @memberOf _ - * @category Collections - * @param {Array|Object|string} collection The collection to shuffle. - * @returns {Array} Returns a new shuffled collection. + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Object} Returns `object`. * @example * - * _.shuffle([1, 2, 3, 4, 5, 6]); - * // => [4, 1, 6, 3, 5, 2] + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.forIn(new Foo, function(value, key) { + * console.log(key); + * }); + * // => logs 'a', 'b', and 'c' (iteration order is not guaranteed) */ - function shuffle(collection) { - var index = -1, - length = collection ? collection.length : 0, - result = Array(typeof length == 'number' ? length : 0); - - forEach(collection, function(value) { - var rand = baseRandom(0, ++index); - result[index] = result[rand]; - result[rand] = value; - }); - return result; + function forIn(object, iteratee, thisArg) { + if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return baseFor(object, iteratee, keysIn); } /** - * Gets the size of the `collection` by returning `collection.length` for arrays - * and array-like objects or the number of own enumerable properties for objects. + * This method is like `_.forIn` except that it iterates over properties of + * `object` in the opposite order. * * @static * @memberOf _ - * @category Collections - * @param {Array|Object|string} collection The collection to inspect. - * @returns {number} Returns `collection.length` or number of own enumerable properties. + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Object} Returns `object`. * @example * - * _.size([1, 2]); - * // => 2 + * function Foo() { + * this.a = 1; + * this.b = 2; + * } * - * _.size({ 'one': 1, 'two': 2, 'three': 3 }); - * // => 3 + * Foo.prototype.c = 3; * - * _.size('pebbles'); - * // => 7 + * _.forInRight(new Foo, function(value, key) { + * console.log(key); + * }); + * // => logs 'c', 'b', and 'a' assuming `_.forIn ` logs 'a', 'b', and 'c' */ - function size(collection) { - var length = collection ? collection.length : 0; - return typeof length == 'number' ? length : keys(collection).length; + function forInRight(object, iteratee, thisArg) { + iteratee = bindCallback(iteratee, thisArg, 3); + return baseForRight(object, iteratee, keysIn); } /** - * Checks if the callback returns a truey value for **any** element of a - * collection. The function returns as soon as it finds a passing value and - * does not iterate over the entire collection. The callback is bound to - * `thisArg` and invoked with three arguments; (value, index|key, collection). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Iterates over own enumerable properties of an object invoking `iteratee` + * for each property. The `iteratee` is bound to `thisArg` and invoked with + * three arguments; (value, key, object). Iterator functions may exit iteration + * early by explicitly returning `false`. * * @static * @memberOf _ - * @alias any - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {boolean} Returns `true` if any element passed the callback check, - * else `false`. + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Object} Returns `object`. * @example * - * _.some([null, 0, 'yes', false], Boolean); - * // => true - * - * var characters = [ - * { 'name': 'barney', 'age': 36, 'blocked': false }, - * { 'name': 'fred', 'age': 40, 'blocked': true } - * ]; + * function Foo() { + * this.a = 1; + * this.b = 2; + * } * - * // using "_.pluck" callback shorthand - * _.some(characters, 'blocked'); - * // => true + * Foo.prototype.c = 3; * - * // using "_.where" callback shorthand - * _.some(characters, { 'age': 1 }); - * // => false + * _.forOwn(new Foo, function(value, key) { + * console.log(key); + * }); + * // => logs 'a' and 'b' (iteration order is not guaranteed) */ - function some(collection, callback, thisArg) { - var result; - callback = lodash.createCallback(callback, thisArg, 3); - - var index = -1, - length = collection ? collection.length : 0; - - if (typeof length == 'number') { - while (++index < length) { - if ((result = callback(collection[index], index, collection))) { - break; - } - } - } else { - forOwn(collection, function(value, index, collection) { - return !(result = callback(value, index, collection)); - }); + function forOwn(object, iteratee, thisArg) { + if (typeof iteratee != 'function' || typeof thisArg != 'undefined') { + iteratee = bindCallback(iteratee, thisArg, 3); } - return !!result; + return baseForOwn(object, iteratee); } /** - * Creates an array of elements, sorted in ascending order by the results of - * running each element in a collection through the callback. This method - * performs a stable sort, that is, it will preserve the original sort order - * of equal elements. The callback is bound to `thisArg` and invoked with - * three arguments; (value, index|key, collection). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an array of property names is provided for `callback` the collection - * will be sorted by each property value. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * This method is like `_.forOwn` except that it iterates over properties of + * `object` in the opposite order. * * @static * @memberOf _ - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Array|Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new array of sorted elements. + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Object} Returns `object`. * @example * - * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); }); - * // => [3, 1, 2] - * - * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math); - * // => [3, 1, 2] - * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 }, - * { 'name': 'barney', 'age': 26 }, - * { 'name': 'fred', 'age': 30 } - * ]; + * function Foo() { + * this.a = 1; + * this.b = 2; + * } * - * // using "_.pluck" callback shorthand - * _.map(_.sortBy(characters, 'age'), _.values); - * // => [['barney', 26], ['fred', 30], ['barney', 36], ['fred', 40]] + * Foo.prototype.c = 3; * - * // sorting by multiple properties - * _.map(_.sortBy(characters, ['name', 'age']), _.values); - * // = > [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]] + * _.forOwnRight(new Foo, function(value, key) { + * console.log(key); + * }); + * // => logs 'b' and 'a' assuming `_.forOwn` logs 'a' and 'b' */ - function sortBy(collection, callback, thisArg) { - var index = -1, - isArr = isArray(callback), - length = collection ? collection.length : 0, - result = Array(typeof length == 'number' ? length : 0); - - if (!isArr) { - callback = lodash.createCallback(callback, thisArg, 3); - } - forEach(collection, function(value, key, collection) { - var object = result[++index] = getObject(); - if (isArr) { - object.criteria = map(callback, function(key) { return value[key]; }); - } else { - (object.criteria = getArray())[0] = callback(value, key, collection); - } - object.index = index; - object.value = value; - }); - - length = result.length; - result.sort(compareAscending); - while (length--) { - var object = result[length]; - result[length] = object.value; - if (!isArr) { - releaseArray(object.criteria); - } - releaseObject(object); - } - return result; + function forOwnRight(object, iteratee, thisArg) { + iteratee = bindCallback(iteratee, thisArg, 3); + return baseForRight(object, iteratee, keys); } /** - * Converts the `collection` to an array. + * Creates an array of function property names from all enumerable properties, + * own and inherited, of `object`. * * @static * @memberOf _ - * @category Collections - * @param {Array|Object|string} collection The collection to convert. - * @returns {Array} Returns the new converted array. + * @alias methods + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the new array of property names. * @example * - * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4); - * // => [2, 3, 4] + * _.functions(_); + * // => ['after', 'ary', 'assign', ...] */ - function toArray(collection) { - if (collection && typeof collection.length == 'number') { - return slice(collection); - } - return values(collection); + function functions(object) { + return baseFunctions(object, keysIn(object)); } /** - * Performs a deep comparison of each element in a `collection` to the given - * `properties` object, returning an array of all elements that have equivalent - * property values. + * Checks if `key` exists as a direct property of `object` instead of an + * inherited property. * * @static * @memberOf _ - * @type Function - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Object} props The object of property values to filter by. - * @returns {Array} Returns a new array of elements that have the given properties. + * @category Object + * @param {Object} object The object to inspect. + * @param {string} key The key to check. + * @returns {boolean} Returns `true` if `key` is a direct property, else `false`. * @example * - * var characters = [ - * { 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }, - * { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] } - * ]; - * - * _.where(characters, { 'age': 36 }); - * // => [{ 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }] + * var object = { 'a': 1, 'b': 2, 'c': 3 }; * - * _.where(characters, { 'pets': ['dino'] }); - * // => [{ 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }] + * _.has(object, 'b'); + * // => true */ - var where = filter; - - /*--------------------------------------------------------------------------*/ + function has(object, key) { + return object ? hasOwnProperty.call(object, key) : false; + } /** - * Creates an array with all falsey values removed. The values `false`, `null`, - * `0`, `""`, `undefined`, and `NaN` are all falsey. + * Creates an object composed of the inverted keys and values of `object`. + * If `object` contains duplicate values, subsequent values overwrite property + * assignments of previous values unless `multiValue` is `true`. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to compact. - * @returns {Array} Returns a new array of filtered values. + * @category Object + * @param {Object} object The object to invert. + * @param {boolean} [multiValue] Allow multiple values per key. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {Object} Returns the new inverted object. * @example * - * _.compact([0, 1, false, 2, '', 3]); - * // => [1, 2, 3] + * var object = { 'a': 1, 'b': 2, 'c': 1 }; + * + * _.invert(object); + * // => { '1': 'c', '2': 'b' } + * + * // with `multiValue` + * _.invert(object, true); + * // => { '1': ['a', 'c'], '2': ['b'] } */ - function compact(array) { + function invert(object, multiValue, guard) { + if (guard && isIterateeCall(object, multiValue, guard)) { + multiValue = null; + } var index = -1, - length = array ? array.length : 0, - result = []; + props = keys(object), + length = props.length, + result = {}; while (++index < length) { - var value = array[index]; - if (value) { - result.push(value); + var key = props[index], + value = object[key]; + + if (multiValue) { + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [key]; + } + } + else { + result[value] = key; } } return result; } /** - * Creates an array excluding all values of the provided arrays using strict - * equality for comparisons, i.e. `===`. + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.keys) + * for more details. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to process. - * @param {...Array} [values] The arrays of values to exclude. - * @returns {Array} Returns a new array of filtered values. + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the array of property names. * @example * - * _.difference([1, 2, 3, 4, 5], [5, 2, 10]); - * // => [1, 3, 4] + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] */ - function difference(array) { - return baseDifference(array, baseFlatten(arguments, true, true, 1)); - } + var keys = !nativeKeys ? shimKeys : function(object) { + if (object) { + var Ctor = object.constructor, + length = object.length; + } + if ((typeof Ctor == 'function' && Ctor.prototype === object) || + (typeof object != 'function' && (length && isLength(length)))) { + return shimKeys(object); + } + return isObject(object) ? nativeKeys(object) : []; + }; /** - * This method is like `_.find` except that it returns the index of the first - * element that passes the callback check, instead of the element itself. - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * Creates an array of the own and inherited enumerable property names of `object`. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * **Note:** Non-object values are coerced to objects. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to search. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {number} Returns the index of the found element, else `-1`. + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the array of property names. * @example * - * var characters = [ - * { 'name': 'barney', 'age': 36, 'blocked': false }, - * { 'name': 'fred', 'age': 40, 'blocked': true }, - * { 'name': 'pebbles', 'age': 1, 'blocked': false } - * ]; - * - * _.findIndex(characters, function(chr) { - * return chr.age < 20; - * }); - * // => 2 + * function Foo() { + * this.a = 1; + * this.b = 2; + * } * - * // using "_.where" callback shorthand - * _.findIndex(characters, { 'age': 36 }); - * // => 0 + * Foo.prototype.c = 3; * - * // using "_.pluck" callback shorthand - * _.findIndex(characters, 'blocked'); - * // => 1 + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) */ - function findIndex(array, callback, thisArg) { - var index = -1, - length = array ? array.length : 0; + function keysIn(object) { + if (object == null) { + return []; + } + if (!isObject(object)) { + object = Object(object); + } + var length = object.length; + length = (length && isLength(length) && + (isArray(object) || (support.nonEnumArgs && isArguments(object))) && length) || 0; + + var Ctor = object.constructor, + index = -1, + isProto = typeof Ctor == 'function' && Ctor.prototype === object, + result = Array(length), + skipIndexes = length > 0; - callback = lodash.createCallback(callback, thisArg, 3); while (++index < length) { - if (callback(array[index], index, array)) { - return index; + result[index] = (index + ''); + } + for (var key in object) { + if (!(skipIndexes && isIndex(key, length)) && + !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); } } - return -1; + return result; } /** - * This method is like `_.findIndex` except that it iterates over elements - * of a `collection` from right to left. + * Creates an object with the same keys as `object` and values generated by + * running each own enumerable property of `object` through `iteratee`. The + * iteratee function is bound to `thisArg` and invoked with three arguments; + * (value, key, object). * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * If a property name is provided for `iteratee` the created `_.property` + * style callback returns the property value of the given element. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `iteratee` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to search. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {number} Returns the index of the found element, else `-1`. + * @category Object + * @param {Object} object The object to iterate over. + * @param {Function|Object|string} [iteratee=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Object} Returns the new mapped object. * @example * - * var characters = [ - * { 'name': 'barney', 'age': 36, 'blocked': true }, - * { 'name': 'fred', 'age': 40, 'blocked': false }, - * { 'name': 'pebbles', 'age': 1, 'blocked': true } - * ]; - * - * _.findLastIndex(characters, function(chr) { - * return chr.age > 30; + * _.mapValues({ 'a': 1, 'b': 2 }, function(n) { + * return n * 3; * }); - * // => 1 + * // => { 'a': 3, 'b': 6 } * - * // using "_.where" callback shorthand - * _.findLastIndex(characters, { 'age': 36 }); - * // => 0 + * var users = { + * 'fred': { 'user': 'fred', 'age': 40 }, + * 'pebbles': { 'user': 'pebbles', 'age': 1 } + * }; * - * // using "_.pluck" callback shorthand - * _.findLastIndex(characters, 'blocked'); - * // => 2 + * // using the `_.property` callback shorthand + * _.mapValues(users, 'age'); + * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) */ - function findLastIndex(array, callback, thisArg) { - var length = array ? array.length : 0; - callback = lodash.createCallback(callback, thisArg, 3); - while (length--) { - if (callback(array[length], length, array)) { - return length; - } - } - return -1; + function mapValues(object, iteratee, thisArg) { + var result = {}; + iteratee = getCallback(iteratee, thisArg, 3); + + baseForOwn(object, function(value, key, object) { + result[key] = iteratee(value, key, object); + }); + return result; } /** - * Gets the first element or first `n` elements of an array. If a callback - * is provided elements at the beginning of the array are returned as long - * as the callback returns truey. The callback is bound to `thisArg` and - * invoked with three arguments; (value, index, array). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Recursively merges own enumerable properties of the source object(s), that + * don't resolve to `undefined` into the destination object. Subsequent sources + * overwrite property assignments of previous sources. If `customizer` is + * provided it is invoked to produce the merged values of the destination and + * source properties. If `customizer` returns `undefined` merging is handled + * by the method instead. The `customizer` is bound to `thisArg` and invoked + * with five arguments; (objectValue, sourceValue, key, object, source). * * @static * @memberOf _ - * @alias head, take - * @category Arrays - * @param {Array} array The array to query. - * @param {Function|Object|number|string} [callback] The function called - * per element or the number of elements to return. If a property name or - * object is provided it will be used to create a "_.pluck" or "_.where" - * style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the first element(s) of `array`. + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @param {Function} [customizer] The function to customize merging properties. + * @param {*} [thisArg] The `this` binding of `customizer`. + * @returns {Object} Returns `object`. * @example * - * _.first([1, 2, 3]); - * // => 1 + * var users = { + * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }] + * }; * - * _.first([1, 2, 3], 2); - * // => [1, 2] + * var ages = { + * 'data': [{ 'age': 36 }, { 'age': 40 }] + * }; * - * _.first([1, 2, 3], function(num) { - * return num < 3; - * }); - * // => [1, 2] + * _.merge(users, ages); + * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] } * - * var characters = [ - * { 'name': 'barney', 'blocked': true, 'employer': 'slate' }, - * { 'name': 'fred', 'blocked': false, 'employer': 'slate' }, - * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' } - * ]; + * // using a customizer callback + * var object = { + * 'fruits': ['apple'], + * 'vegetables': ['beet'] + * }; * - * // using "_.pluck" callback shorthand - * _.first(characters, 'blocked'); - * // => [{ 'name': 'barney', 'blocked': true, 'employer': 'slate' }] + * var other = { + * 'fruits': ['banana'], + * 'vegetables': ['carrot'] + * }; * - * // using "_.where" callback shorthand - * _.pluck(_.first(characters, { 'employer': 'slate' }), 'name'); - * // => ['barney', 'fred'] + * _.merge(object, other, function(a, b) { + * if (_.isArray(a)) { + * return a.concat(b); + * } + * }); + * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] } */ - function first(array, callback, thisArg) { - var n = 0, - length = array ? array.length : 0; - - if (typeof callback != 'number' && callback != null) { - var index = -1; - callback = lodash.createCallback(callback, thisArg, 3); - while (++index < length && callback(array[index], index, array)) { - n++; - } - } else { - n = callback; - if (n == null || thisArg) { - return array ? array[0] : undefined; - } - } - return slice(array, 0, nativeMin(nativeMax(0, n), length)); - } + var merge = createAssigner(baseMerge); /** - * Flattens a nested array (the nesting can be to any depth). If `isShallow` - * is truey, the array will only be flattened a single level. If a callback - * is provided each element of the array is passed through the callback before - * flattening. The callback is bound to `thisArg` and invoked with three - * arguments; (value, index, array). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * The opposite of `_.pick`; this method creates an object composed of the + * own and inherited enumerable properties of `object` that are not omitted. + * Property names may be specified as individual arguments or as arrays of + * property names. If `predicate` is provided it is invoked for each property + * of `object` omitting the properties `predicate` returns truthy for. The + * predicate is bound to `thisArg` and invoked with three arguments; + * (value, key, object). * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to flatten. - * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new flattened array. + * @category Object + * @param {Object} object The source object. + * @param {Function|...(string|string[])} [predicate] The function invoked per + * iteration or property names to omit, specified as individual property + * names or arrays of property names. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Object} Returns the new object. * @example * - * _.flatten([1, [2], [3, [[4]]]]); - * // => [1, 2, 3, 4]; - * - * _.flatten([1, [2], [3, [[4]]]], true); - * // => [1, 2, 3, [[4]]]; + * var object = { 'user': 'fred', 'age': 40 }; * - * var characters = [ - * { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] }, - * { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] } - * ]; + * _.omit(object, 'age'); + * // => { 'user': 'fred' } * - * // using "_.pluck" callback shorthand - * _.flatten(characters, 'pets'); - * // => ['hoppy', 'baby puss', 'dino'] + * _.omit(object, _.isNumber); + * // => { 'user': 'fred' } */ - function flatten(array, isShallow, callback, thisArg) { - // juggle arguments - if (typeof isShallow != 'boolean' && isShallow != null) { - thisArg = callback; - callback = (typeof isShallow != 'function' && thisArg && thisArg[isShallow] === array) ? null : isShallow; - isShallow = false; + function omit(object, predicate, thisArg) { + if (object == null) { + return {}; } - if (callback != null) { - array = map(array, callback, thisArg); + if (typeof predicate != 'function') { + var props = arrayMap(baseFlatten(arguments, false, false, 1), String); + return pickByArray(object, baseDifference(keysIn(object), props)); } - return baseFlatten(array, isShallow); + predicate = bindCallback(predicate, thisArg, 3); + return pickByCallback(object, function(value, key, object) { + return !predicate(value, key, object); + }); } /** - * Gets the index at which the first occurrence of `value` is found using - * strict equality for comparisons, i.e. `===`. If the array is already sorted - * providing `true` for `fromIndex` will run a faster binary search. + * Creates a two dimensional array of the key-value pairs for `object`, + * e.g. `[[key1, value1], [key2, value2]]`. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to search. - * @param {*} value The value to search for. - * @param {boolean|number} [fromIndex=0] The index to search from or `true` - * to perform a binary search on a sorted array. - * @returns {number} Returns the index of the matched value or `-1`. + * @category Object + * @param {Object} object The object to inspect. + * @returns {Array} Returns the new array of key-value pairs. * @example * - * _.indexOf([1, 2, 3, 1, 2, 3], 2); - * // => 1 - * - * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3); - * // => 4 - * - * _.indexOf([1, 1, 2, 2, 3, 3], 2, true); - * // => 2 + * _.pairs({ 'barney': 36, 'fred': 40 }); + * // => [['barney', 36], ['fred', 40]] (iteration order is not guaranteed) */ - function indexOf(array, value, fromIndex) { - if (typeof fromIndex == 'number') { - var length = array ? array.length : 0; - fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0); - } else if (fromIndex) { - var index = sortedIndex(array, value); - return array[index] === value ? index : -1; + function pairs(object) { + var index = -1, + props = keys(object), + length = props.length, + result = Array(length); + + while (++index < length) { + var key = props[index]; + result[index] = [key, object[key]]; } - return baseIndexOf(array, value, fromIndex); + return result; } /** - * Gets all but the last element or last `n` elements of an array. If a - * callback is provided elements at the end of the array are excluded from - * the result as long as the callback returns truey. The callback is bound - * to `thisArg` and invoked with three arguments; (value, index, array). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Creates an object composed of the picked `object` properties. Property + * names may be specified as individual arguments or as arrays of property + * names. If `predicate` is provided it is invoked for each property of `object` + * picking the properties `predicate` returns truthy for. The predicate is + * bound to `thisArg` and invoked with three arguments; (value, key, object). * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to query. - * @param {Function|Object|number|string} [callback=1] The function called - * per element or the number of elements to exclude. If a property name or - * object is provided it will be used to create a "_.pluck" or "_.where" - * style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a slice of `array`. + * @category Object + * @param {Object} object The source object. + * @param {Function|...(string|string[])} [predicate] The function invoked per + * iteration or property names to pick, specified as individual property + * names or arrays of property names. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {Object} Returns the new object. * @example * - * _.initial([1, 2, 3]); - * // => [1, 2] - * - * _.initial([1, 2, 3], 2); - * // => [1] - * - * _.initial([1, 2, 3], function(num) { - * return num > 1; - * }); - * // => [1] - * - * var characters = [ - * { 'name': 'barney', 'blocked': false, 'employer': 'slate' }, - * { 'name': 'fred', 'blocked': true, 'employer': 'slate' }, - * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' } - * ]; + * var object = { 'user': 'fred', 'age': 40 }; * - * // using "_.pluck" callback shorthand - * _.initial(characters, 'blocked'); - * // => [{ 'name': 'barney', 'blocked': false, 'employer': 'slate' }] + * _.pick(object, 'user'); + * // => { 'user': 'fred' } * - * // using "_.where" callback shorthand - * _.pluck(_.initial(characters, { 'employer': 'na' }), 'name'); - * // => ['barney', 'fred'] + * _.pick(object, _.isString); + * // => { 'user': 'fred' } */ - function initial(array, callback, thisArg) { - var n = 0, - length = array ? array.length : 0; - - if (typeof callback != 'number' && callback != null) { - var index = length; - callback = lodash.createCallback(callback, thisArg, 3); - while (index-- && callback(array[index], index, array)) { - n++; - } - } else { - n = (callback == null || thisArg) ? 1 : callback || n; + function pick(object, predicate, thisArg) { + if (object == null) { + return {}; } - return slice(array, 0, nativeMin(nativeMax(0, length - n), length)); + return typeof predicate == 'function' + ? pickByCallback(object, bindCallback(predicate, thisArg, 3)) + : pickByArray(object, baseFlatten(arguments, false, false, 1)); } /** - * Creates an array of unique values present in all provided arrays using - * strict equality for comparisons, i.e. `===`. + * Resolves the value of property `key` on `object`. If the value of `key` is + * a function it is invoked with the `this` binding of `object` and its result + * is returned, else the property value is returned. If the property value is + * `undefined` the `defaultValue` is used in its place. * * @static * @memberOf _ - * @category Arrays - * @param {...Array} [array] The arrays to inspect. - * @returns {Array} Returns an array of shared values. + * @category Object + * @param {Object} object The object to query. + * @param {string} key The key of the property to resolve. + * @param {*} [defaultValue] The value returned if the property value + * resolves to `undefined`. + * @returns {*} Returns the resolved value. * @example * - * _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]); - * // => [1, 2] + * var object = { 'user': 'fred', 'age': _.constant(40) }; + * + * _.result(object, 'user'); + * // => 'fred' + * + * _.result(object, 'age'); + * // => 40 + * + * _.result(object, 'status', 'busy'); + * // => 'busy' + * + * _.result(object, 'status', _.constant('busy')); + * // => 'busy' */ - function intersection() { - var args = [], - argsIndex = -1, - argsLength = arguments.length, - caches = getArray(), - indexOf = getIndexOf(), - trustIndexOf = indexOf === baseIndexOf, - seen = getArray(); - - while (++argsIndex < argsLength) { - var value = arguments[argsIndex]; - if (isArray(value) || isArguments(value)) { - args.push(value); - caches.push(trustIndexOf && value.length >= largeArraySize && - createCache(argsIndex ? args[argsIndex] : seen)); - } - } - var array = args[0], - index = -1, - length = array ? array.length : 0, - result = []; - - outer: - while (++index < length) { - var cache = caches[0]; - value = array[index]; - - if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) { - argsIndex = argsLength; - (cache || seen).push(value); - while (--argsIndex) { - cache = caches[argsIndex]; - if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) { - continue outer; - } - } - result.push(value); - } - } - while (argsLength--) { - cache = caches[argsLength]; - if (cache) { - releaseObject(cache); - } + function result(object, key, defaultValue) { + var value = object == null ? undefined : object[key]; + if (typeof value == 'undefined') { + value = defaultValue; } - releaseArray(caches); - releaseArray(seen); - return result; + return isFunction(value) ? value.call(object) : value; } /** - * Gets the last element or last `n` elements of an array. If a callback is - * provided elements at the end of the array are returned as long as the - * callback returns truey. The callback is bound to `thisArg` and invoked - * with three arguments; (value, index, array). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * An alternative to `_.reduce`; this method transforms `object` to a new + * `accumulator` object which is the result of running each of its own enumerable + * properties through `iteratee`, with each invocation potentially mutating + * the `accumulator` object. The `iteratee` is bound to `thisArg` and invoked + * with four arguments; (accumulator, value, key, object). Iterator functions + * may exit iteration early by explicitly returning `false`. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to query. - * @param {Function|Object|number|string} [callback] The function called - * per element or the number of elements to return. If a property name or - * object is provided it will be used to create a "_.pluck" or "_.where" - * style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the last element(s) of `array`. + * @category Object + * @param {Array|Object} object The object to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [accumulator] The custom accumulator value. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {*} Returns the accumulated value. * @example * - * _.last([1, 2, 3]); - * // => 3 - * - * _.last([1, 2, 3], 2); - * // => [2, 3] - * - * _.last([1, 2, 3], function(num) { - * return num > 1; + * _.transform([2, 3, 4], function(result, n) { + * result.push(n *= n); + * return n % 2 == 0; * }); - * // => [2, 3] - * - * var characters = [ - * { 'name': 'barney', 'blocked': false, 'employer': 'slate' }, - * { 'name': 'fred', 'blocked': true, 'employer': 'slate' }, - * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' } - * ]; + * // => [4, 9] * - * // using "_.pluck" callback shorthand - * _.pluck(_.last(characters, 'blocked'), 'name'); - * // => ['fred', 'pebbles'] - * - * // using "_.where" callback shorthand - * _.last(characters, { 'employer': 'na' }); - * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }] + * _.transform({ 'a': 1, 'b': 2 }, function(result, n, key) { + * result[key] = n * 3; + * }); + * // => { 'a': 3, 'b': 6 } */ - function last(array, callback, thisArg) { - var n = 0, - length = array ? array.length : 0; + function transform(object, iteratee, accumulator, thisArg) { + var isArr = isArray(object) || isTypedArray(object); + iteratee = getCallback(iteratee, thisArg, 4); - if (typeof callback != 'number' && callback != null) { - var index = length; - callback = lodash.createCallback(callback, thisArg, 3); - while (index-- && callback(array[index], index, array)) { - n++; - } - } else { - n = callback; - if (n == null || thisArg) { - return array ? array[length - 1] : undefined; + if (accumulator == null) { + if (isArr || isObject(object)) { + var Ctor = object.constructor; + if (isArr) { + accumulator = isArray(object) ? new Ctor : []; + } else { + accumulator = baseCreate(isFunction(Ctor) && Ctor.prototype); + } + } else { + accumulator = {}; } } - return slice(array, nativeMax(0, length - n)); + (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; } /** - * Gets the index at which the last occurrence of `value` is found using strict - * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used - * as the offset from the end of the collection. + * Creates an array of the own enumerable property values of `object`. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * **Note:** Non-object values are coerced to objects. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to search. - * @param {*} value The value to search for. - * @param {number} [fromIndex=array.length-1] The index to search from. - * @returns {number} Returns the index of the matched value or `-1`. + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. * @example * - * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2); - * // => 4 + * function Foo() { + * this.a = 1; + * this.b = 2; + * } * - * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3); - * // => 1 + * Foo.prototype.c = 3; + * + * _.values(new Foo); + * // => [1, 2] (iteration order is not guaranteed) + * + * _.values('hi'); + * // => ['h', 'i'] */ - function lastIndexOf(array, value, fromIndex) { - var index = array ? array.length : 0; - if (typeof fromIndex == 'number') { - index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1; - } - while (index--) { - if (array[index] === value) { - return index; - } - } - return -1; + function values(object) { + return baseValues(object, keys(object)); } /** - * Removes all provided values from the given array using strict equality for - * comparisons, i.e. `===`. + * Creates an array of the own and inherited enumerable property values + * of `object`. + * + * **Note:** Non-object values are coerced to objects. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to modify. - * @param {...*} [value] The values to remove. - * @returns {Array} Returns `array`. + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. * @example * - * var array = [1, 2, 3, 1, 2, 3]; - * _.pull(array, 2, 3); - * console.log(array); - * // => [1, 1] - */ - function pull(array) { - var args = arguments, - argsIndex = 0, - argsLength = args.length, - length = array ? array.length : 0; - - while (++argsIndex < argsLength) { - var index = -1, - value = args[argsIndex]; - while (++index < length) { - if (array[index] === value) { - splice.call(array, index--, 1); - length--; - } - } - } - return array; + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.valuesIn(new Foo); + * // => [1, 2, 3] (iteration order is not guaranteed) + */ + function valuesIn(object) { + return baseValues(object, keysIn(object)); } + /*------------------------------------------------------------------------*/ + /** - * Creates an array of numbers (positive and/or negative) progressing from - * `start` up to but not including `end`. If `start` is less than `stop` a - * zero-length range is created unless a negative `step` is specified. + * Checks if `n` is between `start` and up to but not including, `end`. If + * `end` is not specified it defaults to `start` with `start` becoming `0`. * * @static * @memberOf _ - * @category Arrays + * @category Number + * @param {number} n The number to check. * @param {number} [start=0] The start of the range. * @param {number} end The end of the range. - * @param {number} [step=1] The value to increment or decrement by. - * @returns {Array} Returns a new range array. + * @returns {boolean} Returns `true` if `n` is in the range, else `false`. * @example * - * _.range(4); - * // => [0, 1, 2, 3] + * _.inRange(3, 2, 4); + * // => true * - * _.range(1, 5); - * // => [1, 2, 3, 4] + * _.inRange(4, 8); + * // => true * - * _.range(0, 20, 5); - * // => [0, 5, 10, 15] + * _.inRange(4, 2); + * // => false * - * _.range(0, -4, -1); - * // => [0, -1, -2, -3] + * _.inRange(2, 2); + * // => false * - * _.range(1, 4, 0); - * // => [1, 1, 1] + * _.inRange(1.2, 2); + * // => true * - * _.range(0); - * // => [] + * _.inRange(5.2, 4); + * // => false */ - function range(start, end, step) { + function inRange(value, start, end) { start = +start || 0; - step = typeof step == 'number' ? step : (+step || 1); - - if (end == null) { + if (typeof end === 'undefined') { end = start; start = 0; + } else { + end = +end || 0; } - // use `Array(length)` so engines like Chakra and V8 avoid slower modes - // http://youtu.be/XAqIpGU8ZZk#t=17m25s - var index = -1, - length = nativeMax(0, ceil((end - start) / (step || 1))), - result = Array(length); - - while (++index < length) { - result[index] = start; - start += step; - } - return result; + return value >= start && value < end; } /** - * Removes all elements from an array that the callback returns truey for - * and returns an array of removed elements. The callback is bound to `thisArg` - * and invoked with three arguments; (value, index, array). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Produces a random number between `min` and `max` (inclusive). If only one + * argument is provided a number between `0` and the given number is returned. + * If `floating` is `true`, or either `min` or `max` are floats, a floating-point + * number is returned instead of an integer. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to modify. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new array of removed elements. + * @category Number + * @param {number} [min=0] The minimum possible value. + * @param {number} [max=1] The maximum possible value. + * @param {boolean} [floating] Specify returning a floating-point number. + * @returns {number} Returns the random number. * @example * - * var array = [1, 2, 3, 4, 5, 6]; - * var evens = _.remove(array, function(num) { return num % 2 == 0; }); + * _.random(0, 5); + * // => an integer between 0 and 5 * - * console.log(array); - * // => [1, 3, 5] + * _.random(5); + * // => also an integer between 0 and 5 * - * console.log(evens); - * // => [2, 4, 6] + * _.random(5, true); + * // => a floating-point number between 0 and 5 + * + * _.random(1.2, 5.2); + * // => a floating-point number between 1.2 and 5.2 */ - function remove(array, callback, thisArg) { - var index = -1, - length = array ? array.length : 0, - result = []; + function random(min, max, floating) { + if (floating && isIterateeCall(min, max, floating)) { + max = floating = null; + } + var noMin = min == null, + noMax = max == null; - callback = lodash.createCallback(callback, thisArg, 3); - while (++index < length) { - var value = array[index]; - if (callback(value, index, array)) { - result.push(value); - splice.call(array, index--, 1); - length--; + if (floating == null) { + if (noMax && typeof min == 'boolean') { + floating = min; + min = 1; + } + else if (typeof max == 'boolean') { + floating = max; + noMax = true; } } - return result; + if (noMin && noMax) { + max = 1; + noMax = false; + } + min = +min || 0; + if (noMax) { + max = min; + min = 0; + } else { + max = +max || 0; + } + if (floating || min % 1 || max % 1) { + var rand = nativeRandom(); + return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand + '').length - 1)))), max); + } + return baseRandom(min, max); } + /*------------------------------------------------------------------------*/ + /** - * The opposite of `_.initial` this method gets all but the first element or - * first `n` elements of an array. If a callback function is provided elements - * at the beginning of the array are excluded from the result as long as the - * callback returns truey. The callback is bound to `thisArg` and invoked - * with three arguments; (value, index, array). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Converts `string` to camel case. + * See [Wikipedia](https://en.wikipedia.org/wiki/CamelCase) for more details. * * @static * @memberOf _ - * @alias drop, tail - * @category Arrays - * @param {Array} array The array to query. - * @param {Function|Object|number|string} [callback=1] The function called - * per element or the number of elements to exclude. If a property name or - * object is provided it will be used to create a "_.pluck" or "_.where" - * style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a slice of `array`. + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the camel cased string. * @example * - * _.rest([1, 2, 3]); - * // => [2, 3] - * - * _.rest([1, 2, 3], 2); - * // => [3] + * _.camelCase('Foo Bar'); + * // => 'fooBar' * - * _.rest([1, 2, 3], function(num) { - * return num < 3; - * }); - * // => [3] + * _.camelCase('--foo-bar'); + * // => 'fooBar' * - * var characters = [ - * { 'name': 'barney', 'blocked': true, 'employer': 'slate' }, - * { 'name': 'fred', 'blocked': false, 'employer': 'slate' }, - * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' } - * ]; + * _.camelCase('__foo_bar__'); + * // => 'fooBar' + */ + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? (word.charAt(0).toUpperCase() + word.slice(1)) : word); + }); + + /** + * Capitalizes the first character of `string`. * - * // using "_.pluck" callback shorthand - * _.pluck(_.rest(characters, 'blocked'), 'name'); - * // => ['fred', 'pebbles'] + * @static + * @memberOf _ + * @category String + * @param {string} [string=''] The string to capitalize. + * @returns {string} Returns the capitalized string. + * @example * - * // using "_.where" callback shorthand - * _.rest(characters, { 'employer': 'slate' }); - * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }] + * _.capitalize('fred'); + * // => 'Fred' */ - function rest(array, callback, thisArg) { - if (typeof callback != 'number' && callback != null) { - var n = 0, - index = -1, - length = array ? array.length : 0; - - callback = lodash.createCallback(callback, thisArg, 3); - while (++index < length && callback(array[index], index, array)) { - n++; - } - } else { - n = (callback == null || thisArg) ? 1 : nativeMax(0, callback); - } - return slice(array, n); + function capitalize(string) { + string = baseToString(string); + return string && (string.charAt(0).toUpperCase() + string.slice(1)); } /** - * Uses a binary search to determine the smallest index at which a value - * should be inserted into a given sorted array in order to maintain the sort - * order of the array. If a callback is provided it will be executed for - * `value` and each element of `array` to compute their sort ranking. The - * callback is bound to `thisArg` and invoked with one argument; (value). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * Deburrs `string` by converting latin-1 supplementary letters to basic latin letters. + * See [Wikipedia](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) + * for more details. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to inspect. - * @param {*} value The value to evaluate. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {number} Returns the index at which `value` should be inserted - * into `array`. + * @category String + * @param {string} [string=''] The string to deburr. + * @returns {string} Returns the deburred string. * @example * - * _.sortedIndex([20, 30, 50], 40); - * // => 2 - * - * // using "_.pluck" callback shorthand - * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); - * // => 2 - * - * var dict = { - * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 } - * }; - * - * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { - * return dict.wordToNumber[word]; - * }); - * // => 2 - * - * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { - * return this.wordToNumber[word]; - * }, dict); - * // => 2 + * _.deburr('déjà vu'); + * // => 'deja vu' */ - function sortedIndex(array, value, callback, thisArg) { - var low = 0, - high = array ? array.length : low; - - // explicitly reference `identity` for better inlining in Firefox - callback = callback ? lodash.createCallback(callback, thisArg, 1) : identity; - value = callback(value); - - while (low < high) { - var mid = (low + high) >>> 1; - (callback(array[mid]) < value) - ? low = mid + 1 - : high = mid; - } - return low; + function deburr(string) { + string = baseToString(string); + return string && string.replace(reLatin1, deburrLetter); } /** - * Creates an array of unique values, in order, of the provided arrays using - * strict equality for comparisons, i.e. `===`. + * Checks if `string` ends with the given target string. * * @static * @memberOf _ - * @category Arrays - * @param {...Array} [array] The arrays to inspect. - * @returns {Array} Returns an array of combined values. + * @category String + * @param {string} [string=''] The string to search. + * @param {string} [target] The string to search for. + * @param {number} [position=string.length] The position to search from. + * @returns {boolean} Returns `true` if `string` ends with `target`, else `false`. * @example * - * _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]); - * // => [1, 2, 3, 5, 4] + * _.endsWith('abc', 'c'); + * // => true + * + * _.endsWith('abc', 'b'); + * // => false + * + * _.endsWith('abc', 'b', 2); + * // => true */ - function union() { - return baseUniq(baseFlatten(arguments, true, true)); + function endsWith(string, target, position) { + string = baseToString(string); + target = (target + ''); + + var length = string.length; + position = (typeof position == 'undefined' ? length : nativeMin(position < 0 ? 0 : (+position || 0), length)) - target.length; + return position >= 0 && string.indexOf(target, position) == position; } /** - * Creates a duplicate-value-free version of an array using strict equality - * for comparisons, i.e. `===`. If the array is sorted, providing - * `true` for `isSorted` will use a faster algorithm. If a callback is provided - * each element of `array` is passed through the callback before uniqueness - * is computed. The callback is bound to `thisArg` and invoked with three - * arguments; (value, index, array). + * Converts the characters "&", "<", ">", '"', "'", and '`', in `string` to + * their corresponding HTML entities. + * + * **Note:** No other characters are escaped. To escape additional characters + * use a third-party library like [_he_](https://mths.be/he). + * + * Though the ">" character is escaped for symmetry, characters like + * ">" and "/" don't require escaping in HTML and have no special meaning + * unless they're part of a tag or unquoted attribute value. + * See [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) + * (under "semi-related fun fact") for more details. * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. + * Backticks are escaped because in Internet Explorer < 9, they can break out + * of attribute values or HTML comments. See [#102](https://html5sec.org/#102), + * [#108](https://html5sec.org/#108), and [#133](https://html5sec.org/#133) of + * the [HTML5 Security Cheatsheet](https://html5sec.org/) for more details. * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. + * When working with HTML you should always quote attribute values to reduce + * XSS vectors. See [Ryan Grove's article](http://wonko.com/post/html-escaping) + * for more details. * * @static * @memberOf _ - * @alias unique - * @category Arrays - * @param {Array} array The array to process. - * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a duplicate-value-free array. + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. * @example * - * _.uniq([1, 2, 1, 3, 1]); - * // => [1, 2, 3] - * - * _.uniq([1, 1, 2, 2, 3], true); - * // => [1, 2, 3] - * - * _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); }); - * // => ['A', 'b', 'C'] - * - * _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math); - * // => [1, 2.5, 3] - * - * // using "_.pluck" callback shorthand - * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); - * // => [{ 'x': 1 }, { 'x': 2 }] + * _.escape('fred, barney, & pebbles'); + * // => 'fred, barney, & pebbles' */ - function uniq(array, isSorted, callback, thisArg) { - // juggle arguments - if (typeof isSorted != 'boolean' && isSorted != null) { - thisArg = callback; - callback = (typeof isSorted != 'function' && thisArg && thisArg[isSorted] === array) ? null : isSorted; - isSorted = false; - } - if (callback != null) { - callback = lodash.createCallback(callback, thisArg, 3); - } - return baseUniq(array, isSorted, callback); + function escape(string) { + // Reset `lastIndex` because in IE < 9 `String#replace` does not. + string = baseToString(string); + return (string && reHasUnescapedHtml.test(string)) + ? string.replace(reUnescapedHtml, escapeHtmlChar) + : string; } /** - * Creates an array excluding all provided values using strict equality for - * comparisons, i.e. `===`. + * Escapes the `RegExp` special characters "\", "^", "$", ".", "|", "?", "*", + * "+", "(", ")", "[", "]", "{" and "}" in `string`. * * @static * @memberOf _ - * @category Arrays - * @param {Array} array The array to filter. - * @param {...*} [value] The values to exclude. - * @returns {Array} Returns a new array of filtered values. + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. * @example * - * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); - * // => [2, 3, 4] + * _.escapeRegExp('[lodash](https://lodash.com/)'); + * // => '\[lodash\]\(https://lodash\.com/\)' */ - function without(array) { - return baseDifference(array, slice(arguments, 1)); + function escapeRegExp(string) { + string = baseToString(string); + return (string && reHasRegExpChars.test(string)) + ? string.replace(reRegExpChars, '\\$&') + : string; } /** - * Creates an array that is the symmetric difference of the provided arrays. - * See http://en.wikipedia.org/wiki/Symmetric_difference. + * Converts `string` to kebab case. + * See [Wikipedia](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles) for + * more details. * * @static * @memberOf _ - * @category Arrays - * @param {...Array} [array] The arrays to inspect. - * @returns {Array} Returns an array of values. + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the kebab cased string. * @example * - * _.xor([1, 2, 3], [5, 2, 1, 4]); - * // => [3, 5, 4] + * _.kebabCase('Foo Bar'); + * // => 'foo-bar' + * + * _.kebabCase('fooBar'); + * // => 'foo-bar' * - * _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]); - * // => [1, 4, 5] + * _.kebabCase('__foo_bar__'); + * // => 'foo-bar' */ - function xor() { - var index = -1, - length = arguments.length; - - while (++index < length) { - var array = arguments[index]; - if (isArray(array) || isArguments(array)) { - var result = result - ? baseUniq(baseDifference(result, array).concat(baseDifference(array, result))) - : array; - } - } - return result || []; - } + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? '-' : '') + word.toLowerCase(); + }); /** - * Creates an array of grouped elements, the first of which contains the first - * elements of the given arrays, the second of which contains the second - * elements of the given arrays, and so on. + * Pads `string` on the left and right sides if it is shorter then the given + * padding length. The `chars` string may be truncated if the number of padding + * characters can't be evenly divided by the padding length. * * @static * @memberOf _ - * @alias unzip - * @category Arrays - * @param {...Array} [array] Arrays to process. - * @returns {Array} Returns a new array of grouped elements. + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. * @example * - * _.zip(['fred', 'barney'], [30, 40], [true, false]); - * // => [['fred', 30, true], ['barney', 40, false]] + * _.pad('abc', 8); + * // => ' abc ' + * + * _.pad('abc', 8, '_-'); + * // => '_-abc_-_' + * + * _.pad('abc', 3); + * // => 'abc' */ - function zip() { - var array = arguments.length > 1 ? arguments : arguments[0], - index = -1, - length = array ? max(pluck(array, 'length')) : 0, - result = Array(length < 0 ? 0 : length); + function pad(string, length, chars) { + string = baseToString(string); + length = +length; - while (++index < length) { - result[index] = pluck(array, index); + var strLength = string.length; + if (strLength >= length || !nativeIsFinite(length)) { + return string; } - return result; + var mid = (length - strLength) / 2, + leftLength = floor(mid), + rightLength = ceil(mid); + + chars = createPad('', rightLength, chars); + return chars.slice(0, leftLength) + string + chars; } /** - * Creates an object composed from arrays of `keys` and `values`. Provide - * either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]` - * or two arrays, one of `keys` and one of corresponding `values`. + * Pads `string` on the left side if it is shorter then the given padding + * length. The `chars` string may be truncated if the number of padding + * characters exceeds the padding length. * * @static * @memberOf _ - * @alias object - * @category Arrays - * @param {Array} keys The array of keys. - * @param {Array} [values=[]] The array of values. - * @returns {Object} Returns an object composed of the given keys and - * corresponding values. + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. * @example * - * _.zipObject(['fred', 'barney'], [30, 40]); - * // => { 'fred': 30, 'barney': 40 } + * _.padLeft('abc', 6); + * // => ' abc' + * + * _.padLeft('abc', 6, '_-'); + * // => '_-_abc' + * + * _.padLeft('abc', 3); + * // => 'abc' */ - function zipObject(keys, values) { - var index = -1, - length = keys ? keys.length : 0, - result = {}; - - if (!values && length && !isArray(keys[0])) { - values = []; - } - while (++index < length) { - var key = keys[index]; - if (values) { - result[key] = values[index]; - } else if (key) { - result[key[0]] = key[1]; - } - } - return result; + function padLeft(string, length, chars) { + string = baseToString(string); + return string && (createPad(string, length, chars) + string); } - /*--------------------------------------------------------------------------*/ - /** - * Creates a function that executes `func`, with the `this` binding and - * arguments of the created function, only after being called `n` times. + * Pads `string` on the right side if it is shorter then the given padding + * length. The `chars` string may be truncated if the number of padding + * characters exceeds the padding length. * * @static * @memberOf _ - * @category Functions - * @param {number} n The number of times the function must be called before - * `func` is executed. - * @param {Function} func The function to restrict. - * @returns {Function} Returns the new restricted function. + * @category String + * @param {string} [string=''] The string to pad. + * @param {number} [length=0] The padding length. + * @param {string} [chars=' '] The string used as padding. + * @returns {string} Returns the padded string. * @example * - * var saves = ['profile', 'settings']; + * _.padRight('abc', 6); + * // => 'abc ' * - * var done = _.after(saves.length, function() { - * console.log('Done saving!'); - * }); + * _.padRight('abc', 6, '_-'); + * // => 'abc_-_' * - * _.forEach(saves, function(type) { - * asyncSave({ 'type': type, 'complete': done }); - * }); - * // => logs 'Done saving!', after all saves have completed + * _.padRight('abc', 3); + * // => 'abc' */ - function after(n, func) { - if (!isFunction(func)) { - throw new TypeError; - } - return function() { - if (--n < 1) { - return func.apply(this, arguments); - } - }; + function padRight(string, length, chars) { + string = baseToString(string); + return string && (string + createPad(string, length, chars)); } /** - * Creates a function that, when called, invokes `func` with the `this` - * binding of `thisArg` and prepends any additional `bind` arguments to those - * provided to the bound function. + * Converts `string` to an integer of the specified radix. If `radix` is + * `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal, + * in which case a `radix` of `16` is used. + * + * **Note:** This method aligns with the ES5 implementation of `parseInt`. + * See the [ES5 spec](https://es5.github.io/#E) for more details. * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to bind. - * @param {*} [thisArg] The `this` binding of `func`. - * @param {...*} [arg] Arguments to be partially applied. - * @returns {Function} Returns the new bound function. + * @category String + * @param {string} string The string to convert. + * @param {number} [radix] The radix to interpret `value` by. + * @param- {Object} [guard] Enables use as a callback for functions like `_.map`. + * @returns {number} Returns the converted integer. * @example * - * var func = function(greeting) { - * return greeting + ' ' + this.name; - * }; + * _.parseInt('08'); + * // => 8 * - * func = _.bind(func, { 'name': 'fred' }, 'hi'); - * func(); - * // => 'hi fred' + * _.map(['6', '08', '10'], _.parseInt); + * // => [6, 8, 10] */ - function bind(func, thisArg) { - return arguments.length > 2 - ? createWrapper(func, 17, slice(arguments, 2), null, thisArg) - : createWrapper(func, 1, null, null, thisArg); + function parseInt(string, radix, guard) { + if (guard && isIterateeCall(string, radix, guard)) { + radix = 0; + } + return nativeParseInt(string, radix); + } + // Fallback for environments with pre-ES5 implementations. + if (nativeParseInt(whitespace + '08') != 8) { + parseInt = function(string, radix, guard) { + // Firefox < 21 and Opera < 15 follow ES3 for `parseInt`. + // Chrome fails to trim leading whitespace characters. + // See https://code.google.com/p/v8/issues/detail?id=3109 for more details. + if (guard ? isIterateeCall(string, radix, guard) : radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + string = trim(string); + return nativeParseInt(string, radix || (reHexPrefix.test(string) ? 16 : 10)); + }; } /** - * Binds methods of an object to the object itself, overwriting the existing - * method. Method names may be specified as individual arguments or as arrays - * of method names. If no method names are provided all the function properties - * of `object` will be bound. + * Repeats the given string `n` times. * * @static * @memberOf _ - * @category Functions - * @param {Object} object The object to bind and assign the bound methods to. - * @param {...string} [methodName] The object method names to - * bind, specified as individual method names or arrays of method names. - * @returns {Object} Returns `object`. + * @category String + * @param {string} [string=''] The string to repeat. + * @param {number} [n=0] The number of times to repeat the string. + * @returns {string} Returns the repeated string. * @example * - * var view = { - * 'label': 'docs', - * 'onClick': function() { console.log('clicked ' + this.label); } - * }; + * _.repeat('*', 3); + * // => '***' * - * _.bindAll(view); - * jQuery('#docs').on('click', view.onClick); - * // => logs 'clicked docs', when the button is clicked + * _.repeat('abc', 2); + * // => 'abcabc' + * + * _.repeat('abc', 0); + * // => '' */ - function bindAll(object) { - var funcs = arguments.length > 1 ? baseFlatten(arguments, true, false, 1) : functions(object), - index = -1, - length = funcs.length; - - while (++index < length) { - var key = funcs[index]; - object[key] = createWrapper(object[key], 1, null, null, object); + function repeat(string, n) { + var result = ''; + string = baseToString(string); + n = +n; + if (n < 1 || !string || !nativeIsFinite(n)) { + return result; } - return object; + // Leverage the exponentiation by squaring algorithm for a faster repeat. + // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details. + do { + if (n % 2) { + result += string; + } + n = floor(n / 2); + string += string; + } while (n); + + return result; } /** - * Creates a function that, when called, invokes the method at `object[key]` - * and prepends any additional `bindKey` arguments to those provided to the bound - * function. This method differs from `_.bind` by allowing bound functions to - * reference methods that will be redefined or don't yet exist. - * See http://michaux.ca/articles/lazy-function-definition-pattern. + * Converts `string` to snake case. + * See [Wikipedia](https://en.wikipedia.org/wiki/Snake_case) for more details. * * @static * @memberOf _ - * @category Functions - * @param {Object} object The object the method belongs to. - * @param {string} key The key of the method. - * @param {...*} [arg] Arguments to be partially applied. - * @returns {Function} Returns the new bound function. + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the snake cased string. * @example * - * var object = { - * 'name': 'fred', - * 'greet': function(greeting) { - * return greeting + ' ' + this.name; - * } - * }; - * - * var func = _.bindKey(object, 'greet', 'hi'); - * func(); - * // => 'hi fred' + * _.snakeCase('Foo Bar'); + * // => 'foo_bar' * - * object.greet = function(greeting) { - * return greeting + 'ya ' + this.name + '!'; - * }; + * _.snakeCase('fooBar'); + * // => 'foo_bar' * - * func(); - * // => 'hiya fred!' + * _.snakeCase('--foo-bar'); + * // => 'foo_bar' */ - function bindKey(object, key) { - return arguments.length > 2 - ? createWrapper(key, 19, slice(arguments, 2), null, object) - : createWrapper(key, 3, null, null, object); - } + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? '_' : '') + word.toLowerCase(); + }); /** - * Creates a function that is the composition of the provided functions, - * where each function consumes the return value of the function that follows. - * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`. - * Each function is executed with the `this` binding of the composed function. + * Converts `string` to start case. + * See [Wikipedia](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage) + * for more details. * * @static * @memberOf _ - * @category Functions - * @param {...Function} [func] Functions to compose. - * @returns {Function} Returns the new composed function. + * @category String + * @param {string} [string=''] The string to convert. + * @returns {string} Returns the start cased string. * @example * - * var realNameMap = { - * 'pebbles': 'penelope' - * }; - * - * var format = function(name) { - * name = realNameMap[name.toLowerCase()] || name; - * return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase(); - * }; + * _.startCase('--foo-bar'); + * // => 'Foo Bar' * - * var greet = function(formatted) { - * return 'Hiya ' + formatted + '!'; - * }; + * _.startCase('fooBar'); + * // => 'Foo Bar' * - * var welcome = _.compose(greet, format); - * welcome('pebbles'); - * // => 'Hiya Penelope!' + * _.startCase('__foo_bar__'); + * // => 'Foo Bar' */ - function compose() { - var funcs = arguments, - length = funcs.length; - - while (length--) { - if (!isFunction(funcs[length])) { - throw new TypeError; - } - } - return function() { - var args = arguments, - length = funcs.length; - - while (length--) { - args = [funcs[length].apply(this, args)]; - } - return args[0]; - }; - } + var startCase = createCompounder(function(result, word, index) { + return result + (index ? ' ' : '') + (word.charAt(0).toUpperCase() + word.slice(1)); + }); /** - * Creates a function which accepts one or more arguments of `func` that when - * invoked either executes `func` returning its result, if all `func` arguments - * have been provided, or returns a function that accepts one or more of the - * remaining `func` arguments, and so on. The arity of `func` can be specified - * if `func.length` is not sufficient. + * Checks if `string` starts with the given target string. * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to curry. - * @param {number} [arity=func.length] The arity of `func`. - * @returns {Function} Returns the new curried function. + * @category String + * @param {string} [string=''] The string to search. + * @param {string} [target] The string to search for. + * @param {number} [position=0] The position to search from. + * @returns {boolean} Returns `true` if `string` starts with `target`, else `false`. * @example * - * var curried = _.curry(function(a, b, c) { - * console.log(a + b + c); - * }); - * - * curried(1)(2)(3); - * // => 6 + * _.startsWith('abc', 'a'); + * // => true * - * curried(1, 2)(3); - * // => 6 + * _.startsWith('abc', 'b'); + * // => false * - * curried(1, 2, 3); - * // => 6 + * _.startsWith('abc', 'b', 1); + * // => true */ - function curry(func, arity) { - arity = typeof arity == 'number' ? arity : (+arity || func.length); - return createWrapper(func, 4, null, null, null, arity); + function startsWith(string, target, position) { + string = baseToString(string); + position = position == null ? 0 : nativeMin(position < 0 ? 0 : (+position || 0), string.length); + return string.lastIndexOf(target, position) == position; } /** - * Creates a function that will delay the execution of `func` until after - * `wait` milliseconds have elapsed since the last time it was invoked. - * Provide an options object to indicate that `func` should be invoked on - * the leading and/or trailing edge of the `wait` timeout. Subsequent calls - * to the debounced function will return the result of the last `func` call. + * Creates a compiled template function that can interpolate data properties + * in "interpolate" delimiters, HTML-escape interpolated data properties in + * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data + * properties may be accessed as free variables in the template. If a setting + * object is provided it takes precedence over `_.templateSettings` values. * - * Note: If `leading` and `trailing` options are `true` `func` will be called - * on the trailing edge of the timeout only if the the debounced function is - * invoked more than once during the `wait` timeout. + * **Note:** In the development build `_.template` utilizes sourceURLs for easier debugging. + * See the [HTML5 Rocks article on sourcemaps](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) + * for more details. + * + * For more information on precompiling templates see + * [lodash's custom builds documentation](https://lodash.com/custom-builds). + * + * For more information on Chrome extension sandboxes see + * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval). * * @static * @memberOf _ - * @category Functions - * @param {Function} func The function to debounce. - * @param {number} wait The number of milliseconds to delay. + * @category String + * @param {string} [string=''] The template string. * @param {Object} [options] The options object. - * @param {boolean} [options.leading=false] Specify execution on the leading edge of the timeout. - * @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's called. - * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout. - * @returns {Function} Returns the new debounced function. + * @param {RegExp} [options.escape] The HTML "escape" delimiter. + * @param {RegExp} [options.evaluate] The "evaluate" delimiter. + * @param {Object} [options.imports] An object to import into the template as free variables. + * @param {RegExp} [options.interpolate] The "interpolate" delimiter. + * @param {string} [options.sourceURL] The sourceURL of the template's compiled source. + * @param {string} [options.variable] The data object variable name. + * @param- {Object} [otherOptions] Enables the legacy `options` param signature. + * @returns {Function} Returns the compiled template function. * @example * - * // avoid costly calculations while the window size is in flux - * var lazyLayout = _.debounce(calculateLayout, 150); - * jQuery(window).on('resize', lazyLayout); + * // using the "interpolate" delimiter to create a compiled template + * var compiled = _.template('hello <%= user %>!'); + * compiled({ 'user': 'fred' }); + * // => 'hello fred!' * - * // execute `sendMail` when the click event is fired, debouncing subsequent calls - * jQuery('#postbox').on('click', _.debounce(sendMail, 300, { - * 'leading': true, - * 'trailing': false - * }); + * // using the HTML "escape" delimiter to escape data property values + * var compiled = _.template('<%- value %>'); + * compiled({ 'value': '