| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 |
- webpackJsonp([0],[
- /* 0 */
- /***/ function(module, exports, __webpack_require__) {
- eval("/* WEBPACK VAR INJECTION */(function(process) {\"use strict\";\nvar platform_browser_dynamic_1 = __webpack_require__(2);\nvar core_1 = __webpack_require__(4);\nvar app_module_1 = __webpack_require__(24);\nif (process.env.ENV === 'production') {\n core_1.enableProdMode();\n}\nplatform_browser_dynamic_1.platformBrowserDynamic().bootstrapModule(app_module_1.AppModule);\n\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMC5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL3NyYy9tYWluLnRzPzdkNjQiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcGxhdGZvcm1Ccm93c2VyRHluYW1pYyB9IGZyb20gJ0Bhbmd1bGFyL3BsYXRmb3JtLWJyb3dzZXItZHluYW1pYyc7XG5pbXBvcnQgeyBlbmFibGVQcm9kTW9kZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQXBwTW9kdWxlIH0gZnJvbSAnLi9hcHAvYXBwLm1vZHVsZSc7XG5pZiAocHJvY2Vzcy5lbnYuRU5WID09PSAncHJvZHVjdGlvbicpIHtcbiAgZW5hYmxlUHJvZE1vZGUoKTtcbn1cbnBsYXRmb3JtQnJvd3NlckR5bmFtaWMoKS5ib290c3RyYXBNb2R1bGUoQXBwTW9kdWxlKTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyBub2RlX21vZHVsZXMvYW5ndWxhcjItdGVtcGxhdGUtbG9hZGVyIS4vc3JjL21haW4udHMiXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Iiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 1 */,
- /* 2 */,
- /* 3 */,
- /* 4 */,
- /* 5 */,
- /* 6 */,
- /* 7 */,
- /* 8 */,
- /* 9 */,
- /* 10 */,
- /* 11 */,
- /* 12 */,
- /* 13 */,
- /* 14 */,
- /* 15 */,
- /* 16 */,
- /* 17 */,
- /* 18 */,
- /* 19 */,
- /* 20 */,
- /* 21 */,
- /* 22 */,
- /* 23 */,
- /* 24 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar core_1 = __webpack_require__(4);\nvar forms_1 = __webpack_require__(25);\nvar platform_browser_1 = __webpack_require__(22);\nvar app_component_1 = __webpack_require__(29);\nvar app_routing_1 = __webpack_require__(31);\nvar home_component_1 = __webpack_require__(62);\nvar archive_component_1 = __webpack_require__(104);\nvar bin_component_1 = __webpack_require__(106);\nvar about_component_1 = __webpack_require__(108);\nvar spinner_1 = __webpack_require__(111);\nvar angular2_notifications_1 = __webpack_require__(63);\nvar dragula_1 = __webpack_require__(112);\nvar fluid_height_1 = __webpack_require__(113);\nvar dragula_2 = __webpack_require__(76);\nvar notes_table_1 = __webpack_require__(114);\nvar notes_table_service_1 = __webpack_require__(88);\nvar bin_table_service_1 = __webpack_require__(101);\nvar archive_table_service_1 = __webpack_require__(102);\nvar AppModule = (function () {\n function AppModule() {\n }\n AppModule = __decorate([\n core_1.NgModule({\n imports: [\n platform_browser_1.BrowserModule,\n app_routing_1.AppRoutingModule,\n angular2_notifications_1.SimpleNotificationsModule,\n forms_1.FormsModule\n ],\n declarations: [\n app_component_1.AppComponent,\n home_component_1.HomeComponent,\n archive_component_1.ArchiveComponent,\n bin_component_1.BinComponent,\n about_component_1.AboutComponent,\n spinner_1.Spinner,\n dragula_1.Dragula,\n fluid_height_1.FluidHeightDirective\n ],\n providers: [dragula_2.DragulaService, notes_table_1.NotesTable, notes_table_service_1.NotesTableService, bin_table_service_1.BinNotesTableService, archive_table_service_1.ArchiveNotesTableService],\n bootstrap: [app_component_1.AppComponent]\n }), \n __metadata('design:paramtypes', [])\n ], AppModule);\n return AppModule;\n}());\nexports.AppModule = AppModule;\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMjQuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvYXBwL2FwcC5tb2R1bGUudHM/MjU2YSJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBOZ01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybXNNb2R1bGUgfSAgIGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEJyb3dzZXJNb2R1bGUgfSAgZnJvbSAnQGFuZ3VsYXIvcGxhdGZvcm0tYnJvd3Nlcic7XG5pbXBvcnQgeyBBcHBDb21wb25lbnQgfSBmcm9tICcuL2FwcC5jb21wb25lbnQnO1xuaW1wb3J0IHsgQXBwUm91dGluZ01vZHVsZSB9IGZyb20gJy4vYXBwLnJvdXRpbmcnO1xuaW1wb3J0IHsgSG9tZUNvbXBvbmVudCB9IGZyb20gJy4vY29tcG9uZW50cy9ob21lL2hvbWUuY29tcG9uZW50JztcbmltcG9ydCB7IEFyY2hpdmVDb21wb25lbnQgfSBmcm9tICcuL2NvbXBvbmVudHMvYXJjaGl2ZS1ub3Rlcy9hcmNoaXZlLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBCaW5Db21wb25lbnQgfSBmcm9tICcuL2NvbXBvbmVudHMvYmluL2Jpbi5jb21wb25lbnQnO1xuaW1wb3J0IHsgQWJvdXRDb21wb25lbnQgfSBmcm9tICcuL2NvbXBvbmVudHMvYWJvdXQvYWJvdXQuY29tcG9uZW50JztcbmltcG9ydCB7IFNwaW5uZXIgfSBmcm9tICcuL2NvbXBvbmVudHMvc3Bpbm5lci9zcGlubmVyJztcblxuaW1wb3J0IHsgTm90aWZpY2F0aW9uc1NlcnZpY2UsIFNpbXBsZU5vdGlmaWNhdGlvbnNNb2R1bGUgfSBmcm9tIFwiYW5ndWxhcjItbm90aWZpY2F0aW9uc1wiO1xuXG5pbXBvcnQgeyBEcmFndWxhIH0gZnJvbSAnLi9kaXJlY3RpdmVzL2RyYWd1bGEnO1xuaW1wb3J0IHsgRmx1aWRIZWlnaHREaXJlY3RpdmUgfSBmcm9tICcuL2RpcmVjdGl2ZXMvZmx1aWQtaGVpZ2h0JztcbmltcG9ydCB7IERyYWd1bGFTZXJ2aWNlIH0gZnJvbSAnLi9wcm92aWRlcnMvZHJhZ3VsYSc7XG5pbXBvcnQgeyBOb3Rlc1RhYmxlIH0gZnJvbSAnLi9zZXJ2aWNlcy9ub3Rlc190YWJsZSc7XG5pbXBvcnQgeyBOb3Rlc1RhYmxlU2VydmljZSB9IGZyb20gJy4vc2VydmljZXMvbm90ZXNfdGFibGUuc2VydmljZSc7XG5pbXBvcnQgeyBCaW5Ob3Rlc1RhYmxlU2VydmljZSB9IGZyb20gJy4vc2VydmljZXMvYmluX3RhYmxlLnNlcnZpY2UnO1xuaW1wb3J0IHsgQXJjaGl2ZU5vdGVzVGFibGVTZXJ2aWNlIH0gZnJvbSAnLi9zZXJ2aWNlcy9hcmNoaXZlX3RhYmxlLnNlcnZpY2UnO1xuXG5ATmdNb2R1bGUoe1xuICBpbXBvcnRzOiBbXG4gICAgQnJvd3Nlck1vZHVsZSxcbiAgICBBcHBSb3V0aW5nTW9kdWxlLFxuICAgIFNpbXBsZU5vdGlmaWNhdGlvbnNNb2R1bGUsXG4gICAgRm9ybXNNb2R1bGVcbiAgXSxcbiAgZGVjbGFyYXRpb25zOiBbXG4gICAgQXBwQ29tcG9uZW50LFxuICAgIEhvbWVDb21wb25lbnQsXG4gICAgQXJjaGl2ZUNvbXBvbmVudCxcbiAgICBCaW5Db21wb25lbnQsXG4gICAgQWJvdXRDb21wb25lbnQsXG4gICAgU3Bpbm5lcixcbiAgICBEcmFndWxhLFxuICAgIEZsdWlkSGVpZ2h0RGlyZWN0aXZlXG4gIF0sXG4gIHByb3ZpZGVyczogWyBEcmFndWxhU2VydmljZSwgTm90ZXNUYWJsZSwgTm90ZXNUYWJsZVNlcnZpY2UsIEJpbk5vdGVzVGFibGVTZXJ2aWNlLCBBcmNoaXZlTm90ZXNUYWJsZVNlcnZpY2UgXSxcbiAgYm9vdHN0cmFwOiBbIEFwcENvbXBvbmVudCBdXG59KVxuZXhwb3J0IGNsYXNzIEFwcE1vZHVsZSB7IH1cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyBub2RlX21vZHVsZXMvYW5ndWxhcjItdGVtcGxhdGUtbG9hZGVyIS4vc3JjL2FwcC9hcHAubW9kdWxlLnRzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBc0JBO0FBQUE7QUFBQTtBQXBCQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBQUE7QUFDQTtBQUFBO0FBQUE7Iiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 25 */
- /***/ function(module, exports, __webpack_require__) {
- eval("/**\n * @license Angular v2.4.1\n * (c) 2010-2016 Google, Inc. https://angular.io/\n * License: MIT\n */\n(function (global, factory) {\n true ? factory(exports, __webpack_require__(4), __webpack_require__(26), __webpack_require__(5), __webpack_require__(6), __webpack_require__(27)) :\n typeof define === 'function' && define.amd ? define(['exports', '@angular/core', 'rxjs/operator/toPromise', 'rxjs/Subject', 'rxjs/Observable', 'rxjs/observable/fromPromise'], factory) :\n (factory((global.ng = global.ng || {}, global.ng.forms = global.ng.forms || {}),global.ng.core,global.Rx.Observable.prototype,global.Rx,global.Rx,global.Rx.Observable));\n}(this, function (exports,_angular_core,rxjs_operator_toPromise,rxjs_Subject,rxjs_Observable,rxjs_observable_fromPromise) { 'use strict';\n\n /**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n /**\n * Base class for control directives.\n * *\n * Only used internally in the forms module.\n * *\n * @abstract\n */\n var AbstractControlDirective = (function () {\n function AbstractControlDirective() {\n }\n Object.defineProperty(AbstractControlDirective.prototype, \"control\", {\n /**\n * @return {?}\n */\n get: function () { throw new Error('unimplemented'); },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControlDirective.prototype, \"value\", {\n /**\n * @return {?}\n */\n get: function () { return this.control ? this.control.value : null; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControlDirective.prototype, \"valid\", {\n /**\n * @return {?}\n */\n get: function () { return this.control ? this.control.valid : null; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControlDirective.prototype, \"invalid\", {\n /**\n * @return {?}\n */\n get: function () { return this.control ? this.control.invalid : null; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControlDirective.prototype, \"pending\", {\n /**\n * @return {?}\n */\n get: function () { return this.control ? this.control.pending : null; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControlDirective.prototype, \"errors\", {\n /**\n * @return {?}\n */\n get: function () { return this.control ? this.control.errors : null; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControlDirective.prototype, \"pristine\", {\n /**\n * @return {?}\n */\n get: function () { return this.control ? this.control.pristine : null; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControlDirective.prototype, \"dirty\", {\n /**\n * @return {?}\n */\n get: function () { return this.control ? this.control.dirty : null; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControlDirective.prototype, \"touched\", {\n /**\n * @return {?}\n */\n get: function () { return this.control ? this.control.touched : null; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControlDirective.prototype, \"untouched\", {\n /**\n * @return {?}\n */\n get: function () { return this.control ? this.control.untouched : null; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControlDirective.prototype, \"disabled\", {\n /**\n * @return {?}\n */\n get: function () { return this.control ? this.control.disabled : null; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControlDirective.prototype, \"enabled\", {\n /**\n * @return {?}\n */\n get: function () { return this.control ? this.control.enabled : null; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControlDirective.prototype, \"statusChanges\", {\n /**\n * @return {?}\n */\n get: function () { return this.control ? this.control.statusChanges : null; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControlDirective.prototype, \"valueChanges\", {\n /**\n * @return {?}\n */\n get: function () { return this.control ? this.control.valueChanges : null; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControlDirective.prototype, \"path\", {\n /**\n * @return {?}\n */\n get: function () { return null; },\n enumerable: true,\n configurable: true\n });\n /**\n * @param {?=} value\n * @return {?}\n */\n AbstractControlDirective.prototype.reset = function (value) {\n if (value === void 0) { value = undefined; }\n if (this.control)\n this.control.reset(value);\n };\n /**\n * @param {?} errorCode\n * @param {?=} path\n * @return {?}\n */\n AbstractControlDirective.prototype.hasError = function (errorCode, path) {\n if (path === void 0) { path = null; }\n return this.control ? this.control.hasError(errorCode, path) : false;\n };\n /**\n * @param {?} errorCode\n * @param {?=} path\n * @return {?}\n */\n AbstractControlDirective.prototype.getError = function (errorCode, path) {\n if (path === void 0) { path = null; }\n return this.control ? this.control.getError(errorCode, path) : null;\n };\n return AbstractControlDirective;\n }());\n\n /**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n var __extends$1 = (this && this.__extends) || function (d, b) {\n for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n /**\n * A directive that contains multiple {@link NgControl}s.\n * *\n * Only used by the forms module.\n * *\n */\n var ControlContainer = (function (_super) {\n __extends$1(ControlContainer, _super);\n function ControlContainer() {\n _super.apply(this, arguments);\n }\n Object.defineProperty(ControlContainer.prototype, \"formDirective\", {\n /**\n * Get the form to which this container belongs.\n * @return {?}\n */\n get: function () { return null; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(ControlContainer.prototype, \"path\", {\n /**\n * Get the path to this container.\n * @return {?}\n */\n get: function () { return null; },\n enumerable: true,\n configurable: true\n });\n return ControlContainer;\n }(AbstractControlDirective));\n\n /**\n * @param {?} obj\n * @return {?}\n */\n function isPresent(obj) {\n return obj != null;\n }\n /**\n * @param {?} obj\n * @return {?}\n */\n function isBlank(obj) {\n return obj == null;\n }\n /**\n * @param {?} a\n * @param {?} b\n * @return {?}\n */\n function looseIdentical(a, b) {\n return a === b || typeof a === 'number' && typeof b === 'number' && isNaN(a) && isNaN(b);\n }\n /**\n * @param {?} o\n * @return {?}\n */\n function isJsObject(o) {\n return o !== null && (typeof o === 'function' || typeof o === 'object');\n }\n /**\n * @param {?} obj\n * @return {?}\n */\n function isPrimitive(obj) {\n return !isJsObject(obj);\n }\n\n /**\n * Wraps Javascript Objects\n */\n var StringMapWrapper = (function () {\n function StringMapWrapper() {\n }\n /**\n * @param {?} m1\n * @param {?} m2\n * @return {?}\n */\n StringMapWrapper.merge = function (m1, m2) {\n var /** @type {?} */ m = {};\n for (var _i = 0, _a = Object.keys(m1); _i < _a.length; _i++) {\n var k = _a[_i];\n m[k] = m1[k];\n }\n for (var _b = 0, _c = Object.keys(m2); _b < _c.length; _b++) {\n var k = _c[_b];\n m[k] = m2[k];\n }\n return m;\n };\n /**\n * @param {?} m1\n * @param {?} m2\n * @return {?}\n */\n StringMapWrapper.equals = function (m1, m2) {\n var /** @type {?} */ k1 = Object.keys(m1);\n var /** @type {?} */ k2 = Object.keys(m2);\n if (k1.length != k2.length) {\n return false;\n }\n for (var /** @type {?} */ i = 0; i < k1.length; i++) {\n var /** @type {?} */ key = k1[i];\n if (m1[key] !== m2[key]) {\n return false;\n }\n }\n return true;\n };\n return StringMapWrapper;\n }());\n var ListWrapper = (function () {\n function ListWrapper() {\n }\n /**\n * @param {?} arr\n * @param {?} condition\n * @return {?}\n */\n ListWrapper.findLast = function (arr, condition) {\n for (var /** @type {?} */ i = arr.length - 1; i >= 0; i--) {\n if (condition(arr[i])) {\n return arr[i];\n }\n }\n return null;\n };\n /**\n * @param {?} list\n * @param {?} items\n * @return {?}\n */\n ListWrapper.removeAll = function (list, items) {\n for (var /** @type {?} */ i = 0; i < items.length; ++i) {\n var /** @type {?} */ index = list.indexOf(items[i]);\n if (index > -1) {\n list.splice(index, 1);\n }\n }\n };\n /**\n * @param {?} list\n * @param {?} el\n * @return {?}\n */\n ListWrapper.remove = function (list, el) {\n var /** @type {?} */ index = list.indexOf(el);\n if (index > -1) {\n list.splice(index, 1);\n return true;\n }\n return false;\n };\n /**\n * @param {?} a\n * @param {?} b\n * @return {?}\n */\n ListWrapper.equals = function (a, b) {\n if (a.length != b.length)\n return false;\n for (var /** @type {?} */ i = 0; i < a.length; ++i) {\n if (a[i] !== b[i])\n return false;\n }\n return true;\n };\n /**\n * @param {?} list\n * @return {?}\n */\n ListWrapper.flatten = function (list) {\n return list.reduce(function (flat, item) {\n var /** @type {?} */ flatItem = Array.isArray(item) ? ListWrapper.flatten(item) : item;\n return ((flat)).concat(flatItem);\n }, []);\n };\n return ListWrapper;\n }());\n\n var /** @type {?} */ isPromise = _angular_core.__core_private__.isPromise;\n\n /**\n * @param {?} value\n * @return {?}\n */\n function isEmptyInputValue(value) {\n return value == null || typeof value === 'string' && value.length === 0;\n }\n /**\n * Providers for validators to be used for {@link FormControl}s in a form.\n *\n * Provide this using `multi: true` to add validators.\n *\n * ### Example\n *\n * {@example core/forms/ts/ng_validators/ng_validators.ts region='ng_validators'}\n * @stable\n */\n var /** @type {?} */ NG_VALIDATORS = new _angular_core.OpaqueToken('NgValidators');\n /**\n * Providers for asynchronous validators to be used for {@link FormControl}s\n * in a form.\n *\n * Provide this using `multi: true` to add validators.\n *\n * See {@link NG_VALIDATORS} for more details.\n *\n * @stable\n */\n var /** @type {?} */ NG_ASYNC_VALIDATORS = new _angular_core.OpaqueToken('NgAsyncValidators');\n /**\n * Provides a set of validators used by form controls.\n * *\n * A validator is a function that processes a {@link FormControl} or collection of\n * controls and returns a map of errors. A null map means that validation has passed.\n * *\n * ### Example\n * *\n * ```typescript\n * var loginControl = new FormControl(\"\", Validators.required)\n * ```\n * *\n */\n var Validators = (function () {\n function Validators() {\n }\n /**\n * Validator that requires controls to have a non-empty value.\n * @param {?} control\n * @return {?}\n */\n Validators.required = function (control) {\n return isEmptyInputValue(control.value) ? { 'required': true } : null;\n };\n /**\n * Validator that requires control value to be true.\n * @param {?} control\n * @return {?}\n */\n Validators.requiredTrue = function (control) {\n return control.value === true ? null : { 'required': true };\n };\n /**\n * Validator that requires controls to have a value of a minimum length.\n * @param {?} minLength\n * @return {?}\n */\n Validators.minLength = function (minLength) {\n return function (control) {\n if (isEmptyInputValue(control.value)) {\n return null; // don't validate empty values to allow optional controls\n }\n var /** @type {?} */ length = control.value ? control.value.length : 0;\n return length < minLength ?\n { 'minlength': { 'requiredLength': minLength, 'actualLength': length } } :\n null;\n };\n };\n /**\n * Validator that requires controls to have a value of a maximum length.\n * @param {?} maxLength\n * @return {?}\n */\n Validators.maxLength = function (maxLength) {\n return function (control) {\n var /** @type {?} */ length = control.value ? control.value.length : 0;\n return length > maxLength ?\n { 'maxlength': { 'requiredLength': maxLength, 'actualLength': length } } :\n null;\n };\n };\n /**\n * Validator that requires a control to match a regex to its value.\n * @param {?} pattern\n * @return {?}\n */\n Validators.pattern = function (pattern) {\n if (!pattern)\n return Validators.nullValidator;\n var /** @type {?} */ regex;\n var /** @type {?} */ regexStr;\n if (typeof pattern === 'string') {\n regexStr = \"^\" + pattern + \"$\";\n regex = new RegExp(regexStr);\n }\n else {\n regexStr = pattern.toString();\n regex = pattern;\n }\n return function (control) {\n if (isEmptyInputValue(control.value)) {\n return null; // don't validate empty values to allow optional controls\n }\n var /** @type {?} */ value = control.value;\n return regex.test(value) ? null :\n { 'pattern': { 'requiredPattern': regexStr, 'actualValue': value } };\n };\n };\n /**\n * No-op validator.\n * @param {?} c\n * @return {?}\n */\n Validators.nullValidator = function (c) { return null; };\n /**\n * Compose multiple validators into a single function that returns the union\n * of the individual error maps.\n * @param {?} validators\n * @return {?}\n */\n Validators.compose = function (validators) {\n if (!validators)\n return null;\n var /** @type {?} */ presentValidators = validators.filter(isPresent);\n if (presentValidators.length == 0)\n return null;\n return function (control) {\n return _mergeErrors(_executeValidators(control, presentValidators));\n };\n };\n /**\n * @param {?} validators\n * @return {?}\n */\n Validators.composeAsync = function (validators) {\n if (!validators)\n return null;\n var /** @type {?} */ presentValidators = validators.filter(isPresent);\n if (presentValidators.length == 0)\n return null;\n return function (control) {\n var /** @type {?} */ promises = _executeAsyncValidators(control, presentValidators).map(_convertToPromise);\n return Promise.all(promises).then(_mergeErrors);\n };\n };\n return Validators;\n }());\n /**\n * @param {?} obj\n * @return {?}\n */\n function _convertToPromise(obj) {\n return isPromise(obj) ? obj : rxjs_operator_toPromise.toPromise.call(obj);\n }\n /**\n * @param {?} control\n * @param {?} validators\n * @return {?}\n */\n function _executeValidators(control, validators) {\n return validators.map(function (v) { return v(control); });\n }\n /**\n * @param {?} control\n * @param {?} validators\n * @return {?}\n */\n function _executeAsyncValidators(control, validators) {\n return validators.map(function (v) { return v(control); });\n }\n /**\n * @param {?} arrayOfErrors\n * @return {?}\n */\n function _mergeErrors(arrayOfErrors) {\n var /** @type {?} */ res = arrayOfErrors.reduce(function (res, errors) {\n return isPresent(errors) ? StringMapWrapper.merge(res, errors) : res;\n }, {});\n return Object.keys(res).length === 0 ? null : res;\n }\n\n /**\n * Used to provide a {@link ControlValueAccessor} for form controls.\n *\n * See {@link DefaultValueAccessor} for how to implement one.\n * @stable\n */\n var /** @type {?} */ NG_VALUE_ACCESSOR = new _angular_core.OpaqueToken('NgValueAccessor');\n\n var /** @type {?} */ CHECKBOX_VALUE_ACCESSOR = {\n provide: NG_VALUE_ACCESSOR,\n useExisting: _angular_core.forwardRef(function () { return CheckboxControlValueAccessor; }),\n multi: true,\n };\n /**\n * The accessor for writing a value and listening to changes on a checkbox input element.\n * *\n * ### Example\n * ```\n * <input type=\"checkbox\" name=\"rememberLogin\" ngModel>\n * ```\n * *\n * @stable\n */\n var CheckboxControlValueAccessor = (function () {\n /**\n * @param {?} _renderer\n * @param {?} _elementRef\n */\n function CheckboxControlValueAccessor(_renderer, _elementRef) {\n this._renderer = _renderer;\n this._elementRef = _elementRef;\n this.onChange = function (_) { };\n this.onTouched = function () { };\n }\n /**\n * @param {?} value\n * @return {?}\n */\n CheckboxControlValueAccessor.prototype.writeValue = function (value) {\n this._renderer.setElementProperty(this._elementRef.nativeElement, 'checked', value);\n };\n /**\n * @param {?} fn\n * @return {?}\n */\n CheckboxControlValueAccessor.prototype.registerOnChange = function (fn) { this.onChange = fn; };\n /**\n * @param {?} fn\n * @return {?}\n */\n CheckboxControlValueAccessor.prototype.registerOnTouched = function (fn) { this.onTouched = fn; };\n /**\n * @param {?} isDisabled\n * @return {?}\n */\n CheckboxControlValueAccessor.prototype.setDisabledState = function (isDisabled) {\n this._renderer.setElementProperty(this._elementRef.nativeElement, 'disabled', isDisabled);\n };\n CheckboxControlValueAccessor.decorators = [\n { type: _angular_core.Directive, args: [{\n selector: 'input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]',\n host: { '(change)': 'onChange($event.target.checked)', '(blur)': 'onTouched()' },\n providers: [CHECKBOX_VALUE_ACCESSOR]\n },] },\n ];\n /** @nocollapse */\n CheckboxControlValueAccessor.ctorParameters = function () { return [\n { type: _angular_core.Renderer, },\n { type: _angular_core.ElementRef, },\n ]; };\n return CheckboxControlValueAccessor;\n }());\n\n var /** @type {?} */ DEFAULT_VALUE_ACCESSOR = {\n provide: NG_VALUE_ACCESSOR,\n useExisting: _angular_core.forwardRef(function () { return DefaultValueAccessor; }),\n multi: true\n };\n /**\n * The default accessor for writing a value and listening to changes that is used by the\n * {@link NgModel}, {@link FormControlDirective}, and {@link FormControlName} directives.\n * *\n * ### Example\n * ```\n * <input type=\"text\" name=\"searchQuery\" ngModel>\n * ```\n * *\n * @stable\n */\n var DefaultValueAccessor = (function () {\n /**\n * @param {?} _renderer\n * @param {?} _elementRef\n */\n function DefaultValueAccessor(_renderer, _elementRef) {\n this._renderer = _renderer;\n this._elementRef = _elementRef;\n this.onChange = function (_) { };\n this.onTouched = function () { };\n }\n /**\n * @param {?} value\n * @return {?}\n */\n DefaultValueAccessor.prototype.writeValue = function (value) {\n var /** @type {?} */ normalizedValue = value == null ? '' : value;\n this._renderer.setElementProperty(this._elementRef.nativeElement, 'value', normalizedValue);\n };\n /**\n * @param {?} fn\n * @return {?}\n */\n DefaultValueAccessor.prototype.registerOnChange = function (fn) { this.onChange = fn; };\n /**\n * @param {?} fn\n * @return {?}\n */\n DefaultValueAccessor.prototype.registerOnTouched = function (fn) { this.onTouched = fn; };\n /**\n * @param {?} isDisabled\n * @return {?}\n */\n DefaultValueAccessor.prototype.setDisabledState = function (isDisabled) {\n this._renderer.setElementProperty(this._elementRef.nativeElement, 'disabled', isDisabled);\n };\n DefaultValueAccessor.decorators = [\n { type: _angular_core.Directive, args: [{\n selector: 'input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]',\n // TODO: vsavkin replace the above selector with the one below it once\n // https://github.com/angular/angular/issues/3011 is implemented\n // selector: '[ngControl],[ngModel],[ngFormControl]',\n host: { '(input)': 'onChange($event.target.value)', '(blur)': 'onTouched()' },\n providers: [DEFAULT_VALUE_ACCESSOR]\n },] },\n ];\n /** @nocollapse */\n DefaultValueAccessor.ctorParameters = function () { return [\n { type: _angular_core.Renderer, },\n { type: _angular_core.ElementRef, },\n ]; };\n return DefaultValueAccessor;\n }());\n\n /**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n /**\n * @param {?} validator\n * @return {?}\n */\n function normalizeValidator(validator) {\n if (((validator)).validate) {\n return function (c) { return ((validator)).validate(c); };\n }\n else {\n return (validator);\n }\n }\n /**\n * @param {?} validator\n * @return {?}\n */\n function normalizeAsyncValidator(validator) {\n if (((validator)).validate) {\n return function (c) { return ((validator)).validate(c); };\n }\n else {\n return (validator);\n }\n }\n\n var /** @type {?} */ NUMBER_VALUE_ACCESSOR = {\n provide: NG_VALUE_ACCESSOR,\n useExisting: _angular_core.forwardRef(function () { return NumberValueAccessor; }),\n multi: true\n };\n /**\n * The accessor for writing a number value and listening to changes that is used by the\n * {@link NgModel}, {@link FormControlDirective}, and {@link FormControlName} directives.\n * *\n * ### Example\n * ```\n * <input type=\"number\" [(ngModel)]=\"age\">\n * ```\n */\n var NumberValueAccessor = (function () {\n /**\n * @param {?} _renderer\n * @param {?} _elementRef\n */\n function NumberValueAccessor(_renderer, _elementRef) {\n this._renderer = _renderer;\n this._elementRef = _elementRef;\n this.onChange = function (_) { };\n this.onTouched = function () { };\n }\n /**\n * @param {?} value\n * @return {?}\n */\n NumberValueAccessor.prototype.writeValue = function (value) {\n // The value needs to be normalized for IE9, otherwise it is set to 'null' when null\n var /** @type {?} */ normalizedValue = value == null ? '' : value;\n this._renderer.setElementProperty(this._elementRef.nativeElement, 'value', normalizedValue);\n };\n /**\n * @param {?} fn\n * @return {?}\n */\n NumberValueAccessor.prototype.registerOnChange = function (fn) {\n this.onChange = function (value) { fn(value == '' ? null : parseFloat(value)); };\n };\n /**\n * @param {?} fn\n * @return {?}\n */\n NumberValueAccessor.prototype.registerOnTouched = function (fn) { this.onTouched = fn; };\n /**\n * @param {?} isDisabled\n * @return {?}\n */\n NumberValueAccessor.prototype.setDisabledState = function (isDisabled) {\n this._renderer.setElementProperty(this._elementRef.nativeElement, 'disabled', isDisabled);\n };\n NumberValueAccessor.decorators = [\n { type: _angular_core.Directive, args: [{\n selector: 'input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]',\n host: {\n '(change)': 'onChange($event.target.value)',\n '(input)': 'onChange($event.target.value)',\n '(blur)': 'onTouched()'\n },\n providers: [NUMBER_VALUE_ACCESSOR]\n },] },\n ];\n /** @nocollapse */\n NumberValueAccessor.ctorParameters = function () { return [\n { type: _angular_core.Renderer, },\n { type: _angular_core.ElementRef, },\n ]; };\n return NumberValueAccessor;\n }());\n\n /**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n var __extends$2 = (this && this.__extends) || function (d, b) {\n for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n /**\n * @return {?}\n */\n function unimplemented() {\n throw new Error('unimplemented');\n }\n /**\n * A base class that all control directive extend.\n * It binds a {@link FormControl} object to a DOM element.\n * *\n * Used internally by Angular forms.\n * *\n * @abstract\n */\n var NgControl = (function (_super) {\n __extends$2(NgControl, _super);\n function NgControl() {\n _super.apply(this, arguments);\n /** @internal */\n this._parent = null;\n this.name = null;\n this.valueAccessor = null;\n /** @internal */\n this._rawValidators = [];\n /** @internal */\n this._rawAsyncValidators = [];\n }\n Object.defineProperty(NgControl.prototype, \"validator\", {\n /**\n * @return {?}\n */\n get: function () { return (unimplemented()); },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(NgControl.prototype, \"asyncValidator\", {\n /**\n * @return {?}\n */\n get: function () { return (unimplemented()); },\n enumerable: true,\n configurable: true\n });\n /**\n * @abstract\n * @param {?} newValue\n * @return {?}\n */\n NgControl.prototype.viewToModelUpdate = function (newValue) { };\n return NgControl;\n }(AbstractControlDirective));\n\n var /** @type {?} */ RADIO_VALUE_ACCESSOR = {\n provide: NG_VALUE_ACCESSOR,\n useExisting: _angular_core.forwardRef(function () { return RadioControlValueAccessor; }),\n multi: true\n };\n /**\n * Internal class used by Angular to uncheck radio buttons with the matching name.\n */\n var RadioControlRegistry = (function () {\n function RadioControlRegistry() {\n this._accessors = [];\n }\n /**\n * @param {?} control\n * @param {?} accessor\n * @return {?}\n */\n RadioControlRegistry.prototype.add = function (control, accessor) {\n this._accessors.push([control, accessor]);\n };\n /**\n * @param {?} accessor\n * @return {?}\n */\n RadioControlRegistry.prototype.remove = function (accessor) {\n for (var /** @type {?} */ i = this._accessors.length - 1; i >= 0; --i) {\n if (this._accessors[i][1] === accessor) {\n this._accessors.splice(i, 1);\n return;\n }\n }\n };\n /**\n * @param {?} accessor\n * @return {?}\n */\n RadioControlRegistry.prototype.select = function (accessor) {\n var _this = this;\n this._accessors.forEach(function (c) {\n if (_this._isSameGroup(c, accessor) && c[1] !== accessor) {\n c[1].fireUncheck(accessor.value);\n }\n });\n };\n /**\n * @param {?} controlPair\n * @param {?} accessor\n * @return {?}\n */\n RadioControlRegistry.prototype._isSameGroup = function (controlPair, accessor) {\n if (!controlPair[0].control)\n return false;\n return controlPair[0]._parent === accessor._control._parent &&\n controlPair[1].name === accessor.name;\n };\n RadioControlRegistry.decorators = [\n { type: _angular_core.Injectable },\n ];\n /** @nocollapse */\n RadioControlRegistry.ctorParameters = function () { return []; };\n return RadioControlRegistry;\n }());\n /**\n * *\n * Used by {@link NgModel}, {@link FormControlDirective}, and {@link FormControlName}\n * to keep the view synced with the {@link FormControl} model.\n * *\n * *\n * If you have imported the {@link FormsModule} or the {@link ReactiveFormsModule}, this\n * value accessor will be active on any radio control that has a form directive. You do\n * **not** need to add a special selector to activate it.\n * *\n * ### How to use radio buttons with form directives\n * *\n * To use radio buttons in a template-driven form, you'll want to ensure that radio buttons\n * in the same group have the same `name` attribute. Radio buttons with different `name`\n * attributes do not affect each other.\n * *\n * {@example forms/ts/radioButtons/radio_button_example.ts region='TemplateDriven'}\n * *\n * When using radio buttons in a reactive form, radio buttons in the same group should have the\n * same `formControlName`. You can also add a `name` attribute, but it's optional.\n * *\n * {@example forms/ts/reactiveRadioButtons/reactive_radio_button_example.ts region='Reactive'}\n * *\n * * **npm package**: `@angular/forms`\n * *\n * @stable\n */\n var RadioControlValueAccessor = (function () {\n /**\n * @param {?} _renderer\n * @param {?} _elementRef\n * @param {?} _registry\n * @param {?} _injector\n */\n function RadioControlValueAccessor(_renderer, _elementRef, _registry, _injector) {\n this._renderer = _renderer;\n this._elementRef = _elementRef;\n this._registry = _registry;\n this._injector = _injector;\n this.onChange = function () { };\n this.onTouched = function () { };\n }\n /**\n * @return {?}\n */\n RadioControlValueAccessor.prototype.ngOnInit = function () {\n this._control = this._injector.get(NgControl);\n this._checkName();\n this._registry.add(this._control, this);\n };\n /**\n * @return {?}\n */\n RadioControlValueAccessor.prototype.ngOnDestroy = function () { this._registry.remove(this); };\n /**\n * @param {?} value\n * @return {?}\n */\n RadioControlValueAccessor.prototype.writeValue = function (value) {\n this._state = value === this.value;\n this._renderer.setElementProperty(this._elementRef.nativeElement, 'checked', this._state);\n };\n /**\n * @param {?} fn\n * @return {?}\n */\n RadioControlValueAccessor.prototype.registerOnChange = function (fn) {\n var _this = this;\n this._fn = fn;\n this.onChange = function () {\n fn(_this.value);\n _this._registry.select(_this);\n };\n };\n /**\n * @param {?} value\n * @return {?}\n */\n RadioControlValueAccessor.prototype.fireUncheck = function (value) { this.writeValue(value); };\n /**\n * @param {?} fn\n * @return {?}\n */\n RadioControlValueAccessor.prototype.registerOnTouched = function (fn) { this.onTouched = fn; };\n /**\n * @param {?} isDisabled\n * @return {?}\n */\n RadioControlValueAccessor.prototype.setDisabledState = function (isDisabled) {\n this._renderer.setElementProperty(this._elementRef.nativeElement, 'disabled', isDisabled);\n };\n /**\n * @return {?}\n */\n RadioControlValueAccessor.prototype._checkName = function () {\n if (this.name && this.formControlName && this.name !== this.formControlName) {\n this._throwNameError();\n }\n if (!this.name && this.formControlName)\n this.name = this.formControlName;\n };\n /**\n * @return {?}\n */\n RadioControlValueAccessor.prototype._throwNameError = function () {\n throw new Error(\"\\n If you define both a name and a formControlName attribute on your radio button, their values\\n must match. Ex: <input type=\\\"radio\\\" formControlName=\\\"food\\\" name=\\\"food\\\">\\n \");\n };\n RadioControlValueAccessor.decorators = [\n { type: _angular_core.Directive, args: [{\n selector: 'input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]',\n host: { '(change)': 'onChange()', '(blur)': 'onTouched()' },\n providers: [RADIO_VALUE_ACCESSOR]\n },] },\n ];\n /** @nocollapse */\n RadioControlValueAccessor.ctorParameters = function () { return [\n { type: _angular_core.Renderer, },\n { type: _angular_core.ElementRef, },\n { type: RadioControlRegistry, },\n { type: _angular_core.Injector, },\n ]; };\n RadioControlValueAccessor.propDecorators = {\n 'name': [{ type: _angular_core.Input },],\n 'formControlName': [{ type: _angular_core.Input },],\n 'value': [{ type: _angular_core.Input },],\n };\n return RadioControlValueAccessor;\n }());\n\n var /** @type {?} */ RANGE_VALUE_ACCESSOR = {\n provide: NG_VALUE_ACCESSOR,\n useExisting: _angular_core.forwardRef(function () { return RangeValueAccessor; }),\n multi: true\n };\n /**\n * The accessor for writing a range value and listening to changes that is used by the\n * {@link NgModel}, {@link FormControlDirective}, and {@link FormControlName} directives.\n * *\n * ### Example\n * ```\n * <input type=\"range\" [(ngModel)]=\"age\" >\n * ```\n */\n var RangeValueAccessor = (function () {\n /**\n * @param {?} _renderer\n * @param {?} _elementRef\n */\n function RangeValueAccessor(_renderer, _elementRef) {\n this._renderer = _renderer;\n this._elementRef = _elementRef;\n this.onChange = function (_) { };\n this.onTouched = function () { };\n }\n /**\n * @param {?} value\n * @return {?}\n */\n RangeValueAccessor.prototype.writeValue = function (value) {\n this._renderer.setElementProperty(this._elementRef.nativeElement, 'value', parseFloat(value));\n };\n /**\n * @param {?} fn\n * @return {?}\n */\n RangeValueAccessor.prototype.registerOnChange = function (fn) {\n this.onChange = function (value) { fn(value == '' ? null : parseFloat(value)); };\n };\n /**\n * @param {?} fn\n * @return {?}\n */\n RangeValueAccessor.prototype.registerOnTouched = function (fn) { this.onTouched = fn; };\n /**\n * @param {?} isDisabled\n * @return {?}\n */\n RangeValueAccessor.prototype.setDisabledState = function (isDisabled) {\n this._renderer.setElementProperty(this._elementRef.nativeElement, 'disabled', isDisabled);\n };\n RangeValueAccessor.decorators = [\n { type: _angular_core.Directive, args: [{\n selector: 'input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]',\n host: {\n '(change)': 'onChange($event.target.value)',\n '(input)': 'onChange($event.target.value)',\n '(blur)': 'onTouched()'\n },\n providers: [RANGE_VALUE_ACCESSOR]\n },] },\n ];\n /** @nocollapse */\n RangeValueAccessor.ctorParameters = function () { return [\n { type: _angular_core.Renderer, },\n { type: _angular_core.ElementRef, },\n ]; };\n return RangeValueAccessor;\n }());\n\n var /** @type {?} */ SELECT_VALUE_ACCESSOR = {\n provide: NG_VALUE_ACCESSOR,\n useExisting: _angular_core.forwardRef(function () { return SelectControlValueAccessor; }),\n multi: true\n };\n /**\n * @param {?} id\n * @param {?} value\n * @return {?}\n */\n function _buildValueString(id, value) {\n if (id == null)\n return \"\" + value;\n if (!isPrimitive(value))\n value = 'Object';\n return (id + \": \" + value).slice(0, 50);\n }\n /**\n * @param {?} valueString\n * @return {?}\n */\n function _extractId(valueString) {\n return valueString.split(':')[0];\n }\n /**\n * *\n * Used by {@link NgModel}, {@link FormControlDirective}, and {@link FormControlName}\n * to keep the view synced with the {@link FormControl} model.\n * *\n * *\n * If you have imported the {@link FormsModule} or the {@link ReactiveFormsModule}, this\n * value accessor will be active on any select control that has a form directive. You do\n * **not** need to add a special selector to activate it.\n * *\n * ### How to use select controls with form directives\n * *\n * To use a select in a template-driven form, simply add an `ngModel` and a `name`\n * attribute to the main `<select>` tag.\n * *\n * If your option values are simple strings, you can bind to the normal `value` property\n * on the option. If your option values happen to be objects (and you'd like to save the\n * selection in your form as an object), use `ngValue` instead:\n * *\n * {@example forms/ts/selectControl/select_control_example.ts region='Component'}\n * *\n * In reactive forms, you'll also want to add your form directive (`formControlName` or\n * `formControl`) on the main `<select>` tag. Like in the former example, you have the\n * choice of binding to the `value` or `ngValue` property on the select's options.\n * *\n * {@example forms/ts/reactiveSelectControl/reactive_select_control_example.ts region='Component'}\n * *\n * Note: We listen to the 'change' event because 'input' events aren't fired\n * for selects in Firefox and IE:\n * https://bugzilla.mozilla.org/show_bug.cgi?id=1024350\n * https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/4660045/\n * *\n * * **npm package**: `@angular/forms`\n * *\n */\n var SelectControlValueAccessor = (function () {\n /**\n * @param {?} _renderer\n * @param {?} _elementRef\n */\n function SelectControlValueAccessor(_renderer, _elementRef) {\n this._renderer = _renderer;\n this._elementRef = _elementRef;\n /** @internal */\n this._optionMap = new Map();\n /** @internal */\n this._idCounter = 0;\n this.onChange = function (_) { };\n this.onTouched = function () { };\n }\n /**\n * @param {?} value\n * @return {?}\n */\n SelectControlValueAccessor.prototype.writeValue = function (value) {\n this.value = value;\n var /** @type {?} */ valueString = _buildValueString(this._getOptionId(value), value);\n this._renderer.setElementProperty(this._elementRef.nativeElement, 'value', valueString);\n };\n /**\n * @param {?} fn\n * @return {?}\n */\n SelectControlValueAccessor.prototype.registerOnChange = function (fn) {\n var _this = this;\n this.onChange = function (valueString) {\n _this.value = valueString;\n fn(_this._getOptionValue(valueString));\n };\n };\n /**\n * @param {?} fn\n * @return {?}\n */\n SelectControlValueAccessor.prototype.registerOnTouched = function (fn) { this.onTouched = fn; };\n /**\n * @param {?} isDisabled\n * @return {?}\n */\n SelectControlValueAccessor.prototype.setDisabledState = function (isDisabled) {\n this._renderer.setElementProperty(this._elementRef.nativeElement, 'disabled', isDisabled);\n };\n /**\n * @return {?}\n */\n SelectControlValueAccessor.prototype._registerOption = function () { return (this._idCounter++).toString(); };\n /**\n * @param {?} value\n * @return {?}\n */\n SelectControlValueAccessor.prototype._getOptionId = function (value) {\n for (var _i = 0, _a = Array.from(this._optionMap.keys()); _i < _a.length; _i++) {\n var id = _a[_i];\n if (looseIdentical(this._optionMap.get(id), value))\n return id;\n }\n return null;\n };\n /**\n * @param {?} valueString\n * @return {?}\n */\n SelectControlValueAccessor.prototype._getOptionValue = function (valueString) {\n var /** @type {?} */ id = _extractId(valueString);\n return this._optionMap.has(id) ? this._optionMap.get(id) : valueString;\n };\n SelectControlValueAccessor.decorators = [\n { type: _angular_core.Directive, args: [{\n selector: 'select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]',\n host: { '(change)': 'onChange($event.target.value)', '(blur)': 'onTouched()' },\n providers: [SELECT_VALUE_ACCESSOR]\n },] },\n ];\n /** @nocollapse */\n SelectControlValueAccessor.ctorParameters = function () { return [\n { type: _angular_core.Renderer, },\n { type: _angular_core.ElementRef, },\n ]; };\n return SelectControlValueAccessor;\n }());\n /**\n * *\n * *\n * See docs for {@link SelectControlValueAccessor} for usage examples.\n * *\n */\n var NgSelectOption = (function () {\n /**\n * @param {?} _element\n * @param {?} _renderer\n * @param {?} _select\n */\n function NgSelectOption(_element, _renderer, _select) {\n this._element = _element;\n this._renderer = _renderer;\n this._select = _select;\n if (this._select)\n this.id = this._select._registerOption();\n }\n Object.defineProperty(NgSelectOption.prototype, \"ngValue\", {\n /**\n * @param {?} value\n * @return {?}\n */\n set: function (value) {\n if (this._select == null)\n return;\n this._select._optionMap.set(this.id, value);\n this._setElementValue(_buildValueString(this.id, value));\n this._select.writeValue(this._select.value);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(NgSelectOption.prototype, \"value\", {\n /**\n * @param {?} value\n * @return {?}\n */\n set: function (value) {\n this._setElementValue(value);\n if (this._select)\n this._select.writeValue(this._select.value);\n },\n enumerable: true,\n configurable: true\n });\n /**\n * @param {?} value\n * @return {?}\n */\n NgSelectOption.prototype._setElementValue = function (value) {\n this._renderer.setElementProperty(this._element.nativeElement, 'value', value);\n };\n /**\n * @return {?}\n */\n NgSelectOption.prototype.ngOnDestroy = function () {\n if (this._select) {\n this._select._optionMap.delete(this.id);\n this._select.writeValue(this._select.value);\n }\n };\n NgSelectOption.decorators = [\n { type: _angular_core.Directive, args: [{ selector: 'option' },] },\n ];\n /** @nocollapse */\n NgSelectOption.ctorParameters = function () { return [\n { type: _angular_core.ElementRef, },\n { type: _angular_core.Renderer, },\n { type: SelectControlValueAccessor, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Host },] },\n ]; };\n NgSelectOption.propDecorators = {\n 'ngValue': [{ type: _angular_core.Input, args: ['ngValue',] },],\n 'value': [{ type: _angular_core.Input, args: ['value',] },],\n };\n return NgSelectOption;\n }());\n\n var /** @type {?} */ SELECT_MULTIPLE_VALUE_ACCESSOR = {\n provide: NG_VALUE_ACCESSOR,\n useExisting: _angular_core.forwardRef(function () { return SelectMultipleControlValueAccessor; }),\n multi: true\n };\n /**\n * @param {?} id\n * @param {?} value\n * @return {?}\n */\n function _buildValueString$1(id, value) {\n if (id == null)\n return \"\" + value;\n if (typeof value === 'string')\n value = \"'\" + value + \"'\";\n if (!isPrimitive(value))\n value = 'Object';\n return (id + \": \" + value).slice(0, 50);\n }\n /**\n * @param {?} valueString\n * @return {?}\n */\n function _extractId$1(valueString) {\n return valueString.split(':')[0];\n }\n /**\n * The accessor for writing a value and listening to changes on a select element.\n * *\n */\n var SelectMultipleControlValueAccessor = (function () {\n /**\n * @param {?} _renderer\n * @param {?} _elementRef\n */\n function SelectMultipleControlValueAccessor(_renderer, _elementRef) {\n this._renderer = _renderer;\n this._elementRef = _elementRef;\n /** @internal */\n this._optionMap = new Map();\n /** @internal */\n this._idCounter = 0;\n this.onChange = function (_) { };\n this.onTouched = function () { };\n }\n /**\n * @param {?} value\n * @return {?}\n */\n SelectMultipleControlValueAccessor.prototype.writeValue = function (value) {\n var _this = this;\n this.value = value;\n var /** @type {?} */ optionSelectedStateSetter;\n if (Array.isArray(value)) {\n // convert values to ids\n var /** @type {?} */ ids_1 = value.map(function (v) { return _this._getOptionId(v); });\n optionSelectedStateSetter = function (opt, o) { opt._setSelected(ids_1.indexOf(o.toString()) > -1); };\n }\n else {\n optionSelectedStateSetter = function (opt, o) { opt._setSelected(false); };\n }\n this._optionMap.forEach(optionSelectedStateSetter);\n };\n /**\n * @param {?} fn\n * @return {?}\n */\n SelectMultipleControlValueAccessor.prototype.registerOnChange = function (fn) {\n var _this = this;\n this.onChange = function (_) {\n var /** @type {?} */ selected = [];\n if (_.hasOwnProperty('selectedOptions')) {\n var /** @type {?} */ options = _.selectedOptions;\n for (var /** @type {?} */ i = 0; i < options.length; i++) {\n var /** @type {?} */ opt = options.item(i);\n var /** @type {?} */ val = _this._getOptionValue(opt.value);\n selected.push(val);\n }\n }\n else {\n var /** @type {?} */ options = (_.options);\n for (var /** @type {?} */ i = 0; i < options.length; i++) {\n var /** @type {?} */ opt = options.item(i);\n if (opt.selected) {\n var /** @type {?} */ val = _this._getOptionValue(opt.value);\n selected.push(val);\n }\n }\n }\n _this.value = selected;\n fn(selected);\n };\n };\n /**\n * @param {?} fn\n * @return {?}\n */\n SelectMultipleControlValueAccessor.prototype.registerOnTouched = function (fn) { this.onTouched = fn; };\n /**\n * @param {?} isDisabled\n * @return {?}\n */\n SelectMultipleControlValueAccessor.prototype.setDisabledState = function (isDisabled) {\n this._renderer.setElementProperty(this._elementRef.nativeElement, 'disabled', isDisabled);\n };\n /**\n * @param {?} value\n * @return {?}\n */\n SelectMultipleControlValueAccessor.prototype._registerOption = function (value) {\n var /** @type {?} */ id = (this._idCounter++).toString();\n this._optionMap.set(id, value);\n return id;\n };\n /**\n * @param {?} value\n * @return {?}\n */\n SelectMultipleControlValueAccessor.prototype._getOptionId = function (value) {\n for (var _i = 0, _a = Array.from(this._optionMap.keys()); _i < _a.length; _i++) {\n var id = _a[_i];\n if (looseIdentical(this._optionMap.get(id)._value, value))\n return id;\n }\n return null;\n };\n /**\n * @param {?} valueString\n * @return {?}\n */\n SelectMultipleControlValueAccessor.prototype._getOptionValue = function (valueString) {\n var /** @type {?} */ id = _extractId$1(valueString);\n return this._optionMap.has(id) ? this._optionMap.get(id)._value : valueString;\n };\n SelectMultipleControlValueAccessor.decorators = [\n { type: _angular_core.Directive, args: [{\n selector: 'select[multiple][formControlName],select[multiple][formControl],select[multiple][ngModel]',\n host: { '(change)': 'onChange($event.target)', '(blur)': 'onTouched()' },\n providers: [SELECT_MULTIPLE_VALUE_ACCESSOR]\n },] },\n ];\n /** @nocollapse */\n SelectMultipleControlValueAccessor.ctorParameters = function () { return [\n { type: _angular_core.Renderer, },\n { type: _angular_core.ElementRef, },\n ]; };\n return SelectMultipleControlValueAccessor;\n }());\n /**\n * Marks `<option>` as dynamic, so Angular can be notified when options change.\n * *\n * ### Example\n * *\n * ```\n * <select multiple name=\"city\" ngModel>\n * <option *ngFor=\"let c of cities\" [value]=\"c\"></option>\n * </select>\n * ```\n */\n var NgSelectMultipleOption = (function () {\n /**\n * @param {?} _element\n * @param {?} _renderer\n * @param {?} _select\n */\n function NgSelectMultipleOption(_element, _renderer, _select) {\n this._element = _element;\n this._renderer = _renderer;\n this._select = _select;\n if (this._select) {\n this.id = this._select._registerOption(this);\n }\n }\n Object.defineProperty(NgSelectMultipleOption.prototype, \"ngValue\", {\n /**\n * @param {?} value\n * @return {?}\n */\n set: function (value) {\n if (this._select == null)\n return;\n this._value = value;\n this._setElementValue(_buildValueString$1(this.id, value));\n this._select.writeValue(this._select.value);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(NgSelectMultipleOption.prototype, \"value\", {\n /**\n * @param {?} value\n * @return {?}\n */\n set: function (value) {\n if (this._select) {\n this._value = value;\n this._setElementValue(_buildValueString$1(this.id, value));\n this._select.writeValue(this._select.value);\n }\n else {\n this._setElementValue(value);\n }\n },\n enumerable: true,\n configurable: true\n });\n /**\n * @param {?} value\n * @return {?}\n */\n NgSelectMultipleOption.prototype._setElementValue = function (value) {\n this._renderer.setElementProperty(this._element.nativeElement, 'value', value);\n };\n /**\n * @param {?} selected\n * @return {?}\n */\n NgSelectMultipleOption.prototype._setSelected = function (selected) {\n this._renderer.setElementProperty(this._element.nativeElement, 'selected', selected);\n };\n /**\n * @return {?}\n */\n NgSelectMultipleOption.prototype.ngOnDestroy = function () {\n if (this._select) {\n this._select._optionMap.delete(this.id);\n this._select.writeValue(this._select.value);\n }\n };\n NgSelectMultipleOption.decorators = [\n { type: _angular_core.Directive, args: [{ selector: 'option' },] },\n ];\n /** @nocollapse */\n NgSelectMultipleOption.ctorParameters = function () { return [\n { type: _angular_core.ElementRef, },\n { type: _angular_core.Renderer, },\n { type: SelectMultipleControlValueAccessor, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Host },] },\n ]; };\n NgSelectMultipleOption.propDecorators = {\n 'ngValue': [{ type: _angular_core.Input, args: ['ngValue',] },],\n 'value': [{ type: _angular_core.Input, args: ['value',] },],\n };\n return NgSelectMultipleOption;\n }());\n\n /**\n * @param {?} name\n * @param {?} parent\n * @return {?}\n */\n function controlPath(name, parent) {\n return parent.path.concat([name]);\n }\n /**\n * @param {?} control\n * @param {?} dir\n * @return {?}\n */\n function setUpControl(control, dir) {\n if (!control)\n _throwError(dir, 'Cannot find control with');\n if (!dir.valueAccessor)\n _throwError(dir, 'No value accessor for form control with');\n control.validator = Validators.compose([control.validator, dir.validator]);\n control.asyncValidator = Validators.composeAsync([control.asyncValidator, dir.asyncValidator]);\n dir.valueAccessor.writeValue(control.value);\n // view -> model\n dir.valueAccessor.registerOnChange(function (newValue) {\n dir.viewToModelUpdate(newValue);\n control.markAsDirty();\n control.setValue(newValue, { emitModelToViewChange: false });\n });\n // touched\n dir.valueAccessor.registerOnTouched(function () { return control.markAsTouched(); });\n control.registerOnChange(function (newValue, emitModelEvent) {\n // control -> view\n dir.valueAccessor.writeValue(newValue);\n // control -> ngModel\n if (emitModelEvent)\n dir.viewToModelUpdate(newValue);\n });\n if (dir.valueAccessor.setDisabledState) {\n control.registerOnDisabledChange(function (isDisabled) { dir.valueAccessor.setDisabledState(isDisabled); });\n }\n // re-run validation when validator binding changes, e.g. minlength=3 -> minlength=4\n dir._rawValidators.forEach(function (validator) {\n if (((validator)).registerOnValidatorChange)\n ((validator)).registerOnValidatorChange(function () { return control.updateValueAndValidity(); });\n });\n dir._rawAsyncValidators.forEach(function (validator) {\n if (((validator)).registerOnValidatorChange)\n ((validator)).registerOnValidatorChange(function () { return control.updateValueAndValidity(); });\n });\n }\n /**\n * @param {?} control\n * @param {?} dir\n * @return {?}\n */\n function cleanUpControl(control, dir) {\n dir.valueAccessor.registerOnChange(function () { return _noControlError(dir); });\n dir.valueAccessor.registerOnTouched(function () { return _noControlError(dir); });\n dir._rawValidators.forEach(function (validator) {\n if (validator.registerOnValidatorChange) {\n validator.registerOnValidatorChange(null);\n }\n });\n dir._rawAsyncValidators.forEach(function (validator) {\n if (validator.registerOnValidatorChange) {\n validator.registerOnValidatorChange(null);\n }\n });\n if (control)\n control._clearChangeFns();\n }\n /**\n * @param {?} control\n * @param {?} dir\n * @return {?}\n */\n function setUpFormContainer(control, dir) {\n if (isBlank(control))\n _throwError(dir, 'Cannot find control with');\n control.validator = Validators.compose([control.validator, dir.validator]);\n control.asyncValidator = Validators.composeAsync([control.asyncValidator, dir.asyncValidator]);\n }\n /**\n * @param {?} dir\n * @return {?}\n */\n function _noControlError(dir) {\n return _throwError(dir, 'There is no FormControl instance attached to form control element with');\n }\n /**\n * @param {?} dir\n * @param {?} message\n * @return {?}\n */\n function _throwError(dir, message) {\n var /** @type {?} */ messageEnd;\n if (dir.path.length > 1) {\n messageEnd = \"path: '\" + dir.path.join(' -> ') + \"'\";\n }\n else if (dir.path[0]) {\n messageEnd = \"name: '\" + dir.path + \"'\";\n }\n else {\n messageEnd = 'unspecified name attribute';\n }\n throw new Error(message + \" \" + messageEnd);\n }\n /**\n * @param {?} validators\n * @return {?}\n */\n function composeValidators(validators) {\n return isPresent(validators) ? Validators.compose(validators.map(normalizeValidator)) : null;\n }\n /**\n * @param {?} validators\n * @return {?}\n */\n function composeAsyncValidators(validators) {\n return isPresent(validators) ? Validators.composeAsync(validators.map(normalizeAsyncValidator)) :\n null;\n }\n /**\n * @param {?} changes\n * @param {?} viewModel\n * @return {?}\n */\n function isPropertyUpdated(changes, viewModel) {\n if (!changes.hasOwnProperty('model'))\n return false;\n var /** @type {?} */ change = changes['model'];\n if (change.isFirstChange())\n return true;\n return !looseIdentical(viewModel, change.currentValue);\n }\n var /** @type {?} */ BUILTIN_ACCESSORS = [\n CheckboxControlValueAccessor,\n RangeValueAccessor,\n NumberValueAccessor,\n SelectControlValueAccessor,\n SelectMultipleControlValueAccessor,\n RadioControlValueAccessor,\n ];\n /**\n * @param {?} valueAccessor\n * @return {?}\n */\n function isBuiltInAccessor(valueAccessor) {\n return BUILTIN_ACCESSORS.some(function (a) { return valueAccessor.constructor === a; });\n }\n /**\n * @param {?} dir\n * @param {?} valueAccessors\n * @return {?}\n */\n function selectValueAccessor(dir, valueAccessors) {\n if (!valueAccessors)\n return null;\n var /** @type {?} */ defaultAccessor;\n var /** @type {?} */ builtinAccessor;\n var /** @type {?} */ customAccessor;\n valueAccessors.forEach(function (v) {\n if (v.constructor === DefaultValueAccessor) {\n defaultAccessor = v;\n }\n else if (isBuiltInAccessor(v)) {\n if (builtinAccessor)\n _throwError(dir, 'More than one built-in value accessor matches form control with');\n builtinAccessor = v;\n }\n else {\n if (customAccessor)\n _throwError(dir, 'More than one custom value accessor matches form control with');\n customAccessor = v;\n }\n });\n if (customAccessor)\n return customAccessor;\n if (builtinAccessor)\n return builtinAccessor;\n if (defaultAccessor)\n return defaultAccessor;\n _throwError(dir, 'No valid value accessor for form control with');\n return null;\n }\n\n /**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n var __extends = (this && this.__extends) || function (d, b) {\n for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n /**\n * This is a base class for code shared between {@link NgModelGroup} and {@link FormGroupName}.\n * *\n */\n var AbstractFormGroupDirective = (function (_super) {\n __extends(AbstractFormGroupDirective, _super);\n function AbstractFormGroupDirective() {\n _super.apply(this, arguments);\n }\n /**\n * @return {?}\n */\n AbstractFormGroupDirective.prototype.ngOnInit = function () {\n this._checkParentType();\n this.formDirective.addFormGroup(this);\n };\n /**\n * @return {?}\n */\n AbstractFormGroupDirective.prototype.ngOnDestroy = function () {\n if (this.formDirective) {\n this.formDirective.removeFormGroup(this);\n }\n };\n Object.defineProperty(AbstractFormGroupDirective.prototype, \"control\", {\n /**\n * Get the {@link FormGroup} backing this binding.\n * @return {?}\n */\n get: function () { return this.formDirective.getFormGroup(this); },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractFormGroupDirective.prototype, \"path\", {\n /**\n * Get the path to this control group.\n * @return {?}\n */\n get: function () { return controlPath(this.name, this._parent); },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractFormGroupDirective.prototype, \"formDirective\", {\n /**\n * Get the {@link Form} to which this group belongs.\n * @return {?}\n */\n get: function () { return this._parent ? this._parent.formDirective : null; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractFormGroupDirective.prototype, \"validator\", {\n /**\n * @return {?}\n */\n get: function () { return composeValidators(this._validators); },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractFormGroupDirective.prototype, \"asyncValidator\", {\n /**\n * @return {?}\n */\n get: function () { return composeAsyncValidators(this._asyncValidators); },\n enumerable: true,\n configurable: true\n });\n /**\n * @return {?}\n */\n AbstractFormGroupDirective.prototype._checkParentType = function () { };\n return AbstractFormGroupDirective;\n }(ControlContainer));\n\n /**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n var __extends$3 = (this && this.__extends) || function (d, b) {\n for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n var AbstractControlStatus = (function () {\n /**\n * @param {?} cd\n */\n function AbstractControlStatus(cd) {\n this._cd = cd;\n }\n Object.defineProperty(AbstractControlStatus.prototype, \"ngClassUntouched\", {\n /**\n * @return {?}\n */\n get: function () { return this._cd.control ? this._cd.control.untouched : false; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControlStatus.prototype, \"ngClassTouched\", {\n /**\n * @return {?}\n */\n get: function () { return this._cd.control ? this._cd.control.touched : false; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControlStatus.prototype, \"ngClassPristine\", {\n /**\n * @return {?}\n */\n get: function () { return this._cd.control ? this._cd.control.pristine : false; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControlStatus.prototype, \"ngClassDirty\", {\n /**\n * @return {?}\n */\n get: function () { return this._cd.control ? this._cd.control.dirty : false; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControlStatus.prototype, \"ngClassValid\", {\n /**\n * @return {?}\n */\n get: function () { return this._cd.control ? this._cd.control.valid : false; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControlStatus.prototype, \"ngClassInvalid\", {\n /**\n * @return {?}\n */\n get: function () { return this._cd.control ? this._cd.control.invalid : false; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControlStatus.prototype, \"ngClassPending\", {\n /**\n * @return {?}\n */\n get: function () { return this._cd.control ? this._cd.control.pending : false; },\n enumerable: true,\n configurable: true\n });\n return AbstractControlStatus;\n }());\n var /** @type {?} */ ngControlStatusHost = {\n '[class.ng-untouched]': 'ngClassUntouched',\n '[class.ng-touched]': 'ngClassTouched',\n '[class.ng-pristine]': 'ngClassPristine',\n '[class.ng-dirty]': 'ngClassDirty',\n '[class.ng-valid]': 'ngClassValid',\n '[class.ng-invalid]': 'ngClassInvalid',\n '[class.ng-pending]': 'ngClassPending',\n };\n /**\n * Directive automatically applied to Angular form controls that sets CSS classes\n * based on control status (valid/invalid/dirty/etc).\n * *\n */\n var NgControlStatus = (function (_super) {\n __extends$3(NgControlStatus, _super);\n /**\n * @param {?} cd\n */\n function NgControlStatus(cd) {\n _super.call(this, cd);\n }\n NgControlStatus.decorators = [\n { type: _angular_core.Directive, args: [{ selector: '[formControlName],[ngModel],[formControl]', host: ngControlStatusHost },] },\n ];\n /** @nocollapse */\n NgControlStatus.ctorParameters = function () { return [\n { type: NgControl, decorators: [{ type: _angular_core.Self },] },\n ]; };\n return NgControlStatus;\n }(AbstractControlStatus));\n /**\n * Directive automatically applied to Angular form groups that sets CSS classes\n * based on control status (valid/invalid/dirty/etc).\n * *\n */\n var NgControlStatusGroup = (function (_super) {\n __extends$3(NgControlStatusGroup, _super);\n /**\n * @param {?} cd\n */\n function NgControlStatusGroup(cd) {\n _super.call(this, cd);\n }\n NgControlStatusGroup.decorators = [\n { type: _angular_core.Directive, args: [{\n selector: '[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]',\n host: ngControlStatusHost\n },] },\n ];\n /** @nocollapse */\n NgControlStatusGroup.ctorParameters = function () { return [\n { type: ControlContainer, decorators: [{ type: _angular_core.Self },] },\n ]; };\n return NgControlStatusGroup;\n }(AbstractControlStatus));\n\n /**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n var __extends$5 = (this && this.__extends) || function (d, b) {\n for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n /**\n * Use by directives and components to emit custom Events.\n * *\n * ### Examples\n * *\n * In the following example, `Zippy` alternatively emits `open` and `close` events when its\n * title gets clicked:\n * *\n * ```\n * selector: 'zippy',\n * template: `\n * <div class=\"zippy\">\n * <div (click)=\"toggle()\">Toggle</div>\n * <div [hidden]=\"!visible\">\n * <ng-content></ng-content>\n * </div>\n * </div>`})\n * export class Zippy {\n * visible: boolean = true;\n * @Output() open: EventEmitter<any> = new EventEmitter();\n * @Output() close: EventEmitter<any> = new EventEmitter();\n * *\n * toggle() {\n * this.visible = !this.visible;\n * if (this.visible) {\n * this.open.emit(null);\n * } else {\n * this.close.emit(null);\n * }\n * }\n * }\n * ```\n * *\n * The events payload can be accessed by the parameter `$event` on the components output event\n * handler:\n * *\n * ```\n * <zippy (open)=\"onOpen($event)\" (close)=\"onClose($event)\"></zippy>\n * ```\n * *\n * Uses Rx.Observable but provides an adapter to make it work as specified here:\n * https://github.com/jhusain/observable-spec\n * *\n * Once a reference implementation of the spec is available, switch to it.\n */\n var EventEmitter = (function (_super) {\n __extends$5(EventEmitter, _super);\n /**\n * Creates an instance of [EventEmitter], which depending on [isAsync],\n * delivers events synchronously or asynchronously.\n * @param {?=} isAsync\n */\n function EventEmitter(isAsync) {\n if (isAsync === void 0) { isAsync = false; }\n _super.call(this);\n this.__isAsync = isAsync;\n }\n /**\n * @param {?=} value\n * @return {?}\n */\n EventEmitter.prototype.emit = function (value) { _super.prototype.next.call(this, value); };\n /**\n * @param {?=} generatorOrNext\n * @param {?=} error\n * @param {?=} complete\n * @return {?}\n */\n EventEmitter.prototype.subscribe = function (generatorOrNext, error, complete) {\n var /** @type {?} */ schedulerFn;\n var /** @type {?} */ errorFn = function (err) { return null; };\n var /** @type {?} */ completeFn = function () { return null; };\n if (generatorOrNext && typeof generatorOrNext === 'object') {\n schedulerFn = this.__isAsync ? function (value) {\n setTimeout(function () { return generatorOrNext.next(value); });\n } : function (value) { generatorOrNext.next(value); };\n if (generatorOrNext.error) {\n errorFn = this.__isAsync ? function (err) { setTimeout(function () { return generatorOrNext.error(err); }); } :\n function (err) { generatorOrNext.error(err); };\n }\n if (generatorOrNext.complete) {\n completeFn = this.__isAsync ? function () { setTimeout(function () { return generatorOrNext.complete(); }); } :\n function () { generatorOrNext.complete(); };\n }\n }\n else {\n schedulerFn = this.__isAsync ? function (value) { setTimeout(function () { return generatorOrNext(value); }); } :\n function (value) { generatorOrNext(value); };\n if (error) {\n errorFn =\n this.__isAsync ? function (err) { setTimeout(function () { return error(err); }); } : function (err) { error(err); };\n }\n if (complete) {\n completeFn =\n this.__isAsync ? function () { setTimeout(function () { return complete(); }); } : function () { complete(); };\n }\n }\n return _super.prototype.subscribe.call(this, schedulerFn, errorFn, completeFn);\n };\n return EventEmitter;\n }(rxjs_Subject.Subject));\n\n /**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n var __extends$6 = (this && this.__extends) || function (d, b) {\n for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n /**\n * Indicates that a FormControl is valid, i.e. that no errors exist in the input value.\n */\n var /** @type {?} */ VALID = 'VALID';\n /**\n * Indicates that a FormControl is invalid, i.e. that an error exists in the input value.\n */\n var /** @type {?} */ INVALID = 'INVALID';\n /**\n * Indicates that a FormControl is pending, i.e. that async validation is occurring and\n * errors are not yet available for the input value.\n */\n var /** @type {?} */ PENDING = 'PENDING';\n /**\n * Indicates that a FormControl is disabled, i.e. that the control is exempt from ancestor\n * calculations of validity or value.\n */\n var /** @type {?} */ DISABLED = 'DISABLED';\n /**\n * @param {?} control\n * @param {?} path\n * @param {?} delimiter\n * @return {?}\n */\n function _find(control, path, delimiter) {\n if (path == null)\n return null;\n if (!(path instanceof Array)) {\n path = ((path)).split(delimiter);\n }\n if (path instanceof Array && (path.length === 0))\n return null;\n return ((path)).reduce(function (v, name) {\n if (v instanceof FormGroup) {\n return v.controls[name] || null;\n }\n if (v instanceof FormArray) {\n return v.at(/** @type {?} */ (name)) || null;\n }\n return null;\n }, control);\n }\n /**\n * @param {?} r\n * @return {?}\n */\n function toObservable(r) {\n return isPromise(r) ? rxjs_observable_fromPromise.fromPromise(r) : r;\n }\n /**\n * @param {?} validator\n * @return {?}\n */\n function coerceToValidator(validator) {\n return Array.isArray(validator) ? composeValidators(validator) : validator;\n }\n /**\n * @param {?} asyncValidator\n * @return {?}\n */\n function coerceToAsyncValidator(asyncValidator) {\n return Array.isArray(asyncValidator) ? composeAsyncValidators(asyncValidator) : asyncValidator;\n }\n /**\n * {@link FormArray}.\n * *\n * It provides some of the shared behavior that all controls and groups of controls have, like\n * running validators, calculating status, and resetting state. It also defines the properties\n * that are shared between all sub-classes, like `value`, `valid`, and `dirty`. It shouldn't be\n * instantiated directly.\n * *\n * @abstract\n */\n var AbstractControl = (function () {\n /**\n * @param {?} validator\n * @param {?} asyncValidator\n */\n function AbstractControl(validator, asyncValidator) {\n this.validator = validator;\n this.asyncValidator = asyncValidator;\n /** @internal */\n this._onCollectionChange = function () { };\n this._pristine = true;\n this._touched = false;\n /** @internal */\n this._onDisabledChange = [];\n }\n Object.defineProperty(AbstractControl.prototype, \"value\", {\n /**\n * The value of the control.\n * @return {?}\n */\n get: function () { return this._value; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControl.prototype, \"parent\", {\n /**\n * The parent control.\n * @return {?}\n */\n get: function () { return this._parent; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControl.prototype, \"status\", {\n /**\n * The validation status of the control. There are four possible\n * validation statuses:\n * *\n * * **VALID**: control has passed all validation checks\n * * **INVALID**: control has failed at least one validation check\n * * **PENDING**: control is in the midst of conducting a validation check\n * * **DISABLED**: control is exempt from validation checks\n * *\n * These statuses are mutually exclusive, so a control cannot be\n * both valid AND invalid or invalid AND disabled.\n * @return {?}\n */\n get: function () { return this._status; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControl.prototype, \"valid\", {\n /**\n * A control is `valid` when its `status === VALID`.\n * *\n * In order to have this status, the control must have passed all its\n * validation checks.\n * @return {?}\n */\n get: function () { return this._status === VALID; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControl.prototype, \"invalid\", {\n /**\n * A control is `invalid` when its `status === INVALID`.\n * *\n * In order to have this status, the control must have failed\n * at least one of its validation checks.\n * @return {?}\n */\n get: function () { return this._status === INVALID; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControl.prototype, \"pending\", {\n /**\n * A control is `pending` when its `status === PENDING`.\n * *\n * In order to have this status, the control must be in the\n * middle of conducting a validation check.\n * @return {?}\n */\n get: function () { return this._status == PENDING; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControl.prototype, \"disabled\", {\n /**\n * A control is `disabled` when its `status === DISABLED`.\n * *\n * Disabled controls are exempt from validation checks and\n * are not included in the aggregate value of their ancestor\n * controls.\n * @return {?}\n */\n get: function () { return this._status === DISABLED; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControl.prototype, \"enabled\", {\n /**\n * A control is `enabled` as long as its `status !== DISABLED`.\n * *\n * In other words, it has a status of `VALID`, `INVALID`, or\n * `PENDING`.\n * @return {?}\n */\n get: function () { return this._status !== DISABLED; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControl.prototype, \"errors\", {\n /**\n * Returns any errors generated by failing validation. If there\n * are no errors, it will return null.\n * @return {?}\n */\n get: function () { return this._errors; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControl.prototype, \"pristine\", {\n /**\n * A control is `pristine` if the user has not yet changed\n * the value in the UI.\n * *\n * Note that programmatic changes to a control's value will\n * *not* mark it dirty.\n * @return {?}\n */\n get: function () { return this._pristine; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControl.prototype, \"dirty\", {\n /**\n * A control is `dirty` if the user has changed the value\n * in the UI.\n * *\n * Note that programmatic changes to a control's value will\n * *not* mark it dirty.\n * @return {?}\n */\n get: function () { return !this.pristine; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControl.prototype, \"touched\", {\n /**\n * A control is marked `touched` once the user has triggered\n * a `blur` event on it.\n * @return {?}\n */\n get: function () { return this._touched; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControl.prototype, \"untouched\", {\n /**\n * A control is `untouched` if the user has not yet triggered\n * a `blur` event on it.\n * @return {?}\n */\n get: function () { return !this._touched; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControl.prototype, \"valueChanges\", {\n /**\n * Emits an event every time the value of the control changes, in\n * the UI or programmatically.\n * @return {?}\n */\n get: function () { return this._valueChanges; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(AbstractControl.prototype, \"statusChanges\", {\n /**\n * Emits an event every time the validation status of the control\n * is re-calculated.\n * @return {?}\n */\n get: function () { return this._statusChanges; },\n enumerable: true,\n configurable: true\n });\n /**\n * Sets the synchronous validators that are active on this control. Calling\n * this will overwrite any existing sync validators.\n * @param {?} newValidator\n * @return {?}\n */\n AbstractControl.prototype.setValidators = function (newValidator) {\n this.validator = coerceToValidator(newValidator);\n };\n /**\n * Sets the async validators that are active on this control. Calling this\n * will overwrite any existing async validators.\n * @param {?} newValidator\n * @return {?}\n */\n AbstractControl.prototype.setAsyncValidators = function (newValidator) {\n this.asyncValidator = coerceToAsyncValidator(newValidator);\n };\n /**\n * Empties out the sync validator list.\n * @return {?}\n */\n AbstractControl.prototype.clearValidators = function () { this.validator = null; };\n /**\n * Empties out the async validator list.\n * @return {?}\n */\n AbstractControl.prototype.clearAsyncValidators = function () { this.asyncValidator = null; };\n /**\n * Marks the control as `touched`.\n * *\n * This will also mark all direct ancestors as `touched` to maintain\n * the model.\n * @param {?=} __0\n * @return {?}\n */\n AbstractControl.prototype.markAsTouched = function (_a) {\n var onlySelf = (_a === void 0 ? {} : _a).onlySelf;\n this._touched = true;\n if (this._parent && !onlySelf) {\n this._parent.markAsTouched({ onlySelf: onlySelf });\n }\n };\n /**\n * Marks the control as `untouched`.\n * *\n * If the control has any children, it will also mark all children as `untouched`\n * to maintain the model, and re-calculate the `touched` status of all parent\n * controls.\n * @param {?=} __0\n * @return {?}\n */\n AbstractControl.prototype.markAsUntouched = function (_a) {\n var onlySelf = (_a === void 0 ? {} : _a).onlySelf;\n this._touched = false;\n this._forEachChild(function (control) { control.markAsUntouched({ onlySelf: true }); });\n if (this._parent && !onlySelf) {\n this._parent._updateTouched({ onlySelf: onlySelf });\n }\n };\n /**\n * Marks the control as `dirty`.\n * *\n * This will also mark all direct ancestors as `dirty` to maintain\n * the model.\n * @param {?=} __0\n * @return {?}\n */\n AbstractControl.prototype.markAsDirty = function (_a) {\n var onlySelf = (_a === void 0 ? {} : _a).onlySelf;\n this._pristine = false;\n if (this._parent && !onlySelf) {\n this._parent.markAsDirty({ onlySelf: onlySelf });\n }\n };\n /**\n * Marks the control as `pristine`.\n * *\n * If the control has any children, it will also mark all children as `pristine`\n * to maintain the model, and re-calculate the `pristine` status of all parent\n * controls.\n * @param {?=} __0\n * @return {?}\n */\n AbstractControl.prototype.markAsPristine = function (_a) {\n var onlySelf = (_a === void 0 ? {} : _a).onlySelf;\n this._pristine = true;\n this._forEachChild(function (control) { control.markAsPristine({ onlySelf: true }); });\n if (this._parent && !onlySelf) {\n this._parent._updatePristine({ onlySelf: onlySelf });\n }\n };\n /**\n * Marks the control as `pending`.\n * @param {?=} __0\n * @return {?}\n */\n AbstractControl.prototype.markAsPending = function (_a) {\n var onlySelf = (_a === void 0 ? {} : _a).onlySelf;\n this._status = PENDING;\n if (this._parent && !onlySelf) {\n this._parent.markAsPending({ onlySelf: onlySelf });\n }\n };\n /**\n * Disables the control. This means the control will be exempt from validation checks and\n * excluded from the aggregate value of any parent. Its status is `DISABLED`.\n * *\n * If the control has children, all children will be disabled to maintain the model.\n * @param {?=} __0\n * @return {?}\n */\n AbstractControl.prototype.disable = function (_a) {\n var _b = _a === void 0 ? {} : _a, onlySelf = _b.onlySelf, emitEvent = _b.emitEvent;\n this._status = DISABLED;\n this._errors = null;\n this._forEachChild(function (control) { control.disable({ onlySelf: true }); });\n this._updateValue();\n if (emitEvent !== false) {\n this._valueChanges.emit(this._value);\n this._statusChanges.emit(this._status);\n }\n this._updateAncestors(onlySelf);\n this._onDisabledChange.forEach(function (changeFn) { return changeFn(true); });\n };\n /**\n * Enables the control. This means the control will be included in validation checks and\n * the aggregate value of its parent. Its status is re-calculated based on its value and\n * its validators.\n * *\n * If the control has children, all children will be enabled.\n * @param {?=} __0\n * @return {?}\n */\n AbstractControl.prototype.enable = function (_a) {\n var _b = _a === void 0 ? {} : _a, onlySelf = _b.onlySelf, emitEvent = _b.emitEvent;\n this._status = VALID;\n this._forEachChild(function (control) { control.enable({ onlySelf: true }); });\n this.updateValueAndValidity({ onlySelf: true, emitEvent: emitEvent });\n this._updateAncestors(onlySelf);\n this._onDisabledChange.forEach(function (changeFn) { return changeFn(false); });\n };\n /**\n * @param {?} onlySelf\n * @return {?}\n */\n AbstractControl.prototype._updateAncestors = function (onlySelf) {\n if (this._parent && !onlySelf) {\n this._parent.updateValueAndValidity();\n this._parent._updatePristine();\n this._parent._updateTouched();\n }\n };\n /**\n * @param {?} parent\n * @return {?}\n */\n AbstractControl.prototype.setParent = function (parent) { this._parent = parent; };\n /**\n * Sets the value of the control. Abstract method (implemented in sub-classes).\n * @abstract\n * @param {?} value\n * @param {?=} options\n * @return {?}\n */\n AbstractControl.prototype.setValue = function (value, options) { };\n /**\n * Patches the value of the control. Abstract method (implemented in sub-classes).\n * @abstract\n * @param {?} value\n * @param {?=} options\n * @return {?}\n */\n AbstractControl.prototype.patchValue = function (value, options) { };\n /**\n * Resets the control. Abstract method (implemented in sub-classes).\n * @abstract\n * @param {?=} value\n * @param {?=} options\n * @return {?}\n */\n AbstractControl.prototype.reset = function (value, options) { };\n /**\n * Re-calculates the value and validation status of the control.\n * *\n * By default, it will also update the value and validity of its ancestors.\n * @param {?=} __0\n * @return {?}\n */\n AbstractControl.prototype.updateValueAndValidity = function (_a) {\n var _b = _a === void 0 ? {} : _a, onlySelf = _b.onlySelf, emitEvent = _b.emitEvent;\n this._setInitialStatus();\n this._updateValue();\n if (this.enabled) {\n this._errors = this._runValidator();\n this._status = this._calculateStatus();\n if (this._status === VALID || this._status === PENDING) {\n this._runAsyncValidator(emitEvent);\n }\n }\n if (emitEvent !== false) {\n this._valueChanges.emit(this._value);\n this._statusChanges.emit(this._status);\n }\n if (this._parent && !onlySelf) {\n this._parent.updateValueAndValidity({ onlySelf: onlySelf, emitEvent: emitEvent });\n }\n };\n /**\n * @param {?=} __0\n * @return {?}\n */\n AbstractControl.prototype._updateTreeValidity = function (_a) {\n var emitEvent = (_a === void 0 ? { emitEvent: true } : _a).emitEvent;\n this._forEachChild(function (ctrl) { return ctrl._updateTreeValidity({ emitEvent: emitEvent }); });\n this.updateValueAndValidity({ onlySelf: true, emitEvent: emitEvent });\n };\n /**\n * @return {?}\n */\n AbstractControl.prototype._setInitialStatus = function () { this._status = this._allControlsDisabled() ? DISABLED : VALID; };\n /**\n * @return {?}\n */\n AbstractControl.prototype._runValidator = function () {\n return this.validator ? this.validator(this) : null;\n };\n /**\n * @param {?} emitEvent\n * @return {?}\n */\n AbstractControl.prototype._runAsyncValidator = function (emitEvent) {\n var _this = this;\n if (this.asyncValidator) {\n this._status = PENDING;\n this._cancelExistingSubscription();\n var /** @type {?} */ obs = toObservable(this.asyncValidator(this));\n this._asyncValidationSubscription =\n obs.subscribe({ next: function (res) { return _this.setErrors(res, { emitEvent: emitEvent }); } });\n }\n };\n /**\n * @return {?}\n */\n AbstractControl.prototype._cancelExistingSubscription = function () {\n if (this._asyncValidationSubscription) {\n this._asyncValidationSubscription.unsubscribe();\n }\n };\n /**\n * Sets errors on a form control.\n * *\n * This is used when validations are run manually by the user, rather than automatically.\n * *\n * Calling `setErrors` will also update the validity of the parent control.\n * *\n * ### Example\n * *\n * ```\n * const login = new FormControl(\"someLogin\");\n * login.setErrors({\n * \"notUnique\": true\n * });\n * *\n * expect(login.valid).toEqual(false);\n * expect(login.errors).toEqual({\"notUnique\": true});\n * *\n * login.setValue(\"someOtherLogin\");\n * *\n * expect(login.valid).toEqual(true);\n * ```\n * @param {?} errors\n * @param {?=} __1\n * @return {?}\n */\n AbstractControl.prototype.setErrors = function (errors, _a) {\n var emitEvent = (_a === void 0 ? {} : _a).emitEvent;\n this._errors = errors;\n this._updateControlsErrors(emitEvent !== false);\n };\n /**\n * Retrieves a child control given the control's name or path.\n * *\n * Paths can be passed in as an array or a string delimited by a dot.\n * *\n * To get a control nested within a `person` sub-group:\n * *\n * * `this.form.get('person.name');`\n * *\n * -OR-\n * *\n * * `this.form.get(['person', 'name']);`\n * @param {?} path\n * @return {?}\n */\n AbstractControl.prototype.get = function (path) { return _find(this, path, '.'); };\n /**\n * Returns true if the control with the given path has the error specified. Otherwise\n * returns null or undefined.\n * *\n * If no path is given, it checks for the error on the present control.\n * @param {?} errorCode\n * @param {?=} path\n * @return {?}\n */\n AbstractControl.prototype.getError = function (errorCode, path) {\n if (path === void 0) { path = null; }\n var /** @type {?} */ control = path ? this.get(path) : this;\n return control && control._errors ? control._errors[errorCode] : null;\n };\n /**\n * Returns true if the control with the given path has the error specified. Otherwise\n * returns false.\n * *\n * If no path is given, it checks for the error on the present control.\n * @param {?} errorCode\n * @param {?=} path\n * @return {?}\n */\n AbstractControl.prototype.hasError = function (errorCode, path) {\n if (path === void 0) { path = null; }\n return !!this.getError(errorCode, path);\n };\n Object.defineProperty(AbstractControl.prototype, \"root\", {\n /**\n * Retrieves the top-level ancestor of this control.\n * @return {?}\n */\n get: function () {\n var /** @type {?} */ x = this;\n while (x._parent) {\n x = x._parent;\n }\n return x;\n },\n enumerable: true,\n configurable: true\n });\n /**\n * @param {?} emitEvent\n * @return {?}\n */\n AbstractControl.prototype._updateControlsErrors = function (emitEvent) {\n this._status = this._calculateStatus();\n if (emitEvent) {\n this._statusChanges.emit(this._status);\n }\n if (this._parent) {\n this._parent._updateControlsErrors(emitEvent);\n }\n };\n /**\n * @return {?}\n */\n AbstractControl.prototype._initObservables = function () {\n this._valueChanges = new EventEmitter();\n this._statusChanges = new EventEmitter();\n };\n /**\n * @return {?}\n */\n AbstractControl.prototype._calculateStatus = function () {\n if (this._allControlsDisabled())\n return DISABLED;\n if (this._errors)\n return INVALID;\n if (this._anyControlsHaveStatus(PENDING))\n return PENDING;\n if (this._anyControlsHaveStatus(INVALID))\n return INVALID;\n return VALID;\n };\n /**\n * @abstract\n * @return {?}\n */\n AbstractControl.prototype._updateValue = function () { };\n /**\n * @abstract\n * @param {?} cb\n * @return {?}\n */\n AbstractControl.prototype._forEachChild = function (cb) { };\n /**\n * @abstract\n * @param {?} condition\n * @return {?}\n */\n AbstractControl.prototype._anyControls = function (condition) { };\n /**\n * @abstract\n * @return {?}\n */\n AbstractControl.prototype._allControlsDisabled = function () { };\n /**\n * @param {?} status\n * @return {?}\n */\n AbstractControl.prototype._anyControlsHaveStatus = function (status) {\n return this._anyControls(function (control) { return control.status === status; });\n };\n /**\n * @return {?}\n */\n AbstractControl.prototype._anyControlsDirty = function () {\n return this._anyControls(function (control) { return control.dirty; });\n };\n /**\n * @return {?}\n */\n AbstractControl.prototype._anyControlsTouched = function () {\n return this._anyControls(function (control) { return control.touched; });\n };\n /**\n * @param {?=} __0\n * @return {?}\n */\n AbstractControl.prototype._updatePristine = function (_a) {\n var onlySelf = (_a === void 0 ? {} : _a).onlySelf;\n this._pristine = !this._anyControlsDirty();\n if (this._parent && !onlySelf) {\n this._parent._updatePristine({ onlySelf: onlySelf });\n }\n };\n /**\n * @param {?=} __0\n * @return {?}\n */\n AbstractControl.prototype._updateTouched = function (_a) {\n var onlySelf = (_a === void 0 ? {} : _a).onlySelf;\n this._touched = this._anyControlsTouched();\n if (this._parent && !onlySelf) {\n this._parent._updateTouched({ onlySelf: onlySelf });\n }\n };\n /**\n * @param {?} formState\n * @return {?}\n */\n AbstractControl.prototype._isBoxedValue = function (formState) {\n return typeof formState === 'object' && formState !== null &&\n Object.keys(formState).length === 2 && 'value' in formState && 'disabled' in formState;\n };\n /**\n * @param {?} fn\n * @return {?}\n */\n AbstractControl.prototype._registerOnCollectionChange = function (fn) { this._onCollectionChange = fn; };\n return AbstractControl;\n }());\n /**\n * *\n * It is one of the three fundamental building blocks of Angular forms, along with\n * {@link FormGroup} and {@link FormArray}.\n * *\n * *\n * When instantiating a {@link FormControl}, you can pass in an initial value as the\n * first argument. Example:\n * *\n * ```ts\n * const ctrl = new FormControl('some value');\n * console.log(ctrl.value); // 'some value'\n * *```\n * *\n * You can also initialize the control with a form state object on instantiation,\n * which includes both the value and whether or not the control is disabled.\n * You can't use the value key without the disabled key; both are required\n * to use this way of initialization.\n * *\n * ```ts\n * const ctrl = new FormControl({value: 'n/a', disabled: true});\n * console.log(ctrl.value); // 'n/a'\n * console.log(ctrl.status); // 'DISABLED'\n * ```\n * *\n * To include a sync validator (or an array of sync validators) with the control,\n * pass it in as the second argument. Async validators are also supported, but\n * have to be passed in separately as the third arg.\n * *\n * ```ts\n * const ctrl = new FormControl('', Validators.required);\n * console.log(ctrl.value); // ''\n * console.log(ctrl.status); // 'INVALID'\n * ```\n * *\n * See its superclass, {@link AbstractControl}, for more properties and methods.\n * *\n * * **npm package**: `@angular/forms`\n * *\n */\n var FormControl = (function (_super) {\n __extends$6(FormControl, _super);\n /**\n * @param {?=} formState\n * @param {?=} validator\n * @param {?=} asyncValidator\n */\n function FormControl(formState, validator, asyncValidator) {\n if (formState === void 0) { formState = null; }\n if (validator === void 0) { validator = null; }\n if (asyncValidator === void 0) { asyncValidator = null; }\n _super.call(this, coerceToValidator(validator), coerceToAsyncValidator(asyncValidator));\n /** @internal */\n this._onChange = [];\n this._applyFormState(formState);\n this.updateValueAndValidity({ onlySelf: true, emitEvent: false });\n this._initObservables();\n }\n /**\n * Set the value of the form control to `value`.\n * *\n * If `onlySelf` is `true`, this change will only affect the validation of this `FormControl`\n * and not its parent component. This defaults to false.\n * *\n * If `emitEvent` is `true`, this\n * change will cause a `valueChanges` event on the `FormControl` to be emitted. This defaults\n * to true (as it falls through to `updateValueAndValidity`).\n * *\n * If `emitModelToViewChange` is `true`, the view will be notified about the new value\n * via an `onChange` event. This is the default behavior if `emitModelToViewChange` is not\n * specified.\n * *\n * If `emitViewToModelChange` is `true`, an ngModelChange event will be fired to update the\n * model. This is the default behavior if `emitViewToModelChange` is not specified.\n * @param {?} value\n * @param {?=} __1\n * @return {?}\n */\n FormControl.prototype.setValue = function (value, _a) {\n var _this = this;\n var _b = _a === void 0 ? {} : _a, onlySelf = _b.onlySelf, emitEvent = _b.emitEvent, emitModelToViewChange = _b.emitModelToViewChange, emitViewToModelChange = _b.emitViewToModelChange;\n this._value = value;\n if (this._onChange.length && emitModelToViewChange !== false) {\n this._onChange.forEach(function (changeFn) { return changeFn(_this._value, emitViewToModelChange !== false); });\n }\n this.updateValueAndValidity({ onlySelf: onlySelf, emitEvent: emitEvent });\n };\n /**\n * Patches the value of a control.\n * *\n * This function is functionally the same as {@link FormControl.setValue} at this level.\n * It exists for symmetry with {@link FormGroup.patchValue} on `FormGroups` and `FormArrays`,\n * where it does behave differently.\n * @param {?} value\n * @param {?=} options\n * @return {?}\n */\n FormControl.prototype.patchValue = function (value, options) {\n if (options === void 0) { options = {}; }\n this.setValue(value, options);\n };\n /**\n * Resets the form control. This means by default:\n * *\n * * it is marked as `pristine`\n * * it is marked as `untouched`\n * * value is set to null\n * *\n * You can also reset to a specific form state by passing through a standalone\n * value or a form state object that contains both a value and a disabled state\n * (these are the only two properties that cannot be calculated).\n * *\n * Ex:\n * *\n * ```ts\n * this.control.reset('Nancy');\n * *\n * console.log(this.control.value); // 'Nancy'\n * ```\n * *\n * OR\n * *\n * ```\n * this.control.reset({value: 'Nancy', disabled: true});\n * *\n * console.log(this.control.value); // 'Nancy'\n * console.log(this.control.status); // 'DISABLED'\n * ```\n * @param {?=} formState\n * @param {?=} __1\n * @return {?}\n */\n FormControl.prototype.reset = function (formState, _a) {\n if (formState === void 0) { formState = null; }\n var _b = _a === void 0 ? {} : _a, onlySelf = _b.onlySelf, emitEvent = _b.emitEvent;\n this._applyFormState(formState);\n this.markAsPristine({ onlySelf: onlySelf });\n this.markAsUntouched({ onlySelf: onlySelf });\n this.setValue(this._value, { onlySelf: onlySelf, emitEvent: emitEvent });\n };\n /**\n * @return {?}\n */\n FormControl.prototype._updateValue = function () { };\n /**\n * @param {?} condition\n * @return {?}\n */\n FormControl.prototype._anyControls = function (condition) { return false; };\n /**\n * @return {?}\n */\n FormControl.prototype._allControlsDisabled = function () { return this.disabled; };\n /**\n * Register a listener for change events.\n * @param {?} fn\n * @return {?}\n */\n FormControl.prototype.registerOnChange = function (fn) { this._onChange.push(fn); };\n /**\n * @return {?}\n */\n FormControl.prototype._clearChangeFns = function () {\n this._onChange = [];\n this._onDisabledChange = [];\n this._onCollectionChange = function () { };\n };\n /**\n * Register a listener for disabled events.\n * @param {?} fn\n * @return {?}\n */\n FormControl.prototype.registerOnDisabledChange = function (fn) {\n this._onDisabledChange.push(fn);\n };\n /**\n * @param {?} cb\n * @return {?}\n */\n FormControl.prototype._forEachChild = function (cb) { };\n /**\n * @param {?} formState\n * @return {?}\n */\n FormControl.prototype._applyFormState = function (formState) {\n if (this._isBoxedValue(formState)) {\n this._value = formState.value;\n formState.disabled ? this.disable({ onlySelf: true, emitEvent: false }) :\n this.enable({ onlySelf: true, emitEvent: false });\n }\n else {\n this._value = formState;\n }\n };\n return FormControl;\n }(AbstractControl));\n /**\n * instances.\n * *\n * A `FormGroup` aggregates the values of each child {@link FormControl} into one object,\n * with each control name as the key. It calculates its status by reducing the statuses\n * of its children. For example, if one of the controls in a group is invalid, the entire\n * group becomes invalid.\n * *\n * `FormGroup` is one of the three fundamental building blocks used to define forms in Angular,\n * along with {@link FormControl} and {@link FormArray}.\n * *\n * *\n * When instantiating a {@link FormGroup}, pass in a collection of child controls as the first\n * argument. The key for each child will be the name under which it is registered.\n * *\n * ### Example\n * *\n * ```\n * const form = new FormGroup({\n * first: new FormControl('Nancy', Validators.minLength(2)),\n * last: new FormControl('Drew'),\n * });\n * *\n * console.log(form.value); // {first: 'Nancy', last; 'Drew'}\n * console.log(form.status); // 'VALID'\n * ```\n * *\n * You can also include group-level validators as the second arg, or group-level async\n * validators as the third arg. These come in handy when you want to perform validation\n * that considers the value of more than one child control.\n * *\n * ### Example\n * *\n * ```\n * const form = new FormGroup({\n * password: new FormControl('', Validators.minLength(2)),\n * passwordConfirm: new FormControl('', Validators.minLength(2)),\n * }, passwordMatchValidator);\n * *\n * *\n * function passwordMatchValidator(g: FormGroup) {\n * return g.get('password').value === g.get('passwordConfirm').value\n * ? null : {'mismatch': true};\n * }\n * ```\n * *\n * * **npm package**: `@angular/forms`\n * *\n */\n var FormGroup = (function (_super) {\n __extends$6(FormGroup, _super);\n /**\n * @param {?} controls\n * @param {?=} validator\n * @param {?=} asyncValidator\n */\n function FormGroup(controls, validator, asyncValidator) {\n if (validator === void 0) { validator = null; }\n if (asyncValidator === void 0) { asyncValidator = null; }\n _super.call(this, validator, asyncValidator);\n this.controls = controls;\n this._initObservables();\n this._setUpControls();\n this.updateValueAndValidity({ onlySelf: true, emitEvent: false });\n }\n /**\n * Registers a control with the group's list of controls.\n * *\n * This method does not update value or validity of the control, so for\n * most cases you'll want to use {@link FormGroup.addControl} instead.\n * @param {?} name\n * @param {?} control\n * @return {?}\n */\n FormGroup.prototype.registerControl = function (name, control) {\n if (this.controls[name])\n return this.controls[name];\n this.controls[name] = control;\n control.setParent(this);\n control._registerOnCollectionChange(this._onCollectionChange);\n return control;\n };\n /**\n * Add a control to this group.\n * @param {?} name\n * @param {?} control\n * @return {?}\n */\n FormGroup.prototype.addControl = function (name, control) {\n this.registerControl(name, control);\n this.updateValueAndValidity();\n this._onCollectionChange();\n };\n /**\n * Remove a control from this group.\n * @param {?} name\n * @return {?}\n */\n FormGroup.prototype.removeControl = function (name) {\n if (this.controls[name])\n this.controls[name]._registerOnCollectionChange(function () { });\n delete (this.controls[name]);\n this.updateValueAndValidity();\n this._onCollectionChange();\n };\n /**\n * Replace an existing control.\n * @param {?} name\n * @param {?} control\n * @return {?}\n */\n FormGroup.prototype.setControl = function (name, control) {\n if (this.controls[name])\n this.controls[name]._registerOnCollectionChange(function () { });\n delete (this.controls[name]);\n if (control)\n this.registerControl(name, control);\n this.updateValueAndValidity();\n this._onCollectionChange();\n };\n /**\n * Check whether there is an enabled control with the given name in the group.\n * *\n * It will return false for disabled controls. If you'd like to check for\n * existence in the group only, use {@link AbstractControl.get} instead.\n * @param {?} controlName\n * @return {?}\n */\n FormGroup.prototype.contains = function (controlName) {\n return this.controls.hasOwnProperty(controlName) && this.controls[controlName].enabled;\n };\n /**\n * Sets the value of the {@link FormGroup}. It accepts an object that matches\n * the structure of the group, with control names as keys.\n * *\n * This method performs strict checks, so it will throw an error if you try\n * to set the value of a control that doesn't exist or if you exclude the\n * value of a control.\n * *\n * ### Example\n * *\n * ```\n * const form = new FormGroup({\n * first: new FormControl(),\n * last: new FormControl()\n * });\n * console.log(form.value); // {first: null, last: null}\n * *\n * form.setValue({first: 'Nancy', last: 'Drew'});\n * console.log(form.value); // {first: 'Nancy', last: 'Drew'}\n * *\n * ```\n * @param {?} value\n * @param {?=} __1\n * @return {?}\n */\n FormGroup.prototype.setValue = function (value, _a) {\n var _this = this;\n var _b = _a === void 0 ? {} : _a, onlySelf = _b.onlySelf, emitEvent = _b.emitEvent;\n this._checkAllValuesPresent(value);\n Object.keys(value).forEach(function (name) {\n _this._throwIfControlMissing(name);\n _this.controls[name].setValue(value[name], { onlySelf: true, emitEvent: emitEvent });\n });\n this.updateValueAndValidity({ onlySelf: onlySelf, emitEvent: emitEvent });\n };\n /**\n * Patches the value of the {@link FormGroup}. It accepts an object with control\n * names as keys, and will do its best to match the values to the correct controls\n * in the group.\n * *\n * It accepts both super-sets and sub-sets of the group without throwing an error.\n * *\n * ### Example\n * *\n * ```\n * const form = new FormGroup({\n * first: new FormControl(),\n * last: new FormControl()\n * });\n * console.log(form.value); // {first: null, last: null}\n * *\n * form.patchValue({first: 'Nancy'});\n * console.log(form.value); // {first: 'Nancy', last: null}\n * *\n * ```\n * @param {?} value\n * @param {?=} __1\n * @return {?}\n */\n FormGroup.prototype.patchValue = function (value, _a) {\n var _this = this;\n var _b = _a === void 0 ? {} : _a, onlySelf = _b.onlySelf, emitEvent = _b.emitEvent;\n Object.keys(value).forEach(function (name) {\n if (_this.controls[name]) {\n _this.controls[name].patchValue(value[name], { onlySelf: true, emitEvent: emitEvent });\n }\n });\n this.updateValueAndValidity({ onlySelf: onlySelf, emitEvent: emitEvent });\n };\n /**\n * Resets the {@link FormGroup}. This means by default:\n * *\n * * The group and all descendants are marked `pristine`\n * * The group and all descendants are marked `untouched`\n * * The value of all descendants will be null or null maps\n * *\n * You can also reset to a specific form state by passing in a map of states\n * that matches the structure of your form, with control names as keys. The state\n * can be a standalone value or a form state object with both a value and a disabled\n * status.\n * *\n * ### Example\n * *\n * ```ts\n * this.form.reset({first: 'name', last: 'last name'});\n * *\n * console.log(this.form.value); // {first: 'name', last: 'last name'}\n * ```\n * *\n * - OR -\n * *\n * ```\n * this.form.reset({\n * first: {value: 'name', disabled: true},\n * last: 'last'\n * });\n * *\n * console.log(this.form.value); // {first: 'name', last: 'last name'}\n * console.log(this.form.get('first').status); // 'DISABLED'\n * ```\n * @param {?=} value\n * @param {?=} __1\n * @return {?}\n */\n FormGroup.prototype.reset = function (value, _a) {\n if (value === void 0) { value = {}; }\n var _b = _a === void 0 ? {} : _a, onlySelf = _b.onlySelf, emitEvent = _b.emitEvent;\n this._forEachChild(function (control, name) {\n control.reset(value[name], { onlySelf: true, emitEvent: emitEvent });\n });\n this.updateValueAndValidity({ onlySelf: onlySelf, emitEvent: emitEvent });\n this._updatePristine({ onlySelf: onlySelf });\n this._updateTouched({ onlySelf: onlySelf });\n };\n /**\n * The aggregate value of the {@link FormGroup}, including any disabled controls.\n * *\n * If you'd like to include all values regardless of disabled status, use this method.\n * Otherwise, the `value` property is the best way to get the value of the group.\n * @return {?}\n */\n FormGroup.prototype.getRawValue = function () {\n return this._reduceChildren({}, function (acc, control, name) {\n acc[name] = control.value;\n return acc;\n });\n };\n /**\n * @param {?} name\n * @return {?}\n */\n FormGroup.prototype._throwIfControlMissing = function (name) {\n if (!Object.keys(this.controls).length) {\n throw new Error(\"\\n There are no form controls registered with this group yet. If you're using ngModel,\\n you may want to check next tick (e.g. use setTimeout).\\n \");\n }\n if (!this.controls[name]) {\n throw new Error(\"Cannot find form control with name: \" + name + \".\");\n }\n };\n /**\n * @param {?} cb\n * @return {?}\n */\n FormGroup.prototype._forEachChild = function (cb) {\n var _this = this;\n Object.keys(this.controls).forEach(function (k) { return cb(_this.controls[k], k); });\n };\n /**\n * @return {?}\n */\n FormGroup.prototype._setUpControls = function () {\n var _this = this;\n this._forEachChild(function (control) {\n control.setParent(_this);\n control._registerOnCollectionChange(_this._onCollectionChange);\n });\n };\n /**\n * @return {?}\n */\n FormGroup.prototype._updateValue = function () { this._value = this._reduceValue(); };\n /**\n * @param {?} condition\n * @return {?}\n */\n FormGroup.prototype._anyControls = function (condition) {\n var _this = this;\n var /** @type {?} */ res = false;\n this._forEachChild(function (control, name) {\n res = res || (_this.contains(name) && condition(control));\n });\n return res;\n };\n /**\n * @return {?}\n */\n FormGroup.prototype._reduceValue = function () {\n var _this = this;\n return this._reduceChildren({}, function (acc, control, name) {\n if (control.enabled || _this.disabled) {\n acc[name] = control.value;\n }\n return acc;\n });\n };\n /**\n * @param {?} initValue\n * @param {?} fn\n * @return {?}\n */\n FormGroup.prototype._reduceChildren = function (initValue, fn) {\n var /** @type {?} */ res = initValue;\n this._forEachChild(function (control, name) { res = fn(res, control, name); });\n return res;\n };\n /**\n * @return {?}\n */\n FormGroup.prototype._allControlsDisabled = function () {\n for (var _i = 0, _a = Object.keys(this.controls); _i < _a.length; _i++) {\n var controlName = _a[_i];\n if (this.controls[controlName].enabled) {\n return false;\n }\n }\n return Object.keys(this.controls).length > 0 || this.disabled;\n };\n /**\n * @param {?} value\n * @return {?}\n */\n FormGroup.prototype._checkAllValuesPresent = function (value) {\n this._forEachChild(function (control, name) {\n if (value[name] === undefined) {\n throw new Error(\"Must supply a value for form control with name: '\" + name + \"'.\");\n }\n });\n };\n return FormGroup;\n }(AbstractControl));\n /**\n * instances.\n * *\n * A `FormArray` aggregates the values of each child {@link FormControl} into an array.\n * It calculates its status by reducing the statuses of its children. For example, if one of\n * the controls in a `FormArray` is invalid, the entire array becomes invalid.\n * *\n * `FormArray` is one of the three fundamental building blocks used to define forms in Angular,\n * along with {@link FormControl} and {@link FormGroup}.\n * *\n * *\n * When instantiating a {@link FormArray}, pass in an array of child controls as the first\n * argument.\n * *\n * ### Example\n * *\n * ```\n * const arr = new FormArray([\n * new FormControl('Nancy', Validators.minLength(2)),\n * new FormControl('Drew'),\n * ]);\n * *\n * console.log(arr.value); // ['Nancy', 'Drew']\n * console.log(arr.status); // 'VALID'\n * ```\n * *\n * You can also include array-level validators as the second arg, or array-level async\n * validators as the third arg. These come in handy when you want to perform validation\n * that considers the value of more than one child control.\n * *\n * ### Adding or removing controls\n * *\n * To change the controls in the array, use the `push`, `insert`, or `removeAt` methods\n * in `FormArray` itself. These methods ensure the controls are properly tracked in the\n * form's hierarchy. Do not modify the array of `AbstractControl`s used to instantiate\n * the `FormArray` directly, as that will result in strange and unexpected behavior such\n * as broken change detection.\n * *\n * * **npm package**: `@angular/forms`\n * *\n */\n var FormArray = (function (_super) {\n __extends$6(FormArray, _super);\n /**\n * @param {?} controls\n * @param {?=} validator\n * @param {?=} asyncValidator\n */\n function FormArray(controls, validator, asyncValidator) {\n if (validator === void 0) { validator = null; }\n if (asyncValidator === void 0) { asyncValidator = null; }\n _super.call(this, validator, asyncValidator);\n this.controls = controls;\n this._initObservables();\n this._setUpControls();\n this.updateValueAndValidity({ onlySelf: true, emitEvent: false });\n }\n /**\n * Get the {@link AbstractControl} at the given `index` in the array.\n * @param {?} index\n * @return {?}\n */\n FormArray.prototype.at = function (index) { return this.controls[index]; };\n /**\n * Insert a new {@link AbstractControl} at the end of the array.\n * @param {?} control\n * @return {?}\n */\n FormArray.prototype.push = function (control) {\n this.controls.push(control);\n this._registerControl(control);\n this.updateValueAndValidity();\n this._onCollectionChange();\n };\n /**\n * Insert a new {@link AbstractControl} at the given `index` in the array.\n * @param {?} index\n * @param {?} control\n * @return {?}\n */\n FormArray.prototype.insert = function (index, control) {\n this.controls.splice(index, 0, control);\n this._registerControl(control);\n this.updateValueAndValidity();\n this._onCollectionChange();\n };\n /**\n * Remove the control at the given `index` in the array.\n * @param {?} index\n * @return {?}\n */\n FormArray.prototype.removeAt = function (index) {\n if (this.controls[index])\n this.controls[index]._registerOnCollectionChange(function () { });\n this.controls.splice(index, 1);\n this.updateValueAndValidity();\n this._onCollectionChange();\n };\n /**\n * Replace an existing control.\n * @param {?} index\n * @param {?} control\n * @return {?}\n */\n FormArray.prototype.setControl = function (index, control) {\n if (this.controls[index])\n this.controls[index]._registerOnCollectionChange(function () { });\n this.controls.splice(index, 1);\n if (control) {\n this.controls.splice(index, 0, control);\n this._registerControl(control);\n }\n this.updateValueAndValidity();\n this._onCollectionChange();\n };\n Object.defineProperty(FormArray.prototype, \"length\", {\n /**\n * Length of the control array.\n * @return {?}\n */\n get: function () { return this.controls.length; },\n enumerable: true,\n configurable: true\n });\n /**\n * Sets the value of the {@link FormArray}. It accepts an array that matches\n * the structure of the control.\n * *\n * This method performs strict checks, so it will throw an error if you try\n * to set the value of a control that doesn't exist or if you exclude the\n * value of a control.\n * *\n * ### Example\n * *\n * ```\n * const arr = new FormArray([\n * new FormControl(),\n * new FormControl()\n * ]);\n * console.log(arr.value); // [null, null]\n * *\n * arr.setValue(['Nancy', 'Drew']);\n * console.log(arr.value); // ['Nancy', 'Drew']\n * ```\n * @param {?} value\n * @param {?=} __1\n * @return {?}\n */\n FormArray.prototype.setValue = function (value, _a) {\n var _this = this;\n var _b = _a === void 0 ? {} : _a, onlySelf = _b.onlySelf, emitEvent = _b.emitEvent;\n this._checkAllValuesPresent(value);\n value.forEach(function (newValue, index) {\n _this._throwIfControlMissing(index);\n _this.at(index).setValue(newValue, { onlySelf: true, emitEvent: emitEvent });\n });\n this.updateValueAndValidity({ onlySelf: onlySelf, emitEvent: emitEvent });\n };\n /**\n * Patches the value of the {@link FormArray}. It accepts an array that matches the\n * structure of the control, and will do its best to match the values to the correct\n * controls in the group.\n * *\n * It accepts both super-sets and sub-sets of the array without throwing an error.\n * *\n * ### Example\n * *\n * ```\n * const arr = new FormArray([\n * new FormControl(),\n * new FormControl()\n * ]);\n * console.log(arr.value); // [null, null]\n * *\n * arr.patchValue(['Nancy']);\n * console.log(arr.value); // ['Nancy', null]\n * ```\n * @param {?} value\n * @param {?=} __1\n * @return {?}\n */\n FormArray.prototype.patchValue = function (value, _a) {\n var _this = this;\n var _b = _a === void 0 ? {} : _a, onlySelf = _b.onlySelf, emitEvent = _b.emitEvent;\n value.forEach(function (newValue, index) {\n if (_this.at(index)) {\n _this.at(index).patchValue(newValue, { onlySelf: true, emitEvent: emitEvent });\n }\n });\n this.updateValueAndValidity({ onlySelf: onlySelf, emitEvent: emitEvent });\n };\n /**\n * Resets the {@link FormArray}. This means by default:\n * *\n * * The array and all descendants are marked `pristine`\n * * The array and all descendants are marked `untouched`\n * * The value of all descendants will be null or null maps\n * *\n * You can also reset to a specific form state by passing in an array of states\n * that matches the structure of the control. The state can be a standalone value\n * or a form state object with both a value and a disabled status.\n * *\n * ### Example\n * *\n * ```ts\n * this.arr.reset(['name', 'last name']);\n * *\n * console.log(this.arr.value); // ['name', 'last name']\n * ```\n * *\n * - OR -\n * *\n * ```\n * this.arr.reset([\n * {value: 'name', disabled: true},\n * 'last'\n * ]);\n * *\n * console.log(this.arr.value); // ['name', 'last name']\n * console.log(this.arr.get(0).status); // 'DISABLED'\n * ```\n * @param {?=} value\n * @param {?=} __1\n * @return {?}\n */\n FormArray.prototype.reset = function (value, _a) {\n if (value === void 0) { value = []; }\n var _b = _a === void 0 ? {} : _a, onlySelf = _b.onlySelf, emitEvent = _b.emitEvent;\n this._forEachChild(function (control, index) {\n control.reset(value[index], { onlySelf: true, emitEvent: emitEvent });\n });\n this.updateValueAndValidity({ onlySelf: onlySelf, emitEvent: emitEvent });\n this._updatePristine({ onlySelf: onlySelf });\n this._updateTouched({ onlySelf: onlySelf });\n };\n /**\n * The aggregate value of the array, including any disabled controls.\n * *\n * If you'd like to include all values regardless of disabled status, use this method.\n * Otherwise, the `value` property is the best way to get the value of the array.\n * @return {?}\n */\n FormArray.prototype.getRawValue = function () { return this.controls.map(function (control) { return control.value; }); };\n /**\n * @param {?} index\n * @return {?}\n */\n FormArray.prototype._throwIfControlMissing = function (index) {\n if (!this.controls.length) {\n throw new Error(\"\\n There are no form controls registered with this array yet. If you're using ngModel,\\n you may want to check next tick (e.g. use setTimeout).\\n \");\n }\n if (!this.at(index)) {\n throw new Error(\"Cannot find form control at index \" + index);\n }\n };\n /**\n * @param {?} cb\n * @return {?}\n */\n FormArray.prototype._forEachChild = function (cb) {\n this.controls.forEach(function (control, index) { cb(control, index); });\n };\n /**\n * @return {?}\n */\n FormArray.prototype._updateValue = function () {\n var _this = this;\n this._value = this.controls.filter(function (control) { return control.enabled || _this.disabled; })\n .map(function (control) { return control.value; });\n };\n /**\n * @param {?} condition\n * @return {?}\n */\n FormArray.prototype._anyControls = function (condition) {\n return this.controls.some(function (control) { return control.enabled && condition(control); });\n };\n /**\n * @return {?}\n */\n FormArray.prototype._setUpControls = function () {\n var _this = this;\n this._forEachChild(function (control) { return _this._registerControl(control); });\n };\n /**\n * @param {?} value\n * @return {?}\n */\n FormArray.prototype._checkAllValuesPresent = function (value) {\n this._forEachChild(function (control, i) {\n if (value[i] === undefined) {\n throw new Error(\"Must supply a value for form control at index: \" + i + \".\");\n }\n });\n };\n /**\n * @return {?}\n */\n FormArray.prototype._allControlsDisabled = function () {\n for (var _i = 0, _a = this.controls; _i < _a.length; _i++) {\n var control = _a[_i];\n if (control.enabled)\n return false;\n }\n return this.controls.length > 0 || this.disabled;\n };\n /**\n * @param {?} control\n * @return {?}\n */\n FormArray.prototype._registerControl = function (control) {\n control.setParent(this);\n control._registerOnCollectionChange(this._onCollectionChange);\n };\n return FormArray;\n }(AbstractControl));\n\n /**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n var __extends$4 = (this && this.__extends) || function (d, b) {\n for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n var /** @type {?} */ formDirectiveProvider = {\n provide: ControlContainer,\n useExisting: _angular_core.forwardRef(function () { return NgForm; })\n };\n var /** @type {?} */ resolvedPromise = Promise.resolve(null);\n /**\n * to track aggregate form value and validation status.\n * *\n * *\n * As soon as you import the `FormsModule`, this directive becomes active by default on\n * all `<form>` tags. You don't need to add a special selector.\n * *\n * You can export the directive into a local template variable using `ngForm` as the key\n * (ex: `#myForm=\"ngForm\"`). This is optional, but useful. Many properties from the underlying\n * {@link FormGroup} instance are duplicated on the directive itself, so a reference to it\n * will give you access to the aggregate value and validity status of the form, as well as\n * user interaction properties like `dirty` and `touched`.\n * *\n * To register child controls with the form, you'll want to use {@link NgModel} with a\n * `name` attribute. You can also use {@link NgModelGroup} if you'd like to create\n * sub-groups within the form.\n * *\n * You can listen to the directive's `ngSubmit` event to be notified when the user has\n * triggered a form submission. The `ngSubmit` event will be emitted with the original form\n * submission event.\n * *\n * {@example forms/ts/simpleForm/simple_form_example.ts region='Component'}\n * *\n * * **npm package**: `@angular/forms`\n * *\n * * **NgModule**: `FormsModule`\n * *\n * @stable\n */\n var NgForm = (function (_super) {\n __extends$4(NgForm, _super);\n /**\n * @param {?} validators\n * @param {?} asyncValidators\n */\n function NgForm(validators, asyncValidators) {\n _super.call(this);\n this._submitted = false;\n this.ngSubmit = new EventEmitter();\n this.form =\n new FormGroup({}, composeValidators(validators), composeAsyncValidators(asyncValidators));\n }\n Object.defineProperty(NgForm.prototype, \"submitted\", {\n /**\n * @return {?}\n */\n get: function () { return this._submitted; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(NgForm.prototype, \"formDirective\", {\n /**\n * @return {?}\n */\n get: function () { return this; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(NgForm.prototype, \"control\", {\n /**\n * @return {?}\n */\n get: function () { return this.form; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(NgForm.prototype, \"path\", {\n /**\n * @return {?}\n */\n get: function () { return []; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(NgForm.prototype, \"controls\", {\n /**\n * @return {?}\n */\n get: function () { return this.form.controls; },\n enumerable: true,\n configurable: true\n });\n /**\n * @param {?} dir\n * @return {?}\n */\n NgForm.prototype.addControl = function (dir) {\n var _this = this;\n resolvedPromise.then(function () {\n var /** @type {?} */ container = _this._findContainer(dir.path);\n dir._control = (container.registerControl(dir.name, dir.control));\n setUpControl(dir.control, dir);\n dir.control.updateValueAndValidity({ emitEvent: false });\n });\n };\n /**\n * @param {?} dir\n * @return {?}\n */\n NgForm.prototype.getControl = function (dir) { return (this.form.get(dir.path)); };\n /**\n * @param {?} dir\n * @return {?}\n */\n NgForm.prototype.removeControl = function (dir) {\n var _this = this;\n resolvedPromise.then(function () {\n var /** @type {?} */ container = _this._findContainer(dir.path);\n if (container) {\n container.removeControl(dir.name);\n }\n });\n };\n /**\n * @param {?} dir\n * @return {?}\n */\n NgForm.prototype.addFormGroup = function (dir) {\n var _this = this;\n resolvedPromise.then(function () {\n var /** @type {?} */ container = _this._findContainer(dir.path);\n var /** @type {?} */ group = new FormGroup({});\n setUpFormContainer(group, dir);\n container.registerControl(dir.name, group);\n group.updateValueAndValidity({ emitEvent: false });\n });\n };\n /**\n * @param {?} dir\n * @return {?}\n */\n NgForm.prototype.removeFormGroup = function (dir) {\n var _this = this;\n resolvedPromise.then(function () {\n var /** @type {?} */ container = _this._findContainer(dir.path);\n if (container) {\n container.removeControl(dir.name);\n }\n });\n };\n /**\n * @param {?} dir\n * @return {?}\n */\n NgForm.prototype.getFormGroup = function (dir) { return (this.form.get(dir.path)); };\n /**\n * @param {?} dir\n * @param {?} value\n * @return {?}\n */\n NgForm.prototype.updateModel = function (dir, value) {\n var _this = this;\n resolvedPromise.then(function () {\n var /** @type {?} */ ctrl = (_this.form.get(dir.path));\n ctrl.setValue(value);\n });\n };\n /**\n * @param {?} value\n * @return {?}\n */\n NgForm.prototype.setValue = function (value) { this.control.setValue(value); };\n /**\n * @param {?} $event\n * @return {?}\n */\n NgForm.prototype.onSubmit = function ($event) {\n this._submitted = true;\n this.ngSubmit.emit($event);\n return false;\n };\n /**\n * @return {?}\n */\n NgForm.prototype.onReset = function () { this.resetForm(); };\n /**\n * @param {?=} value\n * @return {?}\n */\n NgForm.prototype.resetForm = function (value) {\n if (value === void 0) { value = undefined; }\n this.form.reset(value);\n this._submitted = false;\n };\n /**\n * @param {?} path\n * @return {?}\n */\n NgForm.prototype._findContainer = function (path) {\n path.pop();\n return path.length ? (this.form.get(path)) : this.form;\n };\n NgForm.decorators = [\n { type: _angular_core.Directive, args: [{\n selector: 'form:not([ngNoForm]):not([formGroup]),ngForm,[ngForm]',\n providers: [formDirectiveProvider],\n host: { '(submit)': 'onSubmit($event)', '(reset)': 'onReset()' },\n outputs: ['ngSubmit'],\n exportAs: 'ngForm'\n },] },\n ];\n /** @nocollapse */\n NgForm.ctorParameters = function () { return [\n { type: Array, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Self }, { type: _angular_core.Inject, args: [NG_VALIDATORS,] },] },\n { type: Array, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Self }, { type: _angular_core.Inject, args: [NG_ASYNC_VALIDATORS,] },] },\n ]; };\n return NgForm;\n }(ControlContainer));\n\n /**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n var /** @type {?} */ Examples = {\n formControlName: \"\\n <div [formGroup]=\\\"myGroup\\\">\\n <input formControlName=\\\"firstName\\\">\\n </div>\\n\\n In your class:\\n\\n this.myGroup = new FormGroup({\\n firstName: new FormControl()\\n });\",\n formGroupName: \"\\n <div [formGroup]=\\\"myGroup\\\">\\n <div formGroupName=\\\"person\\\">\\n <input formControlName=\\\"firstName\\\">\\n </div>\\n </div>\\n\\n In your class:\\n\\n this.myGroup = new FormGroup({\\n person: new FormGroup({ firstName: new FormControl() })\\n });\",\n formArrayName: \"\\n <div [formGroup]=\\\"myGroup\\\">\\n <div formArrayName=\\\"cities\\\">\\n <div *ngFor=\\\"let city of cityArray.controls; let i=index\\\">\\n <input [formControlName]=\\\"i\\\">\\n </div>\\n </div>\\n </div>\\n\\n In your class:\\n\\n this.cityArray = new FormArray([new FormControl('SF')]);\\n this.myGroup = new FormGroup({\\n cities: this.cityArray\\n });\",\n ngModelGroup: \"\\n <form>\\n <div ngModelGroup=\\\"person\\\">\\n <input [(ngModel)]=\\\"person.name\\\" name=\\\"firstName\\\">\\n </div>\\n </form>\",\n ngModelWithFormGroup: \"\\n <div [formGroup]=\\\"myGroup\\\">\\n <input formControlName=\\\"firstName\\\">\\n <input [(ngModel)]=\\\"showMoreControls\\\" [ngModelOptions]=\\\"{standalone: true}\\\">\\n </div>\\n \"\n };\n\n var TemplateDrivenErrors = (function () {\n function TemplateDrivenErrors() {\n }\n /**\n * @return {?}\n */\n TemplateDrivenErrors.modelParentException = function () {\n throw new Error(\"\\n ngModel cannot be used to register form controls with a parent formGroup directive. Try using\\n formGroup's partner directive \\\"formControlName\\\" instead. Example:\\n\\n \" + Examples.formControlName + \"\\n\\n Or, if you'd like to avoid registering this form control, indicate that it's standalone in ngModelOptions:\\n\\n Example:\\n\\n \" + Examples.ngModelWithFormGroup);\n };\n /**\n * @return {?}\n */\n TemplateDrivenErrors.formGroupNameException = function () {\n throw new Error(\"\\n ngModel cannot be used to register form controls with a parent formGroupName or formArrayName directive.\\n\\n Option 1: Use formControlName instead of ngModel (reactive strategy):\\n\\n \" + Examples.formGroupName + \"\\n\\n Option 2: Update ngModel's parent be ngModelGroup (template-driven strategy):\\n\\n \" + Examples.ngModelGroup);\n };\n /**\n * @return {?}\n */\n TemplateDrivenErrors.missingNameException = function () {\n throw new Error(\"If ngModel is used within a form tag, either the name attribute must be set or the form\\n control must be defined as 'standalone' in ngModelOptions.\\n\\n Example 1: <input [(ngModel)]=\\\"person.firstName\\\" name=\\\"first\\\">\\n Example 2: <input [(ngModel)]=\\\"person.firstName\\\" [ngModelOptions]=\\\"{standalone: true}\\\">\");\n };\n /**\n * @return {?}\n */\n TemplateDrivenErrors.modelGroupParentException = function () {\n throw new Error(\"\\n ngModelGroup cannot be used with a parent formGroup directive.\\n\\n Option 1: Use formGroupName instead of ngModelGroup (reactive strategy):\\n\\n \" + Examples.formGroupName + \"\\n\\n Option 2: Use a regular form tag instead of the formGroup directive (template-driven strategy):\\n\\n \" + Examples.ngModelGroup);\n };\n return TemplateDrivenErrors;\n }());\n\n /**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n var __extends$8 = (this && this.__extends) || function (d, b) {\n for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n var /** @type {?} */ modelGroupProvider = {\n provide: ControlContainer,\n useExisting: _angular_core.forwardRef(function () { return NgModelGroup; })\n };\n /**\n * *\n * *\n * This directive can only be used as a child of {@link NgForm} (or in other words,\n * within `<form>` tags).\n * *\n * Use this directive if you'd like to create a sub-group within a form. This can\n * come in handy if you want to validate a sub-group of your form separately from\n * the rest of your form, or if some values in your domain model make more sense to\n * consume together in a nested object.\n * *\n * Pass in the name you'd like this sub-group to have and it will become the key\n * for the sub-group in the form's full value. You can also export the directive into\n * a local template variable using `ngModelGroup` (ex: `#myGroup=\"ngModelGroup\"`).\n * *\n * {@example forms/ts/ngModelGroup/ng_model_group_example.ts region='Component'}\n * *\n * * **npm package**: `@angular/forms`\n * *\n * * **NgModule**: `FormsModule`\n * *\n */\n var NgModelGroup = (function (_super) {\n __extends$8(NgModelGroup, _super);\n /**\n * @param {?} parent\n * @param {?} validators\n * @param {?} asyncValidators\n */\n function NgModelGroup(parent, validators, asyncValidators) {\n _super.call(this);\n this._parent = parent;\n this._validators = validators;\n this._asyncValidators = asyncValidators;\n }\n /**\n * @return {?}\n */\n NgModelGroup.prototype._checkParentType = function () {\n if (!(this._parent instanceof NgModelGroup) && !(this._parent instanceof NgForm)) {\n TemplateDrivenErrors.modelGroupParentException();\n }\n };\n NgModelGroup.decorators = [\n { type: _angular_core.Directive, args: [{ selector: '[ngModelGroup]', providers: [modelGroupProvider], exportAs: 'ngModelGroup' },] },\n ];\n /** @nocollapse */\n NgModelGroup.ctorParameters = function () { return [\n { type: ControlContainer, decorators: [{ type: _angular_core.Host }, { type: _angular_core.SkipSelf },] },\n { type: Array, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Self }, { type: _angular_core.Inject, args: [NG_VALIDATORS,] },] },\n { type: Array, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Self }, { type: _angular_core.Inject, args: [NG_ASYNC_VALIDATORS,] },] },\n ]; };\n NgModelGroup.propDecorators = {\n 'name': [{ type: _angular_core.Input, args: ['ngModelGroup',] },],\n };\n return NgModelGroup;\n }(AbstractFormGroupDirective));\n\n /**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n var __extends$7 = (this && this.__extends) || function (d, b) {\n for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n var /** @type {?} */ formControlBinding = {\n provide: NgControl,\n useExisting: _angular_core.forwardRef(function () { return NgModel; })\n };\n /**\n * `ngModel` forces an additional change detection run when its inputs change:\n * E.g.:\n * ```\n * <div>{{myModel.valid}}</div>\n * <input [(ngModel)]=\"myValue\" #myModel=\"ngModel\">\n * ```\n * I.e. `ngModel` can export itself on the element and then be used in the template.\n * Normally, this would result in expressions before the `input` that use the exported directive\n * to have and old value as they have been\n * dirty checked before. As this is a very common case for `ngModel`, we added this second change\n * detection run.\n *\n * Notes:\n * - this is just one extra run no matter how many `ngModel` have been changed.\n * - this is a general problem when using `exportAs` for directives!\n */\n var /** @type {?} */ resolvedPromise$1 = Promise.resolve(null);\n /**\n * to a form control element.\n * *\n * The {@link FormControl} instance will track the value, user interaction, and\n * validation status of the control and keep the view synced with the model. If used\n * within a parent form, the directive will also register itself with the form as a child\n * control.\n * *\n * *\n * This directive can be used by itself or as part of a larger form. All you need is the\n * `ngModel` selector to activate it.\n * *\n * It accepts a domain model as an optional {@link @Input}. If you have a one-way binding\n * to `ngModel` with `[]` syntax, changing the value of the domain model in the component\n * class will set the value in the view. If you have a two-way binding with `[()]` syntax\n * (also known as 'banana-box syntax'), the value in the UI will always be synced back to\n * the domain model in your class as well.\n * *\n * If you wish to inspect the properties of the associated {@link FormControl} (like\n * validity state), you can also export the directive into a local template variable using\n * `ngModel` as the key (ex: `#myVar=\"ngModel\"`). You can then access the control using the\n * directive's `control` property, but most properties you'll need (like `valid` and `dirty`)\n * will fall through to the control anyway, so you can access them directly. You can see a\n * full list of properties directly available in {@link AbstractControlDirective}.\n * *\n * The following is an example of a simple standalone control using `ngModel`:\n * *\n * {@example forms/ts/simpleNgModel/simple_ng_model_example.ts region='Component'}\n * *\n * When using the `ngModel` within `<form>` tags, you'll also need to supply a `name` attribute\n * so that the control can be registered with the parent form under that name.\n * *\n * It's worth noting that in the context of a parent form, you often can skip one-way or\n * two-way binding because the parent form will sync the value for you. You can access\n * its properties by exporting it into a local template variable using `ngForm` (ex:\n * `#f=\"ngForm\"`). Then you can pass it where it needs to go on submit.\n * *\n * If you do need to populate initial values into your form, using a one-way binding for\n * `ngModel` tends to be sufficient as long as you use the exported form's value rather\n * than the domain model's value on submit.\n * *\n * Take a look at an example of using `ngModel` within a form:\n * *\n * {@example forms/ts/simpleForm/simple_form_example.ts region='Component'}\n * *\n * To see `ngModel` examples with different form control types, see:\n * *\n * * Radio buttons: {@link RadioControlValueAccessor}\n * * Selects: {@link SelectControlValueAccessor}\n * *\n * **npm package**: `@angular/forms`\n * *\n * **NgModule**: `FormsModule`\n * *\n * @stable\n */\n var NgModel = (function (_super) {\n __extends$7(NgModel, _super);\n /**\n * @param {?} parent\n * @param {?} validators\n * @param {?} asyncValidators\n * @param {?} valueAccessors\n */\n function NgModel(parent, validators, asyncValidators, valueAccessors) {\n _super.call(this);\n /** @internal */\n this._control = new FormControl();\n /** @internal */\n this._registered = false;\n this.update = new EventEmitter();\n this._parent = parent;\n this._rawValidators = validators || [];\n this._rawAsyncValidators = asyncValidators || [];\n this.valueAccessor = selectValueAccessor(this, valueAccessors);\n }\n /**\n * @param {?} changes\n * @return {?}\n */\n NgModel.prototype.ngOnChanges = function (changes) {\n this._checkForErrors();\n if (!this._registered)\n this._setUpControl();\n if ('isDisabled' in changes) {\n this._updateDisabled(changes);\n }\n if (isPropertyUpdated(changes, this.viewModel)) {\n this._updateValue(this.model);\n this.viewModel = this.model;\n }\n };\n /**\n * @return {?}\n */\n NgModel.prototype.ngOnDestroy = function () { this.formDirective && this.formDirective.removeControl(this); };\n Object.defineProperty(NgModel.prototype, \"control\", {\n /**\n * @return {?}\n */\n get: function () { return this._control; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(NgModel.prototype, \"path\", {\n /**\n * @return {?}\n */\n get: function () {\n return this._parent ? controlPath(this.name, this._parent) : [this.name];\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(NgModel.prototype, \"formDirective\", {\n /**\n * @return {?}\n */\n get: function () { return this._parent ? this._parent.formDirective : null; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(NgModel.prototype, \"validator\", {\n /**\n * @return {?}\n */\n get: function () { return composeValidators(this._rawValidators); },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(NgModel.prototype, \"asyncValidator\", {\n /**\n * @return {?}\n */\n get: function () {\n return composeAsyncValidators(this._rawAsyncValidators);\n },\n enumerable: true,\n configurable: true\n });\n /**\n * @param {?} newValue\n * @return {?}\n */\n NgModel.prototype.viewToModelUpdate = function (newValue) {\n this.viewModel = newValue;\n this.update.emit(newValue);\n };\n /**\n * @return {?}\n */\n NgModel.prototype._setUpControl = function () {\n this._isStandalone() ? this._setUpStandalone() :\n this.formDirective.addControl(this);\n this._registered = true;\n };\n /**\n * @return {?}\n */\n NgModel.prototype._isStandalone = function () {\n return !this._parent || (this.options && this.options.standalone);\n };\n /**\n * @return {?}\n */\n NgModel.prototype._setUpStandalone = function () {\n setUpControl(this._control, this);\n this._control.updateValueAndValidity({ emitEvent: false });\n };\n /**\n * @return {?}\n */\n NgModel.prototype._checkForErrors = function () {\n if (!this._isStandalone()) {\n this._checkParentType();\n }\n this._checkName();\n };\n /**\n * @return {?}\n */\n NgModel.prototype._checkParentType = function () {\n if (!(this._parent instanceof NgModelGroup) &&\n this._parent instanceof AbstractFormGroupDirective) {\n TemplateDrivenErrors.formGroupNameException();\n }\n else if (!(this._parent instanceof NgModelGroup) && !(this._parent instanceof NgForm)) {\n TemplateDrivenErrors.modelParentException();\n }\n };\n /**\n * @return {?}\n */\n NgModel.prototype._checkName = function () {\n if (this.options && this.options.name)\n this.name = this.options.name;\n if (!this._isStandalone() && !this.name) {\n TemplateDrivenErrors.missingNameException();\n }\n };\n /**\n * @param {?} value\n * @return {?}\n */\n NgModel.prototype._updateValue = function (value) {\n var _this = this;\n resolvedPromise$1.then(function () { _this.control.setValue(value, { emitViewToModelChange: false }); });\n };\n /**\n * @param {?} changes\n * @return {?}\n */\n NgModel.prototype._updateDisabled = function (changes) {\n var _this = this;\n var /** @type {?} */ disabledValue = changes['isDisabled'].currentValue;\n var /** @type {?} */ isDisabled = disabledValue === '' || (disabledValue && disabledValue !== 'false');\n resolvedPromise$1.then(function () {\n if (isDisabled && !_this.control.disabled) {\n _this.control.disable();\n }\n else if (!isDisabled && _this.control.disabled) {\n _this.control.enable();\n }\n });\n };\n NgModel.decorators = [\n { type: _angular_core.Directive, args: [{\n selector: '[ngModel]:not([formControlName]):not([formControl])',\n providers: [formControlBinding],\n exportAs: 'ngModel'\n },] },\n ];\n /** @nocollapse */\n NgModel.ctorParameters = function () { return [\n { type: ControlContainer, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Host },] },\n { type: Array, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Self }, { type: _angular_core.Inject, args: [NG_VALIDATORS,] },] },\n { type: Array, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Self }, { type: _angular_core.Inject, args: [NG_ASYNC_VALIDATORS,] },] },\n { type: Array, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Self }, { type: _angular_core.Inject, args: [NG_VALUE_ACCESSOR,] },] },\n ]; };\n NgModel.propDecorators = {\n 'name': [{ type: _angular_core.Input },],\n 'isDisabled': [{ type: _angular_core.Input, args: ['disabled',] },],\n 'model': [{ type: _angular_core.Input, args: ['ngModel',] },],\n 'options': [{ type: _angular_core.Input, args: ['ngModelOptions',] },],\n 'update': [{ type: _angular_core.Output, args: ['ngModelChange',] },],\n };\n return NgModel;\n }(NgControl));\n\n var ReactiveErrors = (function () {\n function ReactiveErrors() {\n }\n /**\n * @return {?}\n */\n ReactiveErrors.controlParentException = function () {\n throw new Error(\"formControlName must be used with a parent formGroup directive. You'll want to add a formGroup\\n directive and pass it an existing FormGroup instance (you can create one in your class).\\n\\n Example:\\n\\n \" + Examples.formControlName);\n };\n /**\n * @return {?}\n */\n ReactiveErrors.ngModelGroupException = function () {\n throw new Error(\"formControlName cannot be used with an ngModelGroup parent. It is only compatible with parents\\n that also have a \\\"form\\\" prefix: formGroupName, formArrayName, or formGroup.\\n\\n Option 1: Update the parent to be formGroupName (reactive form strategy)\\n\\n \" + Examples.formGroupName + \"\\n\\n Option 2: Use ngModel instead of formControlName (template-driven strategy)\\n\\n \" + Examples.ngModelGroup);\n };\n /**\n * @return {?}\n */\n ReactiveErrors.missingFormException = function () {\n throw new Error(\"formGroup expects a FormGroup instance. Please pass one in.\\n\\n Example:\\n\\n \" + Examples.formControlName);\n };\n /**\n * @return {?}\n */\n ReactiveErrors.groupParentException = function () {\n throw new Error(\"formGroupName must be used with a parent formGroup directive. You'll want to add a formGroup\\n directive and pass it an existing FormGroup instance (you can create one in your class).\\n\\n Example:\\n\\n \" + Examples.formGroupName);\n };\n /**\n * @return {?}\n */\n ReactiveErrors.arrayParentException = function () {\n throw new Error(\"formArrayName must be used with a parent formGroup directive. You'll want to add a formGroup\\n directive and pass it an existing FormGroup instance (you can create one in your class).\\n\\n Example:\\n\\n \" + Examples.formArrayName);\n };\n /**\n * @return {?}\n */\n ReactiveErrors.disabledAttrWarning = function () {\n console.warn(\"\\n It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true\\n when you set up this control in your component class, the disabled attribute will actually be set in the DOM for\\n you. We recommend using this approach to avoid 'changed after checked' errors.\\n \\n Example: \\n form = new FormGroup({\\n first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),\\n last: new FormControl('Drew', Validators.required)\\n });\\n \");\n };\n return ReactiveErrors;\n }());\n\n /**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n var __extends$9 = (this && this.__extends) || function (d, b) {\n for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n var /** @type {?} */ formControlBinding$1 = {\n provide: NgControl,\n useExisting: _angular_core.forwardRef(function () { return FormControlDirective; })\n };\n /**\n * *\n * In other words, this directive ensures that any values written to the {@link FormControl}\n * instance programmatically will be written to the DOM element (model -> view). Conversely,\n * any values written to the DOM element through user input will be reflected in the\n * {@link FormControl} instance (view -> model).\n * *\n * *\n * Use this directive if you'd like to create and manage a {@link FormControl} instance directly.\n * Simply create a {@link FormControl}, save it to your component class, and pass it into the\n * {@link FormControlDirective}.\n * *\n * This directive is designed to be used as a standalone control. Unlike {@link FormControlName},\n * it does not require that your {@link FormControl} instance be part of any parent\n * {@link FormGroup}, and it won't be registered to any {@link FormGroupDirective} that\n * exists above it.\n * *\n * **Get the value**: the `value` property is always synced and available on the\n * {@link FormControl} instance. See a full list of available properties in\n * {@link AbstractControl}.\n * *\n * **Set the value**: You can pass in an initial value when instantiating the {@link FormControl},\n * or you can set it programmatically later using {@link AbstractControl.setValue} or\n * {@link AbstractControl.patchValue}.\n * *\n * **Listen to value**: If you want to listen to changes in the value of the control, you can\n * subscribe to the {@link AbstractControl.valueChanges} event. You can also listen to\n * {@link AbstractControl.statusChanges} to be notified when the validation status is\n * re-calculated.\n * *\n * ### Example\n * *\n * {@example forms/ts/simpleFormControl/simple_form_control_example.ts region='Component'}\n * *\n * * **npm package**: `@angular/forms`\n * *\n * * **NgModule**: `ReactiveFormsModule`\n * *\n * @stable\n */\n var FormControlDirective = (function (_super) {\n __extends$9(FormControlDirective, _super);\n /**\n * @param {?} validators\n * @param {?} asyncValidators\n * @param {?} valueAccessors\n */\n function FormControlDirective(validators, asyncValidators, valueAccessors) {\n _super.call(this);\n this.update = new EventEmitter();\n this._rawValidators = validators || [];\n this._rawAsyncValidators = asyncValidators || [];\n this.valueAccessor = selectValueAccessor(this, valueAccessors);\n }\n Object.defineProperty(FormControlDirective.prototype, \"isDisabled\", {\n /**\n * @param {?} isDisabled\n * @return {?}\n */\n set: function (isDisabled) { ReactiveErrors.disabledAttrWarning(); },\n enumerable: true,\n configurable: true\n });\n /**\n * @param {?} changes\n * @return {?}\n */\n FormControlDirective.prototype.ngOnChanges = function (changes) {\n if (this._isControlChanged(changes)) {\n setUpControl(this.form, this);\n if (this.control.disabled && this.valueAccessor.setDisabledState) {\n this.valueAccessor.setDisabledState(true);\n }\n this.form.updateValueAndValidity({ emitEvent: false });\n }\n if (isPropertyUpdated(changes, this.viewModel)) {\n this.form.setValue(this.model);\n this.viewModel = this.model;\n }\n };\n Object.defineProperty(FormControlDirective.prototype, \"path\", {\n /**\n * @return {?}\n */\n get: function () { return []; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(FormControlDirective.prototype, \"validator\", {\n /**\n * @return {?}\n */\n get: function () { return composeValidators(this._rawValidators); },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(FormControlDirective.prototype, \"asyncValidator\", {\n /**\n * @return {?}\n */\n get: function () {\n return composeAsyncValidators(this._rawAsyncValidators);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(FormControlDirective.prototype, \"control\", {\n /**\n * @return {?}\n */\n get: function () { return this.form; },\n enumerable: true,\n configurable: true\n });\n /**\n * @param {?} newValue\n * @return {?}\n */\n FormControlDirective.prototype.viewToModelUpdate = function (newValue) {\n this.viewModel = newValue;\n this.update.emit(newValue);\n };\n /**\n * @param {?} changes\n * @return {?}\n */\n FormControlDirective.prototype._isControlChanged = function (changes) {\n return changes.hasOwnProperty('form');\n };\n FormControlDirective.decorators = [\n { type: _angular_core.Directive, args: [{ selector: '[formControl]', providers: [formControlBinding$1], exportAs: 'ngForm' },] },\n ];\n /** @nocollapse */\n FormControlDirective.ctorParameters = function () { return [\n { type: Array, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Self }, { type: _angular_core.Inject, args: [NG_VALIDATORS,] },] },\n { type: Array, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Self }, { type: _angular_core.Inject, args: [NG_ASYNC_VALIDATORS,] },] },\n { type: Array, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Self }, { type: _angular_core.Inject, args: [NG_VALUE_ACCESSOR,] },] },\n ]; };\n FormControlDirective.propDecorators = {\n 'form': [{ type: _angular_core.Input, args: ['formControl',] },],\n 'model': [{ type: _angular_core.Input, args: ['ngModel',] },],\n 'update': [{ type: _angular_core.Output, args: ['ngModelChange',] },],\n 'isDisabled': [{ type: _angular_core.Input, args: ['disabled',] },],\n };\n return FormControlDirective;\n }(NgControl));\n\n /**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n var __extends$11 = (this && this.__extends) || function (d, b) {\n for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n var /** @type {?} */ formDirectiveProvider$1 = {\n provide: ControlContainer,\n useExisting: _angular_core.forwardRef(function () { return FormGroupDirective; })\n };\n /**\n * *\n * *\n * This directive accepts an existing {@link FormGroup} instance. It will then use this\n * {@link FormGroup} instance to match any child {@link FormControl}, {@link FormGroup},\n * and {@link FormArray} instances to child {@link FormControlName}, {@link FormGroupName},\n * and {@link FormArrayName} directives.\n * *\n * **Set value**: You can set the form's initial value when instantiating the\n * {@link FormGroup}, or you can set it programmatically later using the {@link FormGroup}'s\n * {@link AbstractControl.setValue} or {@link AbstractControl.patchValue} methods.\n * *\n * **Listen to value**: If you want to listen to changes in the value of the form, you can subscribe\n * to the {@link FormGroup}'s {@link AbstractControl.valueChanges} event. You can also listen to\n * its {@link AbstractControl.statusChanges} event to be notified when the validation status is\n * re-calculated.\n * *\n * Furthermore, you can listen to the directive's `ngSubmit` event to be notified when the user has\n * triggered a form submission. The `ngSubmit` event will be emitted with the original form\n * submission event.\n * *\n * ### Example\n * *\n * In this example, we create form controls for first name and last name.\n * *\n * {@example forms/ts/simpleFormGroup/simple_form_group_example.ts region='Component'}\n * *\n * **npm package**: `@angular/forms`\n * *\n * **NgModule**: {@link ReactiveFormsModule}\n * *\n * @stable\n */\n var FormGroupDirective = (function (_super) {\n __extends$11(FormGroupDirective, _super);\n /**\n * @param {?} _validators\n * @param {?} _asyncValidators\n */\n function FormGroupDirective(_validators, _asyncValidators) {\n _super.call(this);\n this._validators = _validators;\n this._asyncValidators = _asyncValidators;\n this._submitted = false;\n this.directives = [];\n this.form = null;\n this.ngSubmit = new EventEmitter();\n }\n /**\n * @param {?} changes\n * @return {?}\n */\n FormGroupDirective.prototype.ngOnChanges = function (changes) {\n this._checkFormPresent();\n if (changes.hasOwnProperty('form')) {\n this._updateValidators();\n this._updateDomValue();\n this._updateRegistrations();\n }\n };\n Object.defineProperty(FormGroupDirective.prototype, \"submitted\", {\n /**\n * @return {?}\n */\n get: function () { return this._submitted; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(FormGroupDirective.prototype, \"formDirective\", {\n /**\n * @return {?}\n */\n get: function () { return this; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(FormGroupDirective.prototype, \"control\", {\n /**\n * @return {?}\n */\n get: function () { return this.form; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(FormGroupDirective.prototype, \"path\", {\n /**\n * @return {?}\n */\n get: function () { return []; },\n enumerable: true,\n configurable: true\n });\n /**\n * @param {?} dir\n * @return {?}\n */\n FormGroupDirective.prototype.addControl = function (dir) {\n var /** @type {?} */ ctrl = this.form.get(dir.path);\n setUpControl(ctrl, dir);\n ctrl.updateValueAndValidity({ emitEvent: false });\n this.directives.push(dir);\n return ctrl;\n };\n /**\n * @param {?} dir\n * @return {?}\n */\n FormGroupDirective.prototype.getControl = function (dir) { return (this.form.get(dir.path)); };\n /**\n * @param {?} dir\n * @return {?}\n */\n FormGroupDirective.prototype.removeControl = function (dir) { ListWrapper.remove(this.directives, dir); };\n /**\n * @param {?} dir\n * @return {?}\n */\n FormGroupDirective.prototype.addFormGroup = function (dir) {\n var /** @type {?} */ ctrl = this.form.get(dir.path);\n setUpFormContainer(ctrl, dir);\n ctrl.updateValueAndValidity({ emitEvent: false });\n };\n /**\n * @param {?} dir\n * @return {?}\n */\n FormGroupDirective.prototype.removeFormGroup = function (dir) { };\n /**\n * @param {?} dir\n * @return {?}\n */\n FormGroupDirective.prototype.getFormGroup = function (dir) { return (this.form.get(dir.path)); };\n /**\n * @param {?} dir\n * @return {?}\n */\n FormGroupDirective.prototype.addFormArray = function (dir) {\n var /** @type {?} */ ctrl = this.form.get(dir.path);\n setUpFormContainer(ctrl, dir);\n ctrl.updateValueAndValidity({ emitEvent: false });\n };\n /**\n * @param {?} dir\n * @return {?}\n */\n FormGroupDirective.prototype.removeFormArray = function (dir) { };\n /**\n * @param {?} dir\n * @return {?}\n */\n FormGroupDirective.prototype.getFormArray = function (dir) { return (this.form.get(dir.path)); };\n /**\n * @param {?} dir\n * @param {?} value\n * @return {?}\n */\n FormGroupDirective.prototype.updateModel = function (dir, value) {\n var /** @type {?} */ ctrl = (this.form.get(dir.path));\n ctrl.setValue(value);\n };\n /**\n * @param {?} $event\n * @return {?}\n */\n FormGroupDirective.prototype.onSubmit = function ($event) {\n this._submitted = true;\n this.ngSubmit.emit($event);\n return false;\n };\n /**\n * @return {?}\n */\n FormGroupDirective.prototype.onReset = function () { this.resetForm(); };\n /**\n * @param {?=} value\n * @return {?}\n */\n FormGroupDirective.prototype.resetForm = function (value) {\n if (value === void 0) { value = undefined; }\n this.form.reset(value);\n this._submitted = false;\n };\n /**\n * @return {?}\n */\n FormGroupDirective.prototype._updateDomValue = function () {\n var _this = this;\n this.directives.forEach(function (dir) {\n var /** @type {?} */ newCtrl = _this.form.get(dir.path);\n if (dir._control !== newCtrl) {\n cleanUpControl(dir._control, dir);\n if (newCtrl)\n setUpControl(newCtrl, dir);\n dir._control = newCtrl;\n }\n });\n this.form._updateTreeValidity({ emitEvent: false });\n };\n /**\n * @return {?}\n */\n FormGroupDirective.prototype._updateRegistrations = function () {\n var _this = this;\n this.form._registerOnCollectionChange(function () { return _this._updateDomValue(); });\n if (this._oldForm)\n this._oldForm._registerOnCollectionChange(function () { });\n this._oldForm = this.form;\n };\n /**\n * @return {?}\n */\n FormGroupDirective.prototype._updateValidators = function () {\n var /** @type {?} */ sync = composeValidators(this._validators);\n this.form.validator = Validators.compose([this.form.validator, sync]);\n var /** @type {?} */ async = composeAsyncValidators(this._asyncValidators);\n this.form.asyncValidator = Validators.composeAsync([this.form.asyncValidator, async]);\n };\n /**\n * @return {?}\n */\n FormGroupDirective.prototype._checkFormPresent = function () {\n if (!this.form) {\n ReactiveErrors.missingFormException();\n }\n };\n FormGroupDirective.decorators = [\n { type: _angular_core.Directive, args: [{\n selector: '[formGroup]',\n providers: [formDirectiveProvider$1],\n host: { '(submit)': 'onSubmit($event)', '(reset)': 'onReset()' },\n exportAs: 'ngForm'\n },] },\n ];\n /** @nocollapse */\n FormGroupDirective.ctorParameters = function () { return [\n { type: Array, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Self }, { type: _angular_core.Inject, args: [NG_VALIDATORS,] },] },\n { type: Array, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Self }, { type: _angular_core.Inject, args: [NG_ASYNC_VALIDATORS,] },] },\n ]; };\n FormGroupDirective.propDecorators = {\n 'form': [{ type: _angular_core.Input, args: ['formGroup',] },],\n 'ngSubmit': [{ type: _angular_core.Output },],\n };\n return FormGroupDirective;\n }(ControlContainer));\n\n /**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n var __extends$12 = (this && this.__extends) || function (d, b) {\n for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n var /** @type {?} */ formGroupNameProvider = {\n provide: ControlContainer,\n useExisting: _angular_core.forwardRef(function () { return FormGroupName; })\n };\n /**\n * *\n * *\n * This directive can only be used with a parent {@link FormGroupDirective} (selector:\n * `[formGroup]`).\n * *\n * It accepts the string name of the nested {@link FormGroup} you want to link, and\n * will look for a {@link FormGroup} registered with that name in the parent\n * {@link FormGroup} instance you passed into {@link FormGroupDirective}.\n * *\n * Nested form groups can come in handy when you want to validate a sub-group of a\n * form separately from the rest or when you'd like to group the values of certain\n * controls into their own nested object.\n * *\n * **Access the group**: You can access the associated {@link FormGroup} using the\n * {@link AbstractControl.get} method. Ex: `this.form.get('name')`.\n * *\n * You can also access individual controls within the group using dot syntax.\n * Ex: `this.form.get('name.first')`\n * *\n * **Get the value**: the `value` property is always synced and available on the\n * {@link FormGroup}. See a full list of available properties in {@link AbstractControl}.\n * *\n * **Set the value**: You can set an initial value for each child control when instantiating\n * the {@link FormGroup}, or you can set it programmatically later using\n * {@link AbstractControl.setValue} or {@link AbstractControl.patchValue}.\n * *\n * **Listen to value**: If you want to listen to changes in the value of the group, you can\n * subscribe to the {@link AbstractControl.valueChanges} event. You can also listen to\n * {@link AbstractControl.statusChanges} to be notified when the validation status is\n * re-calculated.\n * *\n * ### Example\n * *\n * {@example forms/ts/nestedFormGroup/nested_form_group_example.ts region='Component'}\n * *\n * * **npm package**: `@angular/forms`\n * *\n * * **NgModule**: `ReactiveFormsModule`\n * *\n */\n var FormGroupName = (function (_super) {\n __extends$12(FormGroupName, _super);\n /**\n * @param {?} parent\n * @param {?} validators\n * @param {?} asyncValidators\n */\n function FormGroupName(parent, validators, asyncValidators) {\n _super.call(this);\n this._parent = parent;\n this._validators = validators;\n this._asyncValidators = asyncValidators;\n }\n /**\n * @return {?}\n */\n FormGroupName.prototype._checkParentType = function () {\n if (_hasInvalidParent(this._parent)) {\n ReactiveErrors.groupParentException();\n }\n };\n FormGroupName.decorators = [\n { type: _angular_core.Directive, args: [{ selector: '[formGroupName]', providers: [formGroupNameProvider] },] },\n ];\n /** @nocollapse */\n FormGroupName.ctorParameters = function () { return [\n { type: ControlContainer, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Host }, { type: _angular_core.SkipSelf },] },\n { type: Array, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Self }, { type: _angular_core.Inject, args: [NG_VALIDATORS,] },] },\n { type: Array, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Self }, { type: _angular_core.Inject, args: [NG_ASYNC_VALIDATORS,] },] },\n ]; };\n FormGroupName.propDecorators = {\n 'name': [{ type: _angular_core.Input, args: ['formGroupName',] },],\n };\n return FormGroupName;\n }(AbstractFormGroupDirective));\n var /** @type {?} */ formArrayNameProvider = {\n provide: ControlContainer,\n useExisting: _angular_core.forwardRef(function () { return FormArrayName; })\n };\n /**\n * *\n * *\n * This directive is designed to be used with a parent {@link FormGroupDirective} (selector:\n * `[formGroup]`).\n * *\n * It accepts the string name of the nested {@link FormArray} you want to link, and\n * will look for a {@link FormArray} registered with that name in the parent\n * {@link FormGroup} instance you passed into {@link FormGroupDirective}.\n * *\n * Nested form arrays can come in handy when you have a group of form controls but\n * you're not sure how many there will be. Form arrays allow you to create new\n * form controls dynamically.\n * *\n * **Access the array**: You can access the associated {@link FormArray} using the\n * {@link AbstractControl.get} method on the parent {@link FormGroup}.\n * Ex: `this.form.get('cities')`.\n * *\n * **Get the value**: the `value` property is always synced and available on the\n * {@link FormArray}. See a full list of available properties in {@link AbstractControl}.\n * *\n * **Set the value**: You can set an initial value for each child control when instantiating\n * the {@link FormArray}, or you can set the value programmatically later using the\n * {@link FormArray}'s {@link AbstractControl.setValue} or {@link AbstractControl.patchValue}\n * methods.\n * *\n * **Listen to value**: If you want to listen to changes in the value of the array, you can\n * subscribe to the {@link FormArray}'s {@link AbstractControl.valueChanges} event. You can also\n * listen to its {@link AbstractControl.statusChanges} event to be notified when the validation\n * status is re-calculated.\n * *\n * **Add new controls**: You can add new controls to the {@link FormArray} dynamically by\n * calling its {@link FormArray.push} method.\n * Ex: `this.form.get('cities').push(new FormControl());`\n * *\n * ### Example\n * *\n * {@example forms/ts/nestedFormArray/nested_form_array_example.ts region='Component'}\n * *\n * * **npm package**: `@angular/forms`\n * *\n * * **NgModule**: `ReactiveFormsModule`\n * *\n */\n var FormArrayName = (function (_super) {\n __extends$12(FormArrayName, _super);\n /**\n * @param {?} parent\n * @param {?} validators\n * @param {?} asyncValidators\n */\n function FormArrayName(parent, validators, asyncValidators) {\n _super.call(this);\n this._parent = parent;\n this._validators = validators;\n this._asyncValidators = asyncValidators;\n }\n /**\n * @return {?}\n */\n FormArrayName.prototype.ngOnInit = function () {\n this._checkParentType();\n this.formDirective.addFormArray(this);\n };\n /**\n * @return {?}\n */\n FormArrayName.prototype.ngOnDestroy = function () {\n if (this.formDirective) {\n this.formDirective.removeFormArray(this);\n }\n };\n Object.defineProperty(FormArrayName.prototype, \"control\", {\n /**\n * @return {?}\n */\n get: function () { return this.formDirective.getFormArray(this); },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(FormArrayName.prototype, \"formDirective\", {\n /**\n * @return {?}\n */\n get: function () {\n return this._parent ? (this._parent.formDirective) : null;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(FormArrayName.prototype, \"path\", {\n /**\n * @return {?}\n */\n get: function () { return controlPath(this.name, this._parent); },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(FormArrayName.prototype, \"validator\", {\n /**\n * @return {?}\n */\n get: function () { return composeValidators(this._validators); },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(FormArrayName.prototype, \"asyncValidator\", {\n /**\n * @return {?}\n */\n get: function () { return composeAsyncValidators(this._asyncValidators); },\n enumerable: true,\n configurable: true\n });\n /**\n * @return {?}\n */\n FormArrayName.prototype._checkParentType = function () {\n if (_hasInvalidParent(this._parent)) {\n ReactiveErrors.arrayParentException();\n }\n };\n FormArrayName.decorators = [\n { type: _angular_core.Directive, args: [{ selector: '[formArrayName]', providers: [formArrayNameProvider] },] },\n ];\n /** @nocollapse */\n FormArrayName.ctorParameters = function () { return [\n { type: ControlContainer, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Host }, { type: _angular_core.SkipSelf },] },\n { type: Array, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Self }, { type: _angular_core.Inject, args: [NG_VALIDATORS,] },] },\n { type: Array, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Self }, { type: _angular_core.Inject, args: [NG_ASYNC_VALIDATORS,] },] },\n ]; };\n FormArrayName.propDecorators = {\n 'name': [{ type: _angular_core.Input, args: ['formArrayName',] },],\n };\n return FormArrayName;\n }(ControlContainer));\n /**\n * @param {?} parent\n * @return {?}\n */\n function _hasInvalidParent(parent) {\n return !(parent instanceof FormGroupName) && !(parent instanceof FormGroupDirective) &&\n !(parent instanceof FormArrayName);\n }\n\n /**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n var __extends$10 = (this && this.__extends) || function (d, b) {\n for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n var /** @type {?} */ controlNameBinding = {\n provide: NgControl,\n useExisting: _angular_core.forwardRef(function () { return FormControlName; })\n };\n /**\n * element by name.\n * *\n * In other words, this directive ensures that any values written to the {@link FormControl}\n * instance programmatically will be written to the DOM element (model -> view). Conversely,\n * any values written to the DOM element through user input will be reflected in the\n * {@link FormControl} instance (view -> model).\n * *\n * *\n * This directive is designed to be used with a parent {@link FormGroupDirective} (selector:\n * `[formGroup]`).\n * *\n * It accepts the string name of the {@link FormControl} instance you want to\n * link, and will look for a {@link FormControl} registered with that name in the\n * closest {@link FormGroup} or {@link FormArray} above it.\n * *\n * **Access the control**: You can access the {@link FormControl} associated with\n * this directive by using the {@link AbstractControl.get} method.\n * Ex: `this.form.get('first');`\n * *\n * **Get value**: the `value` property is always synced and available on the {@link FormControl}.\n * See a full list of available properties in {@link AbstractControl}.\n * *\n * **Set value**: You can set an initial value for the control when instantiating the\n * {@link FormControl}, or you can set it programmatically later using\n * {@link AbstractControl.setValue} or {@link AbstractControl.patchValue}.\n * *\n * **Listen to value**: If you want to listen to changes in the value of the control, you can\n * subscribe to the {@link AbstractControl.valueChanges} event. You can also listen to\n * {@link AbstractControl.statusChanges} to be notified when the validation status is\n * re-calculated.\n * *\n * ### Example\n * *\n * In this example, we create form controls for first name and last name.\n * *\n * {@example forms/ts/simpleFormGroup/simple_form_group_example.ts region='Component'}\n * *\n * To see `formControlName` examples with different form control types, see:\n * *\n * * Radio buttons: {@link RadioControlValueAccessor}\n * * Selects: {@link SelectControlValueAccessor}\n * *\n * **npm package**: `@angular/forms`\n * *\n * **NgModule**: {@link ReactiveFormsModule}\n * *\n * @stable\n */\n var FormControlName = (function (_super) {\n __extends$10(FormControlName, _super);\n /**\n * @param {?} parent\n * @param {?} validators\n * @param {?} asyncValidators\n * @param {?} valueAccessors\n */\n function FormControlName(parent, validators, asyncValidators, valueAccessors) {\n _super.call(this);\n this._added = false;\n this.update = new EventEmitter();\n this._parent = parent;\n this._rawValidators = validators || [];\n this._rawAsyncValidators = asyncValidators || [];\n this.valueAccessor = selectValueAccessor(this, valueAccessors);\n }\n Object.defineProperty(FormControlName.prototype, \"isDisabled\", {\n /**\n * @param {?} isDisabled\n * @return {?}\n */\n set: function (isDisabled) { ReactiveErrors.disabledAttrWarning(); },\n enumerable: true,\n configurable: true\n });\n /**\n * @param {?} changes\n * @return {?}\n */\n FormControlName.prototype.ngOnChanges = function (changes) {\n if (!this._added)\n this._setUpControl();\n if (isPropertyUpdated(changes, this.viewModel)) {\n this.viewModel = this.model;\n this.formDirective.updateModel(this, this.model);\n }\n };\n /**\n * @return {?}\n */\n FormControlName.prototype.ngOnDestroy = function () {\n if (this.formDirective) {\n this.formDirective.removeControl(this);\n }\n };\n /**\n * @param {?} newValue\n * @return {?}\n */\n FormControlName.prototype.viewToModelUpdate = function (newValue) {\n this.viewModel = newValue;\n this.update.emit(newValue);\n };\n Object.defineProperty(FormControlName.prototype, \"path\", {\n /**\n * @return {?}\n */\n get: function () { return controlPath(this.name, this._parent); },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(FormControlName.prototype, \"formDirective\", {\n /**\n * @return {?}\n */\n get: function () { return this._parent ? this._parent.formDirective : null; },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(FormControlName.prototype, \"validator\", {\n /**\n * @return {?}\n */\n get: function () { return composeValidators(this._rawValidators); },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(FormControlName.prototype, \"asyncValidator\", {\n /**\n * @return {?}\n */\n get: function () {\n return composeAsyncValidators(this._rawAsyncValidators);\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(FormControlName.prototype, \"control\", {\n /**\n * @return {?}\n */\n get: function () { return this._control; },\n enumerable: true,\n configurable: true\n });\n /**\n * @return {?}\n */\n FormControlName.prototype._checkParentType = function () {\n if (!(this._parent instanceof FormGroupName) &&\n this._parent instanceof AbstractFormGroupDirective) {\n ReactiveErrors.ngModelGroupException();\n }\n else if (!(this._parent instanceof FormGroupName) && !(this._parent instanceof FormGroupDirective) &&\n !(this._parent instanceof FormArrayName)) {\n ReactiveErrors.controlParentException();\n }\n };\n /**\n * @return {?}\n */\n FormControlName.prototype._setUpControl = function () {\n this._checkParentType();\n this._control = this.formDirective.addControl(this);\n if (this.control.disabled && this.valueAccessor.setDisabledState) {\n this.valueAccessor.setDisabledState(true);\n }\n this._added = true;\n };\n FormControlName.decorators = [\n { type: _angular_core.Directive, args: [{ selector: '[formControlName]', providers: [controlNameBinding] },] },\n ];\n /** @nocollapse */\n FormControlName.ctorParameters = function () { return [\n { type: ControlContainer, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Host }, { type: _angular_core.SkipSelf },] },\n { type: Array, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Self }, { type: _angular_core.Inject, args: [NG_VALIDATORS,] },] },\n { type: Array, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Self }, { type: _angular_core.Inject, args: [NG_ASYNC_VALIDATORS,] },] },\n { type: Array, decorators: [{ type: _angular_core.Optional }, { type: _angular_core.Self }, { type: _angular_core.Inject, args: [NG_VALUE_ACCESSOR,] },] },\n ]; };\n FormControlName.propDecorators = {\n 'name': [{ type: _angular_core.Input, args: ['formControlName',] },],\n 'model': [{ type: _angular_core.Input, args: ['ngModel',] },],\n 'update': [{ type: _angular_core.Output, args: ['ngModelChange',] },],\n 'isDisabled': [{ type: _angular_core.Input, args: ['disabled',] },],\n };\n return FormControlName;\n }(NgControl));\n\n var __extends$13 = (this && this.__extends) || function (d, b) {\n for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n var /** @type {?} */ REQUIRED_VALIDATOR = {\n provide: NG_VALIDATORS,\n useExisting: _angular_core.forwardRef(function () { return RequiredValidator; }),\n multi: true\n };\n var /** @type {?} */ CHECKBOX_REQUIRED_VALIDATOR = {\n provide: NG_VALIDATORS,\n useExisting: _angular_core.forwardRef(function () { return CheckboxRequiredValidator; }),\n multi: true\n };\n /**\n * A Directive that adds the `required` validator to any controls marked with the\n * `required` attribute, via the {@link NG_VALIDATORS} binding.\n * *\n * ### Example\n * *\n * ```\n * <input name=\"fullName\" ngModel required>\n * ```\n * *\n */\n var RequiredValidator = (function () {\n function RequiredValidator() {\n }\n Object.defineProperty(RequiredValidator.prototype, \"required\", {\n /**\n * @return {?}\n */\n get: function () { return this._required; },\n /**\n * @param {?} value\n * @return {?}\n */\n set: function (value) {\n this._required = value != null && value !== false && \"\" + value !== 'false';\n if (this._onChange)\n this._onChange();\n },\n enumerable: true,\n configurable: true\n });\n /**\n * @param {?} c\n * @return {?}\n */\n RequiredValidator.prototype.validate = function (c) {\n return this.required ? Validators.required(c) : null;\n };\n /**\n * @param {?} fn\n * @return {?}\n */\n RequiredValidator.prototype.registerOnValidatorChange = function (fn) { this._onChange = fn; };\n RequiredValidator.decorators = [\n { type: _angular_core.Directive, args: [{\n selector: ':not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]',\n providers: [REQUIRED_VALIDATOR],\n host: { '[attr.required]': 'required ? \"\" : null' }\n },] },\n ];\n /** @nocollapse */\n RequiredValidator.ctorParameters = function () { return []; };\n RequiredValidator.propDecorators = {\n 'required': [{ type: _angular_core.Input },],\n };\n return RequiredValidator;\n }());\n /**\n * A Directive that adds the `required` validator to checkbox controls marked with the\n * `required` attribute, via the {@link NG_VALIDATORS} binding.\n * *\n * ### Example\n * *\n * ```\n * <input type=\"checkbox\" name=\"active\" ngModel required>\n * ```\n * *\n */\n var CheckboxRequiredValidator = (function (_super) {\n __extends$13(CheckboxRequiredValidator, _super);\n function CheckboxRequiredValidator() {\n _super.apply(this, arguments);\n }\n /**\n * @param {?} c\n * @return {?}\n */\n CheckboxRequiredValidator.prototype.validate = function (c) {\n return this.required ? Validators.requiredTrue(c) : null;\n };\n CheckboxRequiredValidator.decorators = [\n { type: _angular_core.Directive, args: [{\n selector: 'input[type=checkbox][required][formControlName],input[type=checkbox][required][formControl],input[type=checkbox][required][ngModel]',\n providers: [CHECKBOX_REQUIRED_VALIDATOR],\n host: { '[attr.required]': 'required ? \"\" : null' }\n },] },\n ];\n /** @nocollapse */\n CheckboxRequiredValidator.ctorParameters = function () { return []; };\n return CheckboxRequiredValidator;\n }(RequiredValidator));\n /**\n * Provider which adds {@link MinLengthValidator} to {@link NG_VALIDATORS}.\n *\n * ## Example:\n *\n * {@example common/forms/ts/validators/validators.ts region='min'}\n */\n var /** @type {?} */ MIN_LENGTH_VALIDATOR = {\n provide: NG_VALIDATORS,\n useExisting: _angular_core.forwardRef(function () { return MinLengthValidator; }),\n multi: true\n };\n /**\n * A directive which installs the {@link MinLengthValidator} for any `formControlName`,\n * `formControl`, or control with `ngModel` that also has a `minlength` attribute.\n * *\n */\n var MinLengthValidator = (function () {\n function MinLengthValidator() {\n }\n /**\n * @param {?} changes\n * @return {?}\n */\n MinLengthValidator.prototype.ngOnChanges = function (changes) {\n if ('minlength' in changes) {\n this._createValidator();\n if (this._onChange)\n this._onChange();\n }\n };\n /**\n * @param {?} c\n * @return {?}\n */\n MinLengthValidator.prototype.validate = function (c) {\n return this.minlength == null ? null : this._validator(c);\n };\n /**\n * @param {?} fn\n * @return {?}\n */\n MinLengthValidator.prototype.registerOnValidatorChange = function (fn) { this._onChange = fn; };\n /**\n * @return {?}\n */\n MinLengthValidator.prototype._createValidator = function () {\n this._validator = Validators.minLength(parseInt(this.minlength, 10));\n };\n MinLengthValidator.decorators = [\n { type: _angular_core.Directive, args: [{\n selector: '[minlength][formControlName],[minlength][formControl],[minlength][ngModel]',\n providers: [MIN_LENGTH_VALIDATOR],\n host: { '[attr.minlength]': 'minlength ? minlength : null' }\n },] },\n ];\n /** @nocollapse */\n MinLengthValidator.ctorParameters = function () { return []; };\n MinLengthValidator.propDecorators = {\n 'minlength': [{ type: _angular_core.Input },],\n };\n return MinLengthValidator;\n }());\n /**\n * Provider which adds {@link MaxLengthValidator} to {@link NG_VALIDATORS}.\n *\n * ## Example:\n *\n * {@example common/forms/ts/validators/validators.ts region='max'}\n */\n var /** @type {?} */ MAX_LENGTH_VALIDATOR = {\n provide: NG_VALIDATORS,\n useExisting: _angular_core.forwardRef(function () { return MaxLengthValidator; }),\n multi: true\n };\n /**\n * A directive which installs the {@link MaxLengthValidator} for any `formControlName,\n * `formControl`,\n * or control with `ngModel` that also has a `maxlength` attribute.\n * *\n */\n var MaxLengthValidator = (function () {\n function MaxLengthValidator() {\n }\n /**\n * @param {?} changes\n * @return {?}\n */\n MaxLengthValidator.prototype.ngOnChanges = function (changes) {\n if ('maxlength' in changes) {\n this._createValidator();\n if (this._onChange)\n this._onChange();\n }\n };\n /**\n * @param {?} c\n * @return {?}\n */\n MaxLengthValidator.prototype.validate = function (c) {\n return this.maxlength != null ? this._validator(c) : null;\n };\n /**\n * @param {?} fn\n * @return {?}\n */\n MaxLengthValidator.prototype.registerOnValidatorChange = function (fn) { this._onChange = fn; };\n /**\n * @return {?}\n */\n MaxLengthValidator.prototype._createValidator = function () {\n this._validator = Validators.maxLength(parseInt(this.maxlength, 10));\n };\n MaxLengthValidator.decorators = [\n { type: _angular_core.Directive, args: [{\n selector: '[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]',\n providers: [MAX_LENGTH_VALIDATOR],\n host: { '[attr.maxlength]': 'maxlength ? maxlength : null' }\n },] },\n ];\n /** @nocollapse */\n MaxLengthValidator.ctorParameters = function () { return []; };\n MaxLengthValidator.propDecorators = {\n 'maxlength': [{ type: _angular_core.Input },],\n };\n return MaxLengthValidator;\n }());\n var /** @type {?} */ PATTERN_VALIDATOR = {\n provide: NG_VALIDATORS,\n useExisting: _angular_core.forwardRef(function () { return PatternValidator; }),\n multi: true\n };\n /**\n * A Directive that adds the `pattern` validator to any controls marked with the\n * `pattern` attribute, via the {@link NG_VALIDATORS} binding. Uses attribute value\n * as the regex to validate Control value against. Follows pattern attribute\n * semantics; i.e. regex must match entire Control value.\n * *\n * ### Example\n * *\n * ```\n * <input [name]=\"fullName\" pattern=\"[a-zA-Z ]*\" ngModel>\n * ```\n */\n var PatternValidator = (function () {\n function PatternValidator() {\n }\n /**\n * @param {?} changes\n * @return {?}\n */\n PatternValidator.prototype.ngOnChanges = function (changes) {\n if ('pattern' in changes) {\n this._createValidator();\n if (this._onChange)\n this._onChange();\n }\n };\n /**\n * @param {?} c\n * @return {?}\n */\n PatternValidator.prototype.validate = function (c) { return this._validator(c); };\n /**\n * @param {?} fn\n * @return {?}\n */\n PatternValidator.prototype.registerOnValidatorChange = function (fn) { this._onChange = fn; };\n /**\n * @return {?}\n */\n PatternValidator.prototype._createValidator = function () { this._validator = Validators.pattern(this.pattern); };\n PatternValidator.decorators = [\n { type: _angular_core.Directive, args: [{\n selector: '[pattern][formControlName],[pattern][formControl],[pattern][ngModel]',\n providers: [PATTERN_VALIDATOR],\n host: { '[attr.pattern]': 'pattern ? pattern : null' }\n },] },\n ];\n /** @nocollapse */\n PatternValidator.ctorParameters = function () { return []; };\n PatternValidator.propDecorators = {\n 'pattern': [{ type: _angular_core.Input },],\n };\n return PatternValidator;\n }());\n\n /**\n * *\n * It is essentially syntactic sugar that shortens the `new FormGroup()`,\n * `new FormControl()`, and `new FormArray()` boilerplate that can build up in larger\n * forms.\n * *\n * *\n * To use, inject `FormBuilder` into your component class. You can then call its methods\n * directly.\n * *\n * {@example forms/ts/formBuilder/form_builder_example.ts region='Component'}\n * *\n * * **npm package**: `@angular/forms`\n * *\n * * **NgModule**: {@link ReactiveFormsModule}\n * *\n */\n var FormBuilder = (function () {\n function FormBuilder() {\n }\n /**\n * Construct a new {@link FormGroup} with the given map of configuration.\n * Valid keys for the `extra` parameter map are `validator` and `asyncValidator`.\n * *\n * See the {@link FormGroup} constructor for more details.\n * @param {?} controlsConfig\n * @param {?=} extra\n * @return {?}\n */\n FormBuilder.prototype.group = function (controlsConfig, extra) {\n if (extra === void 0) { extra = null; }\n var /** @type {?} */ controls = this._reduceControls(controlsConfig);\n var /** @type {?} */ validator = isPresent(extra) ? extra['validator'] : null;\n var /** @type {?} */ asyncValidator = isPresent(extra) ? extra['asyncValidator'] : null;\n return new FormGroup(controls, validator, asyncValidator);\n };\n /**\n * Construct a new {@link FormControl} with the given `formState`,`validator`, and\n * `asyncValidator`.\n * *\n * `formState` can either be a standalone value for the form control or an object\n * that contains both a value and a disabled status.\n * *\n * @param {?} formState\n * @param {?=} validator\n * @param {?=} asyncValidator\n * @return {?}\n */\n FormBuilder.prototype.control = function (formState, validator, asyncValidator) {\n if (validator === void 0) { validator = null; }\n if (asyncValidator === void 0) { asyncValidator = null; }\n return new FormControl(formState, validator, asyncValidator);\n };\n /**\n * Construct a {@link FormArray} from the given `controlsConfig` array of\n * configuration, with the given optional `validator` and `asyncValidator`.\n * @param {?} controlsConfig\n * @param {?=} validator\n * @param {?=} asyncValidator\n * @return {?}\n */\n FormBuilder.prototype.array = function (controlsConfig, validator, asyncValidator) {\n var _this = this;\n if (validator === void 0) { validator = null; }\n if (asyncValidator === void 0) { asyncValidator = null; }\n var /** @type {?} */ controls = controlsConfig.map(function (c) { return _this._createControl(c); });\n return new FormArray(controls, validator, asyncValidator);\n };\n /**\n * @param {?} controlsConfig\n * @return {?}\n */\n FormBuilder.prototype._reduceControls = function (controlsConfig) {\n var _this = this;\n var /** @type {?} */ controls = {};\n Object.keys(controlsConfig).forEach(function (controlName) {\n controls[controlName] = _this._createControl(controlsConfig[controlName]);\n });\n return controls;\n };\n /**\n * @param {?} controlConfig\n * @return {?}\n */\n FormBuilder.prototype._createControl = function (controlConfig) {\n if (controlConfig instanceof FormControl || controlConfig instanceof FormGroup ||\n controlConfig instanceof FormArray) {\n return controlConfig;\n }\n else if (Array.isArray(controlConfig)) {\n var /** @type {?} */ value = controlConfig[0];\n var /** @type {?} */ validator = controlConfig.length > 1 ? controlConfig[1] : null;\n var /** @type {?} */ asyncValidator = controlConfig.length > 2 ? controlConfig[2] : null;\n return this.control(value, validator, asyncValidator);\n }\n else {\n return this.control(controlConfig);\n }\n };\n FormBuilder.decorators = [\n { type: _angular_core.Injectable },\n ];\n /** @nocollapse */\n FormBuilder.ctorParameters = function () { return []; };\n return FormBuilder;\n }());\n\n /**\n * @stable\n */\n var /** @type {?} */ VERSION = new _angular_core.Version('2.4.1');\n\n var /** @type {?} */ SHARED_FORM_DIRECTIVES = [\n NgSelectOption,\n NgSelectMultipleOption,\n DefaultValueAccessor,\n NumberValueAccessor,\n RangeValueAccessor,\n CheckboxControlValueAccessor,\n SelectControlValueAccessor,\n SelectMultipleControlValueAccessor,\n RadioControlValueAccessor,\n NgControlStatus,\n NgControlStatusGroup,\n RequiredValidator,\n MinLengthValidator,\n MaxLengthValidator,\n PatternValidator,\n CheckboxRequiredValidator,\n ];\n var /** @type {?} */ TEMPLATE_DRIVEN_DIRECTIVES = [NgModel, NgModelGroup, NgForm];\n var /** @type {?} */ REACTIVE_DRIVEN_DIRECTIVES = [FormControlDirective, FormGroupDirective, FormControlName, FormGroupName, FormArrayName];\n /**\n * Internal module used for sharing directives between FormsModule and ReactiveFormsModule\n */\n var InternalFormsSharedModule = (function () {\n function InternalFormsSharedModule() {\n }\n InternalFormsSharedModule.decorators = [\n { type: _angular_core.NgModule, args: [{\n declarations: SHARED_FORM_DIRECTIVES,\n exports: SHARED_FORM_DIRECTIVES,\n },] },\n ];\n /** @nocollapse */\n InternalFormsSharedModule.ctorParameters = function () { return []; };\n return InternalFormsSharedModule;\n }());\n\n /**\n * The ng module for forms.\n */\n var FormsModule = (function () {\n function FormsModule() {\n }\n FormsModule.decorators = [\n { type: _angular_core.NgModule, args: [{\n declarations: TEMPLATE_DRIVEN_DIRECTIVES,\n providers: [RadioControlRegistry],\n exports: [InternalFormsSharedModule, TEMPLATE_DRIVEN_DIRECTIVES]\n },] },\n ];\n /** @nocollapse */\n FormsModule.ctorParameters = function () { return []; };\n return FormsModule;\n }());\n /**\n * The ng module for reactive forms.\n */\n var ReactiveFormsModule = (function () {\n function ReactiveFormsModule() {\n }\n ReactiveFormsModule.decorators = [\n { type: _angular_core.NgModule, args: [{\n declarations: [REACTIVE_DRIVEN_DIRECTIVES],\n providers: [FormBuilder, RadioControlRegistry],\n exports: [InternalFormsSharedModule, REACTIVE_DRIVEN_DIRECTIVES]\n },] },\n ];\n /** @nocollapse */\n ReactiveFormsModule.ctorParameters = function () { return []; };\n return ReactiveFormsModule;\n }());\n\n exports.AbstractControlDirective = AbstractControlDirective;\n exports.AbstractFormGroupDirective = AbstractFormGroupDirective;\n exports.CheckboxControlValueAccessor = CheckboxControlValueAccessor;\n exports.ControlContainer = ControlContainer;\n exports.NG_VALUE_ACCESSOR = NG_VALUE_ACCESSOR;\n exports.DefaultValueAccessor = DefaultValueAccessor;\n exports.NgControl = NgControl;\n exports.NgControlStatus = NgControlStatus;\n exports.NgControlStatusGroup = NgControlStatusGroup;\n exports.NgForm = NgForm;\n exports.NgModel = NgModel;\n exports.NgModelGroup = NgModelGroup;\n exports.RadioControlValueAccessor = RadioControlValueAccessor;\n exports.FormControlDirective = FormControlDirective;\n exports.FormControlName = FormControlName;\n exports.FormGroupDirective = FormGroupDirective;\n exports.FormArrayName = FormArrayName;\n exports.FormGroupName = FormGroupName;\n exports.NgSelectOption = NgSelectOption;\n exports.SelectControlValueAccessor = SelectControlValueAccessor;\n exports.SelectMultipleControlValueAccessor = SelectMultipleControlValueAccessor;\n exports.CheckboxRequiredValidator = CheckboxRequiredValidator;\n exports.MaxLengthValidator = MaxLengthValidator;\n exports.MinLengthValidator = MinLengthValidator;\n exports.PatternValidator = PatternValidator;\n exports.RequiredValidator = RequiredValidator;\n exports.FormBuilder = FormBuilder;\n exports.AbstractControl = AbstractControl;\n exports.FormArray = FormArray;\n exports.FormControl = FormControl;\n exports.FormGroup = FormGroup;\n exports.NG_ASYNC_VALIDATORS = NG_ASYNC_VALIDATORS;\n exports.NG_VALIDATORS = NG_VALIDATORS;\n exports.Validators = Validators;\n exports.VERSION = VERSION;\n exports.FormsModule = FormsModule;\n exports.ReactiveFormsModule = ReactiveFormsModule;\n\n}));//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMjUuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L0Bhbmd1bGFyL2Zvcm1zL2J1bmRsZXMvZm9ybXMudW1kLmpzPzkxMjUiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZSBBbmd1bGFyIHYyLjQuMVxuICogKGMpIDIwMTAtMjAxNiBHb29nbGUsIEluYy4gaHR0cHM6Ly9hbmd1bGFyLmlvL1xuICogTGljZW5zZTogTUlUXG4gKi9cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzLCByZXF1aXJlKCdAYW5ndWxhci9jb3JlJyksIHJlcXVpcmUoJ3J4anMvb3BlcmF0b3IvdG9Qcm9taXNlJyksIHJlcXVpcmUoJ3J4anMvU3ViamVjdCcpLCByZXF1aXJlKCdyeGpzL09ic2VydmFibGUnKSwgcmVxdWlyZSgncnhqcy9vYnNlcnZhYmxlL2Zyb21Qcm9taXNlJykpIDpcbiAgICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJywgJ0Bhbmd1bGFyL2NvcmUnLCAncnhqcy9vcGVyYXRvci90b1Byb21pc2UnLCAncnhqcy9TdWJqZWN0JywgJ3J4anMvT2JzZXJ2YWJsZScsICdyeGpzL29ic2VydmFibGUvZnJvbVByb21pc2UnXSwgZmFjdG9yeSkgOlxuICAgIChmYWN0b3J5KChnbG9iYWwubmcgPSBnbG9iYWwubmcgfHwge30sIGdsb2JhbC5uZy5mb3JtcyA9IGdsb2JhbC5uZy5mb3JtcyB8fCB7fSksZ2xvYmFsLm5nLmNvcmUsZ2xvYmFsLlJ4Lk9ic2VydmFibGUucHJvdG90eXBlLGdsb2JhbC5SeCxnbG9iYWwuUngsZ2xvYmFsLlJ4Lk9ic2VydmFibGUpKTtcbn0odGhpcywgZnVuY3Rpb24gKGV4cG9ydHMsX2FuZ3VsYXJfY29yZSxyeGpzX29wZXJhdG9yX3RvUHJvbWlzZSxyeGpzX1N1YmplY3Qscnhqc19PYnNlcnZhYmxlLHJ4anNfb2JzZXJ2YWJsZV9mcm9tUHJvbWlzZSkgeyAndXNlIHN0cmljdCc7XG5cbiAgICAvKipcbiAgICAgKiBAbGljZW5zZVxuICAgICAqIENvcHlyaWdodCBHb29nbGUgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICAgICAqXG4gICAgICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAgICAgKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gICAgICovXG4gICAgLyoqXG4gICAgICogIEJhc2UgY2xhc3MgZm9yIGNvbnRyb2wgZGlyZWN0aXZlcy5cbiAgICAgICogKlxuICAgICAgKiBPbmx5IHVzZWQgaW50ZXJuYWxseSBpbiB0aGUgZm9ybXMgbW9kdWxlLlxuICAgICAgKiAqXG4gICAgICogQGFic3RyYWN0XG4gICAgICovXG4gICAgdmFyIEFic3RyYWN0Q29udHJvbERpcmVjdGl2ZSA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIEFic3RyYWN0Q29udHJvbERpcmVjdGl2ZSgpIHtcbiAgICAgICAgfVxuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQWJzdHJhY3RDb250cm9sRGlyZWN0aXZlLnByb3RvdHlwZSwgXCJjb250cm9sXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHRocm93IG5ldyBFcnJvcigndW5pbXBsZW1lbnRlZCcpOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFic3RyYWN0Q29udHJvbERpcmVjdGl2ZS5wcm90b3R5cGUsIFwidmFsdWVcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuY29udHJvbCA/IHRoaXMuY29udHJvbC52YWx1ZSA6IG51bGw7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQWJzdHJhY3RDb250cm9sRGlyZWN0aXZlLnByb3RvdHlwZSwgXCJ2YWxpZFwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5jb250cm9sID8gdGhpcy5jb250cm9sLnZhbGlkIDogbnVsbDsgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShBYnN0cmFjdENvbnRyb2xEaXJlY3RpdmUucHJvdG90eXBlLCBcImludmFsaWRcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuY29udHJvbCA/IHRoaXMuY29udHJvbC5pbnZhbGlkIDogbnVsbDsgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShBYnN0cmFjdENvbnRyb2xEaXJlY3RpdmUucHJvdG90eXBlLCBcInBlbmRpbmdcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuY29udHJvbCA/IHRoaXMuY29udHJvbC5wZW5kaW5nIDogbnVsbDsgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShBYnN0cmFjdENvbnRyb2xEaXJlY3RpdmUucHJvdG90eXBlLCBcImVycm9yc1wiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5jb250cm9sID8gdGhpcy5jb250cm9sLmVycm9ycyA6IG51bGw7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQWJzdHJhY3RDb250cm9sRGlyZWN0aXZlLnByb3RvdHlwZSwgXCJwcmlzdGluZVwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5jb250cm9sID8gdGhpcy5jb250cm9sLnByaXN0aW5lIDogbnVsbDsgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShBYnN0cmFjdENvbnRyb2xEaXJlY3RpdmUucHJvdG90eXBlLCBcImRpcnR5XCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLmNvbnRyb2wgPyB0aGlzLmNvbnRyb2wuZGlydHkgOiBudWxsOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFic3RyYWN0Q29udHJvbERpcmVjdGl2ZS5wcm90b3R5cGUsIFwidG91Y2hlZFwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5jb250cm9sID8gdGhpcy5jb250cm9sLnRvdWNoZWQgOiBudWxsOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFic3RyYWN0Q29udHJvbERpcmVjdGl2ZS5wcm90b3R5cGUsIFwidW50b3VjaGVkXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLmNvbnRyb2wgPyB0aGlzLmNvbnRyb2wudW50b3VjaGVkIDogbnVsbDsgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShBYnN0cmFjdENvbnRyb2xEaXJlY3RpdmUucHJvdG90eXBlLCBcImRpc2FibGVkXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLmNvbnRyb2wgPyB0aGlzLmNvbnRyb2wuZGlzYWJsZWQgOiBudWxsOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFic3RyYWN0Q29udHJvbERpcmVjdGl2ZS5wcm90b3R5cGUsIFwiZW5hYmxlZFwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5jb250cm9sID8gdGhpcy5jb250cm9sLmVuYWJsZWQgOiBudWxsOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFic3RyYWN0Q29udHJvbERpcmVjdGl2ZS5wcm90b3R5cGUsIFwic3RhdHVzQ2hhbmdlc1wiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5jb250cm9sID8gdGhpcy5jb250cm9sLnN0YXR1c0NoYW5nZXMgOiBudWxsOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFic3RyYWN0Q29udHJvbERpcmVjdGl2ZS5wcm90b3R5cGUsIFwidmFsdWVDaGFuZ2VzXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLmNvbnRyb2wgPyB0aGlzLmNvbnRyb2wudmFsdWVDaGFuZ2VzIDogbnVsbDsgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShBYnN0cmFjdENvbnRyb2xEaXJlY3RpdmUucHJvdG90eXBlLCBcInBhdGhcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIG51bGw7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/PX0gdmFsdWVcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEFic3RyYWN0Q29udHJvbERpcmVjdGl2ZS5wcm90b3R5cGUucmVzZXQgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gdm9pZCAwKSB7IHZhbHVlID0gdW5kZWZpbmVkOyB9XG4gICAgICAgICAgICBpZiAodGhpcy5jb250cm9sKVxuICAgICAgICAgICAgICAgIHRoaXMuY29udHJvbC5yZXNldCh2YWx1ZSk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGVycm9yQ29kZVxuICAgICAgICAgKiBAcGFyYW0gez89fSBwYXRoXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBBYnN0cmFjdENvbnRyb2xEaXJlY3RpdmUucHJvdG90eXBlLmhhc0Vycm9yID0gZnVuY3Rpb24gKGVycm9yQ29kZSwgcGF0aCkge1xuICAgICAgICAgICAgaWYgKHBhdGggPT09IHZvaWQgMCkgeyBwYXRoID0gbnVsbDsgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udHJvbCA/IHRoaXMuY29udHJvbC5oYXNFcnJvcihlcnJvckNvZGUsIHBhdGgpIDogZmFsc2U7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGVycm9yQ29kZVxuICAgICAgICAgKiBAcGFyYW0gez89fSBwYXRoXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBBYnN0cmFjdENvbnRyb2xEaXJlY3RpdmUucHJvdG90eXBlLmdldEVycm9yID0gZnVuY3Rpb24gKGVycm9yQ29kZSwgcGF0aCkge1xuICAgICAgICAgICAgaWYgKHBhdGggPT09IHZvaWQgMCkgeyBwYXRoID0gbnVsbDsgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udHJvbCA/IHRoaXMuY29udHJvbC5nZXRFcnJvcihlcnJvckNvZGUsIHBhdGgpIDogbnVsbDtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIEFic3RyYWN0Q29udHJvbERpcmVjdGl2ZTtcbiAgICB9KCkpO1xuXG4gICAgLyoqXG4gICAgICogQGxpY2Vuc2VcbiAgICAgKiBDb3B5cmlnaHQgR29vZ2xlIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAgICAgKlxuICAgICAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gICAgICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICAgICAqL1xuICAgIHZhciBfX2V4dGVuZHMkMSA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqICBBIGRpcmVjdGl2ZSB0aGF0IGNvbnRhaW5zIG11bHRpcGxlIHtAbGluayBOZ0NvbnRyb2x9cy5cbiAgICAgICogKlxuICAgICAgKiBPbmx5IHVzZWQgYnkgdGhlIGZvcm1zIG1vZHVsZS5cbiAgICAgICogKlxuICAgICAqL1xuICAgIHZhciBDb250cm9sQ29udGFpbmVyID0gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICAgICAgX19leHRlbmRzJDEoQ29udHJvbENvbnRhaW5lciwgX3N1cGVyKTtcbiAgICAgICAgZnVuY3Rpb24gQ29udHJvbENvbnRhaW5lcigpIHtcbiAgICAgICAgICAgIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShDb250cm9sQ29udGFpbmVyLnByb3RvdHlwZSwgXCJmb3JtRGlyZWN0aXZlXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogIEdldCB0aGUgZm9ybSB0byB3aGljaCB0aGlzIGNvbnRhaW5lciBiZWxvbmdzLlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBudWxsOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KENvbnRyb2xDb250YWluZXIucHJvdG90eXBlLCBcInBhdGhcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiAgR2V0IHRoZSBwYXRoIHRvIHRoaXMgY29udGFpbmVyLlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBudWxsOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIENvbnRyb2xDb250YWluZXI7XG4gICAgfShBYnN0cmFjdENvbnRyb2xEaXJlY3RpdmUpKTtcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7P30gb2JqXG4gICAgICogQHJldHVybiB7P31cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc1ByZXNlbnQob2JqKSB7XG4gICAgICAgIHJldHVybiBvYmogIT0gbnVsbDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQHBhcmFtIHs/fSBvYmpcbiAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzQmxhbmsob2JqKSB7XG4gICAgICAgIHJldHVybiBvYmogPT0gbnVsbDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQHBhcmFtIHs/fSBhXG4gICAgICogQHBhcmFtIHs/fSBiXG4gICAgICogQHJldHVybiB7P31cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBsb29zZUlkZW50aWNhbChhLCBiKSB7XG4gICAgICAgIHJldHVybiBhID09PSBiIHx8IHR5cGVvZiBhID09PSAnbnVtYmVyJyAmJiB0eXBlb2YgYiA9PT0gJ251bWJlcicgJiYgaXNOYU4oYSkgJiYgaXNOYU4oYik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7P30gb1xuICAgICAqIEByZXR1cm4gez99XG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNKc09iamVjdChvKSB7XG4gICAgICAgIHJldHVybiBvICE9PSBudWxsICYmICh0eXBlb2YgbyA9PT0gJ2Z1bmN0aW9uJyB8fCB0eXBlb2YgbyA9PT0gJ29iamVjdCcpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gez99IG9ialxuICAgICAqIEByZXR1cm4gez99XG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNQcmltaXRpdmUob2JqKSB7XG4gICAgICAgIHJldHVybiAhaXNKc09iamVjdChvYmopO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqICBXcmFwcyBKYXZhc2NyaXB0IE9iamVjdHNcbiAgICAgKi9cbiAgICB2YXIgU3RyaW5nTWFwV3JhcHBlciA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIFN0cmluZ01hcFdyYXBwZXIoKSB7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gbTFcbiAgICAgICAgICogQHBhcmFtIHs/fSBtMlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgU3RyaW5nTWFwV3JhcHBlci5tZXJnZSA9IGZ1bmN0aW9uIChtMSwgbTIpIHtcbiAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIG0gPSB7fTtcbiAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSBPYmplY3Qua2V5cyhtMSk7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGsgPSBfYVtfaV07XG4gICAgICAgICAgICAgICAgbVtrXSA9IG0xW2tdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yICh2YXIgX2IgPSAwLCBfYyA9IE9iamVjdC5rZXlzKG0yKTsgX2IgPCBfYy5sZW5ndGg7IF9iKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgayA9IF9jW19iXTtcbiAgICAgICAgICAgICAgICBtW2tdID0gbTJba107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gbTFcbiAgICAgICAgICogQHBhcmFtIHs/fSBtMlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgU3RyaW5nTWFwV3JhcHBlci5lcXVhbHMgPSBmdW5jdGlvbiAobTEsIG0yKSB7XG4gICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBrMSA9IE9iamVjdC5rZXlzKG0xKTtcbiAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIGsyID0gT2JqZWN0LmtleXMobTIpO1xuICAgICAgICAgICAgaWYgKGsxLmxlbmd0aCAhPSBrMi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKHZhciAvKiogQHR5cGUgez99ICovIGkgPSAwOyBpIDwgazEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBrZXkgPSBrMVtpXTtcbiAgICAgICAgICAgICAgICBpZiAobTFba2V5XSAhPT0gbTJba2V5XSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBTdHJpbmdNYXBXcmFwcGVyO1xuICAgIH0oKSk7XG4gICAgdmFyIExpc3RXcmFwcGVyID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gTGlzdFdyYXBwZXIoKSB7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gYXJyXG4gICAgICAgICAqIEBwYXJhbSB7P30gY29uZGl0aW9uXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBMaXN0V3JhcHBlci5maW5kTGFzdCA9IGZ1bmN0aW9uIChhcnIsIGNvbmRpdGlvbikge1xuICAgICAgICAgICAgZm9yICh2YXIgLyoqIEB0eXBlIHs/fSAqLyBpID0gYXJyLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbmRpdGlvbihhcnJbaV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcnJbaV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGxpc3RcbiAgICAgICAgICogQHBhcmFtIHs/fSBpdGVtc1xuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgTGlzdFdyYXBwZXIucmVtb3ZlQWxsID0gZnVuY3Rpb24gKGxpc3QsIGl0ZW1zKSB7XG4gICAgICAgICAgICBmb3IgKHZhciAvKiogQHR5cGUgez99ICovIGkgPSAwOyBpIDwgaXRlbXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBpbmRleCA9IGxpc3QuaW5kZXhPZihpdGVtc1tpXSk7XG4gICAgICAgICAgICAgICAgaWYgKGluZGV4ID4gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdC5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gbGlzdFxuICAgICAgICAgKiBAcGFyYW0gez99IGVsXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBMaXN0V3JhcHBlci5yZW1vdmUgPSBmdW5jdGlvbiAobGlzdCwgZWwpIHtcbiAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIGluZGV4ID0gbGlzdC5pbmRleE9mKGVsKTtcbiAgICAgICAgICAgIGlmIChpbmRleCA+IC0xKSB7XG4gICAgICAgICAgICAgICAgbGlzdC5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBhXG4gICAgICAgICAqIEBwYXJhbSB7P30gYlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgTGlzdFdyYXBwZXIuZXF1YWxzID0gZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgICAgIGlmIChhLmxlbmd0aCAhPSBiLmxlbmd0aClcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICBmb3IgKHZhciAvKiogQHR5cGUgez99ICovIGkgPSAwOyBpIDwgYS5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgIGlmIChhW2ldICE9PSBiW2ldKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gbGlzdFxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgTGlzdFdyYXBwZXIuZmxhdHRlbiA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gICAgICAgICAgICByZXR1cm4gbGlzdC5yZWR1Y2UoZnVuY3Rpb24gKGZsYXQsIGl0ZW0pIHtcbiAgICAgICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBmbGF0SXRlbSA9IEFycmF5LmlzQXJyYXkoaXRlbSkgPyBMaXN0V3JhcHBlci5mbGF0dGVuKGl0ZW0pIDogaXRlbTtcbiAgICAgICAgICAgICAgICByZXR1cm4gKChmbGF0KSkuY29uY2F0KGZsYXRJdGVtKTtcbiAgICAgICAgICAgIH0sIFtdKTtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIExpc3RXcmFwcGVyO1xuICAgIH0oKSk7XG5cbiAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBpc1Byb21pc2UgPSBfYW5ndWxhcl9jb3JlLl9fY29yZV9wcml2YXRlX18uaXNQcm9taXNlO1xuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIHs/fSB2YWx1ZVxuICAgICAqIEByZXR1cm4gez99XG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNFbXB0eUlucHV0VmFsdWUodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlID09IG51bGwgfHwgdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiB2YWx1ZS5sZW5ndGggPT09IDA7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFByb3ZpZGVycyBmb3IgdmFsaWRhdG9ycyB0byBiZSB1c2VkIGZvciB7QGxpbmsgRm9ybUNvbnRyb2x9cyBpbiBhIGZvcm0uXG4gICAgICpcbiAgICAgKiBQcm92aWRlIHRoaXMgdXNpbmcgYG11bHRpOiB0cnVlYCB0byBhZGQgdmFsaWRhdG9ycy5cbiAgICAgKlxuICAgICAqICMjIyBFeGFtcGxlXG4gICAgICpcbiAgICAgKiB7QGV4YW1wbGUgY29yZS9mb3Jtcy90cy9uZ192YWxpZGF0b3JzL25nX3ZhbGlkYXRvcnMudHMgcmVnaW9uPSduZ192YWxpZGF0b3JzJ31cbiAgICAgKiBAc3RhYmxlXG4gICAgICovXG4gICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gTkdfVkFMSURBVE9SUyA9IG5ldyBfYW5ndWxhcl9jb3JlLk9wYXF1ZVRva2VuKCdOZ1ZhbGlkYXRvcnMnKTtcbiAgICAvKipcbiAgICAgKiBQcm92aWRlcnMgZm9yIGFzeW5jaHJvbm91cyB2YWxpZGF0b3JzIHRvIGJlIHVzZWQgZm9yIHtAbGluayBGb3JtQ29udHJvbH1zXG4gICAgICogaW4gYSBmb3JtLlxuICAgICAqXG4gICAgICogUHJvdmlkZSB0aGlzIHVzaW5nIGBtdWx0aTogdHJ1ZWAgdG8gYWRkIHZhbGlkYXRvcnMuXG4gICAgICpcbiAgICAgKiBTZWUge0BsaW5rIE5HX1ZBTElEQVRPUlN9IGZvciBtb3JlIGRldGFpbHMuXG4gICAgICpcbiAgICAgKiBAc3RhYmxlXG4gICAgICovXG4gICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gTkdfQVNZTkNfVkFMSURBVE9SUyA9IG5ldyBfYW5ndWxhcl9jb3JlLk9wYXF1ZVRva2VuKCdOZ0FzeW5jVmFsaWRhdG9ycycpO1xuICAgIC8qKlxuICAgICAqICBQcm92aWRlcyBhIHNldCBvZiB2YWxpZGF0b3JzIHVzZWQgYnkgZm9ybSBjb250cm9scy5cbiAgICAgICogKlxuICAgICAgKiBBIHZhbGlkYXRvciBpcyBhIGZ1bmN0aW9uIHRoYXQgcHJvY2Vzc2VzIGEge0BsaW5rIEZvcm1Db250cm9sfSBvciBjb2xsZWN0aW9uIG9mXG4gICAgICAqIGNvbnRyb2xzIGFuZCByZXR1cm5zIGEgbWFwIG9mIGVycm9ycy4gQSBudWxsIG1hcCBtZWFucyB0aGF0IHZhbGlkYXRpb24gaGFzIHBhc3NlZC5cbiAgICAgICogKlxuICAgICAgKiAjIyMgRXhhbXBsZVxuICAgICAgKiAqXG4gICAgICAqIGBgYHR5cGVzY3JpcHRcbiAgICAgICogdmFyIGxvZ2luQ29udHJvbCA9IG5ldyBGb3JtQ29udHJvbChcIlwiLCBWYWxpZGF0b3JzLnJlcXVpcmVkKVxuICAgICAgKiBgYGBcbiAgICAgICogKlxuICAgICAqL1xuICAgIHZhciBWYWxpZGF0b3JzID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gVmFsaWRhdG9ycygpIHtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogIFZhbGlkYXRvciB0aGF0IHJlcXVpcmVzIGNvbnRyb2xzIHRvIGhhdmUgYSBub24tZW1wdHkgdmFsdWUuXG4gICAgICAgICAqIEBwYXJhbSB7P30gY29udHJvbFxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgVmFsaWRhdG9ycy5yZXF1aXJlZCA9IGZ1bmN0aW9uIChjb250cm9sKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNFbXB0eUlucHV0VmFsdWUoY29udHJvbC52YWx1ZSkgPyB7ICdyZXF1aXJlZCc6IHRydWUgfSA6IG51bGw7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiAgVmFsaWRhdG9yIHRoYXQgcmVxdWlyZXMgY29udHJvbCB2YWx1ZSB0byBiZSB0cnVlLlxuICAgICAgICAgKiBAcGFyYW0gez99IGNvbnRyb2xcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIFZhbGlkYXRvcnMucmVxdWlyZWRUcnVlID0gZnVuY3Rpb24gKGNvbnRyb2wpIHtcbiAgICAgICAgICAgIHJldHVybiBjb250cm9sLnZhbHVlID09PSB0cnVlID8gbnVsbCA6IHsgJ3JlcXVpcmVkJzogdHJ1ZSB9O1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogIFZhbGlkYXRvciB0aGF0IHJlcXVpcmVzIGNvbnRyb2xzIHRvIGhhdmUgYSB2YWx1ZSBvZiBhIG1pbmltdW0gbGVuZ3RoLlxuICAgICAgICAgKiBAcGFyYW0gez99IG1pbkxlbmd0aFxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgVmFsaWRhdG9ycy5taW5MZW5ndGggPSBmdW5jdGlvbiAobWluTGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGNvbnRyb2wpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNFbXB0eUlucHV0VmFsdWUoY29udHJvbC52YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7IC8vIGRvbid0IHZhbGlkYXRlIGVtcHR5IHZhbHVlcyB0byBhbGxvdyBvcHRpb25hbCBjb250cm9sc1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBsZW5ndGggPSBjb250cm9sLnZhbHVlID8gY29udHJvbC52YWx1ZS5sZW5ndGggOiAwO1xuICAgICAgICAgICAgICAgIHJldHVybiBsZW5ndGggPCBtaW5MZW5ndGggP1xuICAgICAgICAgICAgICAgICAgICB7ICdtaW5sZW5ndGgnOiB7ICdyZXF1aXJlZExlbmd0aCc6IG1pbkxlbmd0aCwgJ2FjdHVhbExlbmd0aCc6IGxlbmd0aCB9IH0gOlxuICAgICAgICAgICAgICAgICAgICBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqICBWYWxpZGF0b3IgdGhhdCByZXF1aXJlcyBjb250cm9scyB0byBoYXZlIGEgdmFsdWUgb2YgYSBtYXhpbXVtIGxlbmd0aC5cbiAgICAgICAgICogQHBhcmFtIHs/fSBtYXhMZW5ndGhcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIFZhbGlkYXRvcnMubWF4TGVuZ3RoID0gZnVuY3Rpb24gKG1heExlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChjb250cm9sKSB7XG4gICAgICAgICAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gbGVuZ3RoID0gY29udHJvbC52YWx1ZSA/IGNvbnRyb2wudmFsdWUubGVuZ3RoIDogMDtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGVuZ3RoID4gbWF4TGVuZ3RoID9cbiAgICAgICAgICAgICAgICAgICAgeyAnbWF4bGVuZ3RoJzogeyAncmVxdWlyZWRMZW5ndGgnOiBtYXhMZW5ndGgsICdhY3R1YWxMZW5ndGgnOiBsZW5ndGggfSB9IDpcbiAgICAgICAgICAgICAgICAgICAgbnVsbDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiAgVmFsaWRhdG9yIHRoYXQgcmVxdWlyZXMgYSBjb250cm9sIHRvIG1hdGNoIGEgcmVnZXggdG8gaXRzIHZhbHVlLlxuICAgICAgICAgKiBAcGFyYW0gez99IHBhdHRlcm5cbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIFZhbGlkYXRvcnMucGF0dGVybiA9IGZ1bmN0aW9uIChwYXR0ZXJuKSB7XG4gICAgICAgICAgICBpZiAoIXBhdHRlcm4pXG4gICAgICAgICAgICAgICAgcmV0dXJuIFZhbGlkYXRvcnMubnVsbFZhbGlkYXRvcjtcbiAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIHJlZ2V4O1xuICAgICAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gcmVnZXhTdHI7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHBhdHRlcm4gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgcmVnZXhTdHIgPSBcIl5cIiArIHBhdHRlcm4gKyBcIiRcIjtcbiAgICAgICAgICAgICAgICByZWdleCA9IG5ldyBSZWdFeHAocmVnZXhTdHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVnZXhTdHIgPSBwYXR0ZXJuLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgcmVnZXggPSBwYXR0ZXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChjb250cm9sKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzRW1wdHlJbnB1dFZhbHVlKGNvbnRyb2wudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsOyAvLyBkb24ndCB2YWxpZGF0ZSBlbXB0eSB2YWx1ZXMgdG8gYWxsb3cgb3B0aW9uYWwgY29udHJvbHNcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gdmFsdWUgPSBjb250cm9sLnZhbHVlO1xuICAgICAgICAgICAgICAgIHJldHVybiByZWdleC50ZXN0KHZhbHVlKSA/IG51bGwgOlxuICAgICAgICAgICAgICAgICAgICB7ICdwYXR0ZXJuJzogeyAncmVxdWlyZWRQYXR0ZXJuJzogcmVnZXhTdHIsICdhY3R1YWxWYWx1ZSc6IHZhbHVlIH0gfTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiAgTm8tb3AgdmFsaWRhdG9yLlxuICAgICAgICAgKiBAcGFyYW0gez99IGNcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIFZhbGlkYXRvcnMubnVsbFZhbGlkYXRvciA9IGZ1bmN0aW9uIChjKSB7IHJldHVybiBudWxsOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogIENvbXBvc2UgbXVsdGlwbGUgdmFsaWRhdG9ycyBpbnRvIGEgc2luZ2xlIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgdW5pb25cbiAgICAgICAgICAqIG9mIHRoZSBpbmRpdmlkdWFsIGVycm9yIG1hcHMuXG4gICAgICAgICAqIEBwYXJhbSB7P30gdmFsaWRhdG9yc1xuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgVmFsaWRhdG9ycy5jb21wb3NlID0gZnVuY3Rpb24gKHZhbGlkYXRvcnMpIHtcbiAgICAgICAgICAgIGlmICghdmFsaWRhdG9ycylcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIHByZXNlbnRWYWxpZGF0b3JzID0gdmFsaWRhdG9ycy5maWx0ZXIoaXNQcmVzZW50KTtcbiAgICAgICAgICAgIGlmIChwcmVzZW50VmFsaWRhdG9ycy5sZW5ndGggPT0gMClcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoY29udHJvbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBfbWVyZ2VFcnJvcnMoX2V4ZWN1dGVWYWxpZGF0b3JzKGNvbnRyb2wsIHByZXNlbnRWYWxpZGF0b3JzKSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSB2YWxpZGF0b3JzXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBWYWxpZGF0b3JzLmNvbXBvc2VBc3luYyA9IGZ1bmN0aW9uICh2YWxpZGF0b3JzKSB7XG4gICAgICAgICAgICBpZiAoIXZhbGlkYXRvcnMpXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBwcmVzZW50VmFsaWRhdG9ycyA9IHZhbGlkYXRvcnMuZmlsdGVyKGlzUHJlc2VudCk7XG4gICAgICAgICAgICBpZiAocHJlc2VudFZhbGlkYXRvcnMubGVuZ3RoID09IDApXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGNvbnRyb2wpIHtcbiAgICAgICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBwcm9taXNlcyA9IF9leGVjdXRlQXN5bmNWYWxpZGF0b3JzKGNvbnRyb2wsIHByZXNlbnRWYWxpZGF0b3JzKS5tYXAoX2NvbnZlcnRUb1Byb21pc2UpO1xuICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcykudGhlbihfbWVyZ2VFcnJvcnMpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIFZhbGlkYXRvcnM7XG4gICAgfSgpKTtcbiAgICAvKipcbiAgICAgKiBAcGFyYW0gez99IG9ialxuICAgICAqIEByZXR1cm4gez99XG4gICAgICovXG4gICAgZnVuY3Rpb24gX2NvbnZlcnRUb1Byb21pc2Uob2JqKSB7XG4gICAgICAgIHJldHVybiBpc1Byb21pc2Uob2JqKSA/IG9iaiA6IHJ4anNfb3BlcmF0b3JfdG9Qcm9taXNlLnRvUHJvbWlzZS5jYWxsKG9iaik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7P30gY29udHJvbFxuICAgICAqIEBwYXJhbSB7P30gdmFsaWRhdG9yc1xuICAgICAqIEByZXR1cm4gez99XG4gICAgICovXG4gICAgZnVuY3Rpb24gX2V4ZWN1dGVWYWxpZGF0b3JzKGNvbnRyb2wsIHZhbGlkYXRvcnMpIHtcbiAgICAgICAgcmV0dXJuIHZhbGlkYXRvcnMubWFwKGZ1bmN0aW9uICh2KSB7IHJldHVybiB2KGNvbnRyb2wpOyB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQHBhcmFtIHs/fSBjb250cm9sXG4gICAgICogQHBhcmFtIHs/fSB2YWxpZGF0b3JzXG4gICAgICogQHJldHVybiB7P31cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBfZXhlY3V0ZUFzeW5jVmFsaWRhdG9ycyhjb250cm9sLCB2YWxpZGF0b3JzKSB7XG4gICAgICAgIHJldHVybiB2YWxpZGF0b3JzLm1hcChmdW5jdGlvbiAodikgeyByZXR1cm4gdihjb250cm9sKTsgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7P30gYXJyYXlPZkVycm9yc1xuICAgICAqIEByZXR1cm4gez99XG4gICAgICovXG4gICAgZnVuY3Rpb24gX21lcmdlRXJyb3JzKGFycmF5T2ZFcnJvcnMpIHtcbiAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gcmVzID0gYXJyYXlPZkVycm9ycy5yZWR1Y2UoZnVuY3Rpb24gKHJlcywgZXJyb3JzKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNQcmVzZW50KGVycm9ycykgPyBTdHJpbmdNYXBXcmFwcGVyLm1lcmdlKHJlcywgZXJyb3JzKSA6IHJlcztcbiAgICAgICAgfSwge30pO1xuICAgICAgICByZXR1cm4gT2JqZWN0LmtleXMocmVzKS5sZW5ndGggPT09IDAgPyBudWxsIDogcmVzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVzZWQgdG8gcHJvdmlkZSBhIHtAbGluayBDb250cm9sVmFsdWVBY2Nlc3Nvcn0gZm9yIGZvcm0gY29udHJvbHMuXG4gICAgICpcbiAgICAgKiBTZWUge0BsaW5rIERlZmF1bHRWYWx1ZUFjY2Vzc29yfSBmb3IgaG93IHRvIGltcGxlbWVudCBvbmUuXG4gICAgICogQHN0YWJsZVxuICAgICAqL1xuICAgIHZhciAvKiogQHR5cGUgez99ICovIE5HX1ZBTFVFX0FDQ0VTU09SID0gbmV3IF9hbmd1bGFyX2NvcmUuT3BhcXVlVG9rZW4oJ05nVmFsdWVBY2Nlc3NvcicpO1xuXG4gICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gQ0hFQ0tCT1hfVkFMVUVfQUNDRVNTT1IgPSB7XG4gICAgICAgIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuICAgICAgICB1c2VFeGlzdGluZzogX2FuZ3VsYXJfY29yZS5mb3J3YXJkUmVmKGZ1bmN0aW9uICgpIHsgcmV0dXJuIENoZWNrYm94Q29udHJvbFZhbHVlQWNjZXNzb3I7IH0pLFxuICAgICAgICBtdWx0aTogdHJ1ZSxcbiAgICB9O1xuICAgIC8qKlxuICAgICAqICBUaGUgYWNjZXNzb3IgZm9yIHdyaXRpbmcgYSB2YWx1ZSBhbmQgbGlzdGVuaW5nIHRvIGNoYW5nZXMgb24gYSBjaGVja2JveCBpbnB1dCBlbGVtZW50LlxuICAgICAgKiAqXG4gICAgICAqICMjIyBFeGFtcGxlXG4gICAgICAqIGBgYFxuICAgICAgKiA8aW5wdXQgdHlwZT1cImNoZWNrYm94XCIgbmFtZT1cInJlbWVtYmVyTG9naW5cIiBuZ01vZGVsPlxuICAgICAgKiBgYGBcbiAgICAgICogKlxuICAgICAgKiBAc3RhYmxlXG4gICAgICovXG4gICAgdmFyIENoZWNrYm94Q29udHJvbFZhbHVlQWNjZXNzb3IgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBfcmVuZGVyZXJcbiAgICAgICAgICogQHBhcmFtIHs/fSBfZWxlbWVudFJlZlxuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gQ2hlY2tib3hDb250cm9sVmFsdWVBY2Nlc3NvcihfcmVuZGVyZXIsIF9lbGVtZW50UmVmKSB7XG4gICAgICAgICAgICB0aGlzLl9yZW5kZXJlciA9IF9yZW5kZXJlcjtcbiAgICAgICAgICAgIHRoaXMuX2VsZW1lbnRSZWYgPSBfZWxlbWVudFJlZjtcbiAgICAgICAgICAgIHRoaXMub25DaGFuZ2UgPSBmdW5jdGlvbiAoXykgeyB9O1xuICAgICAgICAgICAgdGhpcy5vblRvdWNoZWQgPSBmdW5jdGlvbiAoKSB7IH07XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gdmFsdWVcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIENoZWNrYm94Q29udHJvbFZhbHVlQWNjZXNzb3IucHJvdG90eXBlLndyaXRlVmFsdWUgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMuX3JlbmRlcmVyLnNldEVsZW1lbnRQcm9wZXJ0eSh0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsICdjaGVja2VkJywgdmFsdWUpO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBmblxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgQ2hlY2tib3hDb250cm9sVmFsdWVBY2Nlc3Nvci5wcm90b3R5cGUucmVnaXN0ZXJPbkNoYW5nZSA9IGZ1bmN0aW9uIChmbikgeyB0aGlzLm9uQ2hhbmdlID0gZm47IH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGZuXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBDaGVja2JveENvbnRyb2xWYWx1ZUFjY2Vzc29yLnByb3RvdHlwZS5yZWdpc3Rlck9uVG91Y2hlZCA9IGZ1bmN0aW9uIChmbikgeyB0aGlzLm9uVG91Y2hlZCA9IGZuOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBpc0Rpc2FibGVkXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBDaGVja2JveENvbnRyb2xWYWx1ZUFjY2Vzc29yLnByb3RvdHlwZS5zZXREaXNhYmxlZFN0YXRlID0gZnVuY3Rpb24gKGlzRGlzYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX3JlbmRlcmVyLnNldEVsZW1lbnRQcm9wZXJ0eSh0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsICdkaXNhYmxlZCcsIGlzRGlzYWJsZWQpO1xuICAgICAgICB9O1xuICAgICAgICBDaGVja2JveENvbnRyb2xWYWx1ZUFjY2Vzc29yLmRlY29yYXRvcnMgPSBbXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuRGlyZWN0aXZlLCBhcmdzOiBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0b3I6ICdpbnB1dFt0eXBlPWNoZWNrYm94XVtmb3JtQ29udHJvbE5hbWVdLGlucHV0W3R5cGU9Y2hlY2tib3hdW2Zvcm1Db250cm9sXSxpbnB1dFt0eXBlPWNoZWNrYm94XVtuZ01vZGVsXScsXG4gICAgICAgICAgICAgICAgICAgICAgICBob3N0OiB7ICcoY2hhbmdlKSc6ICdvbkNoYW5nZSgkZXZlbnQudGFyZ2V0LmNoZWNrZWQpJywgJyhibHVyKSc6ICdvblRvdWNoZWQoKScgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3ZpZGVyczogW0NIRUNLQk9YX1ZBTFVFX0FDQ0VTU09SXVxuICAgICAgICAgICAgICAgICAgICB9LF0gfSxcbiAgICAgICAgXTtcbiAgICAgICAgLyoqIEBub2NvbGxhcHNlICovXG4gICAgICAgIENoZWNrYm94Q29udHJvbFZhbHVlQWNjZXNzb3IuY3RvclBhcmFtZXRlcnMgPSBmdW5jdGlvbiAoKSB7IHJldHVybiBbXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuUmVuZGVyZXIsIH0sXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuRWxlbWVudFJlZiwgfSxcbiAgICAgICAgXTsgfTtcbiAgICAgICAgcmV0dXJuIENoZWNrYm94Q29udHJvbFZhbHVlQWNjZXNzb3I7XG4gICAgfSgpKTtcblxuICAgIHZhciAvKiogQHR5cGUgez99ICovIERFRkFVTFRfVkFMVUVfQUNDRVNTT1IgPSB7XG4gICAgICAgIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuICAgICAgICB1c2VFeGlzdGluZzogX2FuZ3VsYXJfY29yZS5mb3J3YXJkUmVmKGZ1bmN0aW9uICgpIHsgcmV0dXJuIERlZmF1bHRWYWx1ZUFjY2Vzc29yOyB9KSxcbiAgICAgICAgbXVsdGk6IHRydWVcbiAgICB9O1xuICAgIC8qKlxuICAgICAqICBUaGUgZGVmYXVsdCBhY2Nlc3NvciBmb3Igd3JpdGluZyBhIHZhbHVlIGFuZCBsaXN0ZW5pbmcgdG8gY2hhbmdlcyB0aGF0IGlzIHVzZWQgYnkgdGhlXG4gICAgICAqIHtAbGluayBOZ01vZGVsfSwge0BsaW5rIEZvcm1Db250cm9sRGlyZWN0aXZlfSwgYW5kIHtAbGluayBGb3JtQ29udHJvbE5hbWV9IGRpcmVjdGl2ZXMuXG4gICAgICAqICpcbiAgICAgICogIyMjIEV4YW1wbGVcbiAgICAgICogYGBgXG4gICAgICAqIDxpbnB1dCB0eXBlPVwidGV4dFwiIG5hbWU9XCJzZWFyY2hRdWVyeVwiIG5nTW9kZWw+XG4gICAgICAqIGBgYFxuICAgICAgKiAqXG4gICAgICAqIEBzdGFibGVcbiAgICAgKi9cbiAgICB2YXIgRGVmYXVsdFZhbHVlQWNjZXNzb3IgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBfcmVuZGVyZXJcbiAgICAgICAgICogQHBhcmFtIHs/fSBfZWxlbWVudFJlZlxuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gRGVmYXVsdFZhbHVlQWNjZXNzb3IoX3JlbmRlcmVyLCBfZWxlbWVudFJlZikge1xuICAgICAgICAgICAgdGhpcy5fcmVuZGVyZXIgPSBfcmVuZGVyZXI7XG4gICAgICAgICAgICB0aGlzLl9lbGVtZW50UmVmID0gX2VsZW1lbnRSZWY7XG4gICAgICAgICAgICB0aGlzLm9uQ2hhbmdlID0gZnVuY3Rpb24gKF8pIHsgfTtcbiAgICAgICAgICAgIHRoaXMub25Ub3VjaGVkID0gZnVuY3Rpb24gKCkgeyB9O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IHZhbHVlXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBEZWZhdWx0VmFsdWVBY2Nlc3Nvci5wcm90b3R5cGUud3JpdGVWYWx1ZSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gbm9ybWFsaXplZFZhbHVlID0gdmFsdWUgPT0gbnVsbCA/ICcnIDogdmFsdWU7XG4gICAgICAgICAgICB0aGlzLl9yZW5kZXJlci5zZXRFbGVtZW50UHJvcGVydHkodGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCAndmFsdWUnLCBub3JtYWxpemVkVmFsdWUpO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBmblxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRGVmYXVsdFZhbHVlQWNjZXNzb3IucHJvdG90eXBlLnJlZ2lzdGVyT25DaGFuZ2UgPSBmdW5jdGlvbiAoZm4pIHsgdGhpcy5vbkNoYW5nZSA9IGZuOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBmblxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRGVmYXVsdFZhbHVlQWNjZXNzb3IucHJvdG90eXBlLnJlZ2lzdGVyT25Ub3VjaGVkID0gZnVuY3Rpb24gKGZuKSB7IHRoaXMub25Ub3VjaGVkID0gZm47IH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGlzRGlzYWJsZWRcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIERlZmF1bHRWYWx1ZUFjY2Vzc29yLnByb3RvdHlwZS5zZXREaXNhYmxlZFN0YXRlID0gZnVuY3Rpb24gKGlzRGlzYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX3JlbmRlcmVyLnNldEVsZW1lbnRQcm9wZXJ0eSh0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsICdkaXNhYmxlZCcsIGlzRGlzYWJsZWQpO1xuICAgICAgICB9O1xuICAgICAgICBEZWZhdWx0VmFsdWVBY2Nlc3Nvci5kZWNvcmF0b3JzID0gW1xuICAgICAgICAgICAgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkRpcmVjdGl2ZSwgYXJnczogW3tcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdG9yOiAnaW5wdXQ6bm90KFt0eXBlPWNoZWNrYm94XSlbZm9ybUNvbnRyb2xOYW1lXSx0ZXh0YXJlYVtmb3JtQ29udHJvbE5hbWVdLGlucHV0Om5vdChbdHlwZT1jaGVja2JveF0pW2Zvcm1Db250cm9sXSx0ZXh0YXJlYVtmb3JtQ29udHJvbF0saW5wdXQ6bm90KFt0eXBlPWNoZWNrYm94XSlbbmdNb2RlbF0sdGV4dGFyZWFbbmdNb2RlbF0sW25nRGVmYXVsdENvbnRyb2xdJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IHZzYXZraW4gcmVwbGFjZSB0aGUgYWJvdmUgc2VsZWN0b3Igd2l0aCB0aGUgb25lIGJlbG93IGl0IG9uY2VcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL2FuZ3VsYXIvaXNzdWVzLzMwMTEgaXMgaW1wbGVtZW50ZWRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNlbGVjdG9yOiAnW25nQ29udHJvbF0sW25nTW9kZWxdLFtuZ0Zvcm1Db250cm9sXScsXG4gICAgICAgICAgICAgICAgICAgICAgICBob3N0OiB7ICcoaW5wdXQpJzogJ29uQ2hhbmdlKCRldmVudC50YXJnZXQudmFsdWUpJywgJyhibHVyKSc6ICdvblRvdWNoZWQoKScgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3ZpZGVyczogW0RFRkFVTFRfVkFMVUVfQUNDRVNTT1JdXG4gICAgICAgICAgICAgICAgICAgIH0sXSB9LFxuICAgICAgICBdO1xuICAgICAgICAvKiogQG5vY29sbGFwc2UgKi9cbiAgICAgICAgRGVmYXVsdFZhbHVlQWNjZXNzb3IuY3RvclBhcmFtZXRlcnMgPSBmdW5jdGlvbiAoKSB7IHJldHVybiBbXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuUmVuZGVyZXIsIH0sXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuRWxlbWVudFJlZiwgfSxcbiAgICAgICAgXTsgfTtcbiAgICAgICAgcmV0dXJuIERlZmF1bHRWYWx1ZUFjY2Vzc29yO1xuICAgIH0oKSk7XG5cbiAgICAvKipcbiAgICAgKiBAbGljZW5zZVxuICAgICAqIENvcHlyaWdodCBHb29nbGUgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICAgICAqXG4gICAgICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAgICAgKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gICAgICovXG4gICAgLyoqXG4gICAgICogQHBhcmFtIHs/fSB2YWxpZGF0b3JcbiAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG5vcm1hbGl6ZVZhbGlkYXRvcih2YWxpZGF0b3IpIHtcbiAgICAgICAgaWYgKCgodmFsaWRhdG9yKSkudmFsaWRhdGUpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoYykgeyByZXR1cm4gKCh2YWxpZGF0b3IpKS52YWxpZGF0ZShjKTsgfTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAodmFsaWRhdG9yKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gez99IHZhbGlkYXRvclxuICAgICAqIEByZXR1cm4gez99XG4gICAgICovXG4gICAgZnVuY3Rpb24gbm9ybWFsaXplQXN5bmNWYWxpZGF0b3IodmFsaWRhdG9yKSB7XG4gICAgICAgIGlmICgoKHZhbGlkYXRvcikpLnZhbGlkYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGMpIHsgcmV0dXJuICgodmFsaWRhdG9yKSkudmFsaWRhdGUoYyk7IH07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gKHZhbGlkYXRvcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBOVU1CRVJfVkFMVUVfQUNDRVNTT1IgPSB7XG4gICAgICAgIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuICAgICAgICB1c2VFeGlzdGluZzogX2FuZ3VsYXJfY29yZS5mb3J3YXJkUmVmKGZ1bmN0aW9uICgpIHsgcmV0dXJuIE51bWJlclZhbHVlQWNjZXNzb3I7IH0pLFxuICAgICAgICBtdWx0aTogdHJ1ZVxuICAgIH07XG4gICAgLyoqXG4gICAgICogIFRoZSBhY2Nlc3NvciBmb3Igd3JpdGluZyBhIG51bWJlciB2YWx1ZSBhbmQgbGlzdGVuaW5nIHRvIGNoYW5nZXMgdGhhdCBpcyB1c2VkIGJ5IHRoZVxuICAgICAgKiB7QGxpbmsgTmdNb2RlbH0sIHtAbGluayBGb3JtQ29udHJvbERpcmVjdGl2ZX0sIGFuZCB7QGxpbmsgRm9ybUNvbnRyb2xOYW1lfSBkaXJlY3RpdmVzLlxuICAgICAgKiAqXG4gICAgICAqICMjIyBFeGFtcGxlXG4gICAgICAqIGBgYFxuICAgICAgKiA8aW5wdXQgdHlwZT1cIm51bWJlclwiIFsobmdNb2RlbCldPVwiYWdlXCI+XG4gICAgICAqIGBgYFxuICAgICAqL1xuICAgIHZhciBOdW1iZXJWYWx1ZUFjY2Vzc29yID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gX3JlbmRlcmVyXG4gICAgICAgICAqIEBwYXJhbSB7P30gX2VsZW1lbnRSZWZcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIE51bWJlclZhbHVlQWNjZXNzb3IoX3JlbmRlcmVyLCBfZWxlbWVudFJlZikge1xuICAgICAgICAgICAgdGhpcy5fcmVuZGVyZXIgPSBfcmVuZGVyZXI7XG4gICAgICAgICAgICB0aGlzLl9lbGVtZW50UmVmID0gX2VsZW1lbnRSZWY7XG4gICAgICAgICAgICB0aGlzLm9uQ2hhbmdlID0gZnVuY3Rpb24gKF8pIHsgfTtcbiAgICAgICAgICAgIHRoaXMub25Ub3VjaGVkID0gZnVuY3Rpb24gKCkgeyB9O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IHZhbHVlXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBOdW1iZXJWYWx1ZUFjY2Vzc29yLnByb3RvdHlwZS53cml0ZVZhbHVlID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAvLyBUaGUgdmFsdWUgbmVlZHMgdG8gYmUgbm9ybWFsaXplZCBmb3IgSUU5LCBvdGhlcndpc2UgaXQgaXMgc2V0IHRvICdudWxsJyB3aGVuIG51bGxcbiAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIG5vcm1hbGl6ZWRWYWx1ZSA9IHZhbHVlID09IG51bGwgPyAnJyA6IHZhbHVlO1xuICAgICAgICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0RWxlbWVudFByb3BlcnR5KHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgJ3ZhbHVlJywgbm9ybWFsaXplZFZhbHVlKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gZm5cbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIE51bWJlclZhbHVlQWNjZXNzb3IucHJvdG90eXBlLnJlZ2lzdGVyT25DaGFuZ2UgPSBmdW5jdGlvbiAoZm4pIHtcbiAgICAgICAgICAgIHRoaXMub25DaGFuZ2UgPSBmdW5jdGlvbiAodmFsdWUpIHsgZm4odmFsdWUgPT0gJycgPyBudWxsIDogcGFyc2VGbG9hdCh2YWx1ZSkpOyB9O1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBmblxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgTnVtYmVyVmFsdWVBY2Nlc3Nvci5wcm90b3R5cGUucmVnaXN0ZXJPblRvdWNoZWQgPSBmdW5jdGlvbiAoZm4pIHsgdGhpcy5vblRvdWNoZWQgPSBmbjsgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gaXNEaXNhYmxlZFxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgTnVtYmVyVmFsdWVBY2Nlc3Nvci5wcm90b3R5cGUuc2V0RGlzYWJsZWRTdGF0ZSA9IGZ1bmN0aW9uIChpc0Rpc2FibGVkKSB7XG4gICAgICAgICAgICB0aGlzLl9yZW5kZXJlci5zZXRFbGVtZW50UHJvcGVydHkodGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCAnZGlzYWJsZWQnLCBpc0Rpc2FibGVkKTtcbiAgICAgICAgfTtcbiAgICAgICAgTnVtYmVyVmFsdWVBY2Nlc3Nvci5kZWNvcmF0b3JzID0gW1xuICAgICAgICAgICAgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkRpcmVjdGl2ZSwgYXJnczogW3tcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdG9yOiAnaW5wdXRbdHlwZT1udW1iZXJdW2Zvcm1Db250cm9sTmFtZV0saW5wdXRbdHlwZT1udW1iZXJdW2Zvcm1Db250cm9sXSxpbnB1dFt0eXBlPW51bWJlcl1bbmdNb2RlbF0nLFxuICAgICAgICAgICAgICAgICAgICAgICAgaG9zdDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICcoY2hhbmdlKSc6ICdvbkNoYW5nZSgkZXZlbnQudGFyZ2V0LnZhbHVlKScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJyhpbnB1dCknOiAnb25DaGFuZ2UoJGV2ZW50LnRhcmdldC52YWx1ZSknLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICcoYmx1ciknOiAnb25Ub3VjaGVkKCknXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJvdmlkZXJzOiBbTlVNQkVSX1ZBTFVFX0FDQ0VTU09SXVxuICAgICAgICAgICAgICAgICAgICB9LF0gfSxcbiAgICAgICAgXTtcbiAgICAgICAgLyoqIEBub2NvbGxhcHNlICovXG4gICAgICAgIE51bWJlclZhbHVlQWNjZXNzb3IuY3RvclBhcmFtZXRlcnMgPSBmdW5jdGlvbiAoKSB7IHJldHVybiBbXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuUmVuZGVyZXIsIH0sXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuRWxlbWVudFJlZiwgfSxcbiAgICAgICAgXTsgfTtcbiAgICAgICAgcmV0dXJuIE51bWJlclZhbHVlQWNjZXNzb3I7XG4gICAgfSgpKTtcblxuICAgIC8qKlxuICAgICAqIEBsaWNlbnNlXG4gICAgICogQ29weXJpZ2h0IEdvb2dsZSBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gICAgICpcbiAgICAgKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICAgICAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAgICAgKi9cbiAgICB2YXIgX19leHRlbmRzJDIgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVuaW1wbGVtZW50ZWQoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigndW5pbXBsZW1lbnRlZCcpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiAgQSBiYXNlIGNsYXNzIHRoYXQgYWxsIGNvbnRyb2wgZGlyZWN0aXZlIGV4dGVuZC5cbiAgICAgICogSXQgYmluZHMgYSB7QGxpbmsgRm9ybUNvbnRyb2x9IG9iamVjdCB0byBhIERPTSBlbGVtZW50LlxuICAgICAgKiAqXG4gICAgICAqIFVzZWQgaW50ZXJuYWxseSBieSBBbmd1bGFyIGZvcm1zLlxuICAgICAgKiAqXG4gICAgICogQGFic3RyYWN0XG4gICAgICovXG4gICAgdmFyIE5nQ29udHJvbCA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgICAgIF9fZXh0ZW5kcyQyKE5nQ29udHJvbCwgX3N1cGVyKTtcbiAgICAgICAgZnVuY3Rpb24gTmdDb250cm9sKCkge1xuICAgICAgICAgICAgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAvKiogQGludGVybmFsICovXG4gICAgICAgICAgICB0aGlzLl9wYXJlbnQgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5uYW1lID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMudmFsdWVBY2Nlc3NvciA9IG51bGw7XG4gICAgICAgICAgICAvKiogQGludGVybmFsICovXG4gICAgICAgICAgICB0aGlzLl9yYXdWYWxpZGF0b3JzID0gW107XG4gICAgICAgICAgICAvKiogQGludGVybmFsICovXG4gICAgICAgICAgICB0aGlzLl9yYXdBc3luY1ZhbGlkYXRvcnMgPSBbXTtcbiAgICAgICAgfVxuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoTmdDb250cm9sLnByb3RvdHlwZSwgXCJ2YWxpZGF0b3JcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuICh1bmltcGxlbWVudGVkKCkpOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE5nQ29udHJvbC5wcm90b3R5cGUsIFwiYXN5bmNWYWxpZGF0b3JcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuICh1bmltcGxlbWVudGVkKCkpOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBhYnN0cmFjdFxuICAgICAgICAgKiBAcGFyYW0gez99IG5ld1ZhbHVlXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBOZ0NvbnRyb2wucHJvdG90eXBlLnZpZXdUb01vZGVsVXBkYXRlID0gZnVuY3Rpb24gKG5ld1ZhbHVlKSB7IH07XG4gICAgICAgIHJldHVybiBOZ0NvbnRyb2w7XG4gICAgfShBYnN0cmFjdENvbnRyb2xEaXJlY3RpdmUpKTtcblxuICAgIHZhciAvKiogQHR5cGUgez99ICovIFJBRElPX1ZBTFVFX0FDQ0VTU09SID0ge1xuICAgICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgICAgdXNlRXhpc3Rpbmc6IF9hbmd1bGFyX2NvcmUuZm9yd2FyZFJlZihmdW5jdGlvbiAoKSB7IHJldHVybiBSYWRpb0NvbnRyb2xWYWx1ZUFjY2Vzc29yOyB9KSxcbiAgICAgICAgbXVsdGk6IHRydWVcbiAgICB9O1xuICAgIC8qKlxuICAgICAqICBJbnRlcm5hbCBjbGFzcyB1c2VkIGJ5IEFuZ3VsYXIgdG8gdW5jaGVjayByYWRpbyBidXR0b25zIHdpdGggdGhlIG1hdGNoaW5nIG5hbWUuXG4gICAgICovXG4gICAgdmFyIFJhZGlvQ29udHJvbFJlZ2lzdHJ5ID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gUmFkaW9Db250cm9sUmVnaXN0cnkoKSB7XG4gICAgICAgICAgICB0aGlzLl9hY2Nlc3NvcnMgPSBbXTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBjb250cm9sXG4gICAgICAgICAqIEBwYXJhbSB7P30gYWNjZXNzb3JcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIFJhZGlvQ29udHJvbFJlZ2lzdHJ5LnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbiAoY29udHJvbCwgYWNjZXNzb3IpIHtcbiAgICAgICAgICAgIHRoaXMuX2FjY2Vzc29ycy5wdXNoKFtjb250cm9sLCBhY2Nlc3Nvcl0pO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBhY2Nlc3NvclxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgUmFkaW9Db250cm9sUmVnaXN0cnkucHJvdG90eXBlLnJlbW92ZSA9IGZ1bmN0aW9uIChhY2Nlc3Nvcikge1xuICAgICAgICAgICAgZm9yICh2YXIgLyoqIEB0eXBlIHs/fSAqLyBpID0gdGhpcy5fYWNjZXNzb3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX2FjY2Vzc29yc1tpXVsxXSA9PT0gYWNjZXNzb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fYWNjZXNzb3JzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gYWNjZXNzb3JcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIFJhZGlvQ29udHJvbFJlZ2lzdHJ5LnByb3RvdHlwZS5zZWxlY3QgPSBmdW5jdGlvbiAoYWNjZXNzb3IpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB0aGlzLl9hY2Nlc3NvcnMuZm9yRWFjaChmdW5jdGlvbiAoYykge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5faXNTYW1lR3JvdXAoYywgYWNjZXNzb3IpICYmIGNbMV0gIT09IGFjY2Vzc29yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNbMV0uZmlyZVVuY2hlY2soYWNjZXNzb3IudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBjb250cm9sUGFpclxuICAgICAgICAgKiBAcGFyYW0gez99IGFjY2Vzc29yXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBSYWRpb0NvbnRyb2xSZWdpc3RyeS5wcm90b3R5cGUuX2lzU2FtZUdyb3VwID0gZnVuY3Rpb24gKGNvbnRyb2xQYWlyLCBhY2Nlc3Nvcikge1xuICAgICAgICAgICAgaWYgKCFjb250cm9sUGFpclswXS5jb250cm9sKVxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybiBjb250cm9sUGFpclswXS5fcGFyZW50ID09PSBhY2Nlc3Nvci5fY29udHJvbC5fcGFyZW50ICYmXG4gICAgICAgICAgICAgICAgY29udHJvbFBhaXJbMV0ubmFtZSA9PT0gYWNjZXNzb3IubmFtZTtcbiAgICAgICAgfTtcbiAgICAgICAgUmFkaW9Db250cm9sUmVnaXN0cnkuZGVjb3JhdG9ycyA9IFtcbiAgICAgICAgICAgIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5JbmplY3RhYmxlIH0sXG4gICAgICAgIF07XG4gICAgICAgIC8qKiBAbm9jb2xsYXBzZSAqL1xuICAgICAgICBSYWRpb0NvbnRyb2xSZWdpc3RyeS5jdG9yUGFyYW1ldGVycyA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIFtdOyB9O1xuICAgICAgICByZXR1cm4gUmFkaW9Db250cm9sUmVnaXN0cnk7XG4gICAgfSgpKTtcbiAgICAvKipcbiAgICAgKiAgKlxuICAgICAgKiBVc2VkIGJ5IHtAbGluayBOZ01vZGVsfSwge0BsaW5rIEZvcm1Db250cm9sRGlyZWN0aXZlfSwgYW5kIHtAbGluayBGb3JtQ29udHJvbE5hbWV9XG4gICAgICAqIHRvIGtlZXAgdGhlIHZpZXcgc3luY2VkIHdpdGggdGhlIHtAbGluayBGb3JtQ29udHJvbH0gbW9kZWwuXG4gICAgICAqICpcbiAgICAgICogKlxuICAgICAgKiBJZiB5b3UgaGF2ZSBpbXBvcnRlZCB0aGUge0BsaW5rIEZvcm1zTW9kdWxlfSBvciB0aGUge0BsaW5rIFJlYWN0aXZlRm9ybXNNb2R1bGV9LCB0aGlzXG4gICAgICAqIHZhbHVlIGFjY2Vzc29yIHdpbGwgYmUgYWN0aXZlIG9uIGFueSByYWRpbyBjb250cm9sIHRoYXQgaGFzIGEgZm9ybSBkaXJlY3RpdmUuIFlvdSBkb1xuICAgICAgKiAqKm5vdCoqIG5lZWQgdG8gYWRkIGEgc3BlY2lhbCBzZWxlY3RvciB0byBhY3RpdmF0ZSBpdC5cbiAgICAgICogKlxuICAgICAgKiAjIyMgSG93IHRvIHVzZSByYWRpbyBidXR0b25zIHdpdGggZm9ybSBkaXJlY3RpdmVzXG4gICAgICAqICpcbiAgICAgICogVG8gdXNlIHJhZGlvIGJ1dHRvbnMgaW4gYSB0ZW1wbGF0ZS1kcml2ZW4gZm9ybSwgeW91J2xsIHdhbnQgdG8gZW5zdXJlIHRoYXQgcmFkaW8gYnV0dG9uc1xuICAgICAgKiBpbiB0aGUgc2FtZSBncm91cCBoYXZlIHRoZSBzYW1lIGBuYW1lYCBhdHRyaWJ1dGUuICBSYWRpbyBidXR0b25zIHdpdGggZGlmZmVyZW50IGBuYW1lYFxuICAgICAgKiBhdHRyaWJ1dGVzIGRvIG5vdCBhZmZlY3QgZWFjaCBvdGhlci5cbiAgICAgICogKlxuICAgICAgKiB7QGV4YW1wbGUgZm9ybXMvdHMvcmFkaW9CdXR0b25zL3JhZGlvX2J1dHRvbl9leGFtcGxlLnRzIHJlZ2lvbj0nVGVtcGxhdGVEcml2ZW4nfVxuICAgICAgKiAqXG4gICAgICAqIFdoZW4gdXNpbmcgcmFkaW8gYnV0dG9ucyBpbiBhIHJlYWN0aXZlIGZvcm0sIHJhZGlvIGJ1dHRvbnMgaW4gdGhlIHNhbWUgZ3JvdXAgc2hvdWxkIGhhdmUgdGhlXG4gICAgICAqIHNhbWUgYGZvcm1Db250cm9sTmFtZWAuIFlvdSBjYW4gYWxzbyBhZGQgYSBgbmFtZWAgYXR0cmlidXRlLCBidXQgaXQncyBvcHRpb25hbC5cbiAgICAgICogKlxuICAgICAgKiB7QGV4YW1wbGUgZm9ybXMvdHMvcmVhY3RpdmVSYWRpb0J1dHRvbnMvcmVhY3RpdmVfcmFkaW9fYnV0dG9uX2V4YW1wbGUudHMgcmVnaW9uPSdSZWFjdGl2ZSd9XG4gICAgICAqICpcbiAgICAgICogKiAqKm5wbSBwYWNrYWdlKio6IGBAYW5ndWxhci9mb3Jtc2BcbiAgICAgICogKlxuICAgICAgKiBAc3RhYmxlXG4gICAgICovXG4gICAgdmFyIFJhZGlvQ29udHJvbFZhbHVlQWNjZXNzb3IgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBfcmVuZGVyZXJcbiAgICAgICAgICogQHBhcmFtIHs/fSBfZWxlbWVudFJlZlxuICAgICAgICAgKiBAcGFyYW0gez99IF9yZWdpc3RyeVxuICAgICAgICAgKiBAcGFyYW0gez99IF9pbmplY3RvclxuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gUmFkaW9Db250cm9sVmFsdWVBY2Nlc3NvcihfcmVuZGVyZXIsIF9lbGVtZW50UmVmLCBfcmVnaXN0cnksIF9pbmplY3Rvcikge1xuICAgICAgICAgICAgdGhpcy5fcmVuZGVyZXIgPSBfcmVuZGVyZXI7XG4gICAgICAgICAgICB0aGlzLl9lbGVtZW50UmVmID0gX2VsZW1lbnRSZWY7XG4gICAgICAgICAgICB0aGlzLl9yZWdpc3RyeSA9IF9yZWdpc3RyeTtcbiAgICAgICAgICAgIHRoaXMuX2luamVjdG9yID0gX2luamVjdG9yO1xuICAgICAgICAgICAgdGhpcy5vbkNoYW5nZSA9IGZ1bmN0aW9uICgpIHsgfTtcbiAgICAgICAgICAgIHRoaXMub25Ub3VjaGVkID0gZnVuY3Rpb24gKCkgeyB9O1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgUmFkaW9Db250cm9sVmFsdWVBY2Nlc3Nvci5wcm90b3R5cGUubmdPbkluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLl9jb250cm9sID0gdGhpcy5faW5qZWN0b3IuZ2V0KE5nQ29udHJvbCk7XG4gICAgICAgICAgICB0aGlzLl9jaGVja05hbWUoKTtcbiAgICAgICAgICAgIHRoaXMuX3JlZ2lzdHJ5LmFkZCh0aGlzLl9jb250cm9sLCB0aGlzKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBSYWRpb0NvbnRyb2xWYWx1ZUFjY2Vzc29yLnByb3RvdHlwZS5uZ09uRGVzdHJveSA9IGZ1bmN0aW9uICgpIHsgdGhpcy5fcmVnaXN0cnkucmVtb3ZlKHRoaXMpOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSB2YWx1ZVxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgUmFkaW9Db250cm9sVmFsdWVBY2Nlc3Nvci5wcm90b3R5cGUud3JpdGVWYWx1ZSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5fc3RhdGUgPSB2YWx1ZSA9PT0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIHRoaXMuX3JlbmRlcmVyLnNldEVsZW1lbnRQcm9wZXJ0eSh0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsICdjaGVja2VkJywgdGhpcy5fc3RhdGUpO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBmblxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgUmFkaW9Db250cm9sVmFsdWVBY2Nlc3Nvci5wcm90b3R5cGUucmVnaXN0ZXJPbkNoYW5nZSA9IGZ1bmN0aW9uIChmbikge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHRoaXMuX2ZuID0gZm47XG4gICAgICAgICAgICB0aGlzLm9uQ2hhbmdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGZuKF90aGlzLnZhbHVlKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5fcmVnaXN0cnkuc2VsZWN0KF90aGlzKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IHZhbHVlXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBSYWRpb0NvbnRyb2xWYWx1ZUFjY2Vzc29yLnByb3RvdHlwZS5maXJlVW5jaGVjayA9IGZ1bmN0aW9uICh2YWx1ZSkgeyB0aGlzLndyaXRlVmFsdWUodmFsdWUpOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBmblxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgUmFkaW9Db250cm9sVmFsdWVBY2Nlc3Nvci5wcm90b3R5cGUucmVnaXN0ZXJPblRvdWNoZWQgPSBmdW5jdGlvbiAoZm4pIHsgdGhpcy5vblRvdWNoZWQgPSBmbjsgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gaXNEaXNhYmxlZFxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgUmFkaW9Db250cm9sVmFsdWVBY2Nlc3Nvci5wcm90b3R5cGUuc2V0RGlzYWJsZWRTdGF0ZSA9IGZ1bmN0aW9uIChpc0Rpc2FibGVkKSB7XG4gICAgICAgICAgICB0aGlzLl9yZW5kZXJlci5zZXRFbGVtZW50UHJvcGVydHkodGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCAnZGlzYWJsZWQnLCBpc0Rpc2FibGVkKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBSYWRpb0NvbnRyb2xWYWx1ZUFjY2Vzc29yLnByb3RvdHlwZS5fY2hlY2tOYW1lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMubmFtZSAmJiB0aGlzLmZvcm1Db250cm9sTmFtZSAmJiB0aGlzLm5hbWUgIT09IHRoaXMuZm9ybUNvbnRyb2xOYW1lKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fdGhyb3dOYW1lRXJyb3IoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghdGhpcy5uYW1lICYmIHRoaXMuZm9ybUNvbnRyb2xOYW1lKVxuICAgICAgICAgICAgICAgIHRoaXMubmFtZSA9IHRoaXMuZm9ybUNvbnRyb2xOYW1lO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIFJhZGlvQ29udHJvbFZhbHVlQWNjZXNzb3IucHJvdG90eXBlLl90aHJvd05hbWVFcnJvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlxcbiAgICAgIElmIHlvdSBkZWZpbmUgYm90aCBhIG5hbWUgYW5kIGEgZm9ybUNvbnRyb2xOYW1lIGF0dHJpYnV0ZSBvbiB5b3VyIHJhZGlvIGJ1dHRvbiwgdGhlaXIgdmFsdWVzXFxuICAgICAgbXVzdCBtYXRjaC4gRXg6IDxpbnB1dCB0eXBlPVxcXCJyYWRpb1xcXCIgZm9ybUNvbnRyb2xOYW1lPVxcXCJmb29kXFxcIiBuYW1lPVxcXCJmb29kXFxcIj5cXG4gICAgXCIpO1xuICAgICAgICB9O1xuICAgICAgICBSYWRpb0NvbnRyb2xWYWx1ZUFjY2Vzc29yLmRlY29yYXRvcnMgPSBbXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuRGlyZWN0aXZlLCBhcmdzOiBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0b3I6ICdpbnB1dFt0eXBlPXJhZGlvXVtmb3JtQ29udHJvbE5hbWVdLGlucHV0W3R5cGU9cmFkaW9dW2Zvcm1Db250cm9sXSxpbnB1dFt0eXBlPXJhZGlvXVtuZ01vZGVsXScsXG4gICAgICAgICAgICAgICAgICAgICAgICBob3N0OiB7ICcoY2hhbmdlKSc6ICdvbkNoYW5nZSgpJywgJyhibHVyKSc6ICdvblRvdWNoZWQoKScgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3ZpZGVyczogW1JBRElPX1ZBTFVFX0FDQ0VTU09SXVxuICAgICAgICAgICAgICAgICAgICB9LF0gfSxcbiAgICAgICAgXTtcbiAgICAgICAgLyoqIEBub2NvbGxhcHNlICovXG4gICAgICAgIFJhZGlvQ29udHJvbFZhbHVlQWNjZXNzb3IuY3RvclBhcmFtZXRlcnMgPSBmdW5jdGlvbiAoKSB7IHJldHVybiBbXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuUmVuZGVyZXIsIH0sXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuRWxlbWVudFJlZiwgfSxcbiAgICAgICAgICAgIHsgdHlwZTogUmFkaW9Db250cm9sUmVnaXN0cnksIH0sXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuSW5qZWN0b3IsIH0sXG4gICAgICAgIF07IH07XG4gICAgICAgIFJhZGlvQ29udHJvbFZhbHVlQWNjZXNzb3IucHJvcERlY29yYXRvcnMgPSB7XG4gICAgICAgICAgICAnbmFtZSc6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuSW5wdXQgfSxdLFxuICAgICAgICAgICAgJ2Zvcm1Db250cm9sTmFtZSc6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuSW5wdXQgfSxdLFxuICAgICAgICAgICAgJ3ZhbHVlJzogW3sgdHlwZTogX2FuZ3VsYXJfY29yZS5JbnB1dCB9LF0sXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBSYWRpb0NvbnRyb2xWYWx1ZUFjY2Vzc29yO1xuICAgIH0oKSk7XG5cbiAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBSQU5HRV9WQUxVRV9BQ0NFU1NPUiA9IHtcbiAgICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICAgIHVzZUV4aXN0aW5nOiBfYW5ndWxhcl9jb3JlLmZvcndhcmRSZWYoZnVuY3Rpb24gKCkgeyByZXR1cm4gUmFuZ2VWYWx1ZUFjY2Vzc29yOyB9KSxcbiAgICAgICAgbXVsdGk6IHRydWVcbiAgICB9O1xuICAgIC8qKlxuICAgICAqICBUaGUgYWNjZXNzb3IgZm9yIHdyaXRpbmcgYSByYW5nZSB2YWx1ZSBhbmQgbGlzdGVuaW5nIHRvIGNoYW5nZXMgdGhhdCBpcyB1c2VkIGJ5IHRoZVxuICAgICAgKiB7QGxpbmsgTmdNb2RlbH0sIHtAbGluayBGb3JtQ29udHJvbERpcmVjdGl2ZX0sIGFuZCB7QGxpbmsgRm9ybUNvbnRyb2xOYW1lfSBkaXJlY3RpdmVzLlxuICAgICAgKiAqXG4gICAgICAqICMjIyBFeGFtcGxlXG4gICAgICAqIGBgYFxuICAgICAgKiA8aW5wdXQgdHlwZT1cInJhbmdlXCIgWyhuZ01vZGVsKV09XCJhZ2VcIiA+XG4gICAgICAqIGBgYFxuICAgICAqL1xuICAgIHZhciBSYW5nZVZhbHVlQWNjZXNzb3IgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBfcmVuZGVyZXJcbiAgICAgICAgICogQHBhcmFtIHs/fSBfZWxlbWVudFJlZlxuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gUmFuZ2VWYWx1ZUFjY2Vzc29yKF9yZW5kZXJlciwgX2VsZW1lbnRSZWYpIHtcbiAgICAgICAgICAgIHRoaXMuX3JlbmRlcmVyID0gX3JlbmRlcmVyO1xuICAgICAgICAgICAgdGhpcy5fZWxlbWVudFJlZiA9IF9lbGVtZW50UmVmO1xuICAgICAgICAgICAgdGhpcy5vbkNoYW5nZSA9IGZ1bmN0aW9uIChfKSB7IH07XG4gICAgICAgICAgICB0aGlzLm9uVG91Y2hlZCA9IGZ1bmN0aW9uICgpIHsgfTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSB2YWx1ZVxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgUmFuZ2VWYWx1ZUFjY2Vzc29yLnByb3RvdHlwZS53cml0ZVZhbHVlID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICB0aGlzLl9yZW5kZXJlci5zZXRFbGVtZW50UHJvcGVydHkodGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCAndmFsdWUnLCBwYXJzZUZsb2F0KHZhbHVlKSk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGZuXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBSYW5nZVZhbHVlQWNjZXNzb3IucHJvdG90eXBlLnJlZ2lzdGVyT25DaGFuZ2UgPSBmdW5jdGlvbiAoZm4pIHtcbiAgICAgICAgICAgIHRoaXMub25DaGFuZ2UgPSBmdW5jdGlvbiAodmFsdWUpIHsgZm4odmFsdWUgPT0gJycgPyBudWxsIDogcGFyc2VGbG9hdCh2YWx1ZSkpOyB9O1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBmblxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgUmFuZ2VWYWx1ZUFjY2Vzc29yLnByb3RvdHlwZS5yZWdpc3Rlck9uVG91Y2hlZCA9IGZ1bmN0aW9uIChmbikgeyB0aGlzLm9uVG91Y2hlZCA9IGZuOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBpc0Rpc2FibGVkXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBSYW5nZVZhbHVlQWNjZXNzb3IucHJvdG90eXBlLnNldERpc2FibGVkU3RhdGUgPSBmdW5jdGlvbiAoaXNEaXNhYmxlZCkge1xuICAgICAgICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0RWxlbWVudFByb3BlcnR5KHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgJ2Rpc2FibGVkJywgaXNEaXNhYmxlZCk7XG4gICAgICAgIH07XG4gICAgICAgIFJhbmdlVmFsdWVBY2Nlc3Nvci5kZWNvcmF0b3JzID0gW1xuICAgICAgICAgICAgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkRpcmVjdGl2ZSwgYXJnczogW3tcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdG9yOiAnaW5wdXRbdHlwZT1yYW5nZV1bZm9ybUNvbnRyb2xOYW1lXSxpbnB1dFt0eXBlPXJhbmdlXVtmb3JtQ29udHJvbF0saW5wdXRbdHlwZT1yYW5nZV1bbmdNb2RlbF0nLFxuICAgICAgICAgICAgICAgICAgICAgICAgaG9zdDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICcoY2hhbmdlKSc6ICdvbkNoYW5nZSgkZXZlbnQudGFyZ2V0LnZhbHVlKScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJyhpbnB1dCknOiAnb25DaGFuZ2UoJGV2ZW50LnRhcmdldC52YWx1ZSknLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICcoYmx1ciknOiAnb25Ub3VjaGVkKCknXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJvdmlkZXJzOiBbUkFOR0VfVkFMVUVfQUNDRVNTT1JdXG4gICAgICAgICAgICAgICAgICAgIH0sXSB9LFxuICAgICAgICBdO1xuICAgICAgICAvKiogQG5vY29sbGFwc2UgKi9cbiAgICAgICAgUmFuZ2VWYWx1ZUFjY2Vzc29yLmN0b3JQYXJhbWV0ZXJzID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gW1xuICAgICAgICAgICAgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLlJlbmRlcmVyLCB9LFxuICAgICAgICAgICAgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkVsZW1lbnRSZWYsIH0sXG4gICAgICAgIF07IH07XG4gICAgICAgIHJldHVybiBSYW5nZVZhbHVlQWNjZXNzb3I7XG4gICAgfSgpKTtcblxuICAgIHZhciAvKiogQHR5cGUgez99ICovIFNFTEVDVF9WQUxVRV9BQ0NFU1NPUiA9IHtcbiAgICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICAgIHVzZUV4aXN0aW5nOiBfYW5ndWxhcl9jb3JlLmZvcndhcmRSZWYoZnVuY3Rpb24gKCkgeyByZXR1cm4gU2VsZWN0Q29udHJvbFZhbHVlQWNjZXNzb3I7IH0pLFxuICAgICAgICBtdWx0aTogdHJ1ZVxuICAgIH07XG4gICAgLyoqXG4gICAgICogQHBhcmFtIHs/fSBpZFxuICAgICAqIEBwYXJhbSB7P30gdmFsdWVcbiAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIF9idWlsZFZhbHVlU3RyaW5nKGlkLCB2YWx1ZSkge1xuICAgICAgICBpZiAoaWQgPT0gbnVsbClcbiAgICAgICAgICAgIHJldHVybiBcIlwiICsgdmFsdWU7XG4gICAgICAgIGlmICghaXNQcmltaXRpdmUodmFsdWUpKVxuICAgICAgICAgICAgdmFsdWUgPSAnT2JqZWN0JztcbiAgICAgICAgcmV0dXJuIChpZCArIFwiOiBcIiArIHZhbHVlKS5zbGljZSgwLCA1MCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7P30gdmFsdWVTdHJpbmdcbiAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIF9leHRyYWN0SWQodmFsdWVTdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlU3RyaW5nLnNwbGl0KCc6JylbMF07XG4gICAgfVxuICAgIC8qKlxuICAgICAqICAqXG4gICAgICAqIFVzZWQgYnkge0BsaW5rIE5nTW9kZWx9LCB7QGxpbmsgRm9ybUNvbnRyb2xEaXJlY3RpdmV9LCBhbmQge0BsaW5rIEZvcm1Db250cm9sTmFtZX1cbiAgICAgICogdG8ga2VlcCB0aGUgdmlldyBzeW5jZWQgd2l0aCB0aGUge0BsaW5rIEZvcm1Db250cm9sfSBtb2RlbC5cbiAgICAgICogKlxuICAgICAgKiAqXG4gICAgICAqIElmIHlvdSBoYXZlIGltcG9ydGVkIHRoZSB7QGxpbmsgRm9ybXNNb2R1bGV9IG9yIHRoZSB7QGxpbmsgUmVhY3RpdmVGb3Jtc01vZHVsZX0sIHRoaXNcbiAgICAgICogdmFsdWUgYWNjZXNzb3Igd2lsbCBiZSBhY3RpdmUgb24gYW55IHNlbGVjdCBjb250cm9sIHRoYXQgaGFzIGEgZm9ybSBkaXJlY3RpdmUuIFlvdSBkb1xuICAgICAgKiAqKm5vdCoqIG5lZWQgdG8gYWRkIGEgc3BlY2lhbCBzZWxlY3RvciB0byBhY3RpdmF0ZSBpdC5cbiAgICAgICogKlxuICAgICAgKiAjIyMgSG93IHRvIHVzZSBzZWxlY3QgY29udHJvbHMgd2l0aCBmb3JtIGRpcmVjdGl2ZXNcbiAgICAgICogKlxuICAgICAgKiBUbyB1c2UgYSBzZWxlY3QgaW4gYSB0ZW1wbGF0ZS1kcml2ZW4gZm9ybSwgc2ltcGx5IGFkZCBhbiBgbmdNb2RlbGAgYW5kIGEgYG5hbWVgXG4gICAgICAqIGF0dHJpYnV0ZSB0byB0aGUgbWFpbiBgPHNlbGVjdD5gIHRhZy5cbiAgICAgICogKlxuICAgICAgKiBJZiB5b3VyIG9wdGlvbiB2YWx1ZXMgYXJlIHNpbXBsZSBzdHJpbmdzLCB5b3UgY2FuIGJpbmQgdG8gdGhlIG5vcm1hbCBgdmFsdWVgIHByb3BlcnR5XG4gICAgICAqIG9uIHRoZSBvcHRpb24uICBJZiB5b3VyIG9wdGlvbiB2YWx1ZXMgaGFwcGVuIHRvIGJlIG9iamVjdHMgKGFuZCB5b3UnZCBsaWtlIHRvIHNhdmUgdGhlXG4gICAgICAqIHNlbGVjdGlvbiBpbiB5b3VyIGZvcm0gYXMgYW4gb2JqZWN0KSwgdXNlIGBuZ1ZhbHVlYCBpbnN0ZWFkOlxuICAgICAgKiAqXG4gICAgICAqIHtAZXhhbXBsZSBmb3Jtcy90cy9zZWxlY3RDb250cm9sL3NlbGVjdF9jb250cm9sX2V4YW1wbGUudHMgcmVnaW9uPSdDb21wb25lbnQnfVxuICAgICAgKiAqXG4gICAgICAqIEluIHJlYWN0aXZlIGZvcm1zLCB5b3UnbGwgYWxzbyB3YW50IHRvIGFkZCB5b3VyIGZvcm0gZGlyZWN0aXZlIChgZm9ybUNvbnRyb2xOYW1lYCBvclxuICAgICAgKiBgZm9ybUNvbnRyb2xgKSBvbiB0aGUgbWFpbiBgPHNlbGVjdD5gIHRhZy4gTGlrZSBpbiB0aGUgZm9ybWVyIGV4YW1wbGUsIHlvdSBoYXZlIHRoZVxuICAgICAgKiBjaG9pY2Ugb2YgYmluZGluZyB0byB0aGUgIGB2YWx1ZWAgb3IgYG5nVmFsdWVgIHByb3BlcnR5IG9uIHRoZSBzZWxlY3QncyBvcHRpb25zLlxuICAgICAgKiAqXG4gICAgICAqIHtAZXhhbXBsZSBmb3Jtcy90cy9yZWFjdGl2ZVNlbGVjdENvbnRyb2wvcmVhY3RpdmVfc2VsZWN0X2NvbnRyb2xfZXhhbXBsZS50cyByZWdpb249J0NvbXBvbmVudCd9XG4gICAgICAqICpcbiAgICAgICogTm90ZTogV2UgbGlzdGVuIHRvIHRoZSAnY2hhbmdlJyBldmVudCBiZWNhdXNlICdpbnB1dCcgZXZlbnRzIGFyZW4ndCBmaXJlZFxuICAgICAgKiBmb3Igc2VsZWN0cyBpbiBGaXJlZm94IGFuZCBJRTpcbiAgICAgICogaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTAyNDM1MFxuICAgICAgKiBodHRwczovL2RldmVsb3Blci5taWNyb3NvZnQuY29tL2VuLXVzL21pY3Jvc29mdC1lZGdlL3BsYXRmb3JtL2lzc3Vlcy80NjYwMDQ1L1xuICAgICAgKiAqXG4gICAgICAqICogKipucG0gcGFja2FnZSoqOiBgQGFuZ3VsYXIvZm9ybXNgXG4gICAgICAqICpcbiAgICAgKi9cbiAgICB2YXIgU2VsZWN0Q29udHJvbFZhbHVlQWNjZXNzb3IgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBfcmVuZGVyZXJcbiAgICAgICAgICogQHBhcmFtIHs/fSBfZWxlbWVudFJlZlxuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gU2VsZWN0Q29udHJvbFZhbHVlQWNjZXNzb3IoX3JlbmRlcmVyLCBfZWxlbWVudFJlZikge1xuICAgICAgICAgICAgdGhpcy5fcmVuZGVyZXIgPSBfcmVuZGVyZXI7XG4gICAgICAgICAgICB0aGlzLl9lbGVtZW50UmVmID0gX2VsZW1lbnRSZWY7XG4gICAgICAgICAgICAvKiogQGludGVybmFsICovXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25NYXAgPSBuZXcgTWFwKCk7XG4gICAgICAgICAgICAvKiogQGludGVybmFsICovXG4gICAgICAgICAgICB0aGlzLl9pZENvdW50ZXIgPSAwO1xuICAgICAgICAgICAgdGhpcy5vbkNoYW5nZSA9IGZ1bmN0aW9uIChfKSB7IH07XG4gICAgICAgICAgICB0aGlzLm9uVG91Y2hlZCA9IGZ1bmN0aW9uICgpIHsgfTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSB2YWx1ZVxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgU2VsZWN0Q29udHJvbFZhbHVlQWNjZXNzb3IucHJvdG90eXBlLndyaXRlVmFsdWUgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIHZhbHVlU3RyaW5nID0gX2J1aWxkVmFsdWVTdHJpbmcodGhpcy5fZ2V0T3B0aW9uSWQodmFsdWUpLCB2YWx1ZSk7XG4gICAgICAgICAgICB0aGlzLl9yZW5kZXJlci5zZXRFbGVtZW50UHJvcGVydHkodGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCAndmFsdWUnLCB2YWx1ZVN0cmluZyk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGZuXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBTZWxlY3RDb250cm9sVmFsdWVBY2Nlc3Nvci5wcm90b3R5cGUucmVnaXN0ZXJPbkNoYW5nZSA9IGZ1bmN0aW9uIChmbikge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHRoaXMub25DaGFuZ2UgPSBmdW5jdGlvbiAodmFsdWVTdHJpbmcpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy52YWx1ZSA9IHZhbHVlU3RyaW5nO1xuICAgICAgICAgICAgICAgIGZuKF90aGlzLl9nZXRPcHRpb25WYWx1ZSh2YWx1ZVN0cmluZykpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gZm5cbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIFNlbGVjdENvbnRyb2xWYWx1ZUFjY2Vzc29yLnByb3RvdHlwZS5yZWdpc3Rlck9uVG91Y2hlZCA9IGZ1bmN0aW9uIChmbikgeyB0aGlzLm9uVG91Y2hlZCA9IGZuOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBpc0Rpc2FibGVkXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBTZWxlY3RDb250cm9sVmFsdWVBY2Nlc3Nvci5wcm90b3R5cGUuc2V0RGlzYWJsZWRTdGF0ZSA9IGZ1bmN0aW9uIChpc0Rpc2FibGVkKSB7XG4gICAgICAgICAgICB0aGlzLl9yZW5kZXJlci5zZXRFbGVtZW50UHJvcGVydHkodGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCAnZGlzYWJsZWQnLCBpc0Rpc2FibGVkKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBTZWxlY3RDb250cm9sVmFsdWVBY2Nlc3Nvci5wcm90b3R5cGUuX3JlZ2lzdGVyT3B0aW9uID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gKHRoaXMuX2lkQ291bnRlcisrKS50b1N0cmluZygpOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSB2YWx1ZVxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgU2VsZWN0Q29udHJvbFZhbHVlQWNjZXNzb3IucHJvdG90eXBlLl9nZXRPcHRpb25JZCA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IEFycmF5LmZyb20odGhpcy5fb3B0aW9uTWFwLmtleXMoKSk7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGlkID0gX2FbX2ldO1xuICAgICAgICAgICAgICAgIGlmIChsb29zZUlkZW50aWNhbCh0aGlzLl9vcHRpb25NYXAuZ2V0KGlkKSwgdmFsdWUpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gdmFsdWVTdHJpbmdcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIFNlbGVjdENvbnRyb2xWYWx1ZUFjY2Vzc29yLnByb3RvdHlwZS5fZ2V0T3B0aW9uVmFsdWUgPSBmdW5jdGlvbiAodmFsdWVTdHJpbmcpIHtcbiAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIGlkID0gX2V4dHJhY3RJZCh2YWx1ZVN0cmluZyk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9uTWFwLmhhcyhpZCkgPyB0aGlzLl9vcHRpb25NYXAuZ2V0KGlkKSA6IHZhbHVlU3RyaW5nO1xuICAgICAgICB9O1xuICAgICAgICBTZWxlY3RDb250cm9sVmFsdWVBY2Nlc3Nvci5kZWNvcmF0b3JzID0gW1xuICAgICAgICAgICAgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkRpcmVjdGl2ZSwgYXJnczogW3tcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdG9yOiAnc2VsZWN0Om5vdChbbXVsdGlwbGVdKVtmb3JtQ29udHJvbE5hbWVdLHNlbGVjdDpub3QoW211bHRpcGxlXSlbZm9ybUNvbnRyb2xdLHNlbGVjdDpub3QoW211bHRpcGxlXSlbbmdNb2RlbF0nLFxuICAgICAgICAgICAgICAgICAgICAgICAgaG9zdDogeyAnKGNoYW5nZSknOiAnb25DaGFuZ2UoJGV2ZW50LnRhcmdldC52YWx1ZSknLCAnKGJsdXIpJzogJ29uVG91Y2hlZCgpJyB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJvdmlkZXJzOiBbU0VMRUNUX1ZBTFVFX0FDQ0VTU09SXVxuICAgICAgICAgICAgICAgICAgICB9LF0gfSxcbiAgICAgICAgXTtcbiAgICAgICAgLyoqIEBub2NvbGxhcHNlICovXG4gICAgICAgIFNlbGVjdENvbnRyb2xWYWx1ZUFjY2Vzc29yLmN0b3JQYXJhbWV0ZXJzID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gW1xuICAgICAgICAgICAgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLlJlbmRlcmVyLCB9LFxuICAgICAgICAgICAgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkVsZW1lbnRSZWYsIH0sXG4gICAgICAgIF07IH07XG4gICAgICAgIHJldHVybiBTZWxlY3RDb250cm9sVmFsdWVBY2Nlc3NvcjtcbiAgICB9KCkpO1xuICAgIC8qKlxuICAgICAqICAqXG4gICAgICAqICpcbiAgICAgICogU2VlIGRvY3MgZm9yIHtAbGluayBTZWxlY3RDb250cm9sVmFsdWVBY2Nlc3Nvcn0gZm9yIHVzYWdlIGV4YW1wbGVzLlxuICAgICAgKiAqXG4gICAgICovXG4gICAgdmFyIE5nU2VsZWN0T3B0aW9uID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gX2VsZW1lbnRcbiAgICAgICAgICogQHBhcmFtIHs/fSBfcmVuZGVyZXJcbiAgICAgICAgICogQHBhcmFtIHs/fSBfc2VsZWN0XG4gICAgICAgICAqL1xuICAgICAgICBmdW5jdGlvbiBOZ1NlbGVjdE9wdGlvbihfZWxlbWVudCwgX3JlbmRlcmVyLCBfc2VsZWN0KSB7XG4gICAgICAgICAgICB0aGlzLl9lbGVtZW50ID0gX2VsZW1lbnQ7XG4gICAgICAgICAgICB0aGlzLl9yZW5kZXJlciA9IF9yZW5kZXJlcjtcbiAgICAgICAgICAgIHRoaXMuX3NlbGVjdCA9IF9zZWxlY3Q7XG4gICAgICAgICAgICBpZiAodGhpcy5fc2VsZWN0KVxuICAgICAgICAgICAgICAgIHRoaXMuaWQgPSB0aGlzLl9zZWxlY3QuX3JlZ2lzdGVyT3B0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE5nU2VsZWN0T3B0aW9uLnByb3RvdHlwZSwgXCJuZ1ZhbHVlXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHBhcmFtIHs/fSB2YWx1ZVxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgc2V0OiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fc2VsZWN0ID09IG51bGwpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZWxlY3QuX29wdGlvbk1hcC5zZXQodGhpcy5pZCwgdmFsdWUpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3NldEVsZW1lbnRWYWx1ZShfYnVpbGRWYWx1ZVN0cmluZyh0aGlzLmlkLCB2YWx1ZSkpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3NlbGVjdC53cml0ZVZhbHVlKHRoaXMuX3NlbGVjdC52YWx1ZSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE5nU2VsZWN0T3B0aW9uLnByb3RvdHlwZSwgXCJ2YWx1ZVwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEBwYXJhbSB7P30gdmFsdWVcbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHNldDogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0RWxlbWVudFZhbHVlKHZhbHVlKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fc2VsZWN0KVxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZWxlY3Qud3JpdGVWYWx1ZSh0aGlzLl9zZWxlY3QudmFsdWUpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IHZhbHVlXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBOZ1NlbGVjdE9wdGlvbi5wcm90b3R5cGUuX3NldEVsZW1lbnRWYWx1ZSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0RWxlbWVudFByb3BlcnR5KHRoaXMuX2VsZW1lbnQubmF0aXZlRWxlbWVudCwgJ3ZhbHVlJywgdmFsdWUpO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIE5nU2VsZWN0T3B0aW9uLnByb3RvdHlwZS5uZ09uRGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9zZWxlY3QpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZWxlY3QuX29wdGlvbk1hcC5kZWxldGUodGhpcy5pZCk7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2VsZWN0LndyaXRlVmFsdWUodGhpcy5fc2VsZWN0LnZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgTmdTZWxlY3RPcHRpb24uZGVjb3JhdG9ycyA9IFtcbiAgICAgICAgICAgIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5EaXJlY3RpdmUsIGFyZ3M6IFt7IHNlbGVjdG9yOiAnb3B0aW9uJyB9LF0gfSxcbiAgICAgICAgXTtcbiAgICAgICAgLyoqIEBub2NvbGxhcHNlICovXG4gICAgICAgIE5nU2VsZWN0T3B0aW9uLmN0b3JQYXJhbWV0ZXJzID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gW1xuICAgICAgICAgICAgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkVsZW1lbnRSZWYsIH0sXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuUmVuZGVyZXIsIH0sXG4gICAgICAgICAgICB7IHR5cGU6IFNlbGVjdENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBkZWNvcmF0b3JzOiBbeyB0eXBlOiBfYW5ndWxhcl9jb3JlLk9wdGlvbmFsIH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5Ib3N0IH0sXSB9LFxuICAgICAgICBdOyB9O1xuICAgICAgICBOZ1NlbGVjdE9wdGlvbi5wcm9wRGVjb3JhdG9ycyA9IHtcbiAgICAgICAgICAgICduZ1ZhbHVlJzogW3sgdHlwZTogX2FuZ3VsYXJfY29yZS5JbnB1dCwgYXJnczogWyduZ1ZhbHVlJyxdIH0sXSxcbiAgICAgICAgICAgICd2YWx1ZSc6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuSW5wdXQsIGFyZ3M6IFsndmFsdWUnLF0gfSxdLFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gTmdTZWxlY3RPcHRpb247XG4gICAgfSgpKTtcblxuICAgIHZhciAvKiogQHR5cGUgez99ICovIFNFTEVDVF9NVUxUSVBMRV9WQUxVRV9BQ0NFU1NPUiA9IHtcbiAgICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICAgIHVzZUV4aXN0aW5nOiBfYW5ndWxhcl9jb3JlLmZvcndhcmRSZWYoZnVuY3Rpb24gKCkgeyByZXR1cm4gU2VsZWN0TXVsdGlwbGVDb250cm9sVmFsdWVBY2Nlc3NvcjsgfSksXG4gICAgICAgIG11bHRpOiB0cnVlXG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBAcGFyYW0gez99IGlkXG4gICAgICogQHBhcmFtIHs/fSB2YWx1ZVxuICAgICAqIEByZXR1cm4gez99XG4gICAgICovXG4gICAgZnVuY3Rpb24gX2J1aWxkVmFsdWVTdHJpbmckMShpZCwgdmFsdWUpIHtcbiAgICAgICAgaWYgKGlkID09IG51bGwpXG4gICAgICAgICAgICByZXR1cm4gXCJcIiArIHZhbHVlO1xuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJylcbiAgICAgICAgICAgIHZhbHVlID0gXCInXCIgKyB2YWx1ZSArIFwiJ1wiO1xuICAgICAgICBpZiAoIWlzUHJpbWl0aXZlKHZhbHVlKSlcbiAgICAgICAgICAgIHZhbHVlID0gJ09iamVjdCc7XG4gICAgICAgIHJldHVybiAoaWQgKyBcIjogXCIgKyB2YWx1ZSkuc2xpY2UoMCwgNTApO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gez99IHZhbHVlU3RyaW5nXG4gICAgICogQHJldHVybiB7P31cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBfZXh0cmFjdElkJDEodmFsdWVTdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlU3RyaW5nLnNwbGl0KCc6JylbMF07XG4gICAgfVxuICAgIC8qKlxuICAgICAqICBUaGUgYWNjZXNzb3IgZm9yIHdyaXRpbmcgYSB2YWx1ZSBhbmQgbGlzdGVuaW5nIHRvIGNoYW5nZXMgb24gYSBzZWxlY3QgZWxlbWVudC5cbiAgICAgICogKlxuICAgICAqL1xuICAgIHZhciBTZWxlY3RNdWx0aXBsZUNvbnRyb2xWYWx1ZUFjY2Vzc29yID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gX3JlbmRlcmVyXG4gICAgICAgICAqIEBwYXJhbSB7P30gX2VsZW1lbnRSZWZcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIFNlbGVjdE11bHRpcGxlQ29udHJvbFZhbHVlQWNjZXNzb3IoX3JlbmRlcmVyLCBfZWxlbWVudFJlZikge1xuICAgICAgICAgICAgdGhpcy5fcmVuZGVyZXIgPSBfcmVuZGVyZXI7XG4gICAgICAgICAgICB0aGlzLl9lbGVtZW50UmVmID0gX2VsZW1lbnRSZWY7XG4gICAgICAgICAgICAvKiogQGludGVybmFsICovXG4gICAgICAgICAgICB0aGlzLl9vcHRpb25NYXAgPSBuZXcgTWFwKCk7XG4gICAgICAgICAgICAvKiogQGludGVybmFsICovXG4gICAgICAgICAgICB0aGlzLl9pZENvdW50ZXIgPSAwO1xuICAgICAgICAgICAgdGhpcy5vbkNoYW5nZSA9IGZ1bmN0aW9uIChfKSB7IH07XG4gICAgICAgICAgICB0aGlzLm9uVG91Y2hlZCA9IGZ1bmN0aW9uICgpIHsgfTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSB2YWx1ZVxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgU2VsZWN0TXVsdGlwbGVDb250cm9sVmFsdWVBY2Nlc3Nvci5wcm90b3R5cGUud3JpdGVWYWx1ZSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIG9wdGlvblNlbGVjdGVkU3RhdGVTZXR0ZXI7XG4gICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAvLyBjb252ZXJ0IHZhbHVlcyB0byBpZHNcbiAgICAgICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBpZHNfMSA9IHZhbHVlLm1hcChmdW5jdGlvbiAodikgeyByZXR1cm4gX3RoaXMuX2dldE9wdGlvbklkKHYpOyB9KTtcbiAgICAgICAgICAgICAgICBvcHRpb25TZWxlY3RlZFN0YXRlU2V0dGVyID0gZnVuY3Rpb24gKG9wdCwgbykgeyBvcHQuX3NldFNlbGVjdGVkKGlkc18xLmluZGV4T2Yoby50b1N0cmluZygpKSA+IC0xKTsgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIG9wdGlvblNlbGVjdGVkU3RhdGVTZXR0ZXIgPSBmdW5jdGlvbiAob3B0LCBvKSB7IG9wdC5fc2V0U2VsZWN0ZWQoZmFsc2UpOyB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fb3B0aW9uTWFwLmZvckVhY2gob3B0aW9uU2VsZWN0ZWRTdGF0ZVNldHRlcik7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGZuXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBTZWxlY3RNdWx0aXBsZUNvbnRyb2xWYWx1ZUFjY2Vzc29yLnByb3RvdHlwZS5yZWdpc3Rlck9uQ2hhbmdlID0gZnVuY3Rpb24gKGZuKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdGhpcy5vbkNoYW5nZSA9IGZ1bmN0aW9uIChfKSB7XG4gICAgICAgICAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gc2VsZWN0ZWQgPSBbXTtcbiAgICAgICAgICAgICAgICBpZiAoXy5oYXNPd25Qcm9wZXJ0eSgnc2VsZWN0ZWRPcHRpb25zJykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gb3B0aW9ucyA9IF8uc2VsZWN0ZWRPcHRpb25zO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciAvKiogQHR5cGUgez99ICovIGkgPSAwOyBpIDwgb3B0aW9ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gb3B0ID0gb3B0aW9ucy5pdGVtKGkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gdmFsID0gX3RoaXMuX2dldE9wdGlvblZhbHVlKG9wdC52YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZC5wdXNoKHZhbCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIG9wdGlvbnMgPSAoXy5vcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgLyoqIEB0eXBlIHs/fSAqLyBpID0gMDsgaSA8IG9wdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIG9wdCA9IG9wdGlvbnMuaXRlbShpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHQuc2VsZWN0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyB2YWwgPSBfdGhpcy5fZ2V0T3B0aW9uVmFsdWUob3B0LnZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZC5wdXNoKHZhbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgX3RoaXMudmFsdWUgPSBzZWxlY3RlZDtcbiAgICAgICAgICAgICAgICBmbihzZWxlY3RlZCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBmblxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgU2VsZWN0TXVsdGlwbGVDb250cm9sVmFsdWVBY2Nlc3Nvci5wcm90b3R5cGUucmVnaXN0ZXJPblRvdWNoZWQgPSBmdW5jdGlvbiAoZm4pIHsgdGhpcy5vblRvdWNoZWQgPSBmbjsgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gaXNEaXNhYmxlZFxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgU2VsZWN0TXVsdGlwbGVDb250cm9sVmFsdWVBY2Nlc3Nvci5wcm90b3R5cGUuc2V0RGlzYWJsZWRTdGF0ZSA9IGZ1bmN0aW9uIChpc0Rpc2FibGVkKSB7XG4gICAgICAgICAgICB0aGlzLl9yZW5kZXJlci5zZXRFbGVtZW50UHJvcGVydHkodGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCAnZGlzYWJsZWQnLCBpc0Rpc2FibGVkKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gdmFsdWVcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIFNlbGVjdE11bHRpcGxlQ29udHJvbFZhbHVlQWNjZXNzb3IucHJvdG90eXBlLl9yZWdpc3Rlck9wdGlvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gaWQgPSAodGhpcy5faWRDb3VudGVyKyspLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICB0aGlzLl9vcHRpb25NYXAuc2V0KGlkLCB2YWx1ZSk7XG4gICAgICAgICAgICByZXR1cm4gaWQ7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IHZhbHVlXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBTZWxlY3RNdWx0aXBsZUNvbnRyb2xWYWx1ZUFjY2Vzc29yLnByb3RvdHlwZS5fZ2V0T3B0aW9uSWQgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSBBcnJheS5mcm9tKHRoaXMuX29wdGlvbk1hcC5rZXlzKCkpOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgIHZhciBpZCA9IF9hW19pXTtcbiAgICAgICAgICAgICAgICBpZiAobG9vc2VJZGVudGljYWwodGhpcy5fb3B0aW9uTWFwLmdldChpZCkuX3ZhbHVlLCB2YWx1ZSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSB2YWx1ZVN0cmluZ1xuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgU2VsZWN0TXVsdGlwbGVDb250cm9sVmFsdWVBY2Nlc3Nvci5wcm90b3R5cGUuX2dldE9wdGlvblZhbHVlID0gZnVuY3Rpb24gKHZhbHVlU3RyaW5nKSB7XG4gICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBpZCA9IF9leHRyYWN0SWQkMSh2YWx1ZVN0cmluZyk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9uTWFwLmhhcyhpZCkgPyB0aGlzLl9vcHRpb25NYXAuZ2V0KGlkKS5fdmFsdWUgOiB2YWx1ZVN0cmluZztcbiAgICAgICAgfTtcbiAgICAgICAgU2VsZWN0TXVsdGlwbGVDb250cm9sVmFsdWVBY2Nlc3Nvci5kZWNvcmF0b3JzID0gW1xuICAgICAgICAgICAgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkRpcmVjdGl2ZSwgYXJnczogW3tcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdG9yOiAnc2VsZWN0W211bHRpcGxlXVtmb3JtQ29udHJvbE5hbWVdLHNlbGVjdFttdWx0aXBsZV1bZm9ybUNvbnRyb2xdLHNlbGVjdFttdWx0aXBsZV1bbmdNb2RlbF0nLFxuICAgICAgICAgICAgICAgICAgICAgICAgaG9zdDogeyAnKGNoYW5nZSknOiAnb25DaGFuZ2UoJGV2ZW50LnRhcmdldCknLCAnKGJsdXIpJzogJ29uVG91Y2hlZCgpJyB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJvdmlkZXJzOiBbU0VMRUNUX01VTFRJUExFX1ZBTFVFX0FDQ0VTU09SXVxuICAgICAgICAgICAgICAgICAgICB9LF0gfSxcbiAgICAgICAgXTtcbiAgICAgICAgLyoqIEBub2NvbGxhcHNlICovXG4gICAgICAgIFNlbGVjdE11bHRpcGxlQ29udHJvbFZhbHVlQWNjZXNzb3IuY3RvclBhcmFtZXRlcnMgPSBmdW5jdGlvbiAoKSB7IHJldHVybiBbXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuUmVuZGVyZXIsIH0sXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuRWxlbWVudFJlZiwgfSxcbiAgICAgICAgXTsgfTtcbiAgICAgICAgcmV0dXJuIFNlbGVjdE11bHRpcGxlQ29udHJvbFZhbHVlQWNjZXNzb3I7XG4gICAgfSgpKTtcbiAgICAvKipcbiAgICAgKiAgTWFya3MgYDxvcHRpb24+YCBhcyBkeW5hbWljLCBzbyBBbmd1bGFyIGNhbiBiZSBub3RpZmllZCB3aGVuIG9wdGlvbnMgY2hhbmdlLlxuICAgICAgKiAqXG4gICAgICAqICMjIyBFeGFtcGxlXG4gICAgICAqICpcbiAgICAgICogYGBgXG4gICAgICAqIDxzZWxlY3QgbXVsdGlwbGUgbmFtZT1cImNpdHlcIiBuZ01vZGVsPlxuICAgICAgKiA8b3B0aW9uICpuZ0Zvcj1cImxldCBjIG9mIGNpdGllc1wiIFt2YWx1ZV09XCJjXCI+PC9vcHRpb24+XG4gICAgICAqIDwvc2VsZWN0PlxuICAgICAgKiBgYGBcbiAgICAgKi9cbiAgICB2YXIgTmdTZWxlY3RNdWx0aXBsZU9wdGlvbiA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IF9lbGVtZW50XG4gICAgICAgICAqIEBwYXJhbSB7P30gX3JlbmRlcmVyXG4gICAgICAgICAqIEBwYXJhbSB7P30gX3NlbGVjdFxuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gTmdTZWxlY3RNdWx0aXBsZU9wdGlvbihfZWxlbWVudCwgX3JlbmRlcmVyLCBfc2VsZWN0KSB7XG4gICAgICAgICAgICB0aGlzLl9lbGVtZW50ID0gX2VsZW1lbnQ7XG4gICAgICAgICAgICB0aGlzLl9yZW5kZXJlciA9IF9yZW5kZXJlcjtcbiAgICAgICAgICAgIHRoaXMuX3NlbGVjdCA9IF9zZWxlY3Q7XG4gICAgICAgICAgICBpZiAodGhpcy5fc2VsZWN0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pZCA9IHRoaXMuX3NlbGVjdC5fcmVnaXN0ZXJPcHRpb24odGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE5nU2VsZWN0TXVsdGlwbGVPcHRpb24ucHJvdG90eXBlLCBcIm5nVmFsdWVcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcGFyYW0gez99IHZhbHVlXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBzZXQ6IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9zZWxlY3QgPT0gbnVsbClcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIHRoaXMuX3ZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0RWxlbWVudFZhbHVlKF9idWlsZFZhbHVlU3RyaW5nJDEodGhpcy5pZCwgdmFsdWUpKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZWxlY3Qud3JpdGVWYWx1ZSh0aGlzLl9zZWxlY3QudmFsdWUpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShOZ1NlbGVjdE11bHRpcGxlT3B0aW9uLnByb3RvdHlwZSwgXCJ2YWx1ZVwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEBwYXJhbSB7P30gdmFsdWVcbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHNldDogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX3NlbGVjdCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl92YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRFbGVtZW50VmFsdWUoX2J1aWxkVmFsdWVTdHJpbmckMSh0aGlzLmlkLCB2YWx1ZSkpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZWxlY3Qud3JpdGVWYWx1ZSh0aGlzLl9zZWxlY3QudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0RWxlbWVudFZhbHVlKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gdmFsdWVcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIE5nU2VsZWN0TXVsdGlwbGVPcHRpb24ucHJvdG90eXBlLl9zZXRFbGVtZW50VmFsdWUgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMuX3JlbmRlcmVyLnNldEVsZW1lbnRQcm9wZXJ0eSh0aGlzLl9lbGVtZW50Lm5hdGl2ZUVsZW1lbnQsICd2YWx1ZScsIHZhbHVlKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gc2VsZWN0ZWRcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIE5nU2VsZWN0TXVsdGlwbGVPcHRpb24ucHJvdG90eXBlLl9zZXRTZWxlY3RlZCA9IGZ1bmN0aW9uIChzZWxlY3RlZCkge1xuICAgICAgICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0RWxlbWVudFByb3BlcnR5KHRoaXMuX2VsZW1lbnQubmF0aXZlRWxlbWVudCwgJ3NlbGVjdGVkJywgc2VsZWN0ZWQpO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIE5nU2VsZWN0TXVsdGlwbGVPcHRpb24ucHJvdG90eXBlLm5nT25EZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuX3NlbGVjdCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3NlbGVjdC5fb3B0aW9uTWFwLmRlbGV0ZSh0aGlzLmlkKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZWxlY3Qud3JpdGVWYWx1ZSh0aGlzLl9zZWxlY3QudmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBOZ1NlbGVjdE11bHRpcGxlT3B0aW9uLmRlY29yYXRvcnMgPSBbXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuRGlyZWN0aXZlLCBhcmdzOiBbeyBzZWxlY3RvcjogJ29wdGlvbicgfSxdIH0sXG4gICAgICAgIF07XG4gICAgICAgIC8qKiBAbm9jb2xsYXBzZSAqL1xuICAgICAgICBOZ1NlbGVjdE11bHRpcGxlT3B0aW9uLmN0b3JQYXJhbWV0ZXJzID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gW1xuICAgICAgICAgICAgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkVsZW1lbnRSZWYsIH0sXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuUmVuZGVyZXIsIH0sXG4gICAgICAgICAgICB7IHR5cGU6IFNlbGVjdE11bHRpcGxlQ29udHJvbFZhbHVlQWNjZXNzb3IsIGRlY29yYXRvcnM6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuT3B0aW9uYWwgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkhvc3QgfSxdIH0sXG4gICAgICAgIF07IH07XG4gICAgICAgIE5nU2VsZWN0TXVsdGlwbGVPcHRpb24ucHJvcERlY29yYXRvcnMgPSB7XG4gICAgICAgICAgICAnbmdWYWx1ZSc6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuSW5wdXQsIGFyZ3M6IFsnbmdWYWx1ZScsXSB9LF0sXG4gICAgICAgICAgICAndmFsdWUnOiBbeyB0eXBlOiBfYW5ndWxhcl9jb3JlLklucHV0LCBhcmdzOiBbJ3ZhbHVlJyxdIH0sXSxcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIE5nU2VsZWN0TXVsdGlwbGVPcHRpb247XG4gICAgfSgpKTtcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7P30gbmFtZVxuICAgICAqIEBwYXJhbSB7P30gcGFyZW50XG4gICAgICogQHJldHVybiB7P31cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb250cm9sUGF0aChuYW1lLCBwYXJlbnQpIHtcbiAgICAgICAgcmV0dXJuIHBhcmVudC5wYXRoLmNvbmNhdChbbmFtZV0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gez99IGNvbnRyb2xcbiAgICAgKiBAcGFyYW0gez99IGRpclxuICAgICAqIEByZXR1cm4gez99XG4gICAgICovXG4gICAgZnVuY3Rpb24gc2V0VXBDb250cm9sKGNvbnRyb2wsIGRpcikge1xuICAgICAgICBpZiAoIWNvbnRyb2wpXG4gICAgICAgICAgICBfdGhyb3dFcnJvcihkaXIsICdDYW5ub3QgZmluZCBjb250cm9sIHdpdGgnKTtcbiAgICAgICAgaWYgKCFkaXIudmFsdWVBY2Nlc3NvcilcbiAgICAgICAgICAgIF90aHJvd0Vycm9yKGRpciwgJ05vIHZhbHVlIGFjY2Vzc29yIGZvciBmb3JtIGNvbnRyb2wgd2l0aCcpO1xuICAgICAgICBjb250cm9sLnZhbGlkYXRvciA9IFZhbGlkYXRvcnMuY29tcG9zZShbY29udHJvbC52YWxpZGF0b3IsIGRpci52YWxpZGF0b3JdKTtcbiAgICAgICAgY29udHJvbC5hc3luY1ZhbGlkYXRvciA9IFZhbGlkYXRvcnMuY29tcG9zZUFzeW5jKFtjb250cm9sLmFzeW5jVmFsaWRhdG9yLCBkaXIuYXN5bmNWYWxpZGF0b3JdKTtcbiAgICAgICAgZGlyLnZhbHVlQWNjZXNzb3Iud3JpdGVWYWx1ZShjb250cm9sLnZhbHVlKTtcbiAgICAgICAgLy8gdmlldyAtPiBtb2RlbFxuICAgICAgICBkaXIudmFsdWVBY2Nlc3Nvci5yZWdpc3Rlck9uQ2hhbmdlKGZ1bmN0aW9uIChuZXdWYWx1ZSkge1xuICAgICAgICAgICAgZGlyLnZpZXdUb01vZGVsVXBkYXRlKG5ld1ZhbHVlKTtcbiAgICAgICAgICAgIGNvbnRyb2wubWFya0FzRGlydHkoKTtcbiAgICAgICAgICAgIGNvbnRyb2wuc2V0VmFsdWUobmV3VmFsdWUsIHsgZW1pdE1vZGVsVG9WaWV3Q2hhbmdlOiBmYWxzZSB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIHRvdWNoZWRcbiAgICAgICAgZGlyLnZhbHVlQWNjZXNzb3IucmVnaXN0ZXJPblRvdWNoZWQoZnVuY3Rpb24gKCkgeyByZXR1cm4gY29udHJvbC5tYXJrQXNUb3VjaGVkKCk7IH0pO1xuICAgICAgICBjb250cm9sLnJlZ2lzdGVyT25DaGFuZ2UoZnVuY3Rpb24gKG5ld1ZhbHVlLCBlbWl0TW9kZWxFdmVudCkge1xuICAgICAgICAgICAgLy8gY29udHJvbCAtPiB2aWV3XG4gICAgICAgICAgICBkaXIudmFsdWVBY2Nlc3Nvci53cml0ZVZhbHVlKG5ld1ZhbHVlKTtcbiAgICAgICAgICAgIC8vIGNvbnRyb2wgLT4gbmdNb2RlbFxuICAgICAgICAgICAgaWYgKGVtaXRNb2RlbEV2ZW50KVxuICAgICAgICAgICAgICAgIGRpci52aWV3VG9Nb2RlbFVwZGF0ZShuZXdWYWx1ZSk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoZGlyLnZhbHVlQWNjZXNzb3Iuc2V0RGlzYWJsZWRTdGF0ZSkge1xuICAgICAgICAgICAgY29udHJvbC5yZWdpc3Rlck9uRGlzYWJsZWRDaGFuZ2UoZnVuY3Rpb24gKGlzRGlzYWJsZWQpIHsgZGlyLnZhbHVlQWNjZXNzb3Iuc2V0RGlzYWJsZWRTdGF0ZShpc0Rpc2FibGVkKTsgfSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gcmUtcnVuIHZhbGlkYXRpb24gd2hlbiB2YWxpZGF0b3IgYmluZGluZyBjaGFuZ2VzLCBlLmcuIG1pbmxlbmd0aD0zIC0+IG1pbmxlbmd0aD00XG4gICAgICAgIGRpci5fcmF3VmFsaWRhdG9ycy5mb3JFYWNoKGZ1bmN0aW9uICh2YWxpZGF0b3IpIHtcbiAgICAgICAgICAgIGlmICgoKHZhbGlkYXRvcikpLnJlZ2lzdGVyT25WYWxpZGF0b3JDaGFuZ2UpXG4gICAgICAgICAgICAgICAgKCh2YWxpZGF0b3IpKS5yZWdpc3Rlck9uVmFsaWRhdG9yQ2hhbmdlKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvbnRyb2wudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSgpOyB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGRpci5fcmF3QXN5bmNWYWxpZGF0b3JzLmZvckVhY2goZnVuY3Rpb24gKHZhbGlkYXRvcikge1xuICAgICAgICAgICAgaWYgKCgodmFsaWRhdG9yKSkucmVnaXN0ZXJPblZhbGlkYXRvckNoYW5nZSlcbiAgICAgICAgICAgICAgICAoKHZhbGlkYXRvcikpLnJlZ2lzdGVyT25WYWxpZGF0b3JDaGFuZ2UoZnVuY3Rpb24gKCkgeyByZXR1cm4gY29udHJvbC51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KCk7IH0pO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQHBhcmFtIHs/fSBjb250cm9sXG4gICAgICogQHBhcmFtIHs/fSBkaXJcbiAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsZWFuVXBDb250cm9sKGNvbnRyb2wsIGRpcikge1xuICAgICAgICBkaXIudmFsdWVBY2Nlc3Nvci5yZWdpc3Rlck9uQ2hhbmdlKGZ1bmN0aW9uICgpIHsgcmV0dXJuIF9ub0NvbnRyb2xFcnJvcihkaXIpOyB9KTtcbiAgICAgICAgZGlyLnZhbHVlQWNjZXNzb3IucmVnaXN0ZXJPblRvdWNoZWQoZnVuY3Rpb24gKCkgeyByZXR1cm4gX25vQ29udHJvbEVycm9yKGRpcik7IH0pO1xuICAgICAgICBkaXIuX3Jhd1ZhbGlkYXRvcnMuZm9yRWFjaChmdW5jdGlvbiAodmFsaWRhdG9yKSB7XG4gICAgICAgICAgICBpZiAodmFsaWRhdG9yLnJlZ2lzdGVyT25WYWxpZGF0b3JDaGFuZ2UpIHtcbiAgICAgICAgICAgICAgICB2YWxpZGF0b3IucmVnaXN0ZXJPblZhbGlkYXRvckNoYW5nZShudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGRpci5fcmF3QXN5bmNWYWxpZGF0b3JzLmZvckVhY2goZnVuY3Rpb24gKHZhbGlkYXRvcikge1xuICAgICAgICAgICAgaWYgKHZhbGlkYXRvci5yZWdpc3Rlck9uVmFsaWRhdG9yQ2hhbmdlKSB7XG4gICAgICAgICAgICAgICAgdmFsaWRhdG9yLnJlZ2lzdGVyT25WYWxpZGF0b3JDaGFuZ2UobnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoY29udHJvbClcbiAgICAgICAgICAgIGNvbnRyb2wuX2NsZWFyQ2hhbmdlRm5zKCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7P30gY29udHJvbFxuICAgICAqIEBwYXJhbSB7P30gZGlyXG4gICAgICogQHJldHVybiB7P31cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzZXRVcEZvcm1Db250YWluZXIoY29udHJvbCwgZGlyKSB7XG4gICAgICAgIGlmIChpc0JsYW5rKGNvbnRyb2wpKVxuICAgICAgICAgICAgX3Rocm93RXJyb3IoZGlyLCAnQ2Fubm90IGZpbmQgY29udHJvbCB3aXRoJyk7XG4gICAgICAgIGNvbnRyb2wudmFsaWRhdG9yID0gVmFsaWRhdG9ycy5jb21wb3NlKFtjb250cm9sLnZhbGlkYXRvciwgZGlyLnZhbGlkYXRvcl0pO1xuICAgICAgICBjb250cm9sLmFzeW5jVmFsaWRhdG9yID0gVmFsaWRhdG9ycy5jb21wb3NlQXN5bmMoW2NvbnRyb2wuYXN5bmNWYWxpZGF0b3IsIGRpci5hc3luY1ZhbGlkYXRvcl0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gez99IGRpclxuICAgICAqIEByZXR1cm4gez99XG4gICAgICovXG4gICAgZnVuY3Rpb24gX25vQ29udHJvbEVycm9yKGRpcikge1xuICAgICAgICByZXR1cm4gX3Rocm93RXJyb3IoZGlyLCAnVGhlcmUgaXMgbm8gRm9ybUNvbnRyb2wgaW5zdGFuY2UgYXR0YWNoZWQgdG8gZm9ybSBjb250cm9sIGVsZW1lbnQgd2l0aCcpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gez99IGRpclxuICAgICAqIEBwYXJhbSB7P30gbWVzc2FnZVxuICAgICAqIEByZXR1cm4gez99XG4gICAgICovXG4gICAgZnVuY3Rpb24gX3Rocm93RXJyb3IoZGlyLCBtZXNzYWdlKSB7XG4gICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIG1lc3NhZ2VFbmQ7XG4gICAgICAgIGlmIChkaXIucGF0aC5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICBtZXNzYWdlRW5kID0gXCJwYXRoOiAnXCIgKyBkaXIucGF0aC5qb2luKCcgLT4gJykgKyBcIidcIjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChkaXIucGF0aFswXSkge1xuICAgICAgICAgICAgbWVzc2FnZUVuZCA9IFwibmFtZTogJ1wiICsgZGlyLnBhdGggKyBcIidcIjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIG1lc3NhZ2VFbmQgPSAndW5zcGVjaWZpZWQgbmFtZSBhdHRyaWJ1dGUnO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtZXNzYWdlICsgXCIgXCIgKyBtZXNzYWdlRW5kKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQHBhcmFtIHs/fSB2YWxpZGF0b3JzXG4gICAgICogQHJldHVybiB7P31cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb21wb3NlVmFsaWRhdG9ycyh2YWxpZGF0b3JzKSB7XG4gICAgICAgIHJldHVybiBpc1ByZXNlbnQodmFsaWRhdG9ycykgPyBWYWxpZGF0b3JzLmNvbXBvc2UodmFsaWRhdG9ycy5tYXAobm9ybWFsaXplVmFsaWRhdG9yKSkgOiBudWxsO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gez99IHZhbGlkYXRvcnNcbiAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNvbXBvc2VBc3luY1ZhbGlkYXRvcnModmFsaWRhdG9ycykge1xuICAgICAgICByZXR1cm4gaXNQcmVzZW50KHZhbGlkYXRvcnMpID8gVmFsaWRhdG9ycy5jb21wb3NlQXN5bmModmFsaWRhdG9ycy5tYXAobm9ybWFsaXplQXN5bmNWYWxpZGF0b3IpKSA6XG4gICAgICAgICAgICBudWxsO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gez99IGNoYW5nZXNcbiAgICAgKiBAcGFyYW0gez99IHZpZXdNb2RlbFxuICAgICAqIEByZXR1cm4gez99XG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNQcm9wZXJ0eVVwZGF0ZWQoY2hhbmdlcywgdmlld01vZGVsKSB7XG4gICAgICAgIGlmICghY2hhbmdlcy5oYXNPd25Qcm9wZXJ0eSgnbW9kZWwnKSlcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gY2hhbmdlID0gY2hhbmdlc1snbW9kZWwnXTtcbiAgICAgICAgaWYgKGNoYW5nZS5pc0ZpcnN0Q2hhbmdlKCkpXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgcmV0dXJuICFsb29zZUlkZW50aWNhbCh2aWV3TW9kZWwsIGNoYW5nZS5jdXJyZW50VmFsdWUpO1xuICAgIH1cbiAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBCVUlMVElOX0FDQ0VTU09SUyA9IFtcbiAgICAgICAgQ2hlY2tib3hDb250cm9sVmFsdWVBY2Nlc3NvcixcbiAgICAgICAgUmFuZ2VWYWx1ZUFjY2Vzc29yLFxuICAgICAgICBOdW1iZXJWYWx1ZUFjY2Vzc29yLFxuICAgICAgICBTZWxlY3RDb250cm9sVmFsdWVBY2Nlc3NvcixcbiAgICAgICAgU2VsZWN0TXVsdGlwbGVDb250cm9sVmFsdWVBY2Nlc3NvcixcbiAgICAgICAgUmFkaW9Db250cm9sVmFsdWVBY2Nlc3NvcixcbiAgICBdO1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7P30gdmFsdWVBY2Nlc3NvclxuICAgICAqIEByZXR1cm4gez99XG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNCdWlsdEluQWNjZXNzb3IodmFsdWVBY2Nlc3Nvcikge1xuICAgICAgICByZXR1cm4gQlVJTFRJTl9BQ0NFU1NPUlMuc29tZShmdW5jdGlvbiAoYSkgeyByZXR1cm4gdmFsdWVBY2Nlc3Nvci5jb25zdHJ1Y3RvciA9PT0gYTsgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7P30gZGlyXG4gICAgICogQHBhcmFtIHs/fSB2YWx1ZUFjY2Vzc29yc1xuICAgICAqIEByZXR1cm4gez99XG4gICAgICovXG4gICAgZnVuY3Rpb24gc2VsZWN0VmFsdWVBY2Nlc3NvcihkaXIsIHZhbHVlQWNjZXNzb3JzKSB7XG4gICAgICAgIGlmICghdmFsdWVBY2Nlc3NvcnMpXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gZGVmYXVsdEFjY2Vzc29yO1xuICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBidWlsdGluQWNjZXNzb3I7XG4gICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIGN1c3RvbUFjY2Vzc29yO1xuICAgICAgICB2YWx1ZUFjY2Vzc29ycy5mb3JFYWNoKGZ1bmN0aW9uICh2KSB7XG4gICAgICAgICAgICBpZiAodi5jb25zdHJ1Y3RvciA9PT0gRGVmYXVsdFZhbHVlQWNjZXNzb3IpIHtcbiAgICAgICAgICAgICAgICBkZWZhdWx0QWNjZXNzb3IgPSB2O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoaXNCdWlsdEluQWNjZXNzb3IodikpIHtcbiAgICAgICAgICAgICAgICBpZiAoYnVpbHRpbkFjY2Vzc29yKVxuICAgICAgICAgICAgICAgICAgICBfdGhyb3dFcnJvcihkaXIsICdNb3JlIHRoYW4gb25lIGJ1aWx0LWluIHZhbHVlIGFjY2Vzc29yIG1hdGNoZXMgZm9ybSBjb250cm9sIHdpdGgnKTtcbiAgICAgICAgICAgICAgICBidWlsdGluQWNjZXNzb3IgPSB2O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGN1c3RvbUFjY2Vzc29yKVxuICAgICAgICAgICAgICAgICAgICBfdGhyb3dFcnJvcihkaXIsICdNb3JlIHRoYW4gb25lIGN1c3RvbSB2YWx1ZSBhY2Nlc3NvciBtYXRjaGVzIGZvcm0gY29udHJvbCB3aXRoJyk7XG4gICAgICAgICAgICAgICAgY3VzdG9tQWNjZXNzb3IgPSB2O1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGN1c3RvbUFjY2Vzc29yKVxuICAgICAgICAgICAgcmV0dXJuIGN1c3RvbUFjY2Vzc29yO1xuICAgICAgICBpZiAoYnVpbHRpbkFjY2Vzc29yKVxuICAgICAgICAgICAgcmV0dXJuIGJ1aWx0aW5BY2Nlc3NvcjtcbiAgICAgICAgaWYgKGRlZmF1bHRBY2Nlc3NvcilcbiAgICAgICAgICAgIHJldHVybiBkZWZhdWx0QWNjZXNzb3I7XG4gICAgICAgIF90aHJvd0Vycm9yKGRpciwgJ05vIHZhbGlkIHZhbHVlIGFjY2Vzc29yIGZvciBmb3JtIGNvbnRyb2wgd2l0aCcpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAbGljZW5zZVxuICAgICAqIENvcHlyaWdodCBHb29nbGUgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICAgICAqXG4gICAgICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAgICAgKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gICAgICovXG4gICAgdmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqICBUaGlzIGlzIGEgYmFzZSBjbGFzcyBmb3IgY29kZSBzaGFyZWQgYmV0d2VlbiB7QGxpbmsgTmdNb2RlbEdyb3VwfSBhbmQge0BsaW5rIEZvcm1Hcm91cE5hbWV9LlxuICAgICAgKiAqXG4gICAgICovXG4gICAgdmFyIEFic3RyYWN0Rm9ybUdyb3VwRGlyZWN0aXZlID0gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICAgICAgX19leHRlbmRzKEFic3RyYWN0Rm9ybUdyb3VwRGlyZWN0aXZlLCBfc3VwZXIpO1xuICAgICAgICBmdW5jdGlvbiBBYnN0cmFjdEZvcm1Hcm91cERpcmVjdGl2ZSgpIHtcbiAgICAgICAgICAgIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgQWJzdHJhY3RGb3JtR3JvdXBEaXJlY3RpdmUucHJvdG90eXBlLm5nT25Jbml0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy5fY2hlY2tQYXJlbnRUeXBlKCk7XG4gICAgICAgICAgICB0aGlzLmZvcm1EaXJlY3RpdmUuYWRkRm9ybUdyb3VwKHRoaXMpO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEFic3RyYWN0Rm9ybUdyb3VwRGlyZWN0aXZlLnByb3RvdHlwZS5uZ09uRGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmZvcm1EaXJlY3RpdmUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZvcm1EaXJlY3RpdmUucmVtb3ZlRm9ybUdyb3VwKHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQWJzdHJhY3RGb3JtR3JvdXBEaXJlY3RpdmUucHJvdG90eXBlLCBcImNvbnRyb2xcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiAgR2V0IHRoZSB7QGxpbmsgRm9ybUdyb3VwfSBiYWNraW5nIHRoaXMgYmluZGluZy5cbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5mb3JtRGlyZWN0aXZlLmdldEZvcm1Hcm91cCh0aGlzKTsgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShBYnN0cmFjdEZvcm1Hcm91cERpcmVjdGl2ZS5wcm90b3R5cGUsIFwicGF0aFwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqICBHZXQgdGhlIHBhdGggdG8gdGhpcyBjb250cm9sIGdyb3VwLlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBjb250cm9sUGF0aCh0aGlzLm5hbWUsIHRoaXMuX3BhcmVudCk7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQWJzdHJhY3RGb3JtR3JvdXBEaXJlY3RpdmUucHJvdG90eXBlLCBcImZvcm1EaXJlY3RpdmVcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiAgR2V0IHRoZSB7QGxpbmsgRm9ybX0gdG8gd2hpY2ggdGhpcyBncm91cCBiZWxvbmdzLlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9wYXJlbnQgPyB0aGlzLl9wYXJlbnQuZm9ybURpcmVjdGl2ZSA6IG51bGw7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQWJzdHJhY3RGb3JtR3JvdXBEaXJlY3RpdmUucHJvdG90eXBlLCBcInZhbGlkYXRvclwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gY29tcG9zZVZhbGlkYXRvcnModGhpcy5fdmFsaWRhdG9ycyk7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQWJzdHJhY3RGb3JtR3JvdXBEaXJlY3RpdmUucHJvdG90eXBlLCBcImFzeW5jVmFsaWRhdG9yXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBjb21wb3NlQXN5bmNWYWxpZGF0b3JzKHRoaXMuX2FzeW5jVmFsaWRhdG9ycyk7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEFic3RyYWN0Rm9ybUdyb3VwRGlyZWN0aXZlLnByb3RvdHlwZS5fY2hlY2tQYXJlbnRUeXBlID0gZnVuY3Rpb24gKCkgeyB9O1xuICAgICAgICByZXR1cm4gQWJzdHJhY3RGb3JtR3JvdXBEaXJlY3RpdmU7XG4gICAgfShDb250cm9sQ29udGFpbmVyKSk7XG5cbiAgICAvKipcbiAgICAgKiBAbGljZW5zZVxuICAgICAqIENvcHlyaWdodCBHb29nbGUgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICAgICAqXG4gICAgICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAgICAgKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gICAgICovXG4gICAgdmFyIF9fZXh0ZW5kcyQzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG4gICAgdmFyIEFic3RyYWN0Q29udHJvbFN0YXR1cyA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGNkXG4gICAgICAgICAqL1xuICAgICAgICBmdW5jdGlvbiBBYnN0cmFjdENvbnRyb2xTdGF0dXMoY2QpIHtcbiAgICAgICAgICAgIHRoaXMuX2NkID0gY2Q7XG4gICAgICAgIH1cbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFic3RyYWN0Q29udHJvbFN0YXR1cy5wcm90b3R5cGUsIFwibmdDbGFzc1VudG91Y2hlZFwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5fY2QuY29udHJvbCA/IHRoaXMuX2NkLmNvbnRyb2wudW50b3VjaGVkIDogZmFsc2U7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQWJzdHJhY3RDb250cm9sU3RhdHVzLnByb3RvdHlwZSwgXCJuZ0NsYXNzVG91Y2hlZFwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5fY2QuY29udHJvbCA/IHRoaXMuX2NkLmNvbnRyb2wudG91Y2hlZCA6IGZhbHNlOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFic3RyYWN0Q29udHJvbFN0YXR1cy5wcm90b3R5cGUsIFwibmdDbGFzc1ByaXN0aW5lXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9jZC5jb250cm9sID8gdGhpcy5fY2QuY29udHJvbC5wcmlzdGluZSA6IGZhbHNlOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFic3RyYWN0Q29udHJvbFN0YXR1cy5wcm90b3R5cGUsIFwibmdDbGFzc0RpcnR5XCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9jZC5jb250cm9sID8gdGhpcy5fY2QuY29udHJvbC5kaXJ0eSA6IGZhbHNlOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFic3RyYWN0Q29udHJvbFN0YXR1cy5wcm90b3R5cGUsIFwibmdDbGFzc1ZhbGlkXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9jZC5jb250cm9sID8gdGhpcy5fY2QuY29udHJvbC52YWxpZCA6IGZhbHNlOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFic3RyYWN0Q29udHJvbFN0YXR1cy5wcm90b3R5cGUsIFwibmdDbGFzc0ludmFsaWRcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2NkLmNvbnRyb2wgPyB0aGlzLl9jZC5jb250cm9sLmludmFsaWQgOiBmYWxzZTsgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShBYnN0cmFjdENvbnRyb2xTdGF0dXMucHJvdG90eXBlLCBcIm5nQ2xhc3NQZW5kaW5nXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9jZC5jb250cm9sID8gdGhpcy5fY2QuY29udHJvbC5wZW5kaW5nIDogZmFsc2U7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gQWJzdHJhY3RDb250cm9sU3RhdHVzO1xuICAgIH0oKSk7XG4gICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gbmdDb250cm9sU3RhdHVzSG9zdCA9IHtcbiAgICAgICAgJ1tjbGFzcy5uZy11bnRvdWNoZWRdJzogJ25nQ2xhc3NVbnRvdWNoZWQnLFxuICAgICAgICAnW2NsYXNzLm5nLXRvdWNoZWRdJzogJ25nQ2xhc3NUb3VjaGVkJyxcbiAgICAgICAgJ1tjbGFzcy5uZy1wcmlzdGluZV0nOiAnbmdDbGFzc1ByaXN0aW5lJyxcbiAgICAgICAgJ1tjbGFzcy5uZy1kaXJ0eV0nOiAnbmdDbGFzc0RpcnR5JyxcbiAgICAgICAgJ1tjbGFzcy5uZy12YWxpZF0nOiAnbmdDbGFzc1ZhbGlkJyxcbiAgICAgICAgJ1tjbGFzcy5uZy1pbnZhbGlkXSc6ICduZ0NsYXNzSW52YWxpZCcsXG4gICAgICAgICdbY2xhc3MubmctcGVuZGluZ10nOiAnbmdDbGFzc1BlbmRpbmcnLFxuICAgIH07XG4gICAgLyoqXG4gICAgICogIERpcmVjdGl2ZSBhdXRvbWF0aWNhbGx5IGFwcGxpZWQgdG8gQW5ndWxhciBmb3JtIGNvbnRyb2xzIHRoYXQgc2V0cyBDU1MgY2xhc3Nlc1xuICAgICAgKiBiYXNlZCBvbiBjb250cm9sIHN0YXR1cyAodmFsaWQvaW52YWxpZC9kaXJ0eS9ldGMpLlxuICAgICAgKiAqXG4gICAgICovXG4gICAgdmFyIE5nQ29udHJvbFN0YXR1cyA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgICAgIF9fZXh0ZW5kcyQzKE5nQ29udHJvbFN0YXR1cywgX3N1cGVyKTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gY2RcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIE5nQ29udHJvbFN0YXR1cyhjZCkge1xuICAgICAgICAgICAgX3N1cGVyLmNhbGwodGhpcywgY2QpO1xuICAgICAgICB9XG4gICAgICAgIE5nQ29udHJvbFN0YXR1cy5kZWNvcmF0b3JzID0gW1xuICAgICAgICAgICAgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkRpcmVjdGl2ZSwgYXJnczogW3sgc2VsZWN0b3I6ICdbZm9ybUNvbnRyb2xOYW1lXSxbbmdNb2RlbF0sW2Zvcm1Db250cm9sXScsIGhvc3Q6IG5nQ29udHJvbFN0YXR1c0hvc3QgfSxdIH0sXG4gICAgICAgIF07XG4gICAgICAgIC8qKiBAbm9jb2xsYXBzZSAqL1xuICAgICAgICBOZ0NvbnRyb2xTdGF0dXMuY3RvclBhcmFtZXRlcnMgPSBmdW5jdGlvbiAoKSB7IHJldHVybiBbXG4gICAgICAgICAgICB7IHR5cGU6IE5nQ29udHJvbCwgZGVjb3JhdG9yczogW3sgdHlwZTogX2FuZ3VsYXJfY29yZS5TZWxmIH0sXSB9LFxuICAgICAgICBdOyB9O1xuICAgICAgICByZXR1cm4gTmdDb250cm9sU3RhdHVzO1xuICAgIH0oQWJzdHJhY3RDb250cm9sU3RhdHVzKSk7XG4gICAgLyoqXG4gICAgICogIERpcmVjdGl2ZSBhdXRvbWF0aWNhbGx5IGFwcGxpZWQgdG8gQW5ndWxhciBmb3JtIGdyb3VwcyB0aGF0IHNldHMgQ1NTIGNsYXNzZXNcbiAgICAgICogYmFzZWQgb24gY29udHJvbCBzdGF0dXMgKHZhbGlkL2ludmFsaWQvZGlydHkvZXRjKS5cbiAgICAgICogKlxuICAgICAqL1xuICAgIHZhciBOZ0NvbnRyb2xTdGF0dXNHcm91cCA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgICAgIF9fZXh0ZW5kcyQzKE5nQ29udHJvbFN0YXR1c0dyb3VwLCBfc3VwZXIpO1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBjZFxuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gTmdDb250cm9sU3RhdHVzR3JvdXAoY2QpIHtcbiAgICAgICAgICAgIF9zdXBlci5jYWxsKHRoaXMsIGNkKTtcbiAgICAgICAgfVxuICAgICAgICBOZ0NvbnRyb2xTdGF0dXNHcm91cC5kZWNvcmF0b3JzID0gW1xuICAgICAgICAgICAgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkRpcmVjdGl2ZSwgYXJnczogW3tcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdG9yOiAnW2Zvcm1Hcm91cE5hbWVdLFtmb3JtQXJyYXlOYW1lXSxbbmdNb2RlbEdyb3VwXSxbZm9ybUdyb3VwXSxmb3JtOm5vdChbbmdOb0Zvcm1dKSxbbmdGb3JtXScsXG4gICAgICAgICAgICAgICAgICAgICAgICBob3N0OiBuZ0NvbnRyb2xTdGF0dXNIb3N0XG4gICAgICAgICAgICAgICAgICAgIH0sXSB9LFxuICAgICAgICBdO1xuICAgICAgICAvKiogQG5vY29sbGFwc2UgKi9cbiAgICAgICAgTmdDb250cm9sU3RhdHVzR3JvdXAuY3RvclBhcmFtZXRlcnMgPSBmdW5jdGlvbiAoKSB7IHJldHVybiBbXG4gICAgICAgICAgICB7IHR5cGU6IENvbnRyb2xDb250YWluZXIsIGRlY29yYXRvcnM6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuU2VsZiB9LF0gfSxcbiAgICAgICAgXTsgfTtcbiAgICAgICAgcmV0dXJuIE5nQ29udHJvbFN0YXR1c0dyb3VwO1xuICAgIH0oQWJzdHJhY3RDb250cm9sU3RhdHVzKSk7XG5cbiAgICAvKipcbiAgICAgKiBAbGljZW5zZVxuICAgICAqIENvcHlyaWdodCBHb29nbGUgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICAgICAqXG4gICAgICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAgICAgKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gICAgICovXG4gICAgdmFyIF9fZXh0ZW5kcyQ1ID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG4gICAgLyoqXG4gICAgICogIFVzZSBieSBkaXJlY3RpdmVzIGFuZCBjb21wb25lbnRzIHRvIGVtaXQgY3VzdG9tIEV2ZW50cy5cbiAgICAgICogKlxuICAgICAgKiAjIyMgRXhhbXBsZXNcbiAgICAgICogKlxuICAgICAgKiBJbiB0aGUgZm9sbG93aW5nIGV4YW1wbGUsIGBaaXBweWAgYWx0ZXJuYXRpdmVseSBlbWl0cyBgb3BlbmAgYW5kIGBjbG9zZWAgZXZlbnRzIHdoZW4gaXRzXG4gICAgICAqIHRpdGxlIGdldHMgY2xpY2tlZDpcbiAgICAgICogKlxuICAgICAgKiBgYGBcbiAgICAgICogc2VsZWN0b3I6ICd6aXBweScsXG4gICAgICAqIHRlbXBsYXRlOiBgXG4gICAgICAqIDxkaXYgY2xhc3M9XCJ6aXBweVwiPlxuICAgICAgKiA8ZGl2IChjbGljayk9XCJ0b2dnbGUoKVwiPlRvZ2dsZTwvZGl2PlxuICAgICAgKiA8ZGl2IFtoaWRkZW5dPVwiIXZpc2libGVcIj5cbiAgICAgICogPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuICAgICAgKiA8L2Rpdj5cbiAgICAgICogPC9kaXY+YH0pXG4gICAgICAqIGV4cG9ydCBjbGFzcyBaaXBweSB7XG4gICAgICAqIHZpc2libGU6IGJvb2xlYW4gPSB0cnVlO1xuICAgICAgKiBAT3V0cHV0KCkgb3BlbjogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgICAqIEBPdXRwdXQoKSBjbG9zZTogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgICAqICpcbiAgICAgICogdG9nZ2xlKCkge1xuICAgICAgKiB0aGlzLnZpc2libGUgPSAhdGhpcy52aXNpYmxlO1xuICAgICAgKiBpZiAodGhpcy52aXNpYmxlKSB7XG4gICAgICAqIHRoaXMub3Blbi5lbWl0KG51bGwpO1xuICAgICAgKiB9IGVsc2Uge1xuICAgICAgKiB0aGlzLmNsb3NlLmVtaXQobnVsbCk7XG4gICAgICAqIH1cbiAgICAgICogfVxuICAgICAgKiB9XG4gICAgICAqIGBgYFxuICAgICAgKiAqXG4gICAgICAqIFRoZSBldmVudHMgcGF5bG9hZCBjYW4gYmUgYWNjZXNzZWQgYnkgdGhlIHBhcmFtZXRlciBgJGV2ZW50YCBvbiB0aGUgY29tcG9uZW50cyBvdXRwdXQgZXZlbnRcbiAgICAgICogaGFuZGxlcjpcbiAgICAgICogKlxuICAgICAgKiBgYGBcbiAgICAgICogPHppcHB5IChvcGVuKT1cIm9uT3BlbigkZXZlbnQpXCIgKGNsb3NlKT1cIm9uQ2xvc2UoJGV2ZW50KVwiPjwvemlwcHk+XG4gICAgICAqIGBgYFxuICAgICAgKiAqXG4gICAgICAqIFVzZXMgUnguT2JzZXJ2YWJsZSBidXQgcHJvdmlkZXMgYW4gYWRhcHRlciB0byBtYWtlIGl0IHdvcmsgYXMgc3BlY2lmaWVkIGhlcmU6XG4gICAgICAqIGh0dHBzOi8vZ2l0aHViLmNvbS9qaHVzYWluL29ic2VydmFibGUtc3BlY1xuICAgICAgKiAqXG4gICAgICAqIE9uY2UgYSByZWZlcmVuY2UgaW1wbGVtZW50YXRpb24gb2YgdGhlIHNwZWMgaXMgYXZhaWxhYmxlLCBzd2l0Y2ggdG8gaXQuXG4gICAgICovXG4gICAgdmFyIEV2ZW50RW1pdHRlciA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgICAgIF9fZXh0ZW5kcyQ1KEV2ZW50RW1pdHRlciwgX3N1cGVyKTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqICBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIFtFdmVudEVtaXR0ZXJdLCB3aGljaCBkZXBlbmRpbmcgb24gW2lzQXN5bmNdLFxuICAgICAgICAgICogZGVsaXZlcnMgZXZlbnRzIHN5bmNocm9ub3VzbHkgb3IgYXN5bmNocm9ub3VzbHkuXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IGlzQXN5bmNcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIEV2ZW50RW1pdHRlcihpc0FzeW5jKSB7XG4gICAgICAgICAgICBpZiAoaXNBc3luYyA9PT0gdm9pZCAwKSB7IGlzQXN5bmMgPSBmYWxzZTsgfVxuICAgICAgICAgICAgX3N1cGVyLmNhbGwodGhpcyk7XG4gICAgICAgICAgICB0aGlzLl9faXNBc3luYyA9IGlzQXN5bmM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IHZhbHVlXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBFdmVudEVtaXR0ZXIucHJvdG90eXBlLmVtaXQgPSBmdW5jdGlvbiAodmFsdWUpIHsgX3N1cGVyLnByb3RvdHlwZS5uZXh0LmNhbGwodGhpcywgdmFsdWUpOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/PX0gZ2VuZXJhdG9yT3JOZXh0XG4gICAgICAgICAqIEBwYXJhbSB7Pz19IGVycm9yXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IGNvbXBsZXRlXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBFdmVudEVtaXR0ZXIucHJvdG90eXBlLnN1YnNjcmliZSA9IGZ1bmN0aW9uIChnZW5lcmF0b3JPck5leHQsIGVycm9yLCBjb21wbGV0ZSkge1xuICAgICAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gc2NoZWR1bGVyRm47XG4gICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBlcnJvckZuID0gZnVuY3Rpb24gKGVycikgeyByZXR1cm4gbnVsbDsgfTtcbiAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIGNvbXBsZXRlRm4gPSBmdW5jdGlvbiAoKSB7IHJldHVybiBudWxsOyB9O1xuICAgICAgICAgICAgaWYgKGdlbmVyYXRvck9yTmV4dCAmJiB0eXBlb2YgZ2VuZXJhdG9yT3JOZXh0ID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgIHNjaGVkdWxlckZuID0gdGhpcy5fX2lzQXN5bmMgPyBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7IHJldHVybiBnZW5lcmF0b3JPck5leHQubmV4dCh2YWx1ZSk7IH0pO1xuICAgICAgICAgICAgICAgIH0gOiBmdW5jdGlvbiAodmFsdWUpIHsgZ2VuZXJhdG9yT3JOZXh0Lm5leHQodmFsdWUpOyB9O1xuICAgICAgICAgICAgICAgIGlmIChnZW5lcmF0b3JPck5leHQuZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JGbiA9IHRoaXMuX19pc0FzeW5jID8gZnVuY3Rpb24gKGVycikgeyBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHsgcmV0dXJuIGdlbmVyYXRvck9yTmV4dC5lcnJvcihlcnIpOyB9KTsgfSA6XG4gICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiAoZXJyKSB7IGdlbmVyYXRvck9yTmV4dC5lcnJvcihlcnIpOyB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZ2VuZXJhdG9yT3JOZXh0LmNvbXBsZXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBsZXRlRm4gPSB0aGlzLl9faXNBc3luYyA/IGZ1bmN0aW9uICgpIHsgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7IHJldHVybiBnZW5lcmF0b3JPck5leHQuY29tcGxldGUoKTsgfSk7IH0gOlxuICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gKCkgeyBnZW5lcmF0b3JPck5leHQuY29tcGxldGUoKTsgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBzY2hlZHVsZXJGbiA9IHRoaXMuX19pc0FzeW5jID8gZnVuY3Rpb24gKHZhbHVlKSB7IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyByZXR1cm4gZ2VuZXJhdG9yT3JOZXh0KHZhbHVlKTsgfSk7IH0gOlxuICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiAodmFsdWUpIHsgZ2VuZXJhdG9yT3JOZXh0KHZhbHVlKTsgfTtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JGbiA9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9faXNBc3luYyA/IGZ1bmN0aW9uIChlcnIpIHsgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7IHJldHVybiBlcnJvcihlcnIpOyB9KTsgfSA6IGZ1bmN0aW9uIChlcnIpIHsgZXJyb3IoZXJyKTsgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGNvbXBsZXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBsZXRlRm4gPVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fX2lzQXN5bmMgPyBmdW5jdGlvbiAoKSB7IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyByZXR1cm4gY29tcGxldGUoKTsgfSk7IH0gOiBmdW5jdGlvbiAoKSB7IGNvbXBsZXRlKCk7IH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIF9zdXBlci5wcm90b3R5cGUuc3Vic2NyaWJlLmNhbGwodGhpcywgc2NoZWR1bGVyRm4sIGVycm9yRm4sIGNvbXBsZXRlRm4pO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gRXZlbnRFbWl0dGVyO1xuICAgIH0ocnhqc19TdWJqZWN0LlN1YmplY3QpKTtcblxuICAgIC8qKlxuICAgICAqIEBsaWNlbnNlXG4gICAgICogQ29weXJpZ2h0IEdvb2dsZSBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gICAgICpcbiAgICAgKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICAgICAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAgICAgKi9cbiAgICB2YXIgX19leHRlbmRzJDYgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbiAgICAvKipcbiAgICAgKiBJbmRpY2F0ZXMgdGhhdCBhIEZvcm1Db250cm9sIGlzIHZhbGlkLCBpLmUuIHRoYXQgbm8gZXJyb3JzIGV4aXN0IGluIHRoZSBpbnB1dCB2YWx1ZS5cbiAgICAgKi9cbiAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBWQUxJRCA9ICdWQUxJRCc7XG4gICAgLyoqXG4gICAgICogSW5kaWNhdGVzIHRoYXQgYSBGb3JtQ29udHJvbCBpcyBpbnZhbGlkLCBpLmUuIHRoYXQgYW4gZXJyb3IgZXhpc3RzIGluIHRoZSBpbnB1dCB2YWx1ZS5cbiAgICAgKi9cbiAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBJTlZBTElEID0gJ0lOVkFMSUQnO1xuICAgIC8qKlxuICAgICAqIEluZGljYXRlcyB0aGF0IGEgRm9ybUNvbnRyb2wgaXMgcGVuZGluZywgaS5lLiB0aGF0IGFzeW5jIHZhbGlkYXRpb24gaXMgb2NjdXJyaW5nIGFuZFxuICAgICAqIGVycm9ycyBhcmUgbm90IHlldCBhdmFpbGFibGUgZm9yIHRoZSBpbnB1dCB2YWx1ZS5cbiAgICAgKi9cbiAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBQRU5ESU5HID0gJ1BFTkRJTkcnO1xuICAgIC8qKlxuICAgICAqIEluZGljYXRlcyB0aGF0IGEgRm9ybUNvbnRyb2wgaXMgZGlzYWJsZWQsIGkuZS4gdGhhdCB0aGUgY29udHJvbCBpcyBleGVtcHQgZnJvbSBhbmNlc3RvclxuICAgICAqIGNhbGN1bGF0aW9ucyBvZiB2YWxpZGl0eSBvciB2YWx1ZS5cbiAgICAgKi9cbiAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBESVNBQkxFRCA9ICdESVNBQkxFRCc7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIHs/fSBjb250cm9sXG4gICAgICogQHBhcmFtIHs/fSBwYXRoXG4gICAgICogQHBhcmFtIHs/fSBkZWxpbWl0ZXJcbiAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIF9maW5kKGNvbnRyb2wsIHBhdGgsIGRlbGltaXRlcikge1xuICAgICAgICBpZiAocGF0aCA9PSBudWxsKVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIGlmICghKHBhdGggaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgICAgIHBhdGggPSAoKHBhdGgpKS5zcGxpdChkZWxpbWl0ZXIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwYXRoIGluc3RhbmNlb2YgQXJyYXkgJiYgKHBhdGgubGVuZ3RoID09PSAwKSlcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICByZXR1cm4gKChwYXRoKSkucmVkdWNlKGZ1bmN0aW9uICh2LCBuYW1lKSB7XG4gICAgICAgICAgICBpZiAodiBpbnN0YW5jZW9mIEZvcm1Hcm91cCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB2LmNvbnRyb2xzW25hbWVdIHx8IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodiBpbnN0YW5jZW9mIEZvcm1BcnJheSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB2LmF0KC8qKiBAdHlwZSB7P30gKi8gKG5hbWUpKSB8fCBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH0sIGNvbnRyb2wpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gez99IHJcbiAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvT2JzZXJ2YWJsZShyKSB7XG4gICAgICAgIHJldHVybiBpc1Byb21pc2UocikgPyByeGpzX29ic2VydmFibGVfZnJvbVByb21pc2UuZnJvbVByb21pc2UocikgOiByO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gez99IHZhbGlkYXRvclxuICAgICAqIEByZXR1cm4gez99XG4gICAgICovXG4gICAgZnVuY3Rpb24gY29lcmNlVG9WYWxpZGF0b3IodmFsaWRhdG9yKSB7XG4gICAgICAgIHJldHVybiBBcnJheS5pc0FycmF5KHZhbGlkYXRvcikgPyBjb21wb3NlVmFsaWRhdG9ycyh2YWxpZGF0b3IpIDogdmFsaWRhdG9yO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gez99IGFzeW5jVmFsaWRhdG9yXG4gICAgICogQHJldHVybiB7P31cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb2VyY2VUb0FzeW5jVmFsaWRhdG9yKGFzeW5jVmFsaWRhdG9yKSB7XG4gICAgICAgIHJldHVybiBBcnJheS5pc0FycmF5KGFzeW5jVmFsaWRhdG9yKSA/IGNvbXBvc2VBc3luY1ZhbGlkYXRvcnMoYXN5bmNWYWxpZGF0b3IpIDogYXN5bmNWYWxpZGF0b3I7XG4gICAgfVxuICAgIC8qKlxuICAgICAqICB7QGxpbmsgRm9ybUFycmF5fS5cbiAgICAgICogKlxuICAgICAgKiBJdCBwcm92aWRlcyBzb21lIG9mIHRoZSBzaGFyZWQgYmVoYXZpb3IgdGhhdCBhbGwgY29udHJvbHMgYW5kIGdyb3VwcyBvZiBjb250cm9scyBoYXZlLCBsaWtlXG4gICAgICAqIHJ1bm5pbmcgdmFsaWRhdG9ycywgY2FsY3VsYXRpbmcgc3RhdHVzLCBhbmQgcmVzZXR0aW5nIHN0YXRlLiBJdCBhbHNvIGRlZmluZXMgdGhlIHByb3BlcnRpZXNcbiAgICAgICogdGhhdCBhcmUgc2hhcmVkIGJldHdlZW4gYWxsIHN1Yi1jbGFzc2VzLCBsaWtlIGB2YWx1ZWAsIGB2YWxpZGAsIGFuZCBgZGlydHlgLiBJdCBzaG91bGRuJ3QgYmVcbiAgICAgICogaW5zdGFudGlhdGVkIGRpcmVjdGx5LlxuICAgICAgKiAqXG4gICAgICogQGFic3RyYWN0XG4gICAgICovXG4gICAgdmFyIEFic3RyYWN0Q29udHJvbCA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IHZhbGlkYXRvclxuICAgICAgICAgKiBAcGFyYW0gez99IGFzeW5jVmFsaWRhdG9yXG4gICAgICAgICAqL1xuICAgICAgICBmdW5jdGlvbiBBYnN0cmFjdENvbnRyb2wodmFsaWRhdG9yLCBhc3luY1ZhbGlkYXRvcikge1xuICAgICAgICAgICAgdGhpcy52YWxpZGF0b3IgPSB2YWxpZGF0b3I7XG4gICAgICAgICAgICB0aGlzLmFzeW5jVmFsaWRhdG9yID0gYXN5bmNWYWxpZGF0b3I7XG4gICAgICAgICAgICAvKiogQGludGVybmFsICovXG4gICAgICAgICAgICB0aGlzLl9vbkNvbGxlY3Rpb25DaGFuZ2UgPSBmdW5jdGlvbiAoKSB7IH07XG4gICAgICAgICAgICB0aGlzLl9wcmlzdGluZSA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLl90b3VjaGVkID0gZmFsc2U7XG4gICAgICAgICAgICAvKiogQGludGVybmFsICovXG4gICAgICAgICAgICB0aGlzLl9vbkRpc2FibGVkQ2hhbmdlID0gW107XG4gICAgICAgIH1cbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUsIFwidmFsdWVcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiAgVGhlIHZhbHVlIG9mIHRoZSBjb250cm9sLlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl92YWx1ZTsgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShBYnN0cmFjdENvbnRyb2wucHJvdG90eXBlLCBcInBhcmVudFwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqICBUaGUgcGFyZW50IGNvbnRyb2wuXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX3BhcmVudDsgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShBYnN0cmFjdENvbnRyb2wucHJvdG90eXBlLCBcInN0YXR1c1wiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqICBUaGUgdmFsaWRhdGlvbiBzdGF0dXMgb2YgdGhlIGNvbnRyb2wuIFRoZXJlIGFyZSBmb3VyIHBvc3NpYmxlXG4gICAgICAgICAgICAgICogdmFsaWRhdGlvbiBzdGF0dXNlczpcbiAgICAgICAgICAgICAgKiAqXG4gICAgICAgICAgICAgICogKiAqKlZBTElEKio6ICBjb250cm9sIGhhcyBwYXNzZWQgYWxsIHZhbGlkYXRpb24gY2hlY2tzXG4gICAgICAgICAgICAgICogKiAqKklOVkFMSUQqKjogY29udHJvbCBoYXMgZmFpbGVkIGF0IGxlYXN0IG9uZSB2YWxpZGF0aW9uIGNoZWNrXG4gICAgICAgICAgICAgICogKiAqKlBFTkRJTkcqKjogY29udHJvbCBpcyBpbiB0aGUgbWlkc3Qgb2YgY29uZHVjdGluZyBhIHZhbGlkYXRpb24gY2hlY2tcbiAgICAgICAgICAgICAgKiAqICoqRElTQUJMRUQqKjogY29udHJvbCBpcyBleGVtcHQgZnJvbSB2YWxpZGF0aW9uIGNoZWNrc1xuICAgICAgICAgICAgICAqICpcbiAgICAgICAgICAgICAgKiBUaGVzZSBzdGF0dXNlcyBhcmUgbXV0dWFsbHkgZXhjbHVzaXZlLCBzbyBhIGNvbnRyb2wgY2Fubm90IGJlXG4gICAgICAgICAgICAgICogYm90aCB2YWxpZCBBTkQgaW52YWxpZCBvciBpbnZhbGlkIEFORCBkaXNhYmxlZC5cbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5fc3RhdHVzOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUsIFwidmFsaWRcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiAgQSBjb250cm9sIGlzIGB2YWxpZGAgd2hlbiBpdHMgYHN0YXR1cyA9PT0gVkFMSURgLlxuICAgICAgICAgICAgICAqICpcbiAgICAgICAgICAgICAgKiBJbiBvcmRlciB0byBoYXZlIHRoaXMgc3RhdHVzLCB0aGUgY29udHJvbCBtdXN0IGhhdmUgcGFzc2VkIGFsbCBpdHNcbiAgICAgICAgICAgICAgKiB2YWxpZGF0aW9uIGNoZWNrcy5cbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5fc3RhdHVzID09PSBWQUxJRDsgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShBYnN0cmFjdENvbnRyb2wucHJvdG90eXBlLCBcImludmFsaWRcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiAgQSBjb250cm9sIGlzIGBpbnZhbGlkYCB3aGVuIGl0cyBgc3RhdHVzID09PSBJTlZBTElEYC5cbiAgICAgICAgICAgICAgKiAqXG4gICAgICAgICAgICAgICogSW4gb3JkZXIgdG8gaGF2ZSB0aGlzIHN0YXR1cywgdGhlIGNvbnRyb2wgbXVzdCBoYXZlIGZhaWxlZFxuICAgICAgICAgICAgICAqIGF0IGxlYXN0IG9uZSBvZiBpdHMgdmFsaWRhdGlvbiBjaGVja3MuXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX3N0YXR1cyA9PT0gSU5WQUxJRDsgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShBYnN0cmFjdENvbnRyb2wucHJvdG90eXBlLCBcInBlbmRpbmdcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiAgQSBjb250cm9sIGlzIGBwZW5kaW5nYCB3aGVuIGl0cyBgc3RhdHVzID09PSBQRU5ESU5HYC5cbiAgICAgICAgICAgICAgKiAqXG4gICAgICAgICAgICAgICogSW4gb3JkZXIgdG8gaGF2ZSB0aGlzIHN0YXR1cywgdGhlIGNvbnRyb2wgbXVzdCBiZSBpbiB0aGVcbiAgICAgICAgICAgICAgKiBtaWRkbGUgb2YgY29uZHVjdGluZyBhIHZhbGlkYXRpb24gY2hlY2suXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX3N0YXR1cyA9PSBQRU5ESU5HOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUsIFwiZGlzYWJsZWRcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiAgQSBjb250cm9sIGlzIGBkaXNhYmxlZGAgd2hlbiBpdHMgYHN0YXR1cyA9PT0gRElTQUJMRURgLlxuICAgICAgICAgICAgICAqICpcbiAgICAgICAgICAgICAgKiBEaXNhYmxlZCBjb250cm9scyBhcmUgZXhlbXB0IGZyb20gdmFsaWRhdGlvbiBjaGVja3MgYW5kXG4gICAgICAgICAgICAgICogYXJlIG5vdCBpbmNsdWRlZCBpbiB0aGUgYWdncmVnYXRlIHZhbHVlIG9mIHRoZWlyIGFuY2VzdG9yXG4gICAgICAgICAgICAgICogY29udHJvbHMuXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX3N0YXR1cyA9PT0gRElTQUJMRUQ7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZSwgXCJlbmFibGVkXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogIEEgY29udHJvbCBpcyBgZW5hYmxlZGAgYXMgbG9uZyBhcyBpdHMgYHN0YXR1cyAhPT0gRElTQUJMRURgLlxuICAgICAgICAgICAgICAqICpcbiAgICAgICAgICAgICAgKiBJbiBvdGhlciB3b3JkcywgaXQgaGFzIGEgc3RhdHVzIG9mIGBWQUxJRGAsIGBJTlZBTElEYCwgb3JcbiAgICAgICAgICAgICAgKiBgUEVORElOR2AuXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX3N0YXR1cyAhPT0gRElTQUJMRUQ7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZSwgXCJlcnJvcnNcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiAgUmV0dXJucyBhbnkgZXJyb3JzIGdlbmVyYXRlZCBieSBmYWlsaW5nIHZhbGlkYXRpb24uIElmIHRoZXJlXG4gICAgICAgICAgICAgICogYXJlIG5vIGVycm9ycywgaXQgd2lsbCByZXR1cm4gbnVsbC5cbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5fZXJyb3JzOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUsIFwicHJpc3RpbmVcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiAgQSBjb250cm9sIGlzIGBwcmlzdGluZWAgaWYgdGhlIHVzZXIgaGFzIG5vdCB5ZXQgY2hhbmdlZFxuICAgICAgICAgICAgICAqIHRoZSB2YWx1ZSBpbiB0aGUgVUkuXG4gICAgICAgICAgICAgICogKlxuICAgICAgICAgICAgICAqIE5vdGUgdGhhdCBwcm9ncmFtbWF0aWMgY2hhbmdlcyB0byBhIGNvbnRyb2wncyB2YWx1ZSB3aWxsXG4gICAgICAgICAgICAgICogKm5vdCogbWFyayBpdCBkaXJ0eS5cbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5fcHJpc3RpbmU7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZSwgXCJkaXJ0eVwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqICBBIGNvbnRyb2wgaXMgYGRpcnR5YCBpZiB0aGUgdXNlciBoYXMgY2hhbmdlZCB0aGUgdmFsdWVcbiAgICAgICAgICAgICAgKiBpbiB0aGUgVUkuXG4gICAgICAgICAgICAgICogKlxuICAgICAgICAgICAgICAqIE5vdGUgdGhhdCBwcm9ncmFtbWF0aWMgY2hhbmdlcyB0byBhIGNvbnRyb2wncyB2YWx1ZSB3aWxsXG4gICAgICAgICAgICAgICogKm5vdCogbWFyayBpdCBkaXJ0eS5cbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gIXRoaXMucHJpc3RpbmU7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZSwgXCJ0b3VjaGVkXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogIEEgY29udHJvbCBpcyBtYXJrZWQgYHRvdWNoZWRgIG9uY2UgdGhlIHVzZXIgaGFzIHRyaWdnZXJlZFxuICAgICAgICAgICAgICAqIGEgYGJsdXJgIGV2ZW50IG9uIGl0LlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl90b3VjaGVkOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUsIFwidW50b3VjaGVkXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogIEEgY29udHJvbCBpcyBgdW50b3VjaGVkYCBpZiB0aGUgdXNlciBoYXMgbm90IHlldCB0cmlnZ2VyZWRcbiAgICAgICAgICAgICAgKiBhIGBibHVyYCBldmVudCBvbiBpdC5cbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gIXRoaXMuX3RvdWNoZWQ7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZSwgXCJ2YWx1ZUNoYW5nZXNcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiAgRW1pdHMgYW4gZXZlbnQgZXZlcnkgdGltZSB0aGUgdmFsdWUgb2YgdGhlIGNvbnRyb2wgY2hhbmdlcywgaW5cbiAgICAgICAgICAgICAgKiB0aGUgVUkgb3IgcHJvZ3JhbW1hdGljYWxseS5cbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5fdmFsdWVDaGFuZ2VzOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUsIFwic3RhdHVzQ2hhbmdlc1wiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqICBFbWl0cyBhbiBldmVudCBldmVyeSB0aW1lIHRoZSB2YWxpZGF0aW9uIHN0YXR1cyBvZiB0aGUgY29udHJvbFxuICAgICAgICAgICAgICAqIGlzIHJlLWNhbGN1bGF0ZWQuXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX3N0YXR1c0NoYW5nZXM7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICAvKipcbiAgICAgICAgICogIFNldHMgdGhlIHN5bmNocm9ub3VzIHZhbGlkYXRvcnMgdGhhdCBhcmUgYWN0aXZlIG9uIHRoaXMgY29udHJvbC4gIENhbGxpbmdcbiAgICAgICAgICAqIHRoaXMgd2lsbCBvdmVyd3JpdGUgYW55IGV4aXN0aW5nIHN5bmMgdmFsaWRhdG9ycy5cbiAgICAgICAgICogQHBhcmFtIHs/fSBuZXdWYWxpZGF0b3JcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUuc2V0VmFsaWRhdG9ycyA9IGZ1bmN0aW9uIChuZXdWYWxpZGF0b3IpIHtcbiAgICAgICAgICAgIHRoaXMudmFsaWRhdG9yID0gY29lcmNlVG9WYWxpZGF0b3IobmV3VmFsaWRhdG9yKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqICBTZXRzIHRoZSBhc3luYyB2YWxpZGF0b3JzIHRoYXQgYXJlIGFjdGl2ZSBvbiB0aGlzIGNvbnRyb2wuIENhbGxpbmcgdGhpc1xuICAgICAgICAgICogd2lsbCBvdmVyd3JpdGUgYW55IGV4aXN0aW5nIGFzeW5jIHZhbGlkYXRvcnMuXG4gICAgICAgICAqIEBwYXJhbSB7P30gbmV3VmFsaWRhdG9yXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBBYnN0cmFjdENvbnRyb2wucHJvdG90eXBlLnNldEFzeW5jVmFsaWRhdG9ycyA9IGZ1bmN0aW9uIChuZXdWYWxpZGF0b3IpIHtcbiAgICAgICAgICAgIHRoaXMuYXN5bmNWYWxpZGF0b3IgPSBjb2VyY2VUb0FzeW5jVmFsaWRhdG9yKG5ld1ZhbGlkYXRvcik7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiAgRW1wdGllcyBvdXQgdGhlIHN5bmMgdmFsaWRhdG9yIGxpc3QuXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBBYnN0cmFjdENvbnRyb2wucHJvdG90eXBlLmNsZWFyVmFsaWRhdG9ycyA9IGZ1bmN0aW9uICgpIHsgdGhpcy52YWxpZGF0b3IgPSBudWxsOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogIEVtcHRpZXMgb3V0IHRoZSBhc3luYyB2YWxpZGF0b3IgbGlzdC5cbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUuY2xlYXJBc3luY1ZhbGlkYXRvcnMgPSBmdW5jdGlvbiAoKSB7IHRoaXMuYXN5bmNWYWxpZGF0b3IgPSBudWxsOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogIE1hcmtzIHRoZSBjb250cm9sIGFzIGB0b3VjaGVkYC5cbiAgICAgICAgICAqICpcbiAgICAgICAgICAqIFRoaXMgd2lsbCBhbHNvIG1hcmsgYWxsIGRpcmVjdCBhbmNlc3RvcnMgYXMgYHRvdWNoZWRgIHRvIG1haW50YWluXG4gICAgICAgICAgKiB0aGUgbW9kZWwuXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IF9fMFxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZS5tYXJrQXNUb3VjaGVkID0gZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICB2YXIgb25seVNlbGYgPSAoX2EgPT09IHZvaWQgMCA/IHt9IDogX2EpLm9ubHlTZWxmO1xuICAgICAgICAgICAgdGhpcy5fdG91Y2hlZCA9IHRydWU7XG4gICAgICAgICAgICBpZiAodGhpcy5fcGFyZW50ICYmICFvbmx5U2VsZikge1xuICAgICAgICAgICAgICAgIHRoaXMuX3BhcmVudC5tYXJrQXNUb3VjaGVkKHsgb25seVNlbGY6IG9ubHlTZWxmIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogIE1hcmtzIHRoZSBjb250cm9sIGFzIGB1bnRvdWNoZWRgLlxuICAgICAgICAgICogKlxuICAgICAgICAgICogSWYgdGhlIGNvbnRyb2wgaGFzIGFueSBjaGlsZHJlbiwgaXQgd2lsbCBhbHNvIG1hcmsgYWxsIGNoaWxkcmVuIGFzIGB1bnRvdWNoZWRgXG4gICAgICAgICAgKiB0byBtYWludGFpbiB0aGUgbW9kZWwsIGFuZCByZS1jYWxjdWxhdGUgdGhlIGB0b3VjaGVkYCBzdGF0dXMgb2YgYWxsIHBhcmVudFxuICAgICAgICAgICogY29udHJvbHMuXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IF9fMFxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZS5tYXJrQXNVbnRvdWNoZWQgPSBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgIHZhciBvbmx5U2VsZiA9IChfYSA9PT0gdm9pZCAwID8ge30gOiBfYSkub25seVNlbGY7XG4gICAgICAgICAgICB0aGlzLl90b3VjaGVkID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLl9mb3JFYWNoQ2hpbGQoZnVuY3Rpb24gKGNvbnRyb2wpIHsgY29udHJvbC5tYXJrQXNVbnRvdWNoZWQoeyBvbmx5U2VsZjogdHJ1ZSB9KTsgfSk7XG4gICAgICAgICAgICBpZiAodGhpcy5fcGFyZW50ICYmICFvbmx5U2VsZikge1xuICAgICAgICAgICAgICAgIHRoaXMuX3BhcmVudC5fdXBkYXRlVG91Y2hlZCh7IG9ubHlTZWxmOiBvbmx5U2VsZiB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqICBNYXJrcyB0aGUgY29udHJvbCBhcyBgZGlydHlgLlxuICAgICAgICAgICogKlxuICAgICAgICAgICogVGhpcyB3aWxsIGFsc28gbWFyayBhbGwgZGlyZWN0IGFuY2VzdG9ycyBhcyBgZGlydHlgIHRvIG1haW50YWluXG4gICAgICAgICAgKiB0aGUgbW9kZWwuXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IF9fMFxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZS5tYXJrQXNEaXJ0eSA9IGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgdmFyIG9ubHlTZWxmID0gKF9hID09PSB2b2lkIDAgPyB7fSA6IF9hKS5vbmx5U2VsZjtcbiAgICAgICAgICAgIHRoaXMuX3ByaXN0aW5lID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAodGhpcy5fcGFyZW50ICYmICFvbmx5U2VsZikge1xuICAgICAgICAgICAgICAgIHRoaXMuX3BhcmVudC5tYXJrQXNEaXJ0eSh7IG9ubHlTZWxmOiBvbmx5U2VsZiB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqICBNYXJrcyB0aGUgY29udHJvbCBhcyBgcHJpc3RpbmVgLlxuICAgICAgICAgICogKlxuICAgICAgICAgICogSWYgdGhlIGNvbnRyb2wgaGFzIGFueSBjaGlsZHJlbiwgaXQgd2lsbCBhbHNvIG1hcmsgYWxsIGNoaWxkcmVuIGFzIGBwcmlzdGluZWBcbiAgICAgICAgICAqIHRvIG1haW50YWluIHRoZSBtb2RlbCwgYW5kIHJlLWNhbGN1bGF0ZSB0aGUgYHByaXN0aW5lYCBzdGF0dXMgb2YgYWxsIHBhcmVudFxuICAgICAgICAgICogY29udHJvbHMuXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IF9fMFxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZS5tYXJrQXNQcmlzdGluZSA9IGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgdmFyIG9ubHlTZWxmID0gKF9hID09PSB2b2lkIDAgPyB7fSA6IF9hKS5vbmx5U2VsZjtcbiAgICAgICAgICAgIHRoaXMuX3ByaXN0aW5lID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuX2ZvckVhY2hDaGlsZChmdW5jdGlvbiAoY29udHJvbCkgeyBjb250cm9sLm1hcmtBc1ByaXN0aW5lKHsgb25seVNlbGY6IHRydWUgfSk7IH0pO1xuICAgICAgICAgICAgaWYgKHRoaXMuX3BhcmVudCAmJiAhb25seVNlbGYpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9wYXJlbnQuX3VwZGF0ZVByaXN0aW5lKHsgb25seVNlbGY6IG9ubHlTZWxmIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogIE1hcmtzIHRoZSBjb250cm9sIGFzIGBwZW5kaW5nYC5cbiAgICAgICAgICogQHBhcmFtIHs/PX0gX18wXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBBYnN0cmFjdENvbnRyb2wucHJvdG90eXBlLm1hcmtBc1BlbmRpbmcgPSBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgIHZhciBvbmx5U2VsZiA9IChfYSA9PT0gdm9pZCAwID8ge30gOiBfYSkub25seVNlbGY7XG4gICAgICAgICAgICB0aGlzLl9zdGF0dXMgPSBQRU5ESU5HO1xuICAgICAgICAgICAgaWYgKHRoaXMuX3BhcmVudCAmJiAhb25seVNlbGYpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9wYXJlbnQubWFya0FzUGVuZGluZyh7IG9ubHlTZWxmOiBvbmx5U2VsZiB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqICBEaXNhYmxlcyB0aGUgY29udHJvbC4gVGhpcyBtZWFucyB0aGUgY29udHJvbCB3aWxsIGJlIGV4ZW1wdCBmcm9tIHZhbGlkYXRpb24gY2hlY2tzIGFuZFxuICAgICAgICAgICogZXhjbHVkZWQgZnJvbSB0aGUgYWdncmVnYXRlIHZhbHVlIG9mIGFueSBwYXJlbnQuIEl0cyBzdGF0dXMgaXMgYERJU0FCTEVEYC5cbiAgICAgICAgICAqICpcbiAgICAgICAgICAqIElmIHRoZSBjb250cm9sIGhhcyBjaGlsZHJlbiwgYWxsIGNoaWxkcmVuIHdpbGwgYmUgZGlzYWJsZWQgdG8gbWFpbnRhaW4gdGhlIG1vZGVsLlxuICAgICAgICAgKiBAcGFyYW0gez89fSBfXzBcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUuZGlzYWJsZSA9IGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgdmFyIF9iID0gX2EgPT09IHZvaWQgMCA/IHt9IDogX2EsIG9ubHlTZWxmID0gX2Iub25seVNlbGYsIGVtaXRFdmVudCA9IF9iLmVtaXRFdmVudDtcbiAgICAgICAgICAgIHRoaXMuX3N0YXR1cyA9IERJU0FCTEVEO1xuICAgICAgICAgICAgdGhpcy5fZXJyb3JzID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuX2ZvckVhY2hDaGlsZChmdW5jdGlvbiAoY29udHJvbCkgeyBjb250cm9sLmRpc2FibGUoeyBvbmx5U2VsZjogdHJ1ZSB9KTsgfSk7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVWYWx1ZSgpO1xuICAgICAgICAgICAgaWYgKGVtaXRFdmVudCAhPT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl92YWx1ZUNoYW5nZXMuZW1pdCh0aGlzLl92YWx1ZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5fc3RhdHVzQ2hhbmdlcy5lbWl0KHRoaXMuX3N0YXR1cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVBbmNlc3RvcnMob25seVNlbGYpO1xuICAgICAgICAgICAgdGhpcy5fb25EaXNhYmxlZENoYW5nZS5mb3JFYWNoKGZ1bmN0aW9uIChjaGFuZ2VGbikgeyByZXR1cm4gY2hhbmdlRm4odHJ1ZSk7IH0pO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogIEVuYWJsZXMgdGhlIGNvbnRyb2wuIFRoaXMgbWVhbnMgdGhlIGNvbnRyb2wgd2lsbCBiZSBpbmNsdWRlZCBpbiB2YWxpZGF0aW9uIGNoZWNrcyBhbmRcbiAgICAgICAgICAqIHRoZSBhZ2dyZWdhdGUgdmFsdWUgb2YgaXRzIHBhcmVudC4gSXRzIHN0YXR1cyBpcyByZS1jYWxjdWxhdGVkIGJhc2VkIG9uIGl0cyB2YWx1ZSBhbmRcbiAgICAgICAgICAqIGl0cyB2YWxpZGF0b3JzLlxuICAgICAgICAgICogKlxuICAgICAgICAgICogSWYgdGhlIGNvbnRyb2wgaGFzIGNoaWxkcmVuLCBhbGwgY2hpbGRyZW4gd2lsbCBiZSBlbmFibGVkLlxuICAgICAgICAgKiBAcGFyYW0gez89fSBfXzBcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUuZW5hYmxlID0gZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICB2YXIgX2IgPSBfYSA9PT0gdm9pZCAwID8ge30gOiBfYSwgb25seVNlbGYgPSBfYi5vbmx5U2VsZiwgZW1pdEV2ZW50ID0gX2IuZW1pdEV2ZW50O1xuICAgICAgICAgICAgdGhpcy5fc3RhdHVzID0gVkFMSUQ7XG4gICAgICAgICAgICB0aGlzLl9mb3JFYWNoQ2hpbGQoZnVuY3Rpb24gKGNvbnRyb2wpIHsgY29udHJvbC5lbmFibGUoeyBvbmx5U2VsZjogdHJ1ZSB9KTsgfSk7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoeyBvbmx5U2VsZjogdHJ1ZSwgZW1pdEV2ZW50OiBlbWl0RXZlbnQgfSk7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVBbmNlc3RvcnMob25seVNlbGYpO1xuICAgICAgICAgICAgdGhpcy5fb25EaXNhYmxlZENoYW5nZS5mb3JFYWNoKGZ1bmN0aW9uIChjaGFuZ2VGbikgeyByZXR1cm4gY2hhbmdlRm4oZmFsc2UpOyB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gb25seVNlbGZcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUuX3VwZGF0ZUFuY2VzdG9ycyA9IGZ1bmN0aW9uIChvbmx5U2VsZikge1xuICAgICAgICAgICAgaWYgKHRoaXMuX3BhcmVudCAmJiAhb25seVNlbGYpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9wYXJlbnQudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3BhcmVudC5fdXBkYXRlUHJpc3RpbmUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9wYXJlbnQuX3VwZGF0ZVRvdWNoZWQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gcGFyZW50XG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBBYnN0cmFjdENvbnRyb2wucHJvdG90eXBlLnNldFBhcmVudCA9IGZ1bmN0aW9uIChwYXJlbnQpIHsgdGhpcy5fcGFyZW50ID0gcGFyZW50OyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogIFNldHMgdGhlIHZhbHVlIG9mIHRoZSBjb250cm9sLiBBYnN0cmFjdCBtZXRob2QgKGltcGxlbWVudGVkIGluIHN1Yi1jbGFzc2VzKS5cbiAgICAgICAgICogQGFic3RyYWN0XG4gICAgICAgICAqIEBwYXJhbSB7P30gdmFsdWVcbiAgICAgICAgICogQHBhcmFtIHs/PX0gb3B0aW9uc1xuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZS5zZXRWYWx1ZSA9IGZ1bmN0aW9uICh2YWx1ZSwgb3B0aW9ucykgeyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogIFBhdGNoZXMgdGhlIHZhbHVlIG9mIHRoZSBjb250cm9sLiBBYnN0cmFjdCBtZXRob2QgKGltcGxlbWVudGVkIGluIHN1Yi1jbGFzc2VzKS5cbiAgICAgICAgICogQGFic3RyYWN0XG4gICAgICAgICAqIEBwYXJhbSB7P30gdmFsdWVcbiAgICAgICAgICogQHBhcmFtIHs/PX0gb3B0aW9uc1xuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZS5wYXRjaFZhbHVlID0gZnVuY3Rpb24gKHZhbHVlLCBvcHRpb25zKSB7IH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiAgUmVzZXRzIHRoZSBjb250cm9sLiBBYnN0cmFjdCBtZXRob2QgKGltcGxlbWVudGVkIGluIHN1Yi1jbGFzc2VzKS5cbiAgICAgICAgICogQGFic3RyYWN0XG4gICAgICAgICAqIEBwYXJhbSB7Pz19IHZhbHVlXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IG9wdGlvbnNcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUucmVzZXQgPSBmdW5jdGlvbiAodmFsdWUsIG9wdGlvbnMpIHsgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqICBSZS1jYWxjdWxhdGVzIHRoZSB2YWx1ZSBhbmQgdmFsaWRhdGlvbiBzdGF0dXMgb2YgdGhlIGNvbnRyb2wuXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiBCeSBkZWZhdWx0LCBpdCB3aWxsIGFsc28gdXBkYXRlIHRoZSB2YWx1ZSBhbmQgdmFsaWRpdHkgb2YgaXRzIGFuY2VzdG9ycy5cbiAgICAgICAgICogQHBhcmFtIHs/PX0gX18wXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBBYnN0cmFjdENvbnRyb2wucHJvdG90eXBlLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkgPSBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgIHZhciBfYiA9IF9hID09PSB2b2lkIDAgPyB7fSA6IF9hLCBvbmx5U2VsZiA9IF9iLm9ubHlTZWxmLCBlbWl0RXZlbnQgPSBfYi5lbWl0RXZlbnQ7XG4gICAgICAgICAgICB0aGlzLl9zZXRJbml0aWFsU3RhdHVzKCk7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVWYWx1ZSgpO1xuICAgICAgICAgICAgaWYgKHRoaXMuZW5hYmxlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2Vycm9ycyA9IHRoaXMuX3J1blZhbGlkYXRvcigpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3N0YXR1cyA9IHRoaXMuX2NhbGN1bGF0ZVN0YXR1cygpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9zdGF0dXMgPT09IFZBTElEIHx8IHRoaXMuX3N0YXR1cyA9PT0gUEVORElORykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9ydW5Bc3luY1ZhbGlkYXRvcihlbWl0RXZlbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChlbWl0RXZlbnQgIT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fdmFsdWVDaGFuZ2VzLmVtaXQodGhpcy5fdmFsdWUpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3N0YXR1c0NoYW5nZXMuZW1pdCh0aGlzLl9zdGF0dXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuX3BhcmVudCAmJiAhb25seVNlbGYpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9wYXJlbnQudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSh7IG9ubHlTZWxmOiBvbmx5U2VsZiwgZW1pdEV2ZW50OiBlbWl0RXZlbnQgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez89fSBfXzBcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUuX3VwZGF0ZVRyZWVWYWxpZGl0eSA9IGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgdmFyIGVtaXRFdmVudCA9IChfYSA9PT0gdm9pZCAwID8geyBlbWl0RXZlbnQ6IHRydWUgfSA6IF9hKS5lbWl0RXZlbnQ7XG4gICAgICAgICAgICB0aGlzLl9mb3JFYWNoQ2hpbGQoZnVuY3Rpb24gKGN0cmwpIHsgcmV0dXJuIGN0cmwuX3VwZGF0ZVRyZWVWYWxpZGl0eSh7IGVtaXRFdmVudDogZW1pdEV2ZW50IH0pOyB9KTtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSh7IG9ubHlTZWxmOiB0cnVlLCBlbWl0RXZlbnQ6IGVtaXRFdmVudCB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBBYnN0cmFjdENvbnRyb2wucHJvdG90eXBlLl9zZXRJbml0aWFsU3RhdHVzID0gZnVuY3Rpb24gKCkgeyB0aGlzLl9zdGF0dXMgPSB0aGlzLl9hbGxDb250cm9sc0Rpc2FibGVkKCkgPyBESVNBQkxFRCA6IFZBTElEOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUuX3J1blZhbGlkYXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbGlkYXRvciA/IHRoaXMudmFsaWRhdG9yKHRoaXMpIDogbnVsbDtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gZW1pdEV2ZW50XG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBBYnN0cmFjdENvbnRyb2wucHJvdG90eXBlLl9ydW5Bc3luY1ZhbGlkYXRvciA9IGZ1bmN0aW9uIChlbWl0RXZlbnQpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICBpZiAodGhpcy5hc3luY1ZhbGlkYXRvcikge1xuICAgICAgICAgICAgICAgIHRoaXMuX3N0YXR1cyA9IFBFTkRJTkc7XG4gICAgICAgICAgICAgICAgdGhpcy5fY2FuY2VsRXhpc3RpbmdTdWJzY3JpcHRpb24oKTtcbiAgICAgICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBvYnMgPSB0b09ic2VydmFibGUodGhpcy5hc3luY1ZhbGlkYXRvcih0aGlzKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5fYXN5bmNWYWxpZGF0aW9uU3Vic2NyaXB0aW9uID1cbiAgICAgICAgICAgICAgICAgICAgb2JzLnN1YnNjcmliZSh7IG5leHQ6IGZ1bmN0aW9uIChyZXMpIHsgcmV0dXJuIF90aGlzLnNldEVycm9ycyhyZXMsIHsgZW1pdEV2ZW50OiBlbWl0RXZlbnQgfSk7IH0gfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZS5fY2FuY2VsRXhpc3RpbmdTdWJzY3JpcHRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5fYXN5bmNWYWxpZGF0aW9uU3Vic2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fYXN5bmNWYWxpZGF0aW9uU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiAgU2V0cyBlcnJvcnMgb24gYSBmb3JtIGNvbnRyb2wuXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiBUaGlzIGlzIHVzZWQgd2hlbiB2YWxpZGF0aW9ucyBhcmUgcnVuIG1hbnVhbGx5IGJ5IHRoZSB1c2VyLCByYXRoZXIgdGhhbiBhdXRvbWF0aWNhbGx5LlxuICAgICAgICAgICogKlxuICAgICAgICAgICogQ2FsbGluZyBgc2V0RXJyb3JzYCB3aWxsIGFsc28gdXBkYXRlIHRoZSB2YWxpZGl0eSBvZiB0aGUgcGFyZW50IGNvbnRyb2wuXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiAjIyMgRXhhbXBsZVxuICAgICAgICAgICogKlxuICAgICAgICAgICogYGBgXG4gICAgICAgICAgKiBjb25zdCBsb2dpbiA9IG5ldyBGb3JtQ29udHJvbChcInNvbWVMb2dpblwiKTtcbiAgICAgICAgICAqIGxvZ2luLnNldEVycm9ycyh7XG4gICAgICAgICAgKiBcIm5vdFVuaXF1ZVwiOiB0cnVlXG4gICAgICAgICAgKiB9KTtcbiAgICAgICAgICAqICpcbiAgICAgICAgICAqIGV4cGVjdChsb2dpbi52YWxpZCkudG9FcXVhbChmYWxzZSk7XG4gICAgICAgICAgKiBleHBlY3QobG9naW4uZXJyb3JzKS50b0VxdWFsKHtcIm5vdFVuaXF1ZVwiOiB0cnVlfSk7XG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiBsb2dpbi5zZXRWYWx1ZShcInNvbWVPdGhlckxvZ2luXCIpO1xuICAgICAgICAgICogKlxuICAgICAgICAgICogZXhwZWN0KGxvZ2luLnZhbGlkKS50b0VxdWFsKHRydWUpO1xuICAgICAgICAgICogYGBgXG4gICAgICAgICAqIEBwYXJhbSB7P30gZXJyb3JzXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IF9fMVxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZS5zZXRFcnJvcnMgPSBmdW5jdGlvbiAoZXJyb3JzLCBfYSkge1xuICAgICAgICAgICAgdmFyIGVtaXRFdmVudCA9IChfYSA9PT0gdm9pZCAwID8ge30gOiBfYSkuZW1pdEV2ZW50O1xuICAgICAgICAgICAgdGhpcy5fZXJyb3JzID0gZXJyb3JzO1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlQ29udHJvbHNFcnJvcnMoZW1pdEV2ZW50ICE9PSBmYWxzZSk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiAgUmV0cmlldmVzIGEgY2hpbGQgY29udHJvbCBnaXZlbiB0aGUgY29udHJvbCdzIG5hbWUgb3IgcGF0aC5cbiAgICAgICAgICAqICpcbiAgICAgICAgICAqIFBhdGhzIGNhbiBiZSBwYXNzZWQgaW4gYXMgYW4gYXJyYXkgb3IgYSBzdHJpbmcgZGVsaW1pdGVkIGJ5IGEgZG90LlxuICAgICAgICAgICogKlxuICAgICAgICAgICogVG8gZ2V0IGEgY29udHJvbCBuZXN0ZWQgd2l0aGluIGEgYHBlcnNvbmAgc3ViLWdyb3VwOlxuICAgICAgICAgICogKlxuICAgICAgICAgICogKiBgdGhpcy5mb3JtLmdldCgncGVyc29uLm5hbWUnKTtgXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiAtT1ItXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiAqIGB0aGlzLmZvcm0uZ2V0KFsncGVyc29uJywgJ25hbWUnXSk7YFxuICAgICAgICAgKiBAcGFyYW0gez99IHBhdGhcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUuZ2V0ID0gZnVuY3Rpb24gKHBhdGgpIHsgcmV0dXJuIF9maW5kKHRoaXMsIHBhdGgsICcuJyk7IH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiAgUmV0dXJucyB0cnVlIGlmIHRoZSBjb250cm9sIHdpdGggdGhlIGdpdmVuIHBhdGggaGFzIHRoZSBlcnJvciBzcGVjaWZpZWQuIE90aGVyd2lzZVxuICAgICAgICAgICogcmV0dXJucyBudWxsIG9yIHVuZGVmaW5lZC5cbiAgICAgICAgICAqICpcbiAgICAgICAgICAqIElmIG5vIHBhdGggaXMgZ2l2ZW4sIGl0IGNoZWNrcyBmb3IgdGhlIGVycm9yIG9uIHRoZSBwcmVzZW50IGNvbnRyb2wuXG4gICAgICAgICAqIEBwYXJhbSB7P30gZXJyb3JDb2RlXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IHBhdGhcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUuZ2V0RXJyb3IgPSBmdW5jdGlvbiAoZXJyb3JDb2RlLCBwYXRoKSB7XG4gICAgICAgICAgICBpZiAocGF0aCA9PT0gdm9pZCAwKSB7IHBhdGggPSBudWxsOyB9XG4gICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBjb250cm9sID0gcGF0aCA/IHRoaXMuZ2V0KHBhdGgpIDogdGhpcztcbiAgICAgICAgICAgIHJldHVybiBjb250cm9sICYmIGNvbnRyb2wuX2Vycm9ycyA/IGNvbnRyb2wuX2Vycm9yc1tlcnJvckNvZGVdIDogbnVsbDtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqICBSZXR1cm5zIHRydWUgaWYgdGhlIGNvbnRyb2wgd2l0aCB0aGUgZ2l2ZW4gcGF0aCBoYXMgdGhlIGVycm9yIHNwZWNpZmllZC4gT3RoZXJ3aXNlXG4gICAgICAgICAgKiByZXR1cm5zIGZhbHNlLlxuICAgICAgICAgICogKlxuICAgICAgICAgICogSWYgbm8gcGF0aCBpcyBnaXZlbiwgaXQgY2hlY2tzIGZvciB0aGUgZXJyb3Igb24gdGhlIHByZXNlbnQgY29udHJvbC5cbiAgICAgICAgICogQHBhcmFtIHs/fSBlcnJvckNvZGVcbiAgICAgICAgICogQHBhcmFtIHs/PX0gcGF0aFxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZS5oYXNFcnJvciA9IGZ1bmN0aW9uIChlcnJvckNvZGUsIHBhdGgpIHtcbiAgICAgICAgICAgIGlmIChwYXRoID09PSB2b2lkIDApIHsgcGF0aCA9IG51bGw7IH1cbiAgICAgICAgICAgIHJldHVybiAhIXRoaXMuZ2V0RXJyb3IoZXJyb3JDb2RlLCBwYXRoKTtcbiAgICAgICAgfTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUsIFwicm9vdFwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqICBSZXRyaWV2ZXMgdGhlIHRvcC1sZXZlbCBhbmNlc3RvciBvZiB0aGlzIGNvbnRyb2wuXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyB4ID0gdGhpcztcbiAgICAgICAgICAgICAgICB3aGlsZSAoeC5fcGFyZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHggPSB4Ll9wYXJlbnQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB4O1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGVtaXRFdmVudFxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZS5fdXBkYXRlQ29udHJvbHNFcnJvcnMgPSBmdW5jdGlvbiAoZW1pdEV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLl9zdGF0dXMgPSB0aGlzLl9jYWxjdWxhdGVTdGF0dXMoKTtcbiAgICAgICAgICAgIGlmIChlbWl0RXZlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zdGF0dXNDaGFuZ2VzLmVtaXQodGhpcy5fc3RhdHVzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLl9wYXJlbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9wYXJlbnQuX3VwZGF0ZUNvbnRyb2xzRXJyb3JzKGVtaXRFdmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZS5faW5pdE9ic2VydmFibGVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy5fdmFsdWVDaGFuZ2VzID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICAgICAgICAgICAgdGhpcy5fc3RhdHVzQ2hhbmdlcyA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBBYnN0cmFjdENvbnRyb2wucHJvdG90eXBlLl9jYWxjdWxhdGVTdGF0dXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5fYWxsQ29udHJvbHNEaXNhYmxlZCgpKVxuICAgICAgICAgICAgICAgIHJldHVybiBESVNBQkxFRDtcbiAgICAgICAgICAgIGlmICh0aGlzLl9lcnJvcnMpXG4gICAgICAgICAgICAgICAgcmV0dXJuIElOVkFMSUQ7XG4gICAgICAgICAgICBpZiAodGhpcy5fYW55Q29udHJvbHNIYXZlU3RhdHVzKFBFTkRJTkcpKVxuICAgICAgICAgICAgICAgIHJldHVybiBQRU5ESU5HO1xuICAgICAgICAgICAgaWYgKHRoaXMuX2FueUNvbnRyb2xzSGF2ZVN0YXR1cyhJTlZBTElEKSlcbiAgICAgICAgICAgICAgICByZXR1cm4gSU5WQUxJRDtcbiAgICAgICAgICAgIHJldHVybiBWQUxJRDtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBhYnN0cmFjdFxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZS5fdXBkYXRlVmFsdWUgPSBmdW5jdGlvbiAoKSB7IH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAYWJzdHJhY3RcbiAgICAgICAgICogQHBhcmFtIHs/fSBjYlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZS5fZm9yRWFjaENoaWxkID0gZnVuY3Rpb24gKGNiKSB7IH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAYWJzdHJhY3RcbiAgICAgICAgICogQHBhcmFtIHs/fSBjb25kaXRpb25cbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUuX2FueUNvbnRyb2xzID0gZnVuY3Rpb24gKGNvbmRpdGlvbikgeyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQGFic3RyYWN0XG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBBYnN0cmFjdENvbnRyb2wucHJvdG90eXBlLl9hbGxDb250cm9sc0Rpc2FibGVkID0gZnVuY3Rpb24gKCkgeyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBzdGF0dXNcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUuX2FueUNvbnRyb2xzSGF2ZVN0YXR1cyA9IGZ1bmN0aW9uIChzdGF0dXMpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9hbnlDb250cm9scyhmdW5jdGlvbiAoY29udHJvbCkgeyByZXR1cm4gY29udHJvbC5zdGF0dXMgPT09IHN0YXR1czsgfSk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZS5fYW55Q29udHJvbHNEaXJ0eSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9hbnlDb250cm9scyhmdW5jdGlvbiAoY29udHJvbCkgeyByZXR1cm4gY29udHJvbC5kaXJ0eTsgfSk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZS5fYW55Q29udHJvbHNUb3VjaGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2FueUNvbnRyb2xzKGZ1bmN0aW9uIChjb250cm9sKSB7IHJldHVybiBjb250cm9sLnRvdWNoZWQ7IH0pO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/PX0gX18wXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBBYnN0cmFjdENvbnRyb2wucHJvdG90eXBlLl91cGRhdGVQcmlzdGluZSA9IGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgdmFyIG9ubHlTZWxmID0gKF9hID09PSB2b2lkIDAgPyB7fSA6IF9hKS5vbmx5U2VsZjtcbiAgICAgICAgICAgIHRoaXMuX3ByaXN0aW5lID0gIXRoaXMuX2FueUNvbnRyb2xzRGlydHkoKTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9wYXJlbnQgJiYgIW9ubHlTZWxmKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcGFyZW50Ll91cGRhdGVQcmlzdGluZSh7IG9ubHlTZWxmOiBvbmx5U2VsZiB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IF9fMFxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgQWJzdHJhY3RDb250cm9sLnByb3RvdHlwZS5fdXBkYXRlVG91Y2hlZCA9IGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgdmFyIG9ubHlTZWxmID0gKF9hID09PSB2b2lkIDAgPyB7fSA6IF9hKS5vbmx5U2VsZjtcbiAgICAgICAgICAgIHRoaXMuX3RvdWNoZWQgPSB0aGlzLl9hbnlDb250cm9sc1RvdWNoZWQoKTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9wYXJlbnQgJiYgIW9ubHlTZWxmKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcGFyZW50Ll91cGRhdGVUb3VjaGVkKHsgb25seVNlbGY6IG9ubHlTZWxmIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBmb3JtU3RhdGVcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUuX2lzQm94ZWRWYWx1ZSA9IGZ1bmN0aW9uIChmb3JtU3RhdGUpIHtcbiAgICAgICAgICAgIHJldHVybiB0eXBlb2YgZm9ybVN0YXRlID09PSAnb2JqZWN0JyAmJiBmb3JtU3RhdGUgIT09IG51bGwgJiZcbiAgICAgICAgICAgICAgICBPYmplY3Qua2V5cyhmb3JtU3RhdGUpLmxlbmd0aCA9PT0gMiAmJiAndmFsdWUnIGluIGZvcm1TdGF0ZSAmJiAnZGlzYWJsZWQnIGluIGZvcm1TdGF0ZTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gZm5cbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEFic3RyYWN0Q29udHJvbC5wcm90b3R5cGUuX3JlZ2lzdGVyT25Db2xsZWN0aW9uQ2hhbmdlID0gZnVuY3Rpb24gKGZuKSB7IHRoaXMuX29uQ29sbGVjdGlvbkNoYW5nZSA9IGZuOyB9O1xuICAgICAgICByZXR1cm4gQWJzdHJhY3RDb250cm9sO1xuICAgIH0oKSk7XG4gICAgLyoqXG4gICAgICogICpcbiAgICAgICogSXQgaXMgb25lIG9mIHRoZSB0aHJlZSBmdW5kYW1lbnRhbCBidWlsZGluZyBibG9ja3Mgb2YgQW5ndWxhciBmb3JtcywgYWxvbmcgd2l0aFxuICAgICAgKiB7QGxpbmsgRm9ybUdyb3VwfSBhbmQge0BsaW5rIEZvcm1BcnJheX0uXG4gICAgICAqICpcbiAgICAgICogKlxuICAgICAgKiBXaGVuIGluc3RhbnRpYXRpbmcgYSB7QGxpbmsgRm9ybUNvbnRyb2x9LCB5b3UgY2FuIHBhc3MgaW4gYW4gaW5pdGlhbCB2YWx1ZSBhcyB0aGVcbiAgICAgICogZmlyc3QgYXJndW1lbnQuIEV4YW1wbGU6XG4gICAgICAqICpcbiAgICAgICogYGBgdHNcbiAgICAgICogY29uc3QgY3RybCA9IG5ldyBGb3JtQ29udHJvbCgnc29tZSB2YWx1ZScpO1xuICAgICAgKiBjb25zb2xlLmxvZyhjdHJsLnZhbHVlKTsgICAgIC8vICdzb21lIHZhbHVlJ1xuICAgICAgKiAqYGBgXG4gICAgICAqICpcbiAgICAgICogWW91IGNhbiBhbHNvIGluaXRpYWxpemUgdGhlIGNvbnRyb2wgd2l0aCBhIGZvcm0gc3RhdGUgb2JqZWN0IG9uIGluc3RhbnRpYXRpb24sXG4gICAgICAqIHdoaWNoIGluY2x1ZGVzIGJvdGggdGhlIHZhbHVlIGFuZCB3aGV0aGVyIG9yIG5vdCB0aGUgY29udHJvbCBpcyBkaXNhYmxlZC5cbiAgICAgICogWW91IGNhbid0IHVzZSB0aGUgdmFsdWUga2V5IHdpdGhvdXQgdGhlIGRpc2FibGVkIGtleTsgYm90aCBhcmUgcmVxdWlyZWRcbiAgICAgICogdG8gdXNlIHRoaXMgd2F5IG9mIGluaXRpYWxpemF0aW9uLlxuICAgICAgKiAqXG4gICAgICAqIGBgYHRzXG4gICAgICAqIGNvbnN0IGN0cmwgPSBuZXcgRm9ybUNvbnRyb2woe3ZhbHVlOiAnbi9hJywgZGlzYWJsZWQ6IHRydWV9KTtcbiAgICAgICogY29uc29sZS5sb2coY3RybC52YWx1ZSk7ICAgICAvLyAnbi9hJ1xuICAgICAgKiBjb25zb2xlLmxvZyhjdHJsLnN0YXR1cyk7ICAgLy8gJ0RJU0FCTEVEJ1xuICAgICAgKiBgYGBcbiAgICAgICogKlxuICAgICAgKiBUbyBpbmNsdWRlIGEgc3luYyB2YWxpZGF0b3IgKG9yIGFuIGFycmF5IG9mIHN5bmMgdmFsaWRhdG9ycykgd2l0aCB0aGUgY29udHJvbCxcbiAgICAgICogcGFzcyBpdCBpbiBhcyB0aGUgc2Vjb25kIGFyZ3VtZW50LiBBc3luYyB2YWxpZGF0b3JzIGFyZSBhbHNvIHN1cHBvcnRlZCwgYnV0XG4gICAgICAqIGhhdmUgdG8gYmUgcGFzc2VkIGluIHNlcGFyYXRlbHkgYXMgdGhlIHRoaXJkIGFyZy5cbiAgICAgICogKlxuICAgICAgKiBgYGB0c1xuICAgICAgKiBjb25zdCBjdHJsID0gbmV3IEZvcm1Db250cm9sKCcnLCBWYWxpZGF0b3JzLnJlcXVpcmVkKTtcbiAgICAgICogY29uc29sZS5sb2coY3RybC52YWx1ZSk7ICAgICAvLyAnJ1xuICAgICAgKiBjb25zb2xlLmxvZyhjdHJsLnN0YXR1cyk7ICAgLy8gJ0lOVkFMSUQnXG4gICAgICAqIGBgYFxuICAgICAgKiAqXG4gICAgICAqIFNlZSBpdHMgc3VwZXJjbGFzcywge0BsaW5rIEFic3RyYWN0Q29udHJvbH0sIGZvciBtb3JlIHByb3BlcnRpZXMgYW5kIG1ldGhvZHMuXG4gICAgICAqICpcbiAgICAgICogKiAqKm5wbSBwYWNrYWdlKio6IGBAYW5ndWxhci9mb3Jtc2BcbiAgICAgICogKlxuICAgICAqL1xuICAgIHZhciBGb3JtQ29udHJvbCA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgICAgIF9fZXh0ZW5kcyQ2KEZvcm1Db250cm9sLCBfc3VwZXIpO1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/PX0gZm9ybVN0YXRlXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IHZhbGlkYXRvclxuICAgICAgICAgKiBAcGFyYW0gez89fSBhc3luY1ZhbGlkYXRvclxuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gRm9ybUNvbnRyb2woZm9ybVN0YXRlLCB2YWxpZGF0b3IsIGFzeW5jVmFsaWRhdG9yKSB7XG4gICAgICAgICAgICBpZiAoZm9ybVN0YXRlID09PSB2b2lkIDApIHsgZm9ybVN0YXRlID0gbnVsbDsgfVxuICAgICAgICAgICAgaWYgKHZhbGlkYXRvciA9PT0gdm9pZCAwKSB7IHZhbGlkYXRvciA9IG51bGw7IH1cbiAgICAgICAgICAgIGlmIChhc3luY1ZhbGlkYXRvciA9PT0gdm9pZCAwKSB7IGFzeW5jVmFsaWRhdG9yID0gbnVsbDsgfVxuICAgICAgICAgICAgX3N1cGVyLmNhbGwodGhpcywgY29lcmNlVG9WYWxpZGF0b3IodmFsaWRhdG9yKSwgY29lcmNlVG9Bc3luY1ZhbGlkYXRvcihhc3luY1ZhbGlkYXRvcikpO1xuICAgICAgICAgICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgICAgICAgICAgdGhpcy5fb25DaGFuZ2UgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX2FwcGx5Rm9ybVN0YXRlKGZvcm1TdGF0ZSk7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoeyBvbmx5U2VsZjogdHJ1ZSwgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgICAgIHRoaXMuX2luaXRPYnNlcnZhYmxlcygpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiAgU2V0IHRoZSB2YWx1ZSBvZiB0aGUgZm9ybSBjb250cm9sIHRvIGB2YWx1ZWAuXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiBJZiBgb25seVNlbGZgIGlzIGB0cnVlYCwgdGhpcyBjaGFuZ2Ugd2lsbCBvbmx5IGFmZmVjdCB0aGUgdmFsaWRhdGlvbiBvZiB0aGlzIGBGb3JtQ29udHJvbGBcbiAgICAgICAgICAqIGFuZCBub3QgaXRzIHBhcmVudCBjb21wb25lbnQuIFRoaXMgZGVmYXVsdHMgdG8gZmFsc2UuXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiBJZiBgZW1pdEV2ZW50YCBpcyBgdHJ1ZWAsIHRoaXNcbiAgICAgICAgICAqIGNoYW5nZSB3aWxsIGNhdXNlIGEgYHZhbHVlQ2hhbmdlc2AgZXZlbnQgb24gdGhlIGBGb3JtQ29udHJvbGAgdG8gYmUgZW1pdHRlZC4gVGhpcyBkZWZhdWx0c1xuICAgICAgICAgICogdG8gdHJ1ZSAoYXMgaXQgZmFsbHMgdGhyb3VnaCB0byBgdXBkYXRlVmFsdWVBbmRWYWxpZGl0eWApLlxuICAgICAgICAgICogKlxuICAgICAgICAgICogSWYgYGVtaXRNb2RlbFRvVmlld0NoYW5nZWAgaXMgYHRydWVgLCB0aGUgdmlldyB3aWxsIGJlIG5vdGlmaWVkIGFib3V0IHRoZSBuZXcgdmFsdWVcbiAgICAgICAgICAqIHZpYSBhbiBgb25DaGFuZ2VgIGV2ZW50LiBUaGlzIGlzIHRoZSBkZWZhdWx0IGJlaGF2aW9yIGlmIGBlbWl0TW9kZWxUb1ZpZXdDaGFuZ2VgIGlzIG5vdFxuICAgICAgICAgICogc3BlY2lmaWVkLlxuICAgICAgICAgICogKlxuICAgICAgICAgICogSWYgYGVtaXRWaWV3VG9Nb2RlbENoYW5nZWAgaXMgYHRydWVgLCBhbiBuZ01vZGVsQ2hhbmdlIGV2ZW50IHdpbGwgYmUgZmlyZWQgdG8gdXBkYXRlIHRoZVxuICAgICAgICAgICogbW9kZWwuICBUaGlzIGlzIHRoZSBkZWZhdWx0IGJlaGF2aW9yIGlmIGBlbWl0Vmlld1RvTW9kZWxDaGFuZ2VgIGlzIG5vdCBzcGVjaWZpZWQuXG4gICAgICAgICAqIEBwYXJhbSB7P30gdmFsdWVcbiAgICAgICAgICogQHBhcmFtIHs/PX0gX18xXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtQ29udHJvbC5wcm90b3R5cGUuc2V0VmFsdWUgPSBmdW5jdGlvbiAodmFsdWUsIF9hKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdmFyIF9iID0gX2EgPT09IHZvaWQgMCA/IHt9IDogX2EsIG9ubHlTZWxmID0gX2Iub25seVNlbGYsIGVtaXRFdmVudCA9IF9iLmVtaXRFdmVudCwgZW1pdE1vZGVsVG9WaWV3Q2hhbmdlID0gX2IuZW1pdE1vZGVsVG9WaWV3Q2hhbmdlLCBlbWl0Vmlld1RvTW9kZWxDaGFuZ2UgPSBfYi5lbWl0Vmlld1RvTW9kZWxDaGFuZ2U7XG4gICAgICAgICAgICB0aGlzLl92YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgaWYgKHRoaXMuX29uQ2hhbmdlLmxlbmd0aCAmJiBlbWl0TW9kZWxUb1ZpZXdDaGFuZ2UgIT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fb25DaGFuZ2UuZm9yRWFjaChmdW5jdGlvbiAoY2hhbmdlRm4pIHsgcmV0dXJuIGNoYW5nZUZuKF90aGlzLl92YWx1ZSwgZW1pdFZpZXdUb01vZGVsQ2hhbmdlICE9PSBmYWxzZSk7IH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KHsgb25seVNlbGY6IG9ubHlTZWxmLCBlbWl0RXZlbnQ6IGVtaXRFdmVudCB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqICBQYXRjaGVzIHRoZSB2YWx1ZSBvZiBhIGNvbnRyb2wuXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiBUaGlzIGZ1bmN0aW9uIGlzIGZ1bmN0aW9uYWxseSB0aGUgc2FtZSBhcyB7QGxpbmsgRm9ybUNvbnRyb2wuc2V0VmFsdWV9IGF0IHRoaXMgbGV2ZWwuXG4gICAgICAgICAgKiBJdCBleGlzdHMgZm9yIHN5bW1ldHJ5IHdpdGgge0BsaW5rIEZvcm1Hcm91cC5wYXRjaFZhbHVlfSBvbiBgRm9ybUdyb3Vwc2AgYW5kIGBGb3JtQXJyYXlzYCxcbiAgICAgICAgICAqIHdoZXJlIGl0IGRvZXMgYmVoYXZlIGRpZmZlcmVudGx5LlxuICAgICAgICAgKiBAcGFyYW0gez99IHZhbHVlXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IG9wdGlvbnNcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Db250cm9sLnByb3RvdHlwZS5wYXRjaFZhbHVlID0gZnVuY3Rpb24gKHZhbHVlLCBvcHRpb25zKSB7XG4gICAgICAgICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7IG9wdGlvbnMgPSB7fTsgfVxuICAgICAgICAgICAgdGhpcy5zZXRWYWx1ZSh2YWx1ZSwgb3B0aW9ucyk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiAgUmVzZXRzIHRoZSBmb3JtIGNvbnRyb2wuIFRoaXMgbWVhbnMgYnkgZGVmYXVsdDpcbiAgICAgICAgICAqICpcbiAgICAgICAgICAqICogaXQgaXMgbWFya2VkIGFzIGBwcmlzdGluZWBcbiAgICAgICAgICAqICogaXQgaXMgbWFya2VkIGFzIGB1bnRvdWNoZWRgXG4gICAgICAgICAgKiAqIHZhbHVlIGlzIHNldCB0byBudWxsXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiBZb3UgY2FuIGFsc28gcmVzZXQgdG8gYSBzcGVjaWZpYyBmb3JtIHN0YXRlIGJ5IHBhc3NpbmcgdGhyb3VnaCBhIHN0YW5kYWxvbmVcbiAgICAgICAgICAqIHZhbHVlIG9yIGEgZm9ybSBzdGF0ZSBvYmplY3QgdGhhdCBjb250YWlucyBib3RoIGEgdmFsdWUgYW5kIGEgZGlzYWJsZWQgc3RhdGVcbiAgICAgICAgICAqICh0aGVzZSBhcmUgdGhlIG9ubHkgdHdvIHByb3BlcnRpZXMgdGhhdCBjYW5ub3QgYmUgY2FsY3VsYXRlZCkuXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiBFeDpcbiAgICAgICAgICAqICpcbiAgICAgICAgICAqIGBgYHRzXG4gICAgICAgICAgKiB0aGlzLmNvbnRyb2wucmVzZXQoJ05hbmN5Jyk7XG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiBjb25zb2xlLmxvZyh0aGlzLmNvbnRyb2wudmFsdWUpOyAgLy8gJ05hbmN5J1xuICAgICAgICAgICogYGBgXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiBPUlxuICAgICAgICAgICogKlxuICAgICAgICAgICogYGBgXG4gICAgICAgICAgKiB0aGlzLmNvbnRyb2wucmVzZXQoe3ZhbHVlOiAnTmFuY3knLCBkaXNhYmxlZDogdHJ1ZX0pO1xuICAgICAgICAgICogKlxuICAgICAgICAgICogY29uc29sZS5sb2codGhpcy5jb250cm9sLnZhbHVlKTsgIC8vICdOYW5jeSdcbiAgICAgICAgICAqIGNvbnNvbGUubG9nKHRoaXMuY29udHJvbC5zdGF0dXMpOyAgLy8gJ0RJU0FCTEVEJ1xuICAgICAgICAgICogYGBgXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IGZvcm1TdGF0ZVxuICAgICAgICAgKiBAcGFyYW0gez89fSBfXzFcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Db250cm9sLnByb3RvdHlwZS5yZXNldCA9IGZ1bmN0aW9uIChmb3JtU3RhdGUsIF9hKSB7XG4gICAgICAgICAgICBpZiAoZm9ybVN0YXRlID09PSB2b2lkIDApIHsgZm9ybVN0YXRlID0gbnVsbDsgfVxuICAgICAgICAgICAgdmFyIF9iID0gX2EgPT09IHZvaWQgMCA/IHt9IDogX2EsIG9ubHlTZWxmID0gX2Iub25seVNlbGYsIGVtaXRFdmVudCA9IF9iLmVtaXRFdmVudDtcbiAgICAgICAgICAgIHRoaXMuX2FwcGx5Rm9ybVN0YXRlKGZvcm1TdGF0ZSk7XG4gICAgICAgICAgICB0aGlzLm1hcmtBc1ByaXN0aW5lKHsgb25seVNlbGY6IG9ubHlTZWxmIH0pO1xuICAgICAgICAgICAgdGhpcy5tYXJrQXNVbnRvdWNoZWQoeyBvbmx5U2VsZjogb25seVNlbGYgfSk7XG4gICAgICAgICAgICB0aGlzLnNldFZhbHVlKHRoaXMuX3ZhbHVlLCB7IG9ubHlTZWxmOiBvbmx5U2VsZiwgZW1pdEV2ZW50OiBlbWl0RXZlbnQgfSk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUNvbnRyb2wucHJvdG90eXBlLl91cGRhdGVWYWx1ZSA9IGZ1bmN0aW9uICgpIHsgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gY29uZGl0aW9uXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtQ29udHJvbC5wcm90b3R5cGUuX2FueUNvbnRyb2xzID0gZnVuY3Rpb24gKGNvbmRpdGlvbikgeyByZXR1cm4gZmFsc2U7IH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUNvbnRyb2wucHJvdG90eXBlLl9hbGxDb250cm9sc0Rpc2FibGVkID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5kaXNhYmxlZDsgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqICBSZWdpc3RlciBhIGxpc3RlbmVyIGZvciBjaGFuZ2UgZXZlbnRzLlxuICAgICAgICAgKiBAcGFyYW0gez99IGZuXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtQ29udHJvbC5wcm90b3R5cGUucmVnaXN0ZXJPbkNoYW5nZSA9IGZ1bmN0aW9uIChmbikgeyB0aGlzLl9vbkNoYW5nZS5wdXNoKGZuKTsgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtQ29udHJvbC5wcm90b3R5cGUuX2NsZWFyQ2hhbmdlRm5zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy5fb25DaGFuZ2UgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX29uRGlzYWJsZWRDaGFuZ2UgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX29uQ29sbGVjdGlvbkNoYW5nZSA9IGZ1bmN0aW9uICgpIHsgfTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqICBSZWdpc3RlciBhIGxpc3RlbmVyIGZvciBkaXNhYmxlZCBldmVudHMuXG4gICAgICAgICAqIEBwYXJhbSB7P30gZm5cbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Db250cm9sLnByb3RvdHlwZS5yZWdpc3Rlck9uRGlzYWJsZWRDaGFuZ2UgPSBmdW5jdGlvbiAoZm4pIHtcbiAgICAgICAgICAgIHRoaXMuX29uRGlzYWJsZWRDaGFuZ2UucHVzaChmbik7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGNiXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtQ29udHJvbC5wcm90b3R5cGUuX2ZvckVhY2hDaGlsZCA9IGZ1bmN0aW9uIChjYikgeyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBmb3JtU3RhdGVcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Db250cm9sLnByb3RvdHlwZS5fYXBwbHlGb3JtU3RhdGUgPSBmdW5jdGlvbiAoZm9ybVN0YXRlKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5faXNCb3hlZFZhbHVlKGZvcm1TdGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl92YWx1ZSA9IGZvcm1TdGF0ZS52YWx1ZTtcbiAgICAgICAgICAgICAgICBmb3JtU3RhdGUuZGlzYWJsZWQgPyB0aGlzLmRpc2FibGUoeyBvbmx5U2VsZjogdHJ1ZSwgZW1pdEV2ZW50OiBmYWxzZSB9KSA6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlKHsgb25seVNlbGY6IHRydWUsIGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLl92YWx1ZSA9IGZvcm1TdGF0ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIEZvcm1Db250cm9sO1xuICAgIH0oQWJzdHJhY3RDb250cm9sKSk7XG4gICAgLyoqXG4gICAgICogIGluc3RhbmNlcy5cbiAgICAgICogKlxuICAgICAgKiBBIGBGb3JtR3JvdXBgIGFnZ3JlZ2F0ZXMgdGhlIHZhbHVlcyBvZiBlYWNoIGNoaWxkIHtAbGluayBGb3JtQ29udHJvbH0gaW50byBvbmUgb2JqZWN0LFxuICAgICAgKiB3aXRoIGVhY2ggY29udHJvbCBuYW1lIGFzIHRoZSBrZXkuICBJdCBjYWxjdWxhdGVzIGl0cyBzdGF0dXMgYnkgcmVkdWNpbmcgdGhlIHN0YXR1c2VzXG4gICAgICAqIG9mIGl0cyBjaGlsZHJlbi4gRm9yIGV4YW1wbGUsIGlmIG9uZSBvZiB0aGUgY29udHJvbHMgaW4gYSBncm91cCBpcyBpbnZhbGlkLCB0aGUgZW50aXJlXG4gICAgICAqIGdyb3VwIGJlY29tZXMgaW52YWxpZC5cbiAgICAgICogKlxuICAgICAgKiBgRm9ybUdyb3VwYCBpcyBvbmUgb2YgdGhlIHRocmVlIGZ1bmRhbWVudGFsIGJ1aWxkaW5nIGJsb2NrcyB1c2VkIHRvIGRlZmluZSBmb3JtcyBpbiBBbmd1bGFyLFxuICAgICAgKiBhbG9uZyB3aXRoIHtAbGluayBGb3JtQ29udHJvbH0gYW5kIHtAbGluayBGb3JtQXJyYXl9LlxuICAgICAgKiAqXG4gICAgICAqICpcbiAgICAgICogV2hlbiBpbnN0YW50aWF0aW5nIGEge0BsaW5rIEZvcm1Hcm91cH0sIHBhc3MgaW4gYSBjb2xsZWN0aW9uIG9mIGNoaWxkIGNvbnRyb2xzIGFzIHRoZSBmaXJzdFxuICAgICAgKiBhcmd1bWVudC4gVGhlIGtleSBmb3IgZWFjaCBjaGlsZCB3aWxsIGJlIHRoZSBuYW1lIHVuZGVyIHdoaWNoIGl0IGlzIHJlZ2lzdGVyZWQuXG4gICAgICAqICpcbiAgICAgICogIyMjIEV4YW1wbGVcbiAgICAgICogKlxuICAgICAgKiBgYGBcbiAgICAgICogY29uc3QgZm9ybSA9IG5ldyBGb3JtR3JvdXAoe1xuICAgICAgKiBmaXJzdDogbmV3IEZvcm1Db250cm9sKCdOYW5jeScsIFZhbGlkYXRvcnMubWluTGVuZ3RoKDIpKSxcbiAgICAgICogbGFzdDogbmV3IEZvcm1Db250cm9sKCdEcmV3JyksXG4gICAgICAqIH0pO1xuICAgICAgKiAqXG4gICAgICAqIGNvbnNvbGUubG9nKGZvcm0udmFsdWUpOyAgIC8vIHtmaXJzdDogJ05hbmN5JywgbGFzdDsgJ0RyZXcnfVxuICAgICAgKiBjb25zb2xlLmxvZyhmb3JtLnN0YXR1cyk7ICAvLyAnVkFMSUQnXG4gICAgICAqIGBgYFxuICAgICAgKiAqXG4gICAgICAqIFlvdSBjYW4gYWxzbyBpbmNsdWRlIGdyb3VwLWxldmVsIHZhbGlkYXRvcnMgYXMgdGhlIHNlY29uZCBhcmcsIG9yIGdyb3VwLWxldmVsIGFzeW5jXG4gICAgICAqIHZhbGlkYXRvcnMgYXMgdGhlIHRoaXJkIGFyZy4gVGhlc2UgY29tZSBpbiBoYW5keSB3aGVuIHlvdSB3YW50IHRvIHBlcmZvcm0gdmFsaWRhdGlvblxuICAgICAgKiB0aGF0IGNvbnNpZGVycyB0aGUgdmFsdWUgb2YgbW9yZSB0aGFuIG9uZSBjaGlsZCBjb250cm9sLlxuICAgICAgKiAqXG4gICAgICAqICMjIyBFeGFtcGxlXG4gICAgICAqICpcbiAgICAgICogYGBgXG4gICAgICAqIGNvbnN0IGZvcm0gPSBuZXcgRm9ybUdyb3VwKHtcbiAgICAgICogcGFzc3dvcmQ6IG5ldyBGb3JtQ29udHJvbCgnJywgVmFsaWRhdG9ycy5taW5MZW5ndGgoMikpLFxuICAgICAgKiBwYXNzd29yZENvbmZpcm06IG5ldyBGb3JtQ29udHJvbCgnJywgVmFsaWRhdG9ycy5taW5MZW5ndGgoMikpLFxuICAgICAgKiB9LCBwYXNzd29yZE1hdGNoVmFsaWRhdG9yKTtcbiAgICAgICogKlxuICAgICAgKiAqXG4gICAgICAqIGZ1bmN0aW9uIHBhc3N3b3JkTWF0Y2hWYWxpZGF0b3IoZzogRm9ybUdyb3VwKSB7XG4gICAgICAqIHJldHVybiBnLmdldCgncGFzc3dvcmQnKS52YWx1ZSA9PT0gZy5nZXQoJ3Bhc3N3b3JkQ29uZmlybScpLnZhbHVlXG4gICAgICAqID8gbnVsbCA6IHsnbWlzbWF0Y2gnOiB0cnVlfTtcbiAgICAgICogfVxuICAgICAgKiBgYGBcbiAgICAgICogKlxuICAgICAgKiAqICoqbnBtIHBhY2thZ2UqKjogYEBhbmd1bGFyL2Zvcm1zYFxuICAgICAgKiAqXG4gICAgICovXG4gICAgdmFyIEZvcm1Hcm91cCA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgICAgIF9fZXh0ZW5kcyQ2KEZvcm1Hcm91cCwgX3N1cGVyKTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gY29udHJvbHNcbiAgICAgICAgICogQHBhcmFtIHs/PX0gdmFsaWRhdG9yXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IGFzeW5jVmFsaWRhdG9yXG4gICAgICAgICAqL1xuICAgICAgICBmdW5jdGlvbiBGb3JtR3JvdXAoY29udHJvbHMsIHZhbGlkYXRvciwgYXN5bmNWYWxpZGF0b3IpIHtcbiAgICAgICAgICAgIGlmICh2YWxpZGF0b3IgPT09IHZvaWQgMCkgeyB2YWxpZGF0b3IgPSBudWxsOyB9XG4gICAgICAgICAgICBpZiAoYXN5bmNWYWxpZGF0b3IgPT09IHZvaWQgMCkgeyBhc3luY1ZhbGlkYXRvciA9IG51bGw7IH1cbiAgICAgICAgICAgIF9zdXBlci5jYWxsKHRoaXMsIHZhbGlkYXRvciwgYXN5bmNWYWxpZGF0b3IpO1xuICAgICAgICAgICAgdGhpcy5jb250cm9scyA9IGNvbnRyb2xzO1xuICAgICAgICAgICAgdGhpcy5faW5pdE9ic2VydmFibGVzKCk7XG4gICAgICAgICAgICB0aGlzLl9zZXRVcENvbnRyb2xzKCk7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoeyBvbmx5U2VsZjogdHJ1ZSwgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogIFJlZ2lzdGVycyBhIGNvbnRyb2wgd2l0aCB0aGUgZ3JvdXAncyBsaXN0IG9mIGNvbnRyb2xzLlxuICAgICAgICAgICogKlxuICAgICAgICAgICogVGhpcyBtZXRob2QgZG9lcyBub3QgdXBkYXRlIHZhbHVlIG9yIHZhbGlkaXR5IG9mIHRoZSBjb250cm9sLCBzbyBmb3JcbiAgICAgICAgICAqIG1vc3QgY2FzZXMgeW91J2xsIHdhbnQgdG8gdXNlIHtAbGluayBGb3JtR3JvdXAuYWRkQ29udHJvbH0gaW5zdGVhZC5cbiAgICAgICAgICogQHBhcmFtIHs/fSBuYW1lXG4gICAgICAgICAqIEBwYXJhbSB7P30gY29udHJvbFxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUdyb3VwLnByb3RvdHlwZS5yZWdpc3RlckNvbnRyb2wgPSBmdW5jdGlvbiAobmFtZSwgY29udHJvbCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuY29udHJvbHNbbmFtZV0pXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udHJvbHNbbmFtZV07XG4gICAgICAgICAgICB0aGlzLmNvbnRyb2xzW25hbWVdID0gY29udHJvbDtcbiAgICAgICAgICAgIGNvbnRyb2wuc2V0UGFyZW50KHRoaXMpO1xuICAgICAgICAgICAgY29udHJvbC5fcmVnaXN0ZXJPbkNvbGxlY3Rpb25DaGFuZ2UodGhpcy5fb25Db2xsZWN0aW9uQ2hhbmdlKTtcbiAgICAgICAgICAgIHJldHVybiBjb250cm9sO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogIEFkZCBhIGNvbnRyb2wgdG8gdGhpcyBncm91cC5cbiAgICAgICAgICogQHBhcmFtIHs/fSBuYW1lXG4gICAgICAgICAqIEBwYXJhbSB7P30gY29udHJvbFxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUdyb3VwLnByb3RvdHlwZS5hZGRDb250cm9sID0gZnVuY3Rpb24gKG5hbWUsIGNvbnRyb2wpIHtcbiAgICAgICAgICAgIHRoaXMucmVnaXN0ZXJDb250cm9sKG5hbWUsIGNvbnRyb2wpO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KCk7XG4gICAgICAgICAgICB0aGlzLl9vbkNvbGxlY3Rpb25DaGFuZ2UoKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqICBSZW1vdmUgYSBjb250cm9sIGZyb20gdGhpcyBncm91cC5cbiAgICAgICAgICogQHBhcmFtIHs/fSBuYW1lXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtR3JvdXAucHJvdG90eXBlLnJlbW92ZUNvbnRyb2wgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuY29udHJvbHNbbmFtZV0pXG4gICAgICAgICAgICAgICAgdGhpcy5jb250cm9sc1tuYW1lXS5fcmVnaXN0ZXJPbkNvbGxlY3Rpb25DaGFuZ2UoZnVuY3Rpb24gKCkgeyB9KTtcbiAgICAgICAgICAgIGRlbGV0ZSAodGhpcy5jb250cm9sc1tuYW1lXSk7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcbiAgICAgICAgICAgIHRoaXMuX29uQ29sbGVjdGlvbkNoYW5nZSgpO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogIFJlcGxhY2UgYW4gZXhpc3RpbmcgY29udHJvbC5cbiAgICAgICAgICogQHBhcmFtIHs/fSBuYW1lXG4gICAgICAgICAqIEBwYXJhbSB7P30gY29udHJvbFxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUdyb3VwLnByb3RvdHlwZS5zZXRDb250cm9sID0gZnVuY3Rpb24gKG5hbWUsIGNvbnRyb2wpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbnRyb2xzW25hbWVdKVxuICAgICAgICAgICAgICAgIHRoaXMuY29udHJvbHNbbmFtZV0uX3JlZ2lzdGVyT25Db2xsZWN0aW9uQ2hhbmdlKGZ1bmN0aW9uICgpIHsgfSk7XG4gICAgICAgICAgICBkZWxldGUgKHRoaXMuY29udHJvbHNbbmFtZV0pO1xuICAgICAgICAgICAgaWYgKGNvbnRyb2wpXG4gICAgICAgICAgICAgICAgdGhpcy5yZWdpc3RlckNvbnRyb2wobmFtZSwgY29udHJvbCk7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcbiAgICAgICAgICAgIHRoaXMuX29uQ29sbGVjdGlvbkNoYW5nZSgpO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogIENoZWNrIHdoZXRoZXIgdGhlcmUgaXMgYW4gZW5hYmxlZCBjb250cm9sIHdpdGggdGhlIGdpdmVuIG5hbWUgaW4gdGhlIGdyb3VwLlxuICAgICAgICAgICogKlxuICAgICAgICAgICogSXQgd2lsbCByZXR1cm4gZmFsc2UgZm9yIGRpc2FibGVkIGNvbnRyb2xzLiBJZiB5b3UnZCBsaWtlIHRvIGNoZWNrIGZvclxuICAgICAgICAgICogZXhpc3RlbmNlIGluIHRoZSBncm91cCBvbmx5LCB1c2Uge0BsaW5rIEFic3RyYWN0Q29udHJvbC5nZXR9IGluc3RlYWQuXG4gICAgICAgICAqIEBwYXJhbSB7P30gY29udHJvbE5hbWVcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Hcm91cC5wcm90b3R5cGUuY29udGFpbnMgPSBmdW5jdGlvbiAoY29udHJvbE5hbWUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnRyb2xzLmhhc093blByb3BlcnR5KGNvbnRyb2xOYW1lKSAmJiB0aGlzLmNvbnRyb2xzW2NvbnRyb2xOYW1lXS5lbmFibGVkO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogIFNldHMgdGhlIHZhbHVlIG9mIHRoZSB7QGxpbmsgRm9ybUdyb3VwfS4gSXQgYWNjZXB0cyBhbiBvYmplY3QgdGhhdCBtYXRjaGVzXG4gICAgICAgICAgKiB0aGUgc3RydWN0dXJlIG9mIHRoZSBncm91cCwgd2l0aCBjb250cm9sIG5hbWVzIGFzIGtleXMuXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiBUaGlzIG1ldGhvZCBwZXJmb3JtcyBzdHJpY3QgY2hlY2tzLCBzbyBpdCB3aWxsIHRocm93IGFuIGVycm9yIGlmIHlvdSB0cnlcbiAgICAgICAgICAqIHRvIHNldCB0aGUgdmFsdWUgb2YgYSBjb250cm9sIHRoYXQgZG9lc24ndCBleGlzdCBvciBpZiB5b3UgZXhjbHVkZSB0aGVcbiAgICAgICAgICAqIHZhbHVlIG9mIGEgY29udHJvbC5cbiAgICAgICAgICAqICpcbiAgICAgICAgICAqICMjIyBFeGFtcGxlXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiBgYGBcbiAgICAgICAgICAqIGNvbnN0IGZvcm0gPSBuZXcgRm9ybUdyb3VwKHtcbiAgICAgICAgICAqIGZpcnN0OiBuZXcgRm9ybUNvbnRyb2woKSxcbiAgICAgICAgICAqIGxhc3Q6IG5ldyBGb3JtQ29udHJvbCgpXG4gICAgICAgICAgKiB9KTtcbiAgICAgICAgICAqIGNvbnNvbGUubG9nKGZvcm0udmFsdWUpOyAgIC8vIHtmaXJzdDogbnVsbCwgbGFzdDogbnVsbH1cbiAgICAgICAgICAqICpcbiAgICAgICAgICAqIGZvcm0uc2V0VmFsdWUoe2ZpcnN0OiAnTmFuY3knLCBsYXN0OiAnRHJldyd9KTtcbiAgICAgICAgICAqIGNvbnNvbGUubG9nKGZvcm0udmFsdWUpOyAgIC8vIHtmaXJzdDogJ05hbmN5JywgbGFzdDogJ0RyZXcnfVxuICAgICAgICAgICogKlxuICAgICAgICAgICogYGBgXG4gICAgICAgICAqIEBwYXJhbSB7P30gdmFsdWVcbiAgICAgICAgICogQHBhcmFtIHs/PX0gX18xXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtR3JvdXAucHJvdG90eXBlLnNldFZhbHVlID0gZnVuY3Rpb24gKHZhbHVlLCBfYSkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHZhciBfYiA9IF9hID09PSB2b2lkIDAgPyB7fSA6IF9hLCBvbmx5U2VsZiA9IF9iLm9ubHlTZWxmLCBlbWl0RXZlbnQgPSBfYi5lbWl0RXZlbnQ7XG4gICAgICAgICAgICB0aGlzLl9jaGVja0FsbFZhbHVlc1ByZXNlbnQodmFsdWUpO1xuICAgICAgICAgICAgT2JqZWN0LmtleXModmFsdWUpLmZvckVhY2goZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5fdGhyb3dJZkNvbnRyb2xNaXNzaW5nKG5hbWUpO1xuICAgICAgICAgICAgICAgIF90aGlzLmNvbnRyb2xzW25hbWVdLnNldFZhbHVlKHZhbHVlW25hbWVdLCB7IG9ubHlTZWxmOiB0cnVlLCBlbWl0RXZlbnQ6IGVtaXRFdmVudCB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KHsgb25seVNlbGY6IG9ubHlTZWxmLCBlbWl0RXZlbnQ6IGVtaXRFdmVudCB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqICBQYXRjaGVzIHRoZSB2YWx1ZSBvZiB0aGUge0BsaW5rIEZvcm1Hcm91cH0uIEl0IGFjY2VwdHMgYW4gb2JqZWN0IHdpdGggY29udHJvbFxuICAgICAgICAgICogbmFtZXMgYXMga2V5cywgYW5kIHdpbGwgZG8gaXRzIGJlc3QgdG8gbWF0Y2ggdGhlIHZhbHVlcyB0byB0aGUgY29ycmVjdCBjb250cm9sc1xuICAgICAgICAgICogaW4gdGhlIGdyb3VwLlxuICAgICAgICAgICogKlxuICAgICAgICAgICogSXQgYWNjZXB0cyBib3RoIHN1cGVyLXNldHMgYW5kIHN1Yi1zZXRzIG9mIHRoZSBncm91cCB3aXRob3V0IHRocm93aW5nIGFuIGVycm9yLlxuICAgICAgICAgICogKlxuICAgICAgICAgICogIyMjIEV4YW1wbGVcbiAgICAgICAgICAqICpcbiAgICAgICAgICAqIGBgYFxuICAgICAgICAgICogY29uc3QgZm9ybSA9IG5ldyBGb3JtR3JvdXAoe1xuICAgICAgICAgICogZmlyc3Q6IG5ldyBGb3JtQ29udHJvbCgpLFxuICAgICAgICAgICogbGFzdDogbmV3IEZvcm1Db250cm9sKClcbiAgICAgICAgICAqIH0pO1xuICAgICAgICAgICogY29uc29sZS5sb2coZm9ybS52YWx1ZSk7ICAgLy8ge2ZpcnN0OiBudWxsLCBsYXN0OiBudWxsfVxuICAgICAgICAgICogKlxuICAgICAgICAgICogZm9ybS5wYXRjaFZhbHVlKHtmaXJzdDogJ05hbmN5J30pO1xuICAgICAgICAgICogY29uc29sZS5sb2coZm9ybS52YWx1ZSk7ICAgLy8ge2ZpcnN0OiAnTmFuY3knLCBsYXN0OiBudWxsfVxuICAgICAgICAgICogKlxuICAgICAgICAgICogYGBgXG4gICAgICAgICAqIEBwYXJhbSB7P30gdmFsdWVcbiAgICAgICAgICogQHBhcmFtIHs/PX0gX18xXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtR3JvdXAucHJvdG90eXBlLnBhdGNoVmFsdWUgPSBmdW5jdGlvbiAodmFsdWUsIF9hKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdmFyIF9iID0gX2EgPT09IHZvaWQgMCA/IHt9IDogX2EsIG9ubHlTZWxmID0gX2Iub25seVNlbGYsIGVtaXRFdmVudCA9IF9iLmVtaXRFdmVudDtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHZhbHVlKS5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLmNvbnRyb2xzW25hbWVdKSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmNvbnRyb2xzW25hbWVdLnBhdGNoVmFsdWUodmFsdWVbbmFtZV0sIHsgb25seVNlbGY6IHRydWUsIGVtaXRFdmVudDogZW1pdEV2ZW50IH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KHsgb25seVNlbGY6IG9ubHlTZWxmLCBlbWl0RXZlbnQ6IGVtaXRFdmVudCB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqICBSZXNldHMgdGhlIHtAbGluayBGb3JtR3JvdXB9LiBUaGlzIG1lYW5zIGJ5IGRlZmF1bHQ6XG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiAqIFRoZSBncm91cCBhbmQgYWxsIGRlc2NlbmRhbnRzIGFyZSBtYXJrZWQgYHByaXN0aW5lYFxuICAgICAgICAgICogKiBUaGUgZ3JvdXAgYW5kIGFsbCBkZXNjZW5kYW50cyBhcmUgbWFya2VkIGB1bnRvdWNoZWRgXG4gICAgICAgICAgKiAqIFRoZSB2YWx1ZSBvZiBhbGwgZGVzY2VuZGFudHMgd2lsbCBiZSBudWxsIG9yIG51bGwgbWFwc1xuICAgICAgICAgICogKlxuICAgICAgICAgICogWW91IGNhbiBhbHNvIHJlc2V0IHRvIGEgc3BlY2lmaWMgZm9ybSBzdGF0ZSBieSBwYXNzaW5nIGluIGEgbWFwIG9mIHN0YXRlc1xuICAgICAgICAgICogdGhhdCBtYXRjaGVzIHRoZSBzdHJ1Y3R1cmUgb2YgeW91ciBmb3JtLCB3aXRoIGNvbnRyb2wgbmFtZXMgYXMga2V5cy4gVGhlIHN0YXRlXG4gICAgICAgICAgKiBjYW4gYmUgYSBzdGFuZGFsb25lIHZhbHVlIG9yIGEgZm9ybSBzdGF0ZSBvYmplY3Qgd2l0aCBib3RoIGEgdmFsdWUgYW5kIGEgZGlzYWJsZWRcbiAgICAgICAgICAqIHN0YXR1cy5cbiAgICAgICAgICAqICpcbiAgICAgICAgICAqICMjIyBFeGFtcGxlXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiBgYGB0c1xuICAgICAgICAgICogdGhpcy5mb3JtLnJlc2V0KHtmaXJzdDogJ25hbWUnLCBsYXN0OiAnbGFzdCBuYW1lJ30pO1xuICAgICAgICAgICogKlxuICAgICAgICAgICogY29uc29sZS5sb2codGhpcy5mb3JtLnZhbHVlKTsgIC8vIHtmaXJzdDogJ25hbWUnLCBsYXN0OiAnbGFzdCBuYW1lJ31cbiAgICAgICAgICAqIGBgYFxuICAgICAgICAgICogKlxuICAgICAgICAgICogLSBPUiAtXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiBgYGBcbiAgICAgICAgICAqIHRoaXMuZm9ybS5yZXNldCh7XG4gICAgICAgICAgKiBmaXJzdDoge3ZhbHVlOiAnbmFtZScsIGRpc2FibGVkOiB0cnVlfSxcbiAgICAgICAgICAqIGxhc3Q6ICdsYXN0J1xuICAgICAgICAgICogfSk7XG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiBjb25zb2xlLmxvZyh0aGlzLmZvcm0udmFsdWUpOyAgLy8ge2ZpcnN0OiAnbmFtZScsIGxhc3Q6ICdsYXN0IG5hbWUnfVxuICAgICAgICAgICogY29uc29sZS5sb2codGhpcy5mb3JtLmdldCgnZmlyc3QnKS5zdGF0dXMpOyAgLy8gJ0RJU0FCTEVEJ1xuICAgICAgICAgICogYGBgXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IHZhbHVlXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IF9fMVxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUdyb3VwLnByb3RvdHlwZS5yZXNldCA9IGZ1bmN0aW9uICh2YWx1ZSwgX2EpIHtcbiAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gdm9pZCAwKSB7IHZhbHVlID0ge307IH1cbiAgICAgICAgICAgIHZhciBfYiA9IF9hID09PSB2b2lkIDAgPyB7fSA6IF9hLCBvbmx5U2VsZiA9IF9iLm9ubHlTZWxmLCBlbWl0RXZlbnQgPSBfYi5lbWl0RXZlbnQ7XG4gICAgICAgICAgICB0aGlzLl9mb3JFYWNoQ2hpbGQoZnVuY3Rpb24gKGNvbnRyb2wsIG5hbWUpIHtcbiAgICAgICAgICAgICAgICBjb250cm9sLnJlc2V0KHZhbHVlW25hbWVdLCB7IG9ubHlTZWxmOiB0cnVlLCBlbWl0RXZlbnQ6IGVtaXRFdmVudCB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KHsgb25seVNlbGY6IG9ubHlTZWxmLCBlbWl0RXZlbnQ6IGVtaXRFdmVudCB9KTtcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZVByaXN0aW5lKHsgb25seVNlbGY6IG9ubHlTZWxmIH0pO1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlVG91Y2hlZCh7IG9ubHlTZWxmOiBvbmx5U2VsZiB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqICBUaGUgYWdncmVnYXRlIHZhbHVlIG9mIHRoZSB7QGxpbmsgRm9ybUdyb3VwfSwgaW5jbHVkaW5nIGFueSBkaXNhYmxlZCBjb250cm9scy5cbiAgICAgICAgICAqICpcbiAgICAgICAgICAqIElmIHlvdSdkIGxpa2UgdG8gaW5jbHVkZSBhbGwgdmFsdWVzIHJlZ2FyZGxlc3Mgb2YgZGlzYWJsZWQgc3RhdHVzLCB1c2UgdGhpcyBtZXRob2QuXG4gICAgICAgICAgKiBPdGhlcndpc2UsIHRoZSBgdmFsdWVgIHByb3BlcnR5IGlzIHRoZSBiZXN0IHdheSB0byBnZXQgdGhlIHZhbHVlIG9mIHRoZSBncm91cC5cbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Hcm91cC5wcm90b3R5cGUuZ2V0UmF3VmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fcmVkdWNlQ2hpbGRyZW4oe30sIGZ1bmN0aW9uIChhY2MsIGNvbnRyb2wsIG5hbWUpIHtcbiAgICAgICAgICAgICAgICBhY2NbbmFtZV0gPSBjb250cm9sLnZhbHVlO1xuICAgICAgICAgICAgICAgIHJldHVybiBhY2M7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gbmFtZVxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUdyb3VwLnByb3RvdHlwZS5fdGhyb3dJZkNvbnRyb2xNaXNzaW5nID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgICAgICAgIGlmICghT2JqZWN0LmtleXModGhpcy5jb250cm9scykubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiXFxuICAgICAgICBUaGVyZSBhcmUgbm8gZm9ybSBjb250cm9scyByZWdpc3RlcmVkIHdpdGggdGhpcyBncm91cCB5ZXQuICBJZiB5b3UncmUgdXNpbmcgbmdNb2RlbCxcXG4gICAgICAgIHlvdSBtYXkgd2FudCB0byBjaGVjayBuZXh0IHRpY2sgKGUuZy4gdXNlIHNldFRpbWVvdXQpLlxcbiAgICAgIFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghdGhpcy5jb250cm9sc1tuYW1lXSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIGZvcm0gY29udHJvbCB3aXRoIG5hbWU6IFwiICsgbmFtZSArIFwiLlwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gY2JcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Hcm91cC5wcm90b3R5cGUuX2ZvckVhY2hDaGlsZCA9IGZ1bmN0aW9uIChjYikge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHRoaXMuY29udHJvbHMpLmZvckVhY2goZnVuY3Rpb24gKGspIHsgcmV0dXJuIGNiKF90aGlzLmNvbnRyb2xzW2tdLCBrKTsgfSk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUdyb3VwLnByb3RvdHlwZS5fc2V0VXBDb250cm9scyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB0aGlzLl9mb3JFYWNoQ2hpbGQoZnVuY3Rpb24gKGNvbnRyb2wpIHtcbiAgICAgICAgICAgICAgICBjb250cm9sLnNldFBhcmVudChfdGhpcyk7XG4gICAgICAgICAgICAgICAgY29udHJvbC5fcmVnaXN0ZXJPbkNvbGxlY3Rpb25DaGFuZ2UoX3RoaXMuX29uQ29sbGVjdGlvbkNoYW5nZSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtR3JvdXAucHJvdG90eXBlLl91cGRhdGVWYWx1ZSA9IGZ1bmN0aW9uICgpIHsgdGhpcy5fdmFsdWUgPSB0aGlzLl9yZWR1Y2VWYWx1ZSgpOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBjb25kaXRpb25cbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Hcm91cC5wcm90b3R5cGUuX2FueUNvbnRyb2xzID0gZnVuY3Rpb24gKGNvbmRpdGlvbikge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIHJlcyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5fZm9yRWFjaENoaWxkKGZ1bmN0aW9uIChjb250cm9sLCBuYW1lKSB7XG4gICAgICAgICAgICAgICAgcmVzID0gcmVzIHx8IChfdGhpcy5jb250YWlucyhuYW1lKSAmJiBjb25kaXRpb24oY29udHJvbCkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Hcm91cC5wcm90b3R5cGUuX3JlZHVjZVZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9yZWR1Y2VDaGlsZHJlbih7fSwgZnVuY3Rpb24gKGFjYywgY29udHJvbCwgbmFtZSkge1xuICAgICAgICAgICAgICAgIGlmIChjb250cm9sLmVuYWJsZWQgfHwgX3RoaXMuZGlzYWJsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgYWNjW25hbWVdID0gY29udHJvbC52YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFjYztcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBpbml0VmFsdWVcbiAgICAgICAgICogQHBhcmFtIHs/fSBmblxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUdyb3VwLnByb3RvdHlwZS5fcmVkdWNlQ2hpbGRyZW4gPSBmdW5jdGlvbiAoaW5pdFZhbHVlLCBmbikge1xuICAgICAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gcmVzID0gaW5pdFZhbHVlO1xuICAgICAgICAgICAgdGhpcy5fZm9yRWFjaENoaWxkKGZ1bmN0aW9uIChjb250cm9sLCBuYW1lKSB7IHJlcyA9IGZuKHJlcywgY29udHJvbCwgbmFtZSk7IH0pO1xuICAgICAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtR3JvdXAucHJvdG90eXBlLl9hbGxDb250cm9sc0Rpc2FibGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IE9iamVjdC5rZXlzKHRoaXMuY29udHJvbHMpOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgIHZhciBjb250cm9sTmFtZSA9IF9hW19pXTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb250cm9sc1tjb250cm9sTmFtZV0uZW5hYmxlZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKHRoaXMuY29udHJvbHMpLmxlbmd0aCA+IDAgfHwgdGhpcy5kaXNhYmxlZDtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gdmFsdWVcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Hcm91cC5wcm90b3R5cGUuX2NoZWNrQWxsVmFsdWVzUHJlc2VudCA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5fZm9yRWFjaENoaWxkKGZ1bmN0aW9uIChjb250cm9sLCBuYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKHZhbHVlW25hbWVdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTXVzdCBzdXBwbHkgYSB2YWx1ZSBmb3IgZm9ybSBjb250cm9sIHdpdGggbmFtZTogJ1wiICsgbmFtZSArIFwiJy5cIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBGb3JtR3JvdXA7XG4gICAgfShBYnN0cmFjdENvbnRyb2wpKTtcbiAgICAvKipcbiAgICAgKiAgaW5zdGFuY2VzLlxuICAgICAgKiAqXG4gICAgICAqIEEgYEZvcm1BcnJheWAgYWdncmVnYXRlcyB0aGUgdmFsdWVzIG9mIGVhY2ggY2hpbGQge0BsaW5rIEZvcm1Db250cm9sfSBpbnRvIGFuIGFycmF5LlxuICAgICAgKiBJdCBjYWxjdWxhdGVzIGl0cyBzdGF0dXMgYnkgcmVkdWNpbmcgdGhlIHN0YXR1c2VzIG9mIGl0cyBjaGlsZHJlbi4gRm9yIGV4YW1wbGUsIGlmIG9uZSBvZlxuICAgICAgKiB0aGUgY29udHJvbHMgaW4gYSBgRm9ybUFycmF5YCBpcyBpbnZhbGlkLCB0aGUgZW50aXJlIGFycmF5IGJlY29tZXMgaW52YWxpZC5cbiAgICAgICogKlxuICAgICAgKiBgRm9ybUFycmF5YCBpcyBvbmUgb2YgdGhlIHRocmVlIGZ1bmRhbWVudGFsIGJ1aWxkaW5nIGJsb2NrcyB1c2VkIHRvIGRlZmluZSBmb3JtcyBpbiBBbmd1bGFyLFxuICAgICAgKiBhbG9uZyB3aXRoIHtAbGluayBGb3JtQ29udHJvbH0gYW5kIHtAbGluayBGb3JtR3JvdXB9LlxuICAgICAgKiAqXG4gICAgICAqICpcbiAgICAgICogV2hlbiBpbnN0YW50aWF0aW5nIGEge0BsaW5rIEZvcm1BcnJheX0sIHBhc3MgaW4gYW4gYXJyYXkgb2YgY2hpbGQgY29udHJvbHMgYXMgdGhlIGZpcnN0XG4gICAgICAqIGFyZ3VtZW50LlxuICAgICAgKiAqXG4gICAgICAqICMjIyBFeGFtcGxlXG4gICAgICAqICpcbiAgICAgICogYGBgXG4gICAgICAqIGNvbnN0IGFyciA9IG5ldyBGb3JtQXJyYXkoW1xuICAgICAgKiBuZXcgRm9ybUNvbnRyb2woJ05hbmN5JywgVmFsaWRhdG9ycy5taW5MZW5ndGgoMikpLFxuICAgICAgKiBuZXcgRm9ybUNvbnRyb2woJ0RyZXcnKSxcbiAgICAgICogXSk7XG4gICAgICAqICpcbiAgICAgICogY29uc29sZS5sb2coYXJyLnZhbHVlKTsgICAvLyBbJ05hbmN5JywgJ0RyZXcnXVxuICAgICAgKiBjb25zb2xlLmxvZyhhcnIuc3RhdHVzKTsgIC8vICdWQUxJRCdcbiAgICAgICogYGBgXG4gICAgICAqICpcbiAgICAgICogWW91IGNhbiBhbHNvIGluY2x1ZGUgYXJyYXktbGV2ZWwgdmFsaWRhdG9ycyBhcyB0aGUgc2Vjb25kIGFyZywgb3IgYXJyYXktbGV2ZWwgYXN5bmNcbiAgICAgICogdmFsaWRhdG9ycyBhcyB0aGUgdGhpcmQgYXJnLiBUaGVzZSBjb21lIGluIGhhbmR5IHdoZW4geW91IHdhbnQgdG8gcGVyZm9ybSB2YWxpZGF0aW9uXG4gICAgICAqIHRoYXQgY29uc2lkZXJzIHRoZSB2YWx1ZSBvZiBtb3JlIHRoYW4gb25lIGNoaWxkIGNvbnRyb2wuXG4gICAgICAqICpcbiAgICAgICogIyMjIEFkZGluZyBvciByZW1vdmluZyBjb250cm9sc1xuICAgICAgKiAqXG4gICAgICAqIFRvIGNoYW5nZSB0aGUgY29udHJvbHMgaW4gdGhlIGFycmF5LCB1c2UgdGhlIGBwdXNoYCwgYGluc2VydGAsIG9yIGByZW1vdmVBdGAgbWV0aG9kc1xuICAgICAgKiBpbiBgRm9ybUFycmF5YCBpdHNlbGYuIFRoZXNlIG1ldGhvZHMgZW5zdXJlIHRoZSBjb250cm9scyBhcmUgcHJvcGVybHkgdHJhY2tlZCBpbiB0aGVcbiAgICAgICogZm9ybSdzIGhpZXJhcmNoeS4gRG8gbm90IG1vZGlmeSB0aGUgYXJyYXkgb2YgYEFic3RyYWN0Q29udHJvbGBzIHVzZWQgdG8gaW5zdGFudGlhdGVcbiAgICAgICogdGhlIGBGb3JtQXJyYXlgIGRpcmVjdGx5LCBhcyB0aGF0IHdpbGwgcmVzdWx0IGluIHN0cmFuZ2UgYW5kIHVuZXhwZWN0ZWQgYmVoYXZpb3Igc3VjaFxuICAgICAgKiBhcyBicm9rZW4gY2hhbmdlIGRldGVjdGlvbi5cbiAgICAgICogKlxuICAgICAgKiAqICoqbnBtIHBhY2thZ2UqKjogYEBhbmd1bGFyL2Zvcm1zYFxuICAgICAgKiAqXG4gICAgICovXG4gICAgdmFyIEZvcm1BcnJheSA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgICAgIF9fZXh0ZW5kcyQ2KEZvcm1BcnJheSwgX3N1cGVyKTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gY29udHJvbHNcbiAgICAgICAgICogQHBhcmFtIHs/PX0gdmFsaWRhdG9yXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IGFzeW5jVmFsaWRhdG9yXG4gICAgICAgICAqL1xuICAgICAgICBmdW5jdGlvbiBGb3JtQXJyYXkoY29udHJvbHMsIHZhbGlkYXRvciwgYXN5bmNWYWxpZGF0b3IpIHtcbiAgICAgICAgICAgIGlmICh2YWxpZGF0b3IgPT09IHZvaWQgMCkgeyB2YWxpZGF0b3IgPSBudWxsOyB9XG4gICAgICAgICAgICBpZiAoYXN5bmNWYWxpZGF0b3IgPT09IHZvaWQgMCkgeyBhc3luY1ZhbGlkYXRvciA9IG51bGw7IH1cbiAgICAgICAgICAgIF9zdXBlci5jYWxsKHRoaXMsIHZhbGlkYXRvciwgYXN5bmNWYWxpZGF0b3IpO1xuICAgICAgICAgICAgdGhpcy5jb250cm9scyA9IGNvbnRyb2xzO1xuICAgICAgICAgICAgdGhpcy5faW5pdE9ic2VydmFibGVzKCk7XG4gICAgICAgICAgICB0aGlzLl9zZXRVcENvbnRyb2xzKCk7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoeyBvbmx5U2VsZjogdHJ1ZSwgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogIEdldCB0aGUge0BsaW5rIEFic3RyYWN0Q29udHJvbH0gYXQgdGhlIGdpdmVuIGBpbmRleGAgaW4gdGhlIGFycmF5LlxuICAgICAgICAgKiBAcGFyYW0gez99IGluZGV4XG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtQXJyYXkucHJvdG90eXBlLmF0ID0gZnVuY3Rpb24gKGluZGV4KSB7IHJldHVybiB0aGlzLmNvbnRyb2xzW2luZGV4XTsgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqICBJbnNlcnQgYSBuZXcge0BsaW5rIEFic3RyYWN0Q29udHJvbH0gYXQgdGhlIGVuZCBvZiB0aGUgYXJyYXkuXG4gICAgICAgICAqIEBwYXJhbSB7P30gY29udHJvbFxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUFycmF5LnByb3RvdHlwZS5wdXNoID0gZnVuY3Rpb24gKGNvbnRyb2wpIHtcbiAgICAgICAgICAgIHRoaXMuY29udHJvbHMucHVzaChjb250cm9sKTtcbiAgICAgICAgICAgIHRoaXMuX3JlZ2lzdGVyQ29udHJvbChjb250cm9sKTtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSgpO1xuICAgICAgICAgICAgdGhpcy5fb25Db2xsZWN0aW9uQ2hhbmdlKCk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiAgSW5zZXJ0IGEgbmV3IHtAbGluayBBYnN0cmFjdENvbnRyb2x9IGF0IHRoZSBnaXZlbiBgaW5kZXhgIGluIHRoZSBhcnJheS5cbiAgICAgICAgICogQHBhcmFtIHs/fSBpbmRleFxuICAgICAgICAgKiBAcGFyYW0gez99IGNvbnRyb2xcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1BcnJheS5wcm90b3R5cGUuaW5zZXJ0ID0gZnVuY3Rpb24gKGluZGV4LCBjb250cm9sKSB7XG4gICAgICAgICAgICB0aGlzLmNvbnRyb2xzLnNwbGljZShpbmRleCwgMCwgY29udHJvbCk7XG4gICAgICAgICAgICB0aGlzLl9yZWdpc3RlckNvbnRyb2woY29udHJvbCk7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcbiAgICAgICAgICAgIHRoaXMuX29uQ29sbGVjdGlvbkNoYW5nZSgpO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogIFJlbW92ZSB0aGUgY29udHJvbCBhdCB0aGUgZ2l2ZW4gYGluZGV4YCBpbiB0aGUgYXJyYXkuXG4gICAgICAgICAqIEBwYXJhbSB7P30gaW5kZXhcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1BcnJheS5wcm90b3R5cGUucmVtb3ZlQXQgPSBmdW5jdGlvbiAoaW5kZXgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbnRyb2xzW2luZGV4XSlcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnRyb2xzW2luZGV4XS5fcmVnaXN0ZXJPbkNvbGxlY3Rpb25DaGFuZ2UoZnVuY3Rpb24gKCkgeyB9KTtcbiAgICAgICAgICAgIHRoaXMuY29udHJvbHMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSgpO1xuICAgICAgICAgICAgdGhpcy5fb25Db2xsZWN0aW9uQ2hhbmdlKCk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiAgUmVwbGFjZSBhbiBleGlzdGluZyBjb250cm9sLlxuICAgICAgICAgKiBAcGFyYW0gez99IGluZGV4XG4gICAgICAgICAqIEBwYXJhbSB7P30gY29udHJvbFxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUFycmF5LnByb3RvdHlwZS5zZXRDb250cm9sID0gZnVuY3Rpb24gKGluZGV4LCBjb250cm9sKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5jb250cm9sc1tpbmRleF0pXG4gICAgICAgICAgICAgICAgdGhpcy5jb250cm9sc1tpbmRleF0uX3JlZ2lzdGVyT25Db2xsZWN0aW9uQ2hhbmdlKGZ1bmN0aW9uICgpIHsgfSk7XG4gICAgICAgICAgICB0aGlzLmNvbnRyb2xzLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICBpZiAoY29udHJvbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuY29udHJvbHMuc3BsaWNlKGluZGV4LCAwLCBjb250cm9sKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9yZWdpc3RlckNvbnRyb2woY29udHJvbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcbiAgICAgICAgICAgIHRoaXMuX29uQ29sbGVjdGlvbkNoYW5nZSgpO1xuICAgICAgICB9O1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRm9ybUFycmF5LnByb3RvdHlwZSwgXCJsZW5ndGhcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiAgTGVuZ3RoIG9mIHRoZSBjb250cm9sIGFycmF5LlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLmNvbnRyb2xzLmxlbmd0aDsgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiAgU2V0cyB0aGUgdmFsdWUgb2YgdGhlIHtAbGluayBGb3JtQXJyYXl9LiBJdCBhY2NlcHRzIGFuIGFycmF5IHRoYXQgbWF0Y2hlc1xuICAgICAgICAgICogdGhlIHN0cnVjdHVyZSBvZiB0aGUgY29udHJvbC5cbiAgICAgICAgICAqICpcbiAgICAgICAgICAqIFRoaXMgbWV0aG9kIHBlcmZvcm1zIHN0cmljdCBjaGVja3MsIHNvIGl0IHdpbGwgdGhyb3cgYW4gZXJyb3IgaWYgeW91IHRyeVxuICAgICAgICAgICogdG8gc2V0IHRoZSB2YWx1ZSBvZiBhIGNvbnRyb2wgdGhhdCBkb2Vzbid0IGV4aXN0IG9yIGlmIHlvdSBleGNsdWRlIHRoZVxuICAgICAgICAgICogdmFsdWUgb2YgYSBjb250cm9sLlxuICAgICAgICAgICogKlxuICAgICAgICAgICogIyMjIEV4YW1wbGVcbiAgICAgICAgICAqICpcbiAgICAgICAgICAqIGBgYFxuICAgICAgICAgICogY29uc3QgYXJyID0gbmV3IEZvcm1BcnJheShbXG4gICAgICAgICAgKiBuZXcgRm9ybUNvbnRyb2woKSxcbiAgICAgICAgICAqIG5ldyBGb3JtQ29udHJvbCgpXG4gICAgICAgICAgKiBdKTtcbiAgICAgICAgICAqIGNvbnNvbGUubG9nKGFyci52YWx1ZSk7ICAgLy8gW251bGwsIG51bGxdXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiBhcnIuc2V0VmFsdWUoWydOYW5jeScsICdEcmV3J10pO1xuICAgICAgICAgICogY29uc29sZS5sb2coYXJyLnZhbHVlKTsgICAvLyBbJ05hbmN5JywgJ0RyZXcnXVxuICAgICAgICAgICogYGBgXG4gICAgICAgICAqIEBwYXJhbSB7P30gdmFsdWVcbiAgICAgICAgICogQHBhcmFtIHs/PX0gX18xXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtQXJyYXkucHJvdG90eXBlLnNldFZhbHVlID0gZnVuY3Rpb24gKHZhbHVlLCBfYSkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHZhciBfYiA9IF9hID09PSB2b2lkIDAgPyB7fSA6IF9hLCBvbmx5U2VsZiA9IF9iLm9ubHlTZWxmLCBlbWl0RXZlbnQgPSBfYi5lbWl0RXZlbnQ7XG4gICAgICAgICAgICB0aGlzLl9jaGVja0FsbFZhbHVlc1ByZXNlbnQodmFsdWUpO1xuICAgICAgICAgICAgdmFsdWUuZm9yRWFjaChmdW5jdGlvbiAobmV3VmFsdWUsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuX3Rocm93SWZDb250cm9sTWlzc2luZyhpbmRleCk7XG4gICAgICAgICAgICAgICAgX3RoaXMuYXQoaW5kZXgpLnNldFZhbHVlKG5ld1ZhbHVlLCB7IG9ubHlTZWxmOiB0cnVlLCBlbWl0RXZlbnQ6IGVtaXRFdmVudCB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KHsgb25seVNlbGY6IG9ubHlTZWxmLCBlbWl0RXZlbnQ6IGVtaXRFdmVudCB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqICBQYXRjaGVzIHRoZSB2YWx1ZSBvZiB0aGUge0BsaW5rIEZvcm1BcnJheX0uIEl0IGFjY2VwdHMgYW4gYXJyYXkgdGhhdCBtYXRjaGVzIHRoZVxuICAgICAgICAgICogc3RydWN0dXJlIG9mIHRoZSBjb250cm9sLCBhbmQgd2lsbCBkbyBpdHMgYmVzdCB0byBtYXRjaCB0aGUgdmFsdWVzIHRvIHRoZSBjb3JyZWN0XG4gICAgICAgICAgKiBjb250cm9scyBpbiB0aGUgZ3JvdXAuXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiBJdCBhY2NlcHRzIGJvdGggc3VwZXItc2V0cyBhbmQgc3ViLXNldHMgb2YgdGhlIGFycmF5IHdpdGhvdXQgdGhyb3dpbmcgYW4gZXJyb3IuXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiAjIyMgRXhhbXBsZVxuICAgICAgICAgICogKlxuICAgICAgICAgICogYGBgXG4gICAgICAgICAgKiBjb25zdCBhcnIgPSBuZXcgRm9ybUFycmF5KFtcbiAgICAgICAgICAqIG5ldyBGb3JtQ29udHJvbCgpLFxuICAgICAgICAgICogbmV3IEZvcm1Db250cm9sKClcbiAgICAgICAgICAqIF0pO1xuICAgICAgICAgICogY29uc29sZS5sb2coYXJyLnZhbHVlKTsgICAvLyBbbnVsbCwgbnVsbF1cbiAgICAgICAgICAqICpcbiAgICAgICAgICAqIGFyci5wYXRjaFZhbHVlKFsnTmFuY3knXSk7XG4gICAgICAgICAgKiBjb25zb2xlLmxvZyhhcnIudmFsdWUpOyAgIC8vIFsnTmFuY3knLCBudWxsXVxuICAgICAgICAgICogYGBgXG4gICAgICAgICAqIEBwYXJhbSB7P30gdmFsdWVcbiAgICAgICAgICogQHBhcmFtIHs/PX0gX18xXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtQXJyYXkucHJvdG90eXBlLnBhdGNoVmFsdWUgPSBmdW5jdGlvbiAodmFsdWUsIF9hKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdmFyIF9iID0gX2EgPT09IHZvaWQgMCA/IHt9IDogX2EsIG9ubHlTZWxmID0gX2Iub25seVNlbGYsIGVtaXRFdmVudCA9IF9iLmVtaXRFdmVudDtcbiAgICAgICAgICAgIHZhbHVlLmZvckVhY2goZnVuY3Rpb24gKG5ld1ZhbHVlLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5hdChpbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuYXQoaW5kZXgpLnBhdGNoVmFsdWUobmV3VmFsdWUsIHsgb25seVNlbGY6IHRydWUsIGVtaXRFdmVudDogZW1pdEV2ZW50IH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KHsgb25seVNlbGY6IG9ubHlTZWxmLCBlbWl0RXZlbnQ6IGVtaXRFdmVudCB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqICBSZXNldHMgdGhlIHtAbGluayBGb3JtQXJyYXl9LiBUaGlzIG1lYW5zIGJ5IGRlZmF1bHQ6XG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiAqIFRoZSBhcnJheSBhbmQgYWxsIGRlc2NlbmRhbnRzIGFyZSBtYXJrZWQgYHByaXN0aW5lYFxuICAgICAgICAgICogKiBUaGUgYXJyYXkgYW5kIGFsbCBkZXNjZW5kYW50cyBhcmUgbWFya2VkIGB1bnRvdWNoZWRgXG4gICAgICAgICAgKiAqIFRoZSB2YWx1ZSBvZiBhbGwgZGVzY2VuZGFudHMgd2lsbCBiZSBudWxsIG9yIG51bGwgbWFwc1xuICAgICAgICAgICogKlxuICAgICAgICAgICogWW91IGNhbiBhbHNvIHJlc2V0IHRvIGEgc3BlY2lmaWMgZm9ybSBzdGF0ZSBieSBwYXNzaW5nIGluIGFuIGFycmF5IG9mIHN0YXRlc1xuICAgICAgICAgICogdGhhdCBtYXRjaGVzIHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIGNvbnRyb2wuIFRoZSBzdGF0ZSBjYW4gYmUgYSBzdGFuZGFsb25lIHZhbHVlXG4gICAgICAgICAgKiBvciBhIGZvcm0gc3RhdGUgb2JqZWN0IHdpdGggYm90aCBhIHZhbHVlIGFuZCBhIGRpc2FibGVkIHN0YXR1cy5cbiAgICAgICAgICAqICpcbiAgICAgICAgICAqICMjIyBFeGFtcGxlXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiBgYGB0c1xuICAgICAgICAgICogdGhpcy5hcnIucmVzZXQoWyduYW1lJywgJ2xhc3QgbmFtZSddKTtcbiAgICAgICAgICAqICpcbiAgICAgICAgICAqIGNvbnNvbGUubG9nKHRoaXMuYXJyLnZhbHVlKTsgIC8vIFsnbmFtZScsICdsYXN0IG5hbWUnXVxuICAgICAgICAgICogYGBgXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiAtIE9SIC1cbiAgICAgICAgICAqICpcbiAgICAgICAgICAqIGBgYFxuICAgICAgICAgICogdGhpcy5hcnIucmVzZXQoW1xuICAgICAgICAgICoge3ZhbHVlOiAnbmFtZScsIGRpc2FibGVkOiB0cnVlfSxcbiAgICAgICAgICAqICdsYXN0J1xuICAgICAgICAgICogXSk7XG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiBjb25zb2xlLmxvZyh0aGlzLmFyci52YWx1ZSk7ICAvLyBbJ25hbWUnLCAnbGFzdCBuYW1lJ11cbiAgICAgICAgICAqIGNvbnNvbGUubG9nKHRoaXMuYXJyLmdldCgwKS5zdGF0dXMpOyAgLy8gJ0RJU0FCTEVEJ1xuICAgICAgICAgICogYGBgXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IHZhbHVlXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IF9fMVxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUFycmF5LnByb3RvdHlwZS5yZXNldCA9IGZ1bmN0aW9uICh2YWx1ZSwgX2EpIHtcbiAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gdm9pZCAwKSB7IHZhbHVlID0gW107IH1cbiAgICAgICAgICAgIHZhciBfYiA9IF9hID09PSB2b2lkIDAgPyB7fSA6IF9hLCBvbmx5U2VsZiA9IF9iLm9ubHlTZWxmLCBlbWl0RXZlbnQgPSBfYi5lbWl0RXZlbnQ7XG4gICAgICAgICAgICB0aGlzLl9mb3JFYWNoQ2hpbGQoZnVuY3Rpb24gKGNvbnRyb2wsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgY29udHJvbC5yZXNldCh2YWx1ZVtpbmRleF0sIHsgb25seVNlbGY6IHRydWUsIGVtaXRFdmVudDogZW1pdEV2ZW50IH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoeyBvbmx5U2VsZjogb25seVNlbGYsIGVtaXRFdmVudDogZW1pdEV2ZW50IH0pO1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlUHJpc3RpbmUoeyBvbmx5U2VsZjogb25seVNlbGYgfSk7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVUb3VjaGVkKHsgb25seVNlbGY6IG9ubHlTZWxmIH0pO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogIFRoZSBhZ2dyZWdhdGUgdmFsdWUgb2YgdGhlIGFycmF5LCBpbmNsdWRpbmcgYW55IGRpc2FibGVkIGNvbnRyb2xzLlxuICAgICAgICAgICogKlxuICAgICAgICAgICogSWYgeW91J2QgbGlrZSB0byBpbmNsdWRlIGFsbCB2YWx1ZXMgcmVnYXJkbGVzcyBvZiBkaXNhYmxlZCBzdGF0dXMsIHVzZSB0aGlzIG1ldGhvZC5cbiAgICAgICAgICAqIE90aGVyd2lzZSwgdGhlIGB2YWx1ZWAgcHJvcGVydHkgaXMgdGhlIGJlc3Qgd2F5IHRvIGdldCB0aGUgdmFsdWUgb2YgdGhlIGFycmF5LlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUFycmF5LnByb3RvdHlwZS5nZXRSYXdWYWx1ZSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuY29udHJvbHMubWFwKGZ1bmN0aW9uIChjb250cm9sKSB7IHJldHVybiBjb250cm9sLnZhbHVlOyB9KTsgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gaW5kZXhcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1BcnJheS5wcm90b3R5cGUuX3Rocm93SWZDb250cm9sTWlzc2luZyA9IGZ1bmN0aW9uIChpbmRleCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmNvbnRyb2xzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlxcbiAgICAgICAgVGhlcmUgYXJlIG5vIGZvcm0gY29udHJvbHMgcmVnaXN0ZXJlZCB3aXRoIHRoaXMgYXJyYXkgeWV0LiAgSWYgeW91J3JlIHVzaW5nIG5nTW9kZWwsXFxuICAgICAgICB5b3UgbWF5IHdhbnQgdG8gY2hlY2sgbmV4dCB0aWNrIChlLmcuIHVzZSBzZXRUaW1lb3V0KS5cXG4gICAgICBcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXRoaXMuYXQoaW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgZm9ybSBjb250cm9sIGF0IGluZGV4IFwiICsgaW5kZXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBjYlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUFycmF5LnByb3RvdHlwZS5fZm9yRWFjaENoaWxkID0gZnVuY3Rpb24gKGNiKSB7XG4gICAgICAgICAgICB0aGlzLmNvbnRyb2xzLmZvckVhY2goZnVuY3Rpb24gKGNvbnRyb2wsIGluZGV4KSB7IGNiKGNvbnRyb2wsIGluZGV4KTsgfSk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUFycmF5LnByb3RvdHlwZS5fdXBkYXRlVmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdGhpcy5fdmFsdWUgPSB0aGlzLmNvbnRyb2xzLmZpbHRlcihmdW5jdGlvbiAoY29udHJvbCkgeyByZXR1cm4gY29udHJvbC5lbmFibGVkIHx8IF90aGlzLmRpc2FibGVkOyB9KVxuICAgICAgICAgICAgICAgIC5tYXAoZnVuY3Rpb24gKGNvbnRyb2wpIHsgcmV0dXJuIGNvbnRyb2wudmFsdWU7IH0pO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBjb25kaXRpb25cbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1BcnJheS5wcm90b3R5cGUuX2FueUNvbnRyb2xzID0gZnVuY3Rpb24gKGNvbmRpdGlvbikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udHJvbHMuc29tZShmdW5jdGlvbiAoY29udHJvbCkgeyByZXR1cm4gY29udHJvbC5lbmFibGVkICYmIGNvbmRpdGlvbihjb250cm9sKTsgfSk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUFycmF5LnByb3RvdHlwZS5fc2V0VXBDb250cm9scyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICB0aGlzLl9mb3JFYWNoQ2hpbGQoZnVuY3Rpb24gKGNvbnRyb2wpIHsgcmV0dXJuIF90aGlzLl9yZWdpc3RlckNvbnRyb2woY29udHJvbCk7IH0pO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSB2YWx1ZVxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUFycmF5LnByb3RvdHlwZS5fY2hlY2tBbGxWYWx1ZXNQcmVzZW50ID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICB0aGlzLl9mb3JFYWNoQ2hpbGQoZnVuY3Rpb24gKGNvbnRyb2wsIGkpIHtcbiAgICAgICAgICAgICAgICBpZiAodmFsdWVbaV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJNdXN0IHN1cHBseSBhIHZhbHVlIGZvciBmb3JtIGNvbnRyb2wgYXQgaW5kZXg6IFwiICsgaSArIFwiLlwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtQXJyYXkucHJvdG90eXBlLl9hbGxDb250cm9sc0Rpc2FibGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuY29udHJvbHM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbnRyb2wgPSBfYVtfaV07XG4gICAgICAgICAgICAgICAgaWYgKGNvbnRyb2wuZW5hYmxlZClcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udHJvbHMubGVuZ3RoID4gMCB8fCB0aGlzLmRpc2FibGVkO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBjb250cm9sXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtQXJyYXkucHJvdG90eXBlLl9yZWdpc3RlckNvbnRyb2wgPSBmdW5jdGlvbiAoY29udHJvbCkge1xuICAgICAgICAgICAgY29udHJvbC5zZXRQYXJlbnQodGhpcyk7XG4gICAgICAgICAgICBjb250cm9sLl9yZWdpc3Rlck9uQ29sbGVjdGlvbkNoYW5nZSh0aGlzLl9vbkNvbGxlY3Rpb25DaGFuZ2UpO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gRm9ybUFycmF5O1xuICAgIH0oQWJzdHJhY3RDb250cm9sKSk7XG5cbiAgICAvKipcbiAgICAgKiBAbGljZW5zZVxuICAgICAqIENvcHlyaWdodCBHb29nbGUgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICAgICAqXG4gICAgICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAgICAgKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gICAgICovXG4gICAgdmFyIF9fZXh0ZW5kcyQ0ID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG4gICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gZm9ybURpcmVjdGl2ZVByb3ZpZGVyID0ge1xuICAgICAgICBwcm92aWRlOiBDb250cm9sQ29udGFpbmVyLFxuICAgICAgICB1c2VFeGlzdGluZzogX2FuZ3VsYXJfY29yZS5mb3J3YXJkUmVmKGZ1bmN0aW9uICgpIHsgcmV0dXJuIE5nRm9ybTsgfSlcbiAgICB9O1xuICAgIHZhciAvKiogQHR5cGUgez99ICovIHJlc29sdmVkUHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZShudWxsKTtcbiAgICAvKipcbiAgICAgKiAgdG8gdHJhY2sgYWdncmVnYXRlIGZvcm0gdmFsdWUgYW5kIHZhbGlkYXRpb24gc3RhdHVzLlxuICAgICAgKiAqXG4gICAgICAqICpcbiAgICAgICogQXMgc29vbiBhcyB5b3UgaW1wb3J0IHRoZSBgRm9ybXNNb2R1bGVgLCB0aGlzIGRpcmVjdGl2ZSBiZWNvbWVzIGFjdGl2ZSBieSBkZWZhdWx0IG9uXG4gICAgICAqIGFsbCBgPGZvcm0+YCB0YWdzLiAgWW91IGRvbid0IG5lZWQgdG8gYWRkIGEgc3BlY2lhbCBzZWxlY3Rvci5cbiAgICAgICogKlxuICAgICAgKiBZb3UgY2FuIGV4cG9ydCB0aGUgZGlyZWN0aXZlIGludG8gYSBsb2NhbCB0ZW1wbGF0ZSB2YXJpYWJsZSB1c2luZyBgbmdGb3JtYCBhcyB0aGUga2V5XG4gICAgICAqIChleDogYCNteUZvcm09XCJuZ0Zvcm1cImApLiBUaGlzIGlzIG9wdGlvbmFsLCBidXQgdXNlZnVsLiAgTWFueSBwcm9wZXJ0aWVzIGZyb20gdGhlIHVuZGVybHlpbmdcbiAgICAgICoge0BsaW5rIEZvcm1Hcm91cH0gaW5zdGFuY2UgYXJlIGR1cGxpY2F0ZWQgb24gdGhlIGRpcmVjdGl2ZSBpdHNlbGYsIHNvIGEgcmVmZXJlbmNlIHRvIGl0XG4gICAgICAqIHdpbGwgZ2l2ZSB5b3UgYWNjZXNzIHRvIHRoZSBhZ2dyZWdhdGUgdmFsdWUgYW5kIHZhbGlkaXR5IHN0YXR1cyBvZiB0aGUgZm9ybSwgYXMgd2VsbCBhc1xuICAgICAgKiB1c2VyIGludGVyYWN0aW9uIHByb3BlcnRpZXMgbGlrZSBgZGlydHlgIGFuZCBgdG91Y2hlZGAuXG4gICAgICAqICpcbiAgICAgICogVG8gcmVnaXN0ZXIgY2hpbGQgY29udHJvbHMgd2l0aCB0aGUgZm9ybSwgeW91J2xsIHdhbnQgdG8gdXNlIHtAbGluayBOZ01vZGVsfSB3aXRoIGFcbiAgICAgICogYG5hbWVgIGF0dHJpYnV0ZS4gIFlvdSBjYW4gYWxzbyB1c2Uge0BsaW5rIE5nTW9kZWxHcm91cH0gaWYgeW91J2QgbGlrZSB0byBjcmVhdGVcbiAgICAgICogc3ViLWdyb3VwcyB3aXRoaW4gdGhlIGZvcm0uXG4gICAgICAqICpcbiAgICAgICogWW91IGNhbiBsaXN0ZW4gdG8gdGhlIGRpcmVjdGl2ZSdzIGBuZ1N1Ym1pdGAgZXZlbnQgdG8gYmUgbm90aWZpZWQgd2hlbiB0aGUgdXNlciBoYXNcbiAgICAgICogdHJpZ2dlcmVkIGEgZm9ybSBzdWJtaXNzaW9uLiBUaGUgYG5nU3VibWl0YCBldmVudCB3aWxsIGJlIGVtaXR0ZWQgd2l0aCB0aGUgb3JpZ2luYWwgZm9ybVxuICAgICAgKiBzdWJtaXNzaW9uIGV2ZW50LlxuICAgICAgKiAqXG4gICAgICAqIHtAZXhhbXBsZSBmb3Jtcy90cy9zaW1wbGVGb3JtL3NpbXBsZV9mb3JtX2V4YW1wbGUudHMgcmVnaW9uPSdDb21wb25lbnQnfVxuICAgICAgKiAqXG4gICAgICAqICogKipucG0gcGFja2FnZSoqOiBgQGFuZ3VsYXIvZm9ybXNgXG4gICAgICAqICpcbiAgICAgICogKiAqKk5nTW9kdWxlKio6IGBGb3Jtc01vZHVsZWBcbiAgICAgICogKlxuICAgICAgKiBAc3RhYmxlXG4gICAgICovXG4gICAgdmFyIE5nRm9ybSA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgICAgIF9fZXh0ZW5kcyQ0KE5nRm9ybSwgX3N1cGVyKTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gdmFsaWRhdG9yc1xuICAgICAgICAgKiBAcGFyYW0gez99IGFzeW5jVmFsaWRhdG9yc1xuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gTmdGb3JtKHZhbGlkYXRvcnMsIGFzeW5jVmFsaWRhdG9ycykge1xuICAgICAgICAgICAgX3N1cGVyLmNhbGwodGhpcyk7XG4gICAgICAgICAgICB0aGlzLl9zdWJtaXR0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMubmdTdWJtaXQgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgICAgICAgICB0aGlzLmZvcm0gPVxuICAgICAgICAgICAgICAgIG5ldyBGb3JtR3JvdXAoe30sIGNvbXBvc2VWYWxpZGF0b3JzKHZhbGlkYXRvcnMpLCBjb21wb3NlQXN5bmNWYWxpZGF0b3JzKGFzeW5jVmFsaWRhdG9ycykpO1xuICAgICAgICB9XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShOZ0Zvcm0ucHJvdG90eXBlLCBcInN1Ym1pdHRlZFwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5fc3VibWl0dGVkOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE5nRm9ybS5wcm90b3R5cGUsIFwiZm9ybURpcmVjdGl2ZVwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShOZ0Zvcm0ucHJvdG90eXBlLCBcImNvbnRyb2xcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuZm9ybTsgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShOZ0Zvcm0ucHJvdG90eXBlLCBcInBhdGhcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIFtdOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE5nRm9ybS5wcm90b3R5cGUsIFwiY29udHJvbHNcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuZm9ybS5jb250cm9sczsgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGRpclxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgTmdGb3JtLnByb3RvdHlwZS5hZGRDb250cm9sID0gZnVuY3Rpb24gKGRpcikge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHJlc29sdmVkUHJvbWlzZS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBjb250YWluZXIgPSBfdGhpcy5fZmluZENvbnRhaW5lcihkaXIucGF0aCk7XG4gICAgICAgICAgICAgICAgZGlyLl9jb250cm9sID0gKGNvbnRhaW5lci5yZWdpc3RlckNvbnRyb2woZGlyLm5hbWUsIGRpci5jb250cm9sKSk7XG4gICAgICAgICAgICAgICAgc2V0VXBDb250cm9sKGRpci5jb250cm9sLCBkaXIpO1xuICAgICAgICAgICAgICAgIGRpci5jb250cm9sLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGRpclxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgTmdGb3JtLnByb3RvdHlwZS5nZXRDb250cm9sID0gZnVuY3Rpb24gKGRpcikgeyByZXR1cm4gKHRoaXMuZm9ybS5nZXQoZGlyLnBhdGgpKTsgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gZGlyXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBOZ0Zvcm0ucHJvdG90eXBlLnJlbW92ZUNvbnRyb2wgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgcmVzb2x2ZWRQcm9taXNlLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIGNvbnRhaW5lciA9IF90aGlzLl9maW5kQ29udGFpbmVyKGRpci5wYXRoKTtcbiAgICAgICAgICAgICAgICBpZiAoY29udGFpbmVyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRhaW5lci5yZW1vdmVDb250cm9sKGRpci5uYW1lKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gZGlyXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBOZ0Zvcm0ucHJvdG90eXBlLmFkZEZvcm1Hcm91cCA9IGZ1bmN0aW9uIChkaXIpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgICAgICByZXNvbHZlZFByb21pc2UudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gY29udGFpbmVyID0gX3RoaXMuX2ZpbmRDb250YWluZXIoZGlyLnBhdGgpO1xuICAgICAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIGdyb3VwID0gbmV3IEZvcm1Hcm91cCh7fSk7XG4gICAgICAgICAgICAgICAgc2V0VXBGb3JtQ29udGFpbmVyKGdyb3VwLCBkaXIpO1xuICAgICAgICAgICAgICAgIGNvbnRhaW5lci5yZWdpc3RlckNvbnRyb2woZGlyLm5hbWUsIGdyb3VwKTtcbiAgICAgICAgICAgICAgICBncm91cC51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBkaXJcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIE5nRm9ybS5wcm90b3R5cGUucmVtb3ZlRm9ybUdyb3VwID0gZnVuY3Rpb24gKGRpcikge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHJlc29sdmVkUHJvbWlzZS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBjb250YWluZXIgPSBfdGhpcy5fZmluZENvbnRhaW5lcihkaXIucGF0aCk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbnRhaW5lcikge1xuICAgICAgICAgICAgICAgICAgICBjb250YWluZXIucmVtb3ZlQ29udHJvbChkaXIubmFtZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGRpclxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgTmdGb3JtLnByb3RvdHlwZS5nZXRGb3JtR3JvdXAgPSBmdW5jdGlvbiAoZGlyKSB7IHJldHVybiAodGhpcy5mb3JtLmdldChkaXIucGF0aCkpOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBkaXJcbiAgICAgICAgICogQHBhcmFtIHs/fSB2YWx1ZVxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgTmdGb3JtLnByb3RvdHlwZS51cGRhdGVNb2RlbCA9IGZ1bmN0aW9uIChkaXIsIHZhbHVlKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgcmVzb2x2ZWRQcm9taXNlLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIGN0cmwgPSAoX3RoaXMuZm9ybS5nZXQoZGlyLnBhdGgpKTtcbiAgICAgICAgICAgICAgICBjdHJsLnNldFZhbHVlKHZhbHVlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSB2YWx1ZVxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgTmdGb3JtLnByb3RvdHlwZS5zZXRWYWx1ZSA9IGZ1bmN0aW9uICh2YWx1ZSkgeyB0aGlzLmNvbnRyb2wuc2V0VmFsdWUodmFsdWUpOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSAkZXZlbnRcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIE5nRm9ybS5wcm90b3R5cGUub25TdWJtaXQgPSBmdW5jdGlvbiAoJGV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLl9zdWJtaXR0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5uZ1N1Ym1pdC5lbWl0KCRldmVudCk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgTmdGb3JtLnByb3RvdHlwZS5vblJlc2V0ID0gZnVuY3Rpb24gKCkgeyB0aGlzLnJlc2V0Rm9ybSgpOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/PX0gdmFsdWVcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIE5nRm9ybS5wcm90b3R5cGUucmVzZXRGb3JtID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICBpZiAodmFsdWUgPT09IHZvaWQgMCkgeyB2YWx1ZSA9IHVuZGVmaW5lZDsgfVxuICAgICAgICAgICAgdGhpcy5mb3JtLnJlc2V0KHZhbHVlKTtcbiAgICAgICAgICAgIHRoaXMuX3N1Ym1pdHRlZCA9IGZhbHNlO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBwYXRoXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBOZ0Zvcm0ucHJvdG90eXBlLl9maW5kQ29udGFpbmVyID0gZnVuY3Rpb24gKHBhdGgpIHtcbiAgICAgICAgICAgIHBhdGgucG9wKCk7XG4gICAgICAgICAgICByZXR1cm4gcGF0aC5sZW5ndGggPyAodGhpcy5mb3JtLmdldChwYXRoKSkgOiB0aGlzLmZvcm07XG4gICAgICAgIH07XG4gICAgICAgIE5nRm9ybS5kZWNvcmF0b3JzID0gW1xuICAgICAgICAgICAgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkRpcmVjdGl2ZSwgYXJnczogW3tcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdG9yOiAnZm9ybTpub3QoW25nTm9Gb3JtXSk6bm90KFtmb3JtR3JvdXBdKSxuZ0Zvcm0sW25nRm9ybV0nLFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJvdmlkZXJzOiBbZm9ybURpcmVjdGl2ZVByb3ZpZGVyXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGhvc3Q6IHsgJyhzdWJtaXQpJzogJ29uU3VibWl0KCRldmVudCknLCAnKHJlc2V0KSc6ICdvblJlc2V0KCknIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXRzOiBbJ25nU3VibWl0J10sXG4gICAgICAgICAgICAgICAgICAgICAgICBleHBvcnRBczogJ25nRm9ybSdcbiAgICAgICAgICAgICAgICAgICAgfSxdIH0sXG4gICAgICAgIF07XG4gICAgICAgIC8qKiBAbm9jb2xsYXBzZSAqL1xuICAgICAgICBOZ0Zvcm0uY3RvclBhcmFtZXRlcnMgPSBmdW5jdGlvbiAoKSB7IHJldHVybiBbXG4gICAgICAgICAgICB7IHR5cGU6IEFycmF5LCBkZWNvcmF0b3JzOiBbeyB0eXBlOiBfYW5ndWxhcl9jb3JlLk9wdGlvbmFsIH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5TZWxmIH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5JbmplY3QsIGFyZ3M6IFtOR19WQUxJREFUT1JTLF0gfSxdIH0sXG4gICAgICAgICAgICB7IHR5cGU6IEFycmF5LCBkZWNvcmF0b3JzOiBbeyB0eXBlOiBfYW5ndWxhcl9jb3JlLk9wdGlvbmFsIH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5TZWxmIH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5JbmplY3QsIGFyZ3M6IFtOR19BU1lOQ19WQUxJREFUT1JTLF0gfSxdIH0sXG4gICAgICAgIF07IH07XG4gICAgICAgIHJldHVybiBOZ0Zvcm07XG4gICAgfShDb250cm9sQ29udGFpbmVyKSk7XG5cbiAgICAvKipcbiAgICAgKiBAbGljZW5zZVxuICAgICAqIENvcHlyaWdodCBHb29nbGUgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICAgICAqXG4gICAgICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAgICAgKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gICAgICovXG4gICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gRXhhbXBsZXMgPSB7XG4gICAgICAgIGZvcm1Db250cm9sTmFtZTogXCJcXG4gICAgPGRpdiBbZm9ybUdyb3VwXT1cXFwibXlHcm91cFxcXCI+XFxuICAgICAgPGlucHV0IGZvcm1Db250cm9sTmFtZT1cXFwiZmlyc3ROYW1lXFxcIj5cXG4gICAgPC9kaXY+XFxuXFxuICAgIEluIHlvdXIgY2xhc3M6XFxuXFxuICAgIHRoaXMubXlHcm91cCA9IG5ldyBGb3JtR3JvdXAoe1xcbiAgICAgICBmaXJzdE5hbWU6IG5ldyBGb3JtQ29udHJvbCgpXFxuICAgIH0pO1wiLFxuICAgICAgICBmb3JtR3JvdXBOYW1lOiBcIlxcbiAgICA8ZGl2IFtmb3JtR3JvdXBdPVxcXCJteUdyb3VwXFxcIj5cXG4gICAgICAgPGRpdiBmb3JtR3JvdXBOYW1lPVxcXCJwZXJzb25cXFwiPlxcbiAgICAgICAgICA8aW5wdXQgZm9ybUNvbnRyb2xOYW1lPVxcXCJmaXJzdE5hbWVcXFwiPlxcbiAgICAgICA8L2Rpdj5cXG4gICAgPC9kaXY+XFxuXFxuICAgIEluIHlvdXIgY2xhc3M6XFxuXFxuICAgIHRoaXMubXlHcm91cCA9IG5ldyBGb3JtR3JvdXAoe1xcbiAgICAgICBwZXJzb246IG5ldyBGb3JtR3JvdXAoeyBmaXJzdE5hbWU6IG5ldyBGb3JtQ29udHJvbCgpIH0pXFxuICAgIH0pO1wiLFxuICAgICAgICBmb3JtQXJyYXlOYW1lOiBcIlxcbiAgICA8ZGl2IFtmb3JtR3JvdXBdPVxcXCJteUdyb3VwXFxcIj5cXG4gICAgICA8ZGl2IGZvcm1BcnJheU5hbWU9XFxcImNpdGllc1xcXCI+XFxuICAgICAgICA8ZGl2ICpuZ0Zvcj1cXFwibGV0IGNpdHkgb2YgY2l0eUFycmF5LmNvbnRyb2xzOyBsZXQgaT1pbmRleFxcXCI+XFxuICAgICAgICAgIDxpbnB1dCBbZm9ybUNvbnRyb2xOYW1lXT1cXFwiaVxcXCI+XFxuICAgICAgICA8L2Rpdj5cXG4gICAgICA8L2Rpdj5cXG4gICAgPC9kaXY+XFxuXFxuICAgIEluIHlvdXIgY2xhc3M6XFxuXFxuICAgIHRoaXMuY2l0eUFycmF5ID0gbmV3IEZvcm1BcnJheShbbmV3IEZvcm1Db250cm9sKCdTRicpXSk7XFxuICAgIHRoaXMubXlHcm91cCA9IG5ldyBGb3JtR3JvdXAoe1xcbiAgICAgIGNpdGllczogdGhpcy5jaXR5QXJyYXlcXG4gICAgfSk7XCIsXG4gICAgICAgIG5nTW9kZWxHcm91cDogXCJcXG4gICAgPGZvcm0+XFxuICAgICAgIDxkaXYgbmdNb2RlbEdyb3VwPVxcXCJwZXJzb25cXFwiPlxcbiAgICAgICAgICA8aW5wdXQgWyhuZ01vZGVsKV09XFxcInBlcnNvbi5uYW1lXFxcIiBuYW1lPVxcXCJmaXJzdE5hbWVcXFwiPlxcbiAgICAgICA8L2Rpdj5cXG4gICAgPC9mb3JtPlwiLFxuICAgICAgICBuZ01vZGVsV2l0aEZvcm1Hcm91cDogXCJcXG4gICAgPGRpdiBbZm9ybUdyb3VwXT1cXFwibXlHcm91cFxcXCI+XFxuICAgICAgIDxpbnB1dCBmb3JtQ29udHJvbE5hbWU9XFxcImZpcnN0TmFtZVxcXCI+XFxuICAgICAgIDxpbnB1dCBbKG5nTW9kZWwpXT1cXFwic2hvd01vcmVDb250cm9sc1xcXCIgW25nTW9kZWxPcHRpb25zXT1cXFwie3N0YW5kYWxvbmU6IHRydWV9XFxcIj5cXG4gICAgPC9kaXY+XFxuICBcIlxuICAgIH07XG5cbiAgICB2YXIgVGVtcGxhdGVEcml2ZW5FcnJvcnMgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICBmdW5jdGlvbiBUZW1wbGF0ZURyaXZlbkVycm9ycygpIHtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIFRlbXBsYXRlRHJpdmVuRXJyb3JzLm1vZGVsUGFyZW50RXhjZXB0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiXFxuICAgICAgbmdNb2RlbCBjYW5ub3QgYmUgdXNlZCB0byByZWdpc3RlciBmb3JtIGNvbnRyb2xzIHdpdGggYSBwYXJlbnQgZm9ybUdyb3VwIGRpcmVjdGl2ZS4gIFRyeSB1c2luZ1xcbiAgICAgIGZvcm1Hcm91cCdzIHBhcnRuZXIgZGlyZWN0aXZlIFxcXCJmb3JtQ29udHJvbE5hbWVcXFwiIGluc3RlYWQuICBFeGFtcGxlOlxcblxcbiAgICAgIFwiICsgRXhhbXBsZXMuZm9ybUNvbnRyb2xOYW1lICsgXCJcXG5cXG4gICAgICBPciwgaWYgeW91J2QgbGlrZSB0byBhdm9pZCByZWdpc3RlcmluZyB0aGlzIGZvcm0gY29udHJvbCwgaW5kaWNhdGUgdGhhdCBpdCdzIHN0YW5kYWxvbmUgaW4gbmdNb2RlbE9wdGlvbnM6XFxuXFxuICAgICAgRXhhbXBsZTpcXG5cXG4gICAgICBcIiArIEV4YW1wbGVzLm5nTW9kZWxXaXRoRm9ybUdyb3VwKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBUZW1wbGF0ZURyaXZlbkVycm9ycy5mb3JtR3JvdXBOYW1lRXhjZXB0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiXFxuICAgICAgbmdNb2RlbCBjYW5ub3QgYmUgdXNlZCB0byByZWdpc3RlciBmb3JtIGNvbnRyb2xzIHdpdGggYSBwYXJlbnQgZm9ybUdyb3VwTmFtZSBvciBmb3JtQXJyYXlOYW1lIGRpcmVjdGl2ZS5cXG5cXG4gICAgICBPcHRpb24gMTogVXNlIGZvcm1Db250cm9sTmFtZSBpbnN0ZWFkIG9mIG5nTW9kZWwgKHJlYWN0aXZlIHN0cmF0ZWd5KTpcXG5cXG4gICAgICBcIiArIEV4YW1wbGVzLmZvcm1Hcm91cE5hbWUgKyBcIlxcblxcbiAgICAgIE9wdGlvbiAyOiAgVXBkYXRlIG5nTW9kZWwncyBwYXJlbnQgYmUgbmdNb2RlbEdyb3VwICh0ZW1wbGF0ZS1kcml2ZW4gc3RyYXRlZ3kpOlxcblxcbiAgICAgIFwiICsgRXhhbXBsZXMubmdNb2RlbEdyb3VwKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBUZW1wbGF0ZURyaXZlbkVycm9ycy5taXNzaW5nTmFtZUV4Y2VwdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIklmIG5nTW9kZWwgaXMgdXNlZCB3aXRoaW4gYSBmb3JtIHRhZywgZWl0aGVyIHRoZSBuYW1lIGF0dHJpYnV0ZSBtdXN0IGJlIHNldCBvciB0aGUgZm9ybVxcbiAgICAgIGNvbnRyb2wgbXVzdCBiZSBkZWZpbmVkIGFzICdzdGFuZGFsb25lJyBpbiBuZ01vZGVsT3B0aW9ucy5cXG5cXG4gICAgICBFeGFtcGxlIDE6IDxpbnB1dCBbKG5nTW9kZWwpXT1cXFwicGVyc29uLmZpcnN0TmFtZVxcXCIgbmFtZT1cXFwiZmlyc3RcXFwiPlxcbiAgICAgIEV4YW1wbGUgMjogPGlucHV0IFsobmdNb2RlbCldPVxcXCJwZXJzb24uZmlyc3ROYW1lXFxcIiBbbmdNb2RlbE9wdGlvbnNdPVxcXCJ7c3RhbmRhbG9uZTogdHJ1ZX1cXFwiPlwiKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBUZW1wbGF0ZURyaXZlbkVycm9ycy5tb2RlbEdyb3VwUGFyZW50RXhjZXB0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiXFxuICAgICAgbmdNb2RlbEdyb3VwIGNhbm5vdCBiZSB1c2VkIHdpdGggYSBwYXJlbnQgZm9ybUdyb3VwIGRpcmVjdGl2ZS5cXG5cXG4gICAgICBPcHRpb24gMTogVXNlIGZvcm1Hcm91cE5hbWUgaW5zdGVhZCBvZiBuZ01vZGVsR3JvdXAgKHJlYWN0aXZlIHN0cmF0ZWd5KTpcXG5cXG4gICAgICBcIiArIEV4YW1wbGVzLmZvcm1Hcm91cE5hbWUgKyBcIlxcblxcbiAgICAgIE9wdGlvbiAyOiAgVXNlIGEgcmVndWxhciBmb3JtIHRhZyBpbnN0ZWFkIG9mIHRoZSBmb3JtR3JvdXAgZGlyZWN0aXZlICh0ZW1wbGF0ZS1kcml2ZW4gc3RyYXRlZ3kpOlxcblxcbiAgICAgIFwiICsgRXhhbXBsZXMubmdNb2RlbEdyb3VwKTtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIFRlbXBsYXRlRHJpdmVuRXJyb3JzO1xuICAgIH0oKSk7XG5cbiAgICAvKipcbiAgICAgKiBAbGljZW5zZVxuICAgICAqIENvcHlyaWdodCBHb29nbGUgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICAgICAqXG4gICAgICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAgICAgKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gICAgICovXG4gICAgdmFyIF9fZXh0ZW5kcyQ4ID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG4gICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gbW9kZWxHcm91cFByb3ZpZGVyID0ge1xuICAgICAgICBwcm92aWRlOiBDb250cm9sQ29udGFpbmVyLFxuICAgICAgICB1c2VFeGlzdGluZzogX2FuZ3VsYXJfY29yZS5mb3J3YXJkUmVmKGZ1bmN0aW9uICgpIHsgcmV0dXJuIE5nTW9kZWxHcm91cDsgfSlcbiAgICB9O1xuICAgIC8qKlxuICAgICAqICAqXG4gICAgICAqICpcbiAgICAgICogVGhpcyBkaXJlY3RpdmUgY2FuIG9ubHkgYmUgdXNlZCBhcyBhIGNoaWxkIG9mIHtAbGluayBOZ0Zvcm19IChvciBpbiBvdGhlciB3b3JkcyxcbiAgICAgICogd2l0aGluIGA8Zm9ybT5gIHRhZ3MpLlxuICAgICAgKiAqXG4gICAgICAqIFVzZSB0aGlzIGRpcmVjdGl2ZSBpZiB5b3UnZCBsaWtlIHRvIGNyZWF0ZSBhIHN1Yi1ncm91cCB3aXRoaW4gYSBmb3JtLiBUaGlzIGNhblxuICAgICAgKiBjb21lIGluIGhhbmR5IGlmIHlvdSB3YW50IHRvIHZhbGlkYXRlIGEgc3ViLWdyb3VwIG9mIHlvdXIgZm9ybSBzZXBhcmF0ZWx5IGZyb21cbiAgICAgICogdGhlIHJlc3Qgb2YgeW91ciBmb3JtLCBvciBpZiBzb21lIHZhbHVlcyBpbiB5b3VyIGRvbWFpbiBtb2RlbCBtYWtlIG1vcmUgc2Vuc2UgdG9cbiAgICAgICogY29uc3VtZSB0b2dldGhlciBpbiBhIG5lc3RlZCBvYmplY3QuXG4gICAgICAqICpcbiAgICAgICogUGFzcyBpbiB0aGUgbmFtZSB5b3UnZCBsaWtlIHRoaXMgc3ViLWdyb3VwIHRvIGhhdmUgYW5kIGl0IHdpbGwgYmVjb21lIHRoZSBrZXlcbiAgICAgICogZm9yIHRoZSBzdWItZ3JvdXAgaW4gdGhlIGZvcm0ncyBmdWxsIHZhbHVlLiBZb3UgY2FuIGFsc28gZXhwb3J0IHRoZSBkaXJlY3RpdmUgaW50b1xuICAgICAgKiBhIGxvY2FsIHRlbXBsYXRlIHZhcmlhYmxlIHVzaW5nIGBuZ01vZGVsR3JvdXBgIChleDogYCNteUdyb3VwPVwibmdNb2RlbEdyb3VwXCJgKS5cbiAgICAgICogKlxuICAgICAgKiB7QGV4YW1wbGUgZm9ybXMvdHMvbmdNb2RlbEdyb3VwL25nX21vZGVsX2dyb3VwX2V4YW1wbGUudHMgcmVnaW9uPSdDb21wb25lbnQnfVxuICAgICAgKiAqXG4gICAgICAqICogKipucG0gcGFja2FnZSoqOiBgQGFuZ3VsYXIvZm9ybXNgXG4gICAgICAqICpcbiAgICAgICogKiAqKk5nTW9kdWxlKio6IGBGb3Jtc01vZHVsZWBcbiAgICAgICogKlxuICAgICAqL1xuICAgIHZhciBOZ01vZGVsR3JvdXAgPSAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgICAgICBfX2V4dGVuZHMkOChOZ01vZGVsR3JvdXAsIF9zdXBlcik7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IHBhcmVudFxuICAgICAgICAgKiBAcGFyYW0gez99IHZhbGlkYXRvcnNcbiAgICAgICAgICogQHBhcmFtIHs/fSBhc3luY1ZhbGlkYXRvcnNcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIE5nTW9kZWxHcm91cChwYXJlbnQsIHZhbGlkYXRvcnMsIGFzeW5jVmFsaWRhdG9ycykge1xuICAgICAgICAgICAgX3N1cGVyLmNhbGwodGhpcyk7XG4gICAgICAgICAgICB0aGlzLl9wYXJlbnQgPSBwYXJlbnQ7XG4gICAgICAgICAgICB0aGlzLl92YWxpZGF0b3JzID0gdmFsaWRhdG9ycztcbiAgICAgICAgICAgIHRoaXMuX2FzeW5jVmFsaWRhdG9ycyA9IGFzeW5jVmFsaWRhdG9ycztcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIE5nTW9kZWxHcm91cC5wcm90b3R5cGUuX2NoZWNrUGFyZW50VHlwZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICghKHRoaXMuX3BhcmVudCBpbnN0YW5jZW9mIE5nTW9kZWxHcm91cCkgJiYgISh0aGlzLl9wYXJlbnQgaW5zdGFuY2VvZiBOZ0Zvcm0pKSB7XG4gICAgICAgICAgICAgICAgVGVtcGxhdGVEcml2ZW5FcnJvcnMubW9kZWxHcm91cFBhcmVudEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBOZ01vZGVsR3JvdXAuZGVjb3JhdG9ycyA9IFtcbiAgICAgICAgICAgIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5EaXJlY3RpdmUsIGFyZ3M6IFt7IHNlbGVjdG9yOiAnW25nTW9kZWxHcm91cF0nLCBwcm92aWRlcnM6IFttb2RlbEdyb3VwUHJvdmlkZXJdLCBleHBvcnRBczogJ25nTW9kZWxHcm91cCcgfSxdIH0sXG4gICAgICAgIF07XG4gICAgICAgIC8qKiBAbm9jb2xsYXBzZSAqL1xuICAgICAgICBOZ01vZGVsR3JvdXAuY3RvclBhcmFtZXRlcnMgPSBmdW5jdGlvbiAoKSB7IHJldHVybiBbXG4gICAgICAgICAgICB7IHR5cGU6IENvbnRyb2xDb250YWluZXIsIGRlY29yYXRvcnM6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuSG9zdCB9LCB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuU2tpcFNlbGYgfSxdIH0sXG4gICAgICAgICAgICB7IHR5cGU6IEFycmF5LCBkZWNvcmF0b3JzOiBbeyB0eXBlOiBfYW5ndWxhcl9jb3JlLk9wdGlvbmFsIH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5TZWxmIH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5JbmplY3QsIGFyZ3M6IFtOR19WQUxJREFUT1JTLF0gfSxdIH0sXG4gICAgICAgICAgICB7IHR5cGU6IEFycmF5LCBkZWNvcmF0b3JzOiBbeyB0eXBlOiBfYW5ndWxhcl9jb3JlLk9wdGlvbmFsIH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5TZWxmIH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5JbmplY3QsIGFyZ3M6IFtOR19BU1lOQ19WQUxJREFUT1JTLF0gfSxdIH0sXG4gICAgICAgIF07IH07XG4gICAgICAgIE5nTW9kZWxHcm91cC5wcm9wRGVjb3JhdG9ycyA9IHtcbiAgICAgICAgICAgICduYW1lJzogW3sgdHlwZTogX2FuZ3VsYXJfY29yZS5JbnB1dCwgYXJnczogWyduZ01vZGVsR3JvdXAnLF0gfSxdLFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gTmdNb2RlbEdyb3VwO1xuICAgIH0oQWJzdHJhY3RGb3JtR3JvdXBEaXJlY3RpdmUpKTtcblxuICAgIC8qKlxuICAgICAqIEBsaWNlbnNlXG4gICAgICogQ29weXJpZ2h0IEdvb2dsZSBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gICAgICpcbiAgICAgKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICAgICAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAgICAgKi9cbiAgICB2YXIgX19leHRlbmRzJDcgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbiAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBmb3JtQ29udHJvbEJpbmRpbmcgPSB7XG4gICAgICAgIHByb3ZpZGU6IE5nQ29udHJvbCxcbiAgICAgICAgdXNlRXhpc3Rpbmc6IF9hbmd1bGFyX2NvcmUuZm9yd2FyZFJlZihmdW5jdGlvbiAoKSB7IHJldHVybiBOZ01vZGVsOyB9KVxuICAgIH07XG4gICAgLyoqXG4gICAgICogYG5nTW9kZWxgIGZvcmNlcyBhbiBhZGRpdGlvbmFsIGNoYW5nZSBkZXRlY3Rpb24gcnVuIHdoZW4gaXRzIGlucHV0cyBjaGFuZ2U6XG4gICAgICogRS5nLjpcbiAgICAgKiBgYGBcbiAgICAgKiA8ZGl2Pnt7bXlNb2RlbC52YWxpZH19PC9kaXY+XG4gICAgICogPGlucHV0IFsobmdNb2RlbCldPVwibXlWYWx1ZVwiICNteU1vZGVsPVwibmdNb2RlbFwiPlxuICAgICAqIGBgYFxuICAgICAqIEkuZS4gYG5nTW9kZWxgIGNhbiBleHBvcnQgaXRzZWxmIG9uIHRoZSBlbGVtZW50IGFuZCB0aGVuIGJlIHVzZWQgaW4gdGhlIHRlbXBsYXRlLlxuICAgICAqIE5vcm1hbGx5LCB0aGlzIHdvdWxkIHJlc3VsdCBpbiBleHByZXNzaW9ucyBiZWZvcmUgdGhlIGBpbnB1dGAgdGhhdCB1c2UgdGhlIGV4cG9ydGVkIGRpcmVjdGl2ZVxuICAgICAqIHRvIGhhdmUgYW5kIG9sZCB2YWx1ZSBhcyB0aGV5IGhhdmUgYmVlblxuICAgICAqIGRpcnR5IGNoZWNrZWQgYmVmb3JlLiBBcyB0aGlzIGlzIGEgdmVyeSBjb21tb24gY2FzZSBmb3IgYG5nTW9kZWxgLCB3ZSBhZGRlZCB0aGlzIHNlY29uZCBjaGFuZ2VcbiAgICAgKiBkZXRlY3Rpb24gcnVuLlxuICAgICAqXG4gICAgICogTm90ZXM6XG4gICAgICogLSB0aGlzIGlzIGp1c3Qgb25lIGV4dHJhIHJ1biBubyBtYXR0ZXIgaG93IG1hbnkgYG5nTW9kZWxgIGhhdmUgYmVlbiBjaGFuZ2VkLlxuICAgICAqIC0gdGhpcyBpcyBhIGdlbmVyYWwgcHJvYmxlbSB3aGVuIHVzaW5nIGBleHBvcnRBc2AgZm9yIGRpcmVjdGl2ZXMhXG4gICAgICovXG4gICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gcmVzb2x2ZWRQcm9taXNlJDEgPSBQcm9taXNlLnJlc29sdmUobnVsbCk7XG4gICAgLyoqXG4gICAgICogIHRvIGEgZm9ybSBjb250cm9sIGVsZW1lbnQuXG4gICAgICAqICpcbiAgICAgICogVGhlIHtAbGluayBGb3JtQ29udHJvbH0gaW5zdGFuY2Ugd2lsbCB0cmFjayB0aGUgdmFsdWUsIHVzZXIgaW50ZXJhY3Rpb24sIGFuZFxuICAgICAgKiB2YWxpZGF0aW9uIHN0YXR1cyBvZiB0aGUgY29udHJvbCBhbmQga2VlcCB0aGUgdmlldyBzeW5jZWQgd2l0aCB0aGUgbW9kZWwuIElmIHVzZWRcbiAgICAgICogd2l0aGluIGEgcGFyZW50IGZvcm0sIHRoZSBkaXJlY3RpdmUgd2lsbCBhbHNvIHJlZ2lzdGVyIGl0c2VsZiB3aXRoIHRoZSBmb3JtIGFzIGEgY2hpbGRcbiAgICAgICogY29udHJvbC5cbiAgICAgICogKlxuICAgICAgKiAqXG4gICAgICAqIFRoaXMgZGlyZWN0aXZlIGNhbiBiZSB1c2VkIGJ5IGl0c2VsZiBvciBhcyBwYXJ0IG9mIGEgbGFyZ2VyIGZvcm0uIEFsbCB5b3UgbmVlZCBpcyB0aGVcbiAgICAgICogYG5nTW9kZWxgIHNlbGVjdG9yIHRvIGFjdGl2YXRlIGl0LlxuICAgICAgKiAqXG4gICAgICAqIEl0IGFjY2VwdHMgYSBkb21haW4gbW9kZWwgYXMgYW4gb3B0aW9uYWwge0BsaW5rIEBJbnB1dH0uIElmIHlvdSBoYXZlIGEgb25lLXdheSBiaW5kaW5nXG4gICAgICAqIHRvIGBuZ01vZGVsYCB3aXRoIGBbXWAgc3ludGF4LCBjaGFuZ2luZyB0aGUgdmFsdWUgb2YgdGhlIGRvbWFpbiBtb2RlbCBpbiB0aGUgY29tcG9uZW50XG4gICAgICAqIGNsYXNzIHdpbGwgc2V0IHRoZSB2YWx1ZSBpbiB0aGUgdmlldy4gSWYgeW91IGhhdmUgYSB0d28td2F5IGJpbmRpbmcgd2l0aCBgWygpXWAgc3ludGF4XG4gICAgICAqIChhbHNvIGtub3duIGFzICdiYW5hbmEtYm94IHN5bnRheCcpLCB0aGUgdmFsdWUgaW4gdGhlIFVJIHdpbGwgYWx3YXlzIGJlIHN5bmNlZCBiYWNrIHRvXG4gICAgICAqIHRoZSBkb21haW4gbW9kZWwgaW4geW91ciBjbGFzcyBhcyB3ZWxsLlxuICAgICAgKiAqXG4gICAgICAqIElmIHlvdSB3aXNoIHRvIGluc3BlY3QgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGFzc29jaWF0ZWQge0BsaW5rIEZvcm1Db250cm9sfSAobGlrZVxuICAgICAgKiB2YWxpZGl0eSBzdGF0ZSksIHlvdSBjYW4gYWxzbyBleHBvcnQgdGhlIGRpcmVjdGl2ZSBpbnRvIGEgbG9jYWwgdGVtcGxhdGUgdmFyaWFibGUgdXNpbmdcbiAgICAgICogYG5nTW9kZWxgIGFzIHRoZSBrZXkgKGV4OiBgI215VmFyPVwibmdNb2RlbFwiYCkuIFlvdSBjYW4gdGhlbiBhY2Nlc3MgdGhlIGNvbnRyb2wgdXNpbmcgdGhlXG4gICAgICAqIGRpcmVjdGl2ZSdzIGBjb250cm9sYCBwcm9wZXJ0eSwgYnV0IG1vc3QgcHJvcGVydGllcyB5b3UnbGwgbmVlZCAobGlrZSBgdmFsaWRgIGFuZCBgZGlydHlgKVxuICAgICAgKiB3aWxsIGZhbGwgdGhyb3VnaCB0byB0aGUgY29udHJvbCBhbnl3YXksIHNvIHlvdSBjYW4gYWNjZXNzIHRoZW0gZGlyZWN0bHkuIFlvdSBjYW4gc2VlIGFcbiAgICAgICogZnVsbCBsaXN0IG9mIHByb3BlcnRpZXMgZGlyZWN0bHkgYXZhaWxhYmxlIGluIHtAbGluayBBYnN0cmFjdENvbnRyb2xEaXJlY3RpdmV9LlxuICAgICAgKiAqXG4gICAgICAqIFRoZSBmb2xsb3dpbmcgaXMgYW4gZXhhbXBsZSBvZiBhIHNpbXBsZSBzdGFuZGFsb25lIGNvbnRyb2wgdXNpbmcgYG5nTW9kZWxgOlxuICAgICAgKiAqXG4gICAgICAqIHtAZXhhbXBsZSBmb3Jtcy90cy9zaW1wbGVOZ01vZGVsL3NpbXBsZV9uZ19tb2RlbF9leGFtcGxlLnRzIHJlZ2lvbj0nQ29tcG9uZW50J31cbiAgICAgICogKlxuICAgICAgKiBXaGVuIHVzaW5nIHRoZSBgbmdNb2RlbGAgd2l0aGluIGA8Zm9ybT5gIHRhZ3MsIHlvdSdsbCBhbHNvIG5lZWQgdG8gc3VwcGx5IGEgYG5hbWVgIGF0dHJpYnV0ZVxuICAgICAgKiBzbyB0aGF0IHRoZSBjb250cm9sIGNhbiBiZSByZWdpc3RlcmVkIHdpdGggdGhlIHBhcmVudCBmb3JtIHVuZGVyIHRoYXQgbmFtZS5cbiAgICAgICogKlxuICAgICAgKiBJdCdzIHdvcnRoIG5vdGluZyB0aGF0IGluIHRoZSBjb250ZXh0IG9mIGEgcGFyZW50IGZvcm0sIHlvdSBvZnRlbiBjYW4gc2tpcCBvbmUtd2F5IG9yXG4gICAgICAqIHR3by13YXkgYmluZGluZyBiZWNhdXNlIHRoZSBwYXJlbnQgZm9ybSB3aWxsIHN5bmMgdGhlIHZhbHVlIGZvciB5b3UuIFlvdSBjYW4gYWNjZXNzXG4gICAgICAqIGl0cyBwcm9wZXJ0aWVzIGJ5IGV4cG9ydGluZyBpdCBpbnRvIGEgbG9jYWwgdGVtcGxhdGUgdmFyaWFibGUgdXNpbmcgYG5nRm9ybWAgKGV4OlxuICAgICAgKiBgI2Y9XCJuZ0Zvcm1cImApLiBUaGVuIHlvdSBjYW4gcGFzcyBpdCB3aGVyZSBpdCBuZWVkcyB0byBnbyBvbiBzdWJtaXQuXG4gICAgICAqICpcbiAgICAgICogSWYgeW91IGRvIG5lZWQgdG8gcG9wdWxhdGUgaW5pdGlhbCB2YWx1ZXMgaW50byB5b3VyIGZvcm0sIHVzaW5nIGEgb25lLXdheSBiaW5kaW5nIGZvclxuICAgICAgKiBgbmdNb2RlbGAgdGVuZHMgdG8gYmUgc3VmZmljaWVudCBhcyBsb25nIGFzIHlvdSB1c2UgdGhlIGV4cG9ydGVkIGZvcm0ncyB2YWx1ZSByYXRoZXJcbiAgICAgICogdGhhbiB0aGUgZG9tYWluIG1vZGVsJ3MgdmFsdWUgb24gc3VibWl0LlxuICAgICAgKiAqXG4gICAgICAqIFRha2UgYSBsb29rIGF0IGFuIGV4YW1wbGUgb2YgdXNpbmcgYG5nTW9kZWxgIHdpdGhpbiBhIGZvcm06XG4gICAgICAqICpcbiAgICAgICoge0BleGFtcGxlIGZvcm1zL3RzL3NpbXBsZUZvcm0vc2ltcGxlX2Zvcm1fZXhhbXBsZS50cyByZWdpb249J0NvbXBvbmVudCd9XG4gICAgICAqICpcbiAgICAgICogVG8gc2VlIGBuZ01vZGVsYCBleGFtcGxlcyB3aXRoIGRpZmZlcmVudCBmb3JtIGNvbnRyb2wgdHlwZXMsIHNlZTpcbiAgICAgICogKlxuICAgICAgKiAqIFJhZGlvIGJ1dHRvbnM6IHtAbGluayBSYWRpb0NvbnRyb2xWYWx1ZUFjY2Vzc29yfVxuICAgICAgKiAqIFNlbGVjdHM6IHtAbGluayBTZWxlY3RDb250cm9sVmFsdWVBY2Nlc3Nvcn1cbiAgICAgICogKlxuICAgICAgKiAqKm5wbSBwYWNrYWdlKio6IGBAYW5ndWxhci9mb3Jtc2BcbiAgICAgICogKlxuICAgICAgKiAqKk5nTW9kdWxlKio6IGBGb3Jtc01vZHVsZWBcbiAgICAgICogKlxuICAgICAgKiBAc3RhYmxlXG4gICAgICovXG4gICAgdmFyIE5nTW9kZWwgPSAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgICAgICBfX2V4dGVuZHMkNyhOZ01vZGVsLCBfc3VwZXIpO1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBwYXJlbnRcbiAgICAgICAgICogQHBhcmFtIHs/fSB2YWxpZGF0b3JzXG4gICAgICAgICAqIEBwYXJhbSB7P30gYXN5bmNWYWxpZGF0b3JzXG4gICAgICAgICAqIEBwYXJhbSB7P30gdmFsdWVBY2Nlc3NvcnNcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIE5nTW9kZWwocGFyZW50LCB2YWxpZGF0b3JzLCBhc3luY1ZhbGlkYXRvcnMsIHZhbHVlQWNjZXNzb3JzKSB7XG4gICAgICAgICAgICBfc3VwZXIuY2FsbCh0aGlzKTtcbiAgICAgICAgICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICAgICAgICAgIHRoaXMuX2NvbnRyb2wgPSBuZXcgRm9ybUNvbnRyb2woKTtcbiAgICAgICAgICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICAgICAgICAgIHRoaXMuX3JlZ2lzdGVyZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICAgICAgICAgICAgdGhpcy5fcGFyZW50ID0gcGFyZW50O1xuICAgICAgICAgICAgdGhpcy5fcmF3VmFsaWRhdG9ycyA9IHZhbGlkYXRvcnMgfHwgW107XG4gICAgICAgICAgICB0aGlzLl9yYXdBc3luY1ZhbGlkYXRvcnMgPSBhc3luY1ZhbGlkYXRvcnMgfHwgW107XG4gICAgICAgICAgICB0aGlzLnZhbHVlQWNjZXNzb3IgPSBzZWxlY3RWYWx1ZUFjY2Vzc29yKHRoaXMsIHZhbHVlQWNjZXNzb3JzKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBjaGFuZ2VzXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBOZ01vZGVsLnByb3RvdHlwZS5uZ09uQ2hhbmdlcyA9IGZ1bmN0aW9uIChjaGFuZ2VzKSB7XG4gICAgICAgICAgICB0aGlzLl9jaGVja0ZvckVycm9ycygpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLl9yZWdpc3RlcmVkKVxuICAgICAgICAgICAgICAgIHRoaXMuX3NldFVwQ29udHJvbCgpO1xuICAgICAgICAgICAgaWYgKCdpc0Rpc2FibGVkJyBpbiBjaGFuZ2VzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlRGlzYWJsZWQoY2hhbmdlcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXNQcm9wZXJ0eVVwZGF0ZWQoY2hhbmdlcywgdGhpcy52aWV3TW9kZWwpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlVmFsdWUodGhpcy5tb2RlbCk7XG4gICAgICAgICAgICAgICAgdGhpcy52aWV3TW9kZWwgPSB0aGlzLm1vZGVsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIE5nTW9kZWwucHJvdG90eXBlLm5nT25EZXN0cm95ID0gZnVuY3Rpb24gKCkgeyB0aGlzLmZvcm1EaXJlY3RpdmUgJiYgdGhpcy5mb3JtRGlyZWN0aXZlLnJlbW92ZUNvbnRyb2wodGhpcyk7IH07XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShOZ01vZGVsLnByb3RvdHlwZSwgXCJjb250cm9sXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9jb250cm9sOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE5nTW9kZWwucHJvdG90eXBlLCBcInBhdGhcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fcGFyZW50ID8gY29udHJvbFBhdGgodGhpcy5uYW1lLCB0aGlzLl9wYXJlbnQpIDogW3RoaXMubmFtZV07XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE5nTW9kZWwucHJvdG90eXBlLCBcImZvcm1EaXJlY3RpdmVcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX3BhcmVudCA/IHRoaXMuX3BhcmVudC5mb3JtRGlyZWN0aXZlIDogbnVsbDsgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShOZ01vZGVsLnByb3RvdHlwZSwgXCJ2YWxpZGF0b3JcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvbXBvc2VWYWxpZGF0b3JzKHRoaXMuX3Jhd1ZhbGlkYXRvcnMpOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE5nTW9kZWwucHJvdG90eXBlLCBcImFzeW5jVmFsaWRhdG9yXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvbXBvc2VBc3luY1ZhbGlkYXRvcnModGhpcy5fcmF3QXN5bmNWYWxpZGF0b3JzKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBuZXdWYWx1ZVxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgTmdNb2RlbC5wcm90b3R5cGUudmlld1RvTW9kZWxVcGRhdGUgPSBmdW5jdGlvbiAobmV3VmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMudmlld01vZGVsID0gbmV3VmFsdWU7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZS5lbWl0KG5ld1ZhbHVlKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBOZ01vZGVsLnByb3RvdHlwZS5fc2V0VXBDb250cm9sID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy5faXNTdGFuZGFsb25lKCkgPyB0aGlzLl9zZXRVcFN0YW5kYWxvbmUoKSA6XG4gICAgICAgICAgICAgICAgdGhpcy5mb3JtRGlyZWN0aXZlLmFkZENvbnRyb2wodGhpcyk7XG4gICAgICAgICAgICB0aGlzLl9yZWdpc3RlcmVkID0gdHJ1ZTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBOZ01vZGVsLnByb3RvdHlwZS5faXNTdGFuZGFsb25lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICF0aGlzLl9wYXJlbnQgfHwgKHRoaXMub3B0aW9ucyAmJiB0aGlzLm9wdGlvbnMuc3RhbmRhbG9uZSk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgTmdNb2RlbC5wcm90b3R5cGUuX3NldFVwU3RhbmRhbG9uZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHNldFVwQ29udHJvbCh0aGlzLl9jb250cm9sLCB0aGlzKTtcbiAgICAgICAgICAgIHRoaXMuX2NvbnRyb2wudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSh7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgTmdNb2RlbC5wcm90b3R5cGUuX2NoZWNrRm9yRXJyb3JzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLl9pc1N0YW5kYWxvbmUoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2NoZWNrUGFyZW50VHlwZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fY2hlY2tOYW1lKCk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgTmdNb2RlbC5wcm90b3R5cGUuX2NoZWNrUGFyZW50VHlwZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICghKHRoaXMuX3BhcmVudCBpbnN0YW5jZW9mIE5nTW9kZWxHcm91cCkgJiZcbiAgICAgICAgICAgICAgICB0aGlzLl9wYXJlbnQgaW5zdGFuY2VvZiBBYnN0cmFjdEZvcm1Hcm91cERpcmVjdGl2ZSkge1xuICAgICAgICAgICAgICAgIFRlbXBsYXRlRHJpdmVuRXJyb3JzLmZvcm1Hcm91cE5hbWVFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKCEodGhpcy5fcGFyZW50IGluc3RhbmNlb2YgTmdNb2RlbEdyb3VwKSAmJiAhKHRoaXMuX3BhcmVudCBpbnN0YW5jZW9mIE5nRm9ybSkpIHtcbiAgICAgICAgICAgICAgICBUZW1wbGF0ZURyaXZlbkVycm9ycy5tb2RlbFBhcmVudEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIE5nTW9kZWwucHJvdG90eXBlLl9jaGVja05hbWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5vcHRpb25zICYmIHRoaXMub3B0aW9ucy5uYW1lKVxuICAgICAgICAgICAgICAgIHRoaXMubmFtZSA9IHRoaXMub3B0aW9ucy5uYW1lO1xuICAgICAgICAgICAgaWYgKCF0aGlzLl9pc1N0YW5kYWxvbmUoKSAmJiAhdGhpcy5uYW1lKSB7XG4gICAgICAgICAgICAgICAgVGVtcGxhdGVEcml2ZW5FcnJvcnMubWlzc2luZ05hbWVFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gdmFsdWVcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIE5nTW9kZWwucHJvdG90eXBlLl91cGRhdGVWYWx1ZSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHJlc29sdmVkUHJvbWlzZSQxLnRoZW4oZnVuY3Rpb24gKCkgeyBfdGhpcy5jb250cm9sLnNldFZhbHVlKHZhbHVlLCB7IGVtaXRWaWV3VG9Nb2RlbENoYW5nZTogZmFsc2UgfSk7IH0pO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBjaGFuZ2VzXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBOZ01vZGVsLnByb3RvdHlwZS5fdXBkYXRlRGlzYWJsZWQgPSBmdW5jdGlvbiAoY2hhbmdlcykge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIGRpc2FibGVkVmFsdWUgPSBjaGFuZ2VzWydpc0Rpc2FibGVkJ10uY3VycmVudFZhbHVlO1xuICAgICAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gaXNEaXNhYmxlZCA9IGRpc2FibGVkVmFsdWUgPT09ICcnIHx8IChkaXNhYmxlZFZhbHVlICYmIGRpc2FibGVkVmFsdWUgIT09ICdmYWxzZScpO1xuICAgICAgICAgICAgcmVzb2x2ZWRQcm9taXNlJDEudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzRGlzYWJsZWQgJiYgIV90aGlzLmNvbnRyb2wuZGlzYWJsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbC5kaXNhYmxlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKCFpc0Rpc2FibGVkICYmIF90aGlzLmNvbnRyb2wuZGlzYWJsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMuY29udHJvbC5lbmFibGUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgTmdNb2RlbC5kZWNvcmF0b3JzID0gW1xuICAgICAgICAgICAgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkRpcmVjdGl2ZSwgYXJnczogW3tcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdG9yOiAnW25nTW9kZWxdOm5vdChbZm9ybUNvbnRyb2xOYW1lXSk6bm90KFtmb3JtQ29udHJvbF0pJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3ZpZGVyczogW2Zvcm1Db250cm9sQmluZGluZ10sXG4gICAgICAgICAgICAgICAgICAgICAgICBleHBvcnRBczogJ25nTW9kZWwnXG4gICAgICAgICAgICAgICAgICAgIH0sXSB9LFxuICAgICAgICBdO1xuICAgICAgICAvKiogQG5vY29sbGFwc2UgKi9cbiAgICAgICAgTmdNb2RlbC5jdG9yUGFyYW1ldGVycyA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIFtcbiAgICAgICAgICAgIHsgdHlwZTogQ29udHJvbENvbnRhaW5lciwgZGVjb3JhdG9yczogW3sgdHlwZTogX2FuZ3VsYXJfY29yZS5PcHRpb25hbCB9LCB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuSG9zdCB9LF0gfSxcbiAgICAgICAgICAgIHsgdHlwZTogQXJyYXksIGRlY29yYXRvcnM6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuT3B0aW9uYWwgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLlNlbGYgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkluamVjdCwgYXJnczogW05HX1ZBTElEQVRPUlMsXSB9LF0gfSxcbiAgICAgICAgICAgIHsgdHlwZTogQXJyYXksIGRlY29yYXRvcnM6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuT3B0aW9uYWwgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLlNlbGYgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkluamVjdCwgYXJnczogW05HX0FTWU5DX1ZBTElEQVRPUlMsXSB9LF0gfSxcbiAgICAgICAgICAgIHsgdHlwZTogQXJyYXksIGRlY29yYXRvcnM6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuT3B0aW9uYWwgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLlNlbGYgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkluamVjdCwgYXJnczogW05HX1ZBTFVFX0FDQ0VTU09SLF0gfSxdIH0sXG4gICAgICAgIF07IH07XG4gICAgICAgIE5nTW9kZWwucHJvcERlY29yYXRvcnMgPSB7XG4gICAgICAgICAgICAnbmFtZSc6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuSW5wdXQgfSxdLFxuICAgICAgICAgICAgJ2lzRGlzYWJsZWQnOiBbeyB0eXBlOiBfYW5ndWxhcl9jb3JlLklucHV0LCBhcmdzOiBbJ2Rpc2FibGVkJyxdIH0sXSxcbiAgICAgICAgICAgICdtb2RlbCc6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuSW5wdXQsIGFyZ3M6IFsnbmdNb2RlbCcsXSB9LF0sXG4gICAgICAgICAgICAnb3B0aW9ucyc6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuSW5wdXQsIGFyZ3M6IFsnbmdNb2RlbE9wdGlvbnMnLF0gfSxdLFxuICAgICAgICAgICAgJ3VwZGF0ZSc6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuT3V0cHV0LCBhcmdzOiBbJ25nTW9kZWxDaGFuZ2UnLF0gfSxdLFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gTmdNb2RlbDtcbiAgICB9KE5nQ29udHJvbCkpO1xuXG4gICAgdmFyIFJlYWN0aXZlRXJyb3JzID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gUmVhY3RpdmVFcnJvcnMoKSB7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBSZWFjdGl2ZUVycm9ycy5jb250cm9sUGFyZW50RXhjZXB0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiZm9ybUNvbnRyb2xOYW1lIG11c3QgYmUgdXNlZCB3aXRoIGEgcGFyZW50IGZvcm1Hcm91cCBkaXJlY3RpdmUuICBZb3UnbGwgd2FudCB0byBhZGQgYSBmb3JtR3JvdXBcXG4gICAgICAgZGlyZWN0aXZlIGFuZCBwYXNzIGl0IGFuIGV4aXN0aW5nIEZvcm1Hcm91cCBpbnN0YW5jZSAoeW91IGNhbiBjcmVhdGUgb25lIGluIHlvdXIgY2xhc3MpLlxcblxcbiAgICAgIEV4YW1wbGU6XFxuXFxuICAgICAgXCIgKyBFeGFtcGxlcy5mb3JtQ29udHJvbE5hbWUpO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIFJlYWN0aXZlRXJyb3JzLm5nTW9kZWxHcm91cEV4Y2VwdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImZvcm1Db250cm9sTmFtZSBjYW5ub3QgYmUgdXNlZCB3aXRoIGFuIG5nTW9kZWxHcm91cCBwYXJlbnQuIEl0IGlzIG9ubHkgY29tcGF0aWJsZSB3aXRoIHBhcmVudHNcXG4gICAgICAgdGhhdCBhbHNvIGhhdmUgYSBcXFwiZm9ybVxcXCIgcHJlZml4OiBmb3JtR3JvdXBOYW1lLCBmb3JtQXJyYXlOYW1lLCBvciBmb3JtR3JvdXAuXFxuXFxuICAgICAgIE9wdGlvbiAxOiAgVXBkYXRlIHRoZSBwYXJlbnQgdG8gYmUgZm9ybUdyb3VwTmFtZSAocmVhY3RpdmUgZm9ybSBzdHJhdGVneSlcXG5cXG4gICAgICAgIFwiICsgRXhhbXBsZXMuZm9ybUdyb3VwTmFtZSArIFwiXFxuXFxuICAgICAgICBPcHRpb24gMjogVXNlIG5nTW9kZWwgaW5zdGVhZCBvZiBmb3JtQ29udHJvbE5hbWUgKHRlbXBsYXRlLWRyaXZlbiBzdHJhdGVneSlcXG5cXG4gICAgICAgIFwiICsgRXhhbXBsZXMubmdNb2RlbEdyb3VwKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBSZWFjdGl2ZUVycm9ycy5taXNzaW5nRm9ybUV4Y2VwdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImZvcm1Hcm91cCBleHBlY3RzIGEgRm9ybUdyb3VwIGluc3RhbmNlLiBQbGVhc2UgcGFzcyBvbmUgaW4uXFxuXFxuICAgICAgIEV4YW1wbGU6XFxuXFxuICAgICAgIFwiICsgRXhhbXBsZXMuZm9ybUNvbnRyb2xOYW1lKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBSZWFjdGl2ZUVycm9ycy5ncm91cFBhcmVudEV4Y2VwdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImZvcm1Hcm91cE5hbWUgbXVzdCBiZSB1c2VkIHdpdGggYSBwYXJlbnQgZm9ybUdyb3VwIGRpcmVjdGl2ZS4gIFlvdSdsbCB3YW50IHRvIGFkZCBhIGZvcm1Hcm91cFxcbiAgICAgIGRpcmVjdGl2ZSBhbmQgcGFzcyBpdCBhbiBleGlzdGluZyBGb3JtR3JvdXAgaW5zdGFuY2UgKHlvdSBjYW4gY3JlYXRlIG9uZSBpbiB5b3VyIGNsYXNzKS5cXG5cXG4gICAgICBFeGFtcGxlOlxcblxcbiAgICAgIFwiICsgRXhhbXBsZXMuZm9ybUdyb3VwTmFtZSk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgUmVhY3RpdmVFcnJvcnMuYXJyYXlQYXJlbnRFeGNlcHRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJmb3JtQXJyYXlOYW1lIG11c3QgYmUgdXNlZCB3aXRoIGEgcGFyZW50IGZvcm1Hcm91cCBkaXJlY3RpdmUuICBZb3UnbGwgd2FudCB0byBhZGQgYSBmb3JtR3JvdXBcXG4gICAgICAgZGlyZWN0aXZlIGFuZCBwYXNzIGl0IGFuIGV4aXN0aW5nIEZvcm1Hcm91cCBpbnN0YW5jZSAoeW91IGNhbiBjcmVhdGUgb25lIGluIHlvdXIgY2xhc3MpLlxcblxcbiAgICAgICAgRXhhbXBsZTpcXG5cXG4gICAgICAgIFwiICsgRXhhbXBsZXMuZm9ybUFycmF5TmFtZSk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgUmVhY3RpdmVFcnJvcnMuZGlzYWJsZWRBdHRyV2FybmluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcIlxcbiAgICAgIEl0IGxvb2tzIGxpa2UgeW91J3JlIHVzaW5nIHRoZSBkaXNhYmxlZCBhdHRyaWJ1dGUgd2l0aCBhIHJlYWN0aXZlIGZvcm0gZGlyZWN0aXZlLiBJZiB5b3Ugc2V0IGRpc2FibGVkIHRvIHRydWVcXG4gICAgICB3aGVuIHlvdSBzZXQgdXAgdGhpcyBjb250cm9sIGluIHlvdXIgY29tcG9uZW50IGNsYXNzLCB0aGUgZGlzYWJsZWQgYXR0cmlidXRlIHdpbGwgYWN0dWFsbHkgYmUgc2V0IGluIHRoZSBET00gZm9yXFxuICAgICAgeW91LiBXZSByZWNvbW1lbmQgdXNpbmcgdGhpcyBhcHByb2FjaCB0byBhdm9pZCAnY2hhbmdlZCBhZnRlciBjaGVja2VkJyBlcnJvcnMuXFxuICAgICAgIFxcbiAgICAgIEV4YW1wbGU6IFxcbiAgICAgIGZvcm0gPSBuZXcgRm9ybUdyb3VwKHtcXG4gICAgICAgIGZpcnN0OiBuZXcgRm9ybUNvbnRyb2woe3ZhbHVlOiAnTmFuY3knLCBkaXNhYmxlZDogdHJ1ZX0sIFZhbGlkYXRvcnMucmVxdWlyZWQpLFxcbiAgICAgICAgbGFzdDogbmV3IEZvcm1Db250cm9sKCdEcmV3JywgVmFsaWRhdG9ycy5yZXF1aXJlZClcXG4gICAgICB9KTtcXG4gICAgXCIpO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gUmVhY3RpdmVFcnJvcnM7XG4gICAgfSgpKTtcblxuICAgIC8qKlxuICAgICAqIEBsaWNlbnNlXG4gICAgICogQ29weXJpZ2h0IEdvb2dsZSBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gICAgICpcbiAgICAgKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICAgICAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAgICAgKi9cbiAgICB2YXIgX19leHRlbmRzJDkgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbiAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBmb3JtQ29udHJvbEJpbmRpbmckMSA9IHtcbiAgICAgICAgcHJvdmlkZTogTmdDb250cm9sLFxuICAgICAgICB1c2VFeGlzdGluZzogX2FuZ3VsYXJfY29yZS5mb3J3YXJkUmVmKGZ1bmN0aW9uICgpIHsgcmV0dXJuIEZvcm1Db250cm9sRGlyZWN0aXZlOyB9KVxuICAgIH07XG4gICAgLyoqXG4gICAgICogICpcbiAgICAgICogSW4gb3RoZXIgd29yZHMsIHRoaXMgZGlyZWN0aXZlIGVuc3VyZXMgdGhhdCBhbnkgdmFsdWVzIHdyaXR0ZW4gdG8gdGhlIHtAbGluayBGb3JtQ29udHJvbH1cbiAgICAgICogaW5zdGFuY2UgcHJvZ3JhbW1hdGljYWxseSB3aWxsIGJlIHdyaXR0ZW4gdG8gdGhlIERPTSBlbGVtZW50IChtb2RlbCAtPiB2aWV3KS4gQ29udmVyc2VseSxcbiAgICAgICogYW55IHZhbHVlcyB3cml0dGVuIHRvIHRoZSBET00gZWxlbWVudCB0aHJvdWdoIHVzZXIgaW5wdXQgd2lsbCBiZSByZWZsZWN0ZWQgaW4gdGhlXG4gICAgICAqIHtAbGluayBGb3JtQ29udHJvbH0gaW5zdGFuY2UgKHZpZXcgLT4gbW9kZWwpLlxuICAgICAgKiAqXG4gICAgICAqICpcbiAgICAgICogVXNlIHRoaXMgZGlyZWN0aXZlIGlmIHlvdSdkIGxpa2UgdG8gY3JlYXRlIGFuZCBtYW5hZ2UgYSB7QGxpbmsgRm9ybUNvbnRyb2x9IGluc3RhbmNlIGRpcmVjdGx5LlxuICAgICAgKiBTaW1wbHkgY3JlYXRlIGEge0BsaW5rIEZvcm1Db250cm9sfSwgc2F2ZSBpdCB0byB5b3VyIGNvbXBvbmVudCBjbGFzcywgYW5kIHBhc3MgaXQgaW50byB0aGVcbiAgICAgICoge0BsaW5rIEZvcm1Db250cm9sRGlyZWN0aXZlfS5cbiAgICAgICogKlxuICAgICAgKiBUaGlzIGRpcmVjdGl2ZSBpcyBkZXNpZ25lZCB0byBiZSB1c2VkIGFzIGEgc3RhbmRhbG9uZSBjb250cm9sLiAgVW5saWtlIHtAbGluayBGb3JtQ29udHJvbE5hbWV9LFxuICAgICAgKiBpdCBkb2VzIG5vdCByZXF1aXJlIHRoYXQgeW91ciB7QGxpbmsgRm9ybUNvbnRyb2x9IGluc3RhbmNlIGJlIHBhcnQgb2YgYW55IHBhcmVudFxuICAgICAgKiB7QGxpbmsgRm9ybUdyb3VwfSwgYW5kIGl0IHdvbid0IGJlIHJlZ2lzdGVyZWQgdG8gYW55IHtAbGluayBGb3JtR3JvdXBEaXJlY3RpdmV9IHRoYXRcbiAgICAgICogZXhpc3RzIGFib3ZlIGl0LlxuICAgICAgKiAqXG4gICAgICAqICoqR2V0IHRoZSB2YWx1ZSoqOiB0aGUgYHZhbHVlYCBwcm9wZXJ0eSBpcyBhbHdheXMgc3luY2VkIGFuZCBhdmFpbGFibGUgb24gdGhlXG4gICAgICAqIHtAbGluayBGb3JtQ29udHJvbH0gaW5zdGFuY2UuIFNlZSBhIGZ1bGwgbGlzdCBvZiBhdmFpbGFibGUgcHJvcGVydGllcyBpblxuICAgICAgKiB7QGxpbmsgQWJzdHJhY3RDb250cm9sfS5cbiAgICAgICogKlxuICAgICAgKiAqKlNldCB0aGUgdmFsdWUqKjogWW91IGNhbiBwYXNzIGluIGFuIGluaXRpYWwgdmFsdWUgd2hlbiBpbnN0YW50aWF0aW5nIHRoZSB7QGxpbmsgRm9ybUNvbnRyb2x9LFxuICAgICAgKiBvciB5b3UgY2FuIHNldCBpdCBwcm9ncmFtbWF0aWNhbGx5IGxhdGVyIHVzaW5nIHtAbGluayBBYnN0cmFjdENvbnRyb2wuc2V0VmFsdWV9IG9yXG4gICAgICAqIHtAbGluayBBYnN0cmFjdENvbnRyb2wucGF0Y2hWYWx1ZX0uXG4gICAgICAqICpcbiAgICAgICogKipMaXN0ZW4gdG8gdmFsdWUqKjogSWYgeW91IHdhbnQgdG8gbGlzdGVuIHRvIGNoYW5nZXMgaW4gdGhlIHZhbHVlIG9mIHRoZSBjb250cm9sLCB5b3UgY2FuXG4gICAgICAqIHN1YnNjcmliZSB0byB0aGUge0BsaW5rIEFic3RyYWN0Q29udHJvbC52YWx1ZUNoYW5nZXN9IGV2ZW50LiAgWW91IGNhbiBhbHNvIGxpc3RlbiB0b1xuICAgICAgKiB7QGxpbmsgQWJzdHJhY3RDb250cm9sLnN0YXR1c0NoYW5nZXN9IHRvIGJlIG5vdGlmaWVkIHdoZW4gdGhlIHZhbGlkYXRpb24gc3RhdHVzIGlzXG4gICAgICAqIHJlLWNhbGN1bGF0ZWQuXG4gICAgICAqICpcbiAgICAgICogIyMjIEV4YW1wbGVcbiAgICAgICogKlxuICAgICAgKiB7QGV4YW1wbGUgZm9ybXMvdHMvc2ltcGxlRm9ybUNvbnRyb2wvc2ltcGxlX2Zvcm1fY29udHJvbF9leGFtcGxlLnRzIHJlZ2lvbj0nQ29tcG9uZW50J31cbiAgICAgICogKlxuICAgICAgKiAqICoqbnBtIHBhY2thZ2UqKjogYEBhbmd1bGFyL2Zvcm1zYFxuICAgICAgKiAqXG4gICAgICAqICogKipOZ01vZHVsZSoqOiBgUmVhY3RpdmVGb3Jtc01vZHVsZWBcbiAgICAgICogKlxuICAgICAgKiBAc3RhYmxlXG4gICAgICovXG4gICAgdmFyIEZvcm1Db250cm9sRGlyZWN0aXZlID0gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICAgICAgX19leHRlbmRzJDkoRm9ybUNvbnRyb2xEaXJlY3RpdmUsIF9zdXBlcik7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IHZhbGlkYXRvcnNcbiAgICAgICAgICogQHBhcmFtIHs/fSBhc3luY1ZhbGlkYXRvcnNcbiAgICAgICAgICogQHBhcmFtIHs/fSB2YWx1ZUFjY2Vzc29yc1xuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gRm9ybUNvbnRyb2xEaXJlY3RpdmUodmFsaWRhdG9ycywgYXN5bmNWYWxpZGF0b3JzLCB2YWx1ZUFjY2Vzc29ycykge1xuICAgICAgICAgICAgX3N1cGVyLmNhbGwodGhpcyk7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICAgICAgICAgIHRoaXMuX3Jhd1ZhbGlkYXRvcnMgPSB2YWxpZGF0b3JzIHx8IFtdO1xuICAgICAgICAgICAgdGhpcy5fcmF3QXN5bmNWYWxpZGF0b3JzID0gYXN5bmNWYWxpZGF0b3JzIHx8IFtdO1xuICAgICAgICAgICAgdGhpcy52YWx1ZUFjY2Vzc29yID0gc2VsZWN0VmFsdWVBY2Nlc3Nvcih0aGlzLCB2YWx1ZUFjY2Vzc29ycyk7XG4gICAgICAgIH1cbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEZvcm1Db250cm9sRGlyZWN0aXZlLnByb3RvdHlwZSwgXCJpc0Rpc2FibGVkXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHBhcmFtIHs/fSBpc0Rpc2FibGVkXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBzZXQ6IGZ1bmN0aW9uIChpc0Rpc2FibGVkKSB7IFJlYWN0aXZlRXJyb3JzLmRpc2FibGVkQXR0cldhcm5pbmcoKTsgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGNoYW5nZXNcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Db250cm9sRGlyZWN0aXZlLnByb3RvdHlwZS5uZ09uQ2hhbmdlcyA9IGZ1bmN0aW9uIChjaGFuZ2VzKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5faXNDb250cm9sQ2hhbmdlZChjaGFuZ2VzKSkge1xuICAgICAgICAgICAgICAgIHNldFVwQ29udHJvbCh0aGlzLmZvcm0sIHRoaXMpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbnRyb2wuZGlzYWJsZWQgJiYgdGhpcy52YWx1ZUFjY2Vzc29yLnNldERpc2FibGVkU3RhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy52YWx1ZUFjY2Vzc29yLnNldERpc2FibGVkU3RhdGUodHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZm9ybS51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpc1Byb3BlcnR5VXBkYXRlZChjaGFuZ2VzLCB0aGlzLnZpZXdNb2RlbCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZvcm0uc2V0VmFsdWUodGhpcy5tb2RlbCk7XG4gICAgICAgICAgICAgICAgdGhpcy52aWV3TW9kZWwgPSB0aGlzLm1vZGVsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRm9ybUNvbnRyb2xEaXJlY3RpdmUucHJvdG90eXBlLCBcInBhdGhcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIFtdOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEZvcm1Db250cm9sRGlyZWN0aXZlLnByb3RvdHlwZSwgXCJ2YWxpZGF0b3JcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvbXBvc2VWYWxpZGF0b3JzKHRoaXMuX3Jhd1ZhbGlkYXRvcnMpOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEZvcm1Db250cm9sRGlyZWN0aXZlLnByb3RvdHlwZSwgXCJhc3luY1ZhbGlkYXRvclwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBjb21wb3NlQXN5bmNWYWxpZGF0b3JzKHRoaXMuX3Jhd0FzeW5jVmFsaWRhdG9ycyk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEZvcm1Db250cm9sRGlyZWN0aXZlLnByb3RvdHlwZSwgXCJjb250cm9sXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLmZvcm07IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBuZXdWYWx1ZVxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUNvbnRyb2xEaXJlY3RpdmUucHJvdG90eXBlLnZpZXdUb01vZGVsVXBkYXRlID0gZnVuY3Rpb24gKG5ld1ZhbHVlKSB7XG4gICAgICAgICAgICB0aGlzLnZpZXdNb2RlbCA9IG5ld1ZhbHVlO1xuICAgICAgICAgICAgdGhpcy51cGRhdGUuZW1pdChuZXdWYWx1ZSk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGNoYW5nZXNcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Db250cm9sRGlyZWN0aXZlLnByb3RvdHlwZS5faXNDb250cm9sQ2hhbmdlZCA9IGZ1bmN0aW9uIChjaGFuZ2VzKSB7XG4gICAgICAgICAgICByZXR1cm4gY2hhbmdlcy5oYXNPd25Qcm9wZXJ0eSgnZm9ybScpO1xuICAgICAgICB9O1xuICAgICAgICBGb3JtQ29udHJvbERpcmVjdGl2ZS5kZWNvcmF0b3JzID0gW1xuICAgICAgICAgICAgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkRpcmVjdGl2ZSwgYXJnczogW3sgc2VsZWN0b3I6ICdbZm9ybUNvbnRyb2xdJywgcHJvdmlkZXJzOiBbZm9ybUNvbnRyb2xCaW5kaW5nJDFdLCBleHBvcnRBczogJ25nRm9ybScgfSxdIH0sXG4gICAgICAgIF07XG4gICAgICAgIC8qKiBAbm9jb2xsYXBzZSAqL1xuICAgICAgICBGb3JtQ29udHJvbERpcmVjdGl2ZS5jdG9yUGFyYW1ldGVycyA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIFtcbiAgICAgICAgICAgIHsgdHlwZTogQXJyYXksIGRlY29yYXRvcnM6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuT3B0aW9uYWwgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLlNlbGYgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkluamVjdCwgYXJnczogW05HX1ZBTElEQVRPUlMsXSB9LF0gfSxcbiAgICAgICAgICAgIHsgdHlwZTogQXJyYXksIGRlY29yYXRvcnM6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuT3B0aW9uYWwgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLlNlbGYgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkluamVjdCwgYXJnczogW05HX0FTWU5DX1ZBTElEQVRPUlMsXSB9LF0gfSxcbiAgICAgICAgICAgIHsgdHlwZTogQXJyYXksIGRlY29yYXRvcnM6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuT3B0aW9uYWwgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLlNlbGYgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkluamVjdCwgYXJnczogW05HX1ZBTFVFX0FDQ0VTU09SLF0gfSxdIH0sXG4gICAgICAgIF07IH07XG4gICAgICAgIEZvcm1Db250cm9sRGlyZWN0aXZlLnByb3BEZWNvcmF0b3JzID0ge1xuICAgICAgICAgICAgJ2Zvcm0nOiBbeyB0eXBlOiBfYW5ndWxhcl9jb3JlLklucHV0LCBhcmdzOiBbJ2Zvcm1Db250cm9sJyxdIH0sXSxcbiAgICAgICAgICAgICdtb2RlbCc6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuSW5wdXQsIGFyZ3M6IFsnbmdNb2RlbCcsXSB9LF0sXG4gICAgICAgICAgICAndXBkYXRlJzogW3sgdHlwZTogX2FuZ3VsYXJfY29yZS5PdXRwdXQsIGFyZ3M6IFsnbmdNb2RlbENoYW5nZScsXSB9LF0sXG4gICAgICAgICAgICAnaXNEaXNhYmxlZCc6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuSW5wdXQsIGFyZ3M6IFsnZGlzYWJsZWQnLF0gfSxdLFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gRm9ybUNvbnRyb2xEaXJlY3RpdmU7XG4gICAgfShOZ0NvbnRyb2wpKTtcblxuICAgIC8qKlxuICAgICAqIEBsaWNlbnNlXG4gICAgICogQ29weXJpZ2h0IEdvb2dsZSBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gICAgICpcbiAgICAgKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICAgICAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAgICAgKi9cbiAgICB2YXIgX19leHRlbmRzJDExID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG4gICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gZm9ybURpcmVjdGl2ZVByb3ZpZGVyJDEgPSB7XG4gICAgICAgIHByb3ZpZGU6IENvbnRyb2xDb250YWluZXIsXG4gICAgICAgIHVzZUV4aXN0aW5nOiBfYW5ndWxhcl9jb3JlLmZvcndhcmRSZWYoZnVuY3Rpb24gKCkgeyByZXR1cm4gRm9ybUdyb3VwRGlyZWN0aXZlOyB9KVxuICAgIH07XG4gICAgLyoqXG4gICAgICogICpcbiAgICAgICogKlxuICAgICAgKiBUaGlzIGRpcmVjdGl2ZSBhY2NlcHRzIGFuIGV4aXN0aW5nIHtAbGluayBGb3JtR3JvdXB9IGluc3RhbmNlLiBJdCB3aWxsIHRoZW4gdXNlIHRoaXNcbiAgICAgICoge0BsaW5rIEZvcm1Hcm91cH0gaW5zdGFuY2UgdG8gbWF0Y2ggYW55IGNoaWxkIHtAbGluayBGb3JtQ29udHJvbH0sIHtAbGluayBGb3JtR3JvdXB9LFxuICAgICAgKiBhbmQge0BsaW5rIEZvcm1BcnJheX0gaW5zdGFuY2VzIHRvIGNoaWxkIHtAbGluayBGb3JtQ29udHJvbE5hbWV9LCB7QGxpbmsgRm9ybUdyb3VwTmFtZX0sXG4gICAgICAqIGFuZCB7QGxpbmsgRm9ybUFycmF5TmFtZX0gZGlyZWN0aXZlcy5cbiAgICAgICogKlxuICAgICAgKiAqKlNldCB2YWx1ZSoqOiBZb3UgY2FuIHNldCB0aGUgZm9ybSdzIGluaXRpYWwgdmFsdWUgd2hlbiBpbnN0YW50aWF0aW5nIHRoZVxuICAgICAgKiB7QGxpbmsgRm9ybUdyb3VwfSwgb3IgeW91IGNhbiBzZXQgaXQgcHJvZ3JhbW1hdGljYWxseSBsYXRlciB1c2luZyB0aGUge0BsaW5rIEZvcm1Hcm91cH0nc1xuICAgICAgKiB7QGxpbmsgQWJzdHJhY3RDb250cm9sLnNldFZhbHVlfSBvciB7QGxpbmsgQWJzdHJhY3RDb250cm9sLnBhdGNoVmFsdWV9IG1ldGhvZHMuXG4gICAgICAqICpcbiAgICAgICogKipMaXN0ZW4gdG8gdmFsdWUqKjogSWYgeW91IHdhbnQgdG8gbGlzdGVuIHRvIGNoYW5nZXMgaW4gdGhlIHZhbHVlIG9mIHRoZSBmb3JtLCB5b3UgY2FuIHN1YnNjcmliZVxuICAgICAgKiB0byB0aGUge0BsaW5rIEZvcm1Hcm91cH0ncyB7QGxpbmsgQWJzdHJhY3RDb250cm9sLnZhbHVlQ2hhbmdlc30gZXZlbnQuICBZb3UgY2FuIGFsc28gbGlzdGVuIHRvXG4gICAgICAqIGl0cyB7QGxpbmsgQWJzdHJhY3RDb250cm9sLnN0YXR1c0NoYW5nZXN9IGV2ZW50IHRvIGJlIG5vdGlmaWVkIHdoZW4gdGhlIHZhbGlkYXRpb24gc3RhdHVzIGlzXG4gICAgICAqIHJlLWNhbGN1bGF0ZWQuXG4gICAgICAqICpcbiAgICAgICogRnVydGhlcm1vcmUsIHlvdSBjYW4gbGlzdGVuIHRvIHRoZSBkaXJlY3RpdmUncyBgbmdTdWJtaXRgIGV2ZW50IHRvIGJlIG5vdGlmaWVkIHdoZW4gdGhlIHVzZXIgaGFzXG4gICAgICAqIHRyaWdnZXJlZCBhIGZvcm0gc3VibWlzc2lvbi4gVGhlIGBuZ1N1Ym1pdGAgZXZlbnQgd2lsbCBiZSBlbWl0dGVkIHdpdGggdGhlIG9yaWdpbmFsIGZvcm1cbiAgICAgICogc3VibWlzc2lvbiBldmVudC5cbiAgICAgICogKlxuICAgICAgKiAjIyMgRXhhbXBsZVxuICAgICAgKiAqXG4gICAgICAqIEluIHRoaXMgZXhhbXBsZSwgd2UgY3JlYXRlIGZvcm0gY29udHJvbHMgZm9yIGZpcnN0IG5hbWUgYW5kIGxhc3QgbmFtZS5cbiAgICAgICogKlxuICAgICAgKiB7QGV4YW1wbGUgZm9ybXMvdHMvc2ltcGxlRm9ybUdyb3VwL3NpbXBsZV9mb3JtX2dyb3VwX2V4YW1wbGUudHMgcmVnaW9uPSdDb21wb25lbnQnfVxuICAgICAgKiAqXG4gICAgICAqICoqbnBtIHBhY2thZ2UqKjogYEBhbmd1bGFyL2Zvcm1zYFxuICAgICAgKiAqXG4gICAgICAqICoqTmdNb2R1bGUqKjoge0BsaW5rIFJlYWN0aXZlRm9ybXNNb2R1bGV9XG4gICAgICAqICpcbiAgICAgICogQHN0YWJsZVxuICAgICAqL1xuICAgIHZhciBGb3JtR3JvdXBEaXJlY3RpdmUgPSAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgICAgICBfX2V4dGVuZHMkMTEoRm9ybUdyb3VwRGlyZWN0aXZlLCBfc3VwZXIpO1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBfdmFsaWRhdG9yc1xuICAgICAgICAgKiBAcGFyYW0gez99IF9hc3luY1ZhbGlkYXRvcnNcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIEZvcm1Hcm91cERpcmVjdGl2ZShfdmFsaWRhdG9ycywgX2FzeW5jVmFsaWRhdG9ycykge1xuICAgICAgICAgICAgX3N1cGVyLmNhbGwodGhpcyk7XG4gICAgICAgICAgICB0aGlzLl92YWxpZGF0b3JzID0gX3ZhbGlkYXRvcnM7XG4gICAgICAgICAgICB0aGlzLl9hc3luY1ZhbGlkYXRvcnMgPSBfYXN5bmNWYWxpZGF0b3JzO1xuICAgICAgICAgICAgdGhpcy5fc3VibWl0dGVkID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmRpcmVjdGl2ZXMgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuZm9ybSA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLm5nU3VibWl0ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGNoYW5nZXNcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Hcm91cERpcmVjdGl2ZS5wcm90b3R5cGUubmdPbkNoYW5nZXMgPSBmdW5jdGlvbiAoY2hhbmdlcykge1xuICAgICAgICAgICAgdGhpcy5fY2hlY2tGb3JtUHJlc2VudCgpO1xuICAgICAgICAgICAgaWYgKGNoYW5nZXMuaGFzT3duUHJvcGVydHkoJ2Zvcm0nKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZVZhbGlkYXRvcnMoKTtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGVEb21WYWx1ZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZVJlZ2lzdHJhdGlvbnMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEZvcm1Hcm91cERpcmVjdGl2ZS5wcm90b3R5cGUsIFwic3VibWl0dGVkXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9zdWJtaXR0ZWQ7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRm9ybUdyb3VwRGlyZWN0aXZlLnByb3RvdHlwZSwgXCJmb3JtRGlyZWN0aXZlXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEZvcm1Hcm91cERpcmVjdGl2ZS5wcm90b3R5cGUsIFwiY29udHJvbFwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5mb3JtOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEZvcm1Hcm91cERpcmVjdGl2ZS5wcm90b3R5cGUsIFwicGF0aFwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gW107IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBkaXJcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Hcm91cERpcmVjdGl2ZS5wcm90b3R5cGUuYWRkQ29udHJvbCA9IGZ1bmN0aW9uIChkaXIpIHtcbiAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIGN0cmwgPSB0aGlzLmZvcm0uZ2V0KGRpci5wYXRoKTtcbiAgICAgICAgICAgIHNldFVwQ29udHJvbChjdHJsLCBkaXIpO1xuICAgICAgICAgICAgY3RybC51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgICAgIHRoaXMuZGlyZWN0aXZlcy5wdXNoKGRpcik7XG4gICAgICAgICAgICByZXR1cm4gY3RybDtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gZGlyXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtR3JvdXBEaXJlY3RpdmUucHJvdG90eXBlLmdldENvbnRyb2wgPSBmdW5jdGlvbiAoZGlyKSB7IHJldHVybiAodGhpcy5mb3JtLmdldChkaXIucGF0aCkpOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBkaXJcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Hcm91cERpcmVjdGl2ZS5wcm90b3R5cGUucmVtb3ZlQ29udHJvbCA9IGZ1bmN0aW9uIChkaXIpIHsgTGlzdFdyYXBwZXIucmVtb3ZlKHRoaXMuZGlyZWN0aXZlcywgZGlyKTsgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gZGlyXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtR3JvdXBEaXJlY3RpdmUucHJvdG90eXBlLmFkZEZvcm1Hcm91cCA9IGZ1bmN0aW9uIChkaXIpIHtcbiAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIGN0cmwgPSB0aGlzLmZvcm0uZ2V0KGRpci5wYXRoKTtcbiAgICAgICAgICAgIHNldFVwRm9ybUNvbnRhaW5lcihjdHJsLCBkaXIpO1xuICAgICAgICAgICAgY3RybC51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gZGlyXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtR3JvdXBEaXJlY3RpdmUucHJvdG90eXBlLnJlbW92ZUZvcm1Hcm91cCA9IGZ1bmN0aW9uIChkaXIpIHsgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gZGlyXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtR3JvdXBEaXJlY3RpdmUucHJvdG90eXBlLmdldEZvcm1Hcm91cCA9IGZ1bmN0aW9uIChkaXIpIHsgcmV0dXJuICh0aGlzLmZvcm0uZ2V0KGRpci5wYXRoKSk7IH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGRpclxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUdyb3VwRGlyZWN0aXZlLnByb3RvdHlwZS5hZGRGb3JtQXJyYXkgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBjdHJsID0gdGhpcy5mb3JtLmdldChkaXIucGF0aCk7XG4gICAgICAgICAgICBzZXRVcEZvcm1Db250YWluZXIoY3RybCwgZGlyKTtcbiAgICAgICAgICAgIGN0cmwudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSh7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGRpclxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUdyb3VwRGlyZWN0aXZlLnByb3RvdHlwZS5yZW1vdmVGb3JtQXJyYXkgPSBmdW5jdGlvbiAoZGlyKSB7IH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGRpclxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUdyb3VwRGlyZWN0aXZlLnByb3RvdHlwZS5nZXRGb3JtQXJyYXkgPSBmdW5jdGlvbiAoZGlyKSB7IHJldHVybiAodGhpcy5mb3JtLmdldChkaXIucGF0aCkpOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBkaXJcbiAgICAgICAgICogQHBhcmFtIHs/fSB2YWx1ZVxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUdyb3VwRGlyZWN0aXZlLnByb3RvdHlwZS51cGRhdGVNb2RlbCA9IGZ1bmN0aW9uIChkaXIsIHZhbHVlKSB7XG4gICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBjdHJsID0gKHRoaXMuZm9ybS5nZXQoZGlyLnBhdGgpKTtcbiAgICAgICAgICAgIGN0cmwuc2V0VmFsdWUodmFsdWUpO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSAkZXZlbnRcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Hcm91cERpcmVjdGl2ZS5wcm90b3R5cGUub25TdWJtaXQgPSBmdW5jdGlvbiAoJGV2ZW50KSB7XG4gICAgICAgICAgICB0aGlzLl9zdWJtaXR0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5uZ1N1Ym1pdC5lbWl0KCRldmVudCk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUdyb3VwRGlyZWN0aXZlLnByb3RvdHlwZS5vblJlc2V0ID0gZnVuY3Rpb24gKCkgeyB0aGlzLnJlc2V0Rm9ybSgpOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/PX0gdmFsdWVcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Hcm91cERpcmVjdGl2ZS5wcm90b3R5cGUucmVzZXRGb3JtID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICBpZiAodmFsdWUgPT09IHZvaWQgMCkgeyB2YWx1ZSA9IHVuZGVmaW5lZDsgfVxuICAgICAgICAgICAgdGhpcy5mb3JtLnJlc2V0KHZhbHVlKTtcbiAgICAgICAgICAgIHRoaXMuX3N1Ym1pdHRlZCA9IGZhbHNlO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Hcm91cERpcmVjdGl2ZS5wcm90b3R5cGUuX3VwZGF0ZURvbVZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIHRoaXMuZGlyZWN0aXZlcy5mb3JFYWNoKGZ1bmN0aW9uIChkaXIpIHtcbiAgICAgICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBuZXdDdHJsID0gX3RoaXMuZm9ybS5nZXQoZGlyLnBhdGgpO1xuICAgICAgICAgICAgICAgIGlmIChkaXIuX2NvbnRyb2wgIT09IG5ld0N0cmwpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYW5VcENvbnRyb2woZGlyLl9jb250cm9sLCBkaXIpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobmV3Q3RybClcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFVwQ29udHJvbChuZXdDdHJsLCBkaXIpO1xuICAgICAgICAgICAgICAgICAgICBkaXIuX2NvbnRyb2wgPSBuZXdDdHJsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5mb3JtLl91cGRhdGVUcmVlVmFsaWRpdHkoeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Hcm91cERpcmVjdGl2ZS5wcm90b3R5cGUuX3VwZGF0ZVJlZ2lzdHJhdGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdGhpcy5mb3JtLl9yZWdpc3Rlck9uQ29sbGVjdGlvbkNoYW5nZShmdW5jdGlvbiAoKSB7IHJldHVybiBfdGhpcy5fdXBkYXRlRG9tVmFsdWUoKTsgfSk7XG4gICAgICAgICAgICBpZiAodGhpcy5fb2xkRm9ybSlcbiAgICAgICAgICAgICAgICB0aGlzLl9vbGRGb3JtLl9yZWdpc3Rlck9uQ29sbGVjdGlvbkNoYW5nZShmdW5jdGlvbiAoKSB7IH0pO1xuICAgICAgICAgICAgdGhpcy5fb2xkRm9ybSA9IHRoaXMuZm9ybTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtR3JvdXBEaXJlY3RpdmUucHJvdG90eXBlLl91cGRhdGVWYWxpZGF0b3JzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gc3luYyA9IGNvbXBvc2VWYWxpZGF0b3JzKHRoaXMuX3ZhbGlkYXRvcnMpO1xuICAgICAgICAgICAgdGhpcy5mb3JtLnZhbGlkYXRvciA9IFZhbGlkYXRvcnMuY29tcG9zZShbdGhpcy5mb3JtLnZhbGlkYXRvciwgc3luY10pO1xuICAgICAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gYXN5bmMgPSBjb21wb3NlQXN5bmNWYWxpZGF0b3JzKHRoaXMuX2FzeW5jVmFsaWRhdG9ycyk7XG4gICAgICAgICAgICB0aGlzLmZvcm0uYXN5bmNWYWxpZGF0b3IgPSBWYWxpZGF0b3JzLmNvbXBvc2VBc3luYyhbdGhpcy5mb3JtLmFzeW5jVmFsaWRhdG9yLCBhc3luY10pO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Hcm91cERpcmVjdGl2ZS5wcm90b3R5cGUuX2NoZWNrRm9ybVByZXNlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZm9ybSkge1xuICAgICAgICAgICAgICAgIFJlYWN0aXZlRXJyb3JzLm1pc3NpbmdGb3JtRXhjZXB0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIEZvcm1Hcm91cERpcmVjdGl2ZS5kZWNvcmF0b3JzID0gW1xuICAgICAgICAgICAgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkRpcmVjdGl2ZSwgYXJnczogW3tcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdG9yOiAnW2Zvcm1Hcm91cF0nLFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJvdmlkZXJzOiBbZm9ybURpcmVjdGl2ZVByb3ZpZGVyJDFdLFxuICAgICAgICAgICAgICAgICAgICAgICAgaG9zdDogeyAnKHN1Ym1pdCknOiAnb25TdWJtaXQoJGV2ZW50KScsICcocmVzZXQpJzogJ29uUmVzZXQoKScgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4cG9ydEFzOiAnbmdGb3JtJ1xuICAgICAgICAgICAgICAgICAgICB9LF0gfSxcbiAgICAgICAgXTtcbiAgICAgICAgLyoqIEBub2NvbGxhcHNlICovXG4gICAgICAgIEZvcm1Hcm91cERpcmVjdGl2ZS5jdG9yUGFyYW1ldGVycyA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIFtcbiAgICAgICAgICAgIHsgdHlwZTogQXJyYXksIGRlY29yYXRvcnM6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuT3B0aW9uYWwgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLlNlbGYgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkluamVjdCwgYXJnczogW05HX1ZBTElEQVRPUlMsXSB9LF0gfSxcbiAgICAgICAgICAgIHsgdHlwZTogQXJyYXksIGRlY29yYXRvcnM6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuT3B0aW9uYWwgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLlNlbGYgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkluamVjdCwgYXJnczogW05HX0FTWU5DX1ZBTElEQVRPUlMsXSB9LF0gfSxcbiAgICAgICAgXTsgfTtcbiAgICAgICAgRm9ybUdyb3VwRGlyZWN0aXZlLnByb3BEZWNvcmF0b3JzID0ge1xuICAgICAgICAgICAgJ2Zvcm0nOiBbeyB0eXBlOiBfYW5ndWxhcl9jb3JlLklucHV0LCBhcmdzOiBbJ2Zvcm1Hcm91cCcsXSB9LF0sXG4gICAgICAgICAgICAnbmdTdWJtaXQnOiBbeyB0eXBlOiBfYW5ndWxhcl9jb3JlLk91dHB1dCB9LF0sXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBGb3JtR3JvdXBEaXJlY3RpdmU7XG4gICAgfShDb250cm9sQ29udGFpbmVyKSk7XG5cbiAgICAvKipcbiAgICAgKiBAbGljZW5zZVxuICAgICAqIENvcHlyaWdodCBHb29nbGUgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICAgICAqXG4gICAgICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAgICAgKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gICAgICovXG4gICAgdmFyIF9fZXh0ZW5kcyQxMiA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTtcbiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgICB9O1xuICAgIHZhciAvKiogQHR5cGUgez99ICovIGZvcm1Hcm91cE5hbWVQcm92aWRlciA9IHtcbiAgICAgICAgcHJvdmlkZTogQ29udHJvbENvbnRhaW5lcixcbiAgICAgICAgdXNlRXhpc3Rpbmc6IF9hbmd1bGFyX2NvcmUuZm9yd2FyZFJlZihmdW5jdGlvbiAoKSB7IHJldHVybiBGb3JtR3JvdXBOYW1lOyB9KVxuICAgIH07XG4gICAgLyoqXG4gICAgICogICpcbiAgICAgICogKlxuICAgICAgKiBUaGlzIGRpcmVjdGl2ZSBjYW4gb25seSBiZSB1c2VkIHdpdGggYSBwYXJlbnQge0BsaW5rIEZvcm1Hcm91cERpcmVjdGl2ZX0gKHNlbGVjdG9yOlxuICAgICAgKiBgW2Zvcm1Hcm91cF1gKS5cbiAgICAgICogKlxuICAgICAgKiBJdCBhY2NlcHRzIHRoZSBzdHJpbmcgbmFtZSBvZiB0aGUgbmVzdGVkIHtAbGluayBGb3JtR3JvdXB9IHlvdSB3YW50IHRvIGxpbmssIGFuZFxuICAgICAgKiB3aWxsIGxvb2sgZm9yIGEge0BsaW5rIEZvcm1Hcm91cH0gcmVnaXN0ZXJlZCB3aXRoIHRoYXQgbmFtZSBpbiB0aGUgcGFyZW50XG4gICAgICAqIHtAbGluayBGb3JtR3JvdXB9IGluc3RhbmNlIHlvdSBwYXNzZWQgaW50byB7QGxpbmsgRm9ybUdyb3VwRGlyZWN0aXZlfS5cbiAgICAgICogKlxuICAgICAgKiBOZXN0ZWQgZm9ybSBncm91cHMgY2FuIGNvbWUgaW4gaGFuZHkgd2hlbiB5b3Ugd2FudCB0byB2YWxpZGF0ZSBhIHN1Yi1ncm91cCBvZiBhXG4gICAgICAqIGZvcm0gc2VwYXJhdGVseSBmcm9tIHRoZSByZXN0IG9yIHdoZW4geW91J2QgbGlrZSB0byBncm91cCB0aGUgdmFsdWVzIG9mIGNlcnRhaW5cbiAgICAgICogY29udHJvbHMgaW50byB0aGVpciBvd24gbmVzdGVkIG9iamVjdC5cbiAgICAgICogKlxuICAgICAgKiAqKkFjY2VzcyB0aGUgZ3JvdXAqKjogWW91IGNhbiBhY2Nlc3MgdGhlIGFzc29jaWF0ZWQge0BsaW5rIEZvcm1Hcm91cH0gdXNpbmcgdGhlXG4gICAgICAqIHtAbGluayBBYnN0cmFjdENvbnRyb2wuZ2V0fSBtZXRob2QuIEV4OiBgdGhpcy5mb3JtLmdldCgnbmFtZScpYC5cbiAgICAgICogKlxuICAgICAgKiBZb3UgY2FuIGFsc28gYWNjZXNzIGluZGl2aWR1YWwgY29udHJvbHMgd2l0aGluIHRoZSBncm91cCB1c2luZyBkb3Qgc3ludGF4LlxuICAgICAgKiBFeDogYHRoaXMuZm9ybS5nZXQoJ25hbWUuZmlyc3QnKWBcbiAgICAgICogKlxuICAgICAgKiAqKkdldCB0aGUgdmFsdWUqKjogdGhlIGB2YWx1ZWAgcHJvcGVydHkgaXMgYWx3YXlzIHN5bmNlZCBhbmQgYXZhaWxhYmxlIG9uIHRoZVxuICAgICAgKiB7QGxpbmsgRm9ybUdyb3VwfS4gU2VlIGEgZnVsbCBsaXN0IG9mIGF2YWlsYWJsZSBwcm9wZXJ0aWVzIGluIHtAbGluayBBYnN0cmFjdENvbnRyb2x9LlxuICAgICAgKiAqXG4gICAgICAqICoqU2V0IHRoZSB2YWx1ZSoqOiBZb3UgY2FuIHNldCBhbiBpbml0aWFsIHZhbHVlIGZvciBlYWNoIGNoaWxkIGNvbnRyb2wgd2hlbiBpbnN0YW50aWF0aW5nXG4gICAgICAqIHRoZSB7QGxpbmsgRm9ybUdyb3VwfSwgb3IgeW91IGNhbiBzZXQgaXQgcHJvZ3JhbW1hdGljYWxseSBsYXRlciB1c2luZ1xuICAgICAgKiB7QGxpbmsgQWJzdHJhY3RDb250cm9sLnNldFZhbHVlfSBvciB7QGxpbmsgQWJzdHJhY3RDb250cm9sLnBhdGNoVmFsdWV9LlxuICAgICAgKiAqXG4gICAgICAqICoqTGlzdGVuIHRvIHZhbHVlKio6IElmIHlvdSB3YW50IHRvIGxpc3RlbiB0byBjaGFuZ2VzIGluIHRoZSB2YWx1ZSBvZiB0aGUgZ3JvdXAsIHlvdSBjYW5cbiAgICAgICogc3Vic2NyaWJlIHRvIHRoZSB7QGxpbmsgQWJzdHJhY3RDb250cm9sLnZhbHVlQ2hhbmdlc30gZXZlbnQuICBZb3UgY2FuIGFsc28gbGlzdGVuIHRvXG4gICAgICAqIHtAbGluayBBYnN0cmFjdENvbnRyb2wuc3RhdHVzQ2hhbmdlc30gdG8gYmUgbm90aWZpZWQgd2hlbiB0aGUgdmFsaWRhdGlvbiBzdGF0dXMgaXNcbiAgICAgICogcmUtY2FsY3VsYXRlZC5cbiAgICAgICogKlxuICAgICAgKiAjIyMgRXhhbXBsZVxuICAgICAgKiAqXG4gICAgICAqIHtAZXhhbXBsZSBmb3Jtcy90cy9uZXN0ZWRGb3JtR3JvdXAvbmVzdGVkX2Zvcm1fZ3JvdXBfZXhhbXBsZS50cyByZWdpb249J0NvbXBvbmVudCd9XG4gICAgICAqICpcbiAgICAgICogKiAqKm5wbSBwYWNrYWdlKio6IGBAYW5ndWxhci9mb3Jtc2BcbiAgICAgICogKlxuICAgICAgKiAqICoqTmdNb2R1bGUqKjogYFJlYWN0aXZlRm9ybXNNb2R1bGVgXG4gICAgICAqICpcbiAgICAgKi9cbiAgICB2YXIgRm9ybUdyb3VwTmFtZSA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgICAgIF9fZXh0ZW5kcyQxMihGb3JtR3JvdXBOYW1lLCBfc3VwZXIpO1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBwYXJlbnRcbiAgICAgICAgICogQHBhcmFtIHs/fSB2YWxpZGF0b3JzXG4gICAgICAgICAqIEBwYXJhbSB7P30gYXN5bmNWYWxpZGF0b3JzXG4gICAgICAgICAqL1xuICAgICAgICBmdW5jdGlvbiBGb3JtR3JvdXBOYW1lKHBhcmVudCwgdmFsaWRhdG9ycywgYXN5bmNWYWxpZGF0b3JzKSB7XG4gICAgICAgICAgICBfc3VwZXIuY2FsbCh0aGlzKTtcbiAgICAgICAgICAgIHRoaXMuX3BhcmVudCA9IHBhcmVudDtcbiAgICAgICAgICAgIHRoaXMuX3ZhbGlkYXRvcnMgPSB2YWxpZGF0b3JzO1xuICAgICAgICAgICAgdGhpcy5fYXN5bmNWYWxpZGF0b3JzID0gYXN5bmNWYWxpZGF0b3JzO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUdyb3VwTmFtZS5wcm90b3R5cGUuX2NoZWNrUGFyZW50VHlwZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChfaGFzSW52YWxpZFBhcmVudCh0aGlzLl9wYXJlbnQpKSB7XG4gICAgICAgICAgICAgICAgUmVhY3RpdmVFcnJvcnMuZ3JvdXBQYXJlbnRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgRm9ybUdyb3VwTmFtZS5kZWNvcmF0b3JzID0gW1xuICAgICAgICAgICAgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkRpcmVjdGl2ZSwgYXJnczogW3sgc2VsZWN0b3I6ICdbZm9ybUdyb3VwTmFtZV0nLCBwcm92aWRlcnM6IFtmb3JtR3JvdXBOYW1lUHJvdmlkZXJdIH0sXSB9LFxuICAgICAgICBdO1xuICAgICAgICAvKiogQG5vY29sbGFwc2UgKi9cbiAgICAgICAgRm9ybUdyb3VwTmFtZS5jdG9yUGFyYW1ldGVycyA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIFtcbiAgICAgICAgICAgIHsgdHlwZTogQ29udHJvbENvbnRhaW5lciwgZGVjb3JhdG9yczogW3sgdHlwZTogX2FuZ3VsYXJfY29yZS5PcHRpb25hbCB9LCB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuSG9zdCB9LCB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuU2tpcFNlbGYgfSxdIH0sXG4gICAgICAgICAgICB7IHR5cGU6IEFycmF5LCBkZWNvcmF0b3JzOiBbeyB0eXBlOiBfYW5ndWxhcl9jb3JlLk9wdGlvbmFsIH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5TZWxmIH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5JbmplY3QsIGFyZ3M6IFtOR19WQUxJREFUT1JTLF0gfSxdIH0sXG4gICAgICAgICAgICB7IHR5cGU6IEFycmF5LCBkZWNvcmF0b3JzOiBbeyB0eXBlOiBfYW5ndWxhcl9jb3JlLk9wdGlvbmFsIH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5TZWxmIH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5JbmplY3QsIGFyZ3M6IFtOR19BU1lOQ19WQUxJREFUT1JTLF0gfSxdIH0sXG4gICAgICAgIF07IH07XG4gICAgICAgIEZvcm1Hcm91cE5hbWUucHJvcERlY29yYXRvcnMgPSB7XG4gICAgICAgICAgICAnbmFtZSc6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuSW5wdXQsIGFyZ3M6IFsnZm9ybUdyb3VwTmFtZScsXSB9LF0sXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBGb3JtR3JvdXBOYW1lO1xuICAgIH0oQWJzdHJhY3RGb3JtR3JvdXBEaXJlY3RpdmUpKTtcbiAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBmb3JtQXJyYXlOYW1lUHJvdmlkZXIgPSB7XG4gICAgICAgIHByb3ZpZGU6IENvbnRyb2xDb250YWluZXIsXG4gICAgICAgIHVzZUV4aXN0aW5nOiBfYW5ndWxhcl9jb3JlLmZvcndhcmRSZWYoZnVuY3Rpb24gKCkgeyByZXR1cm4gRm9ybUFycmF5TmFtZTsgfSlcbiAgICB9O1xuICAgIC8qKlxuICAgICAqICAqXG4gICAgICAqICpcbiAgICAgICogVGhpcyBkaXJlY3RpdmUgaXMgZGVzaWduZWQgdG8gYmUgdXNlZCB3aXRoIGEgcGFyZW50IHtAbGluayBGb3JtR3JvdXBEaXJlY3RpdmV9IChzZWxlY3RvcjpcbiAgICAgICogYFtmb3JtR3JvdXBdYCkuXG4gICAgICAqICpcbiAgICAgICogSXQgYWNjZXB0cyB0aGUgc3RyaW5nIG5hbWUgb2YgdGhlIG5lc3RlZCB7QGxpbmsgRm9ybUFycmF5fSB5b3Ugd2FudCB0byBsaW5rLCBhbmRcbiAgICAgICogd2lsbCBsb29rIGZvciBhIHtAbGluayBGb3JtQXJyYXl9IHJlZ2lzdGVyZWQgd2l0aCB0aGF0IG5hbWUgaW4gdGhlIHBhcmVudFxuICAgICAgKiB7QGxpbmsgRm9ybUdyb3VwfSBpbnN0YW5jZSB5b3UgcGFzc2VkIGludG8ge0BsaW5rIEZvcm1Hcm91cERpcmVjdGl2ZX0uXG4gICAgICAqICpcbiAgICAgICogTmVzdGVkIGZvcm0gYXJyYXlzIGNhbiBjb21lIGluIGhhbmR5IHdoZW4geW91IGhhdmUgYSBncm91cCBvZiBmb3JtIGNvbnRyb2xzIGJ1dFxuICAgICAgKiB5b3UncmUgbm90IHN1cmUgaG93IG1hbnkgdGhlcmUgd2lsbCBiZS4gRm9ybSBhcnJheXMgYWxsb3cgeW91IHRvIGNyZWF0ZSBuZXdcbiAgICAgICogZm9ybSBjb250cm9scyBkeW5hbWljYWxseS5cbiAgICAgICogKlxuICAgICAgKiAqKkFjY2VzcyB0aGUgYXJyYXkqKjogWW91IGNhbiBhY2Nlc3MgdGhlIGFzc29jaWF0ZWQge0BsaW5rIEZvcm1BcnJheX0gdXNpbmcgdGhlXG4gICAgICAqIHtAbGluayBBYnN0cmFjdENvbnRyb2wuZ2V0fSBtZXRob2Qgb24gdGhlIHBhcmVudCB7QGxpbmsgRm9ybUdyb3VwfS5cbiAgICAgICogRXg6IGB0aGlzLmZvcm0uZ2V0KCdjaXRpZXMnKWAuXG4gICAgICAqICpcbiAgICAgICogKipHZXQgdGhlIHZhbHVlKio6IHRoZSBgdmFsdWVgIHByb3BlcnR5IGlzIGFsd2F5cyBzeW5jZWQgYW5kIGF2YWlsYWJsZSBvbiB0aGVcbiAgICAgICoge0BsaW5rIEZvcm1BcnJheX0uIFNlZSBhIGZ1bGwgbGlzdCBvZiBhdmFpbGFibGUgcHJvcGVydGllcyBpbiB7QGxpbmsgQWJzdHJhY3RDb250cm9sfS5cbiAgICAgICogKlxuICAgICAgKiAqKlNldCB0aGUgdmFsdWUqKjogWW91IGNhbiBzZXQgYW4gaW5pdGlhbCB2YWx1ZSBmb3IgZWFjaCBjaGlsZCBjb250cm9sIHdoZW4gaW5zdGFudGlhdGluZ1xuICAgICAgKiB0aGUge0BsaW5rIEZvcm1BcnJheX0sIG9yIHlvdSBjYW4gc2V0IHRoZSB2YWx1ZSBwcm9ncmFtbWF0aWNhbGx5IGxhdGVyIHVzaW5nIHRoZVxuICAgICAgKiB7QGxpbmsgRm9ybUFycmF5fSdzIHtAbGluayBBYnN0cmFjdENvbnRyb2wuc2V0VmFsdWV9IG9yIHtAbGluayBBYnN0cmFjdENvbnRyb2wucGF0Y2hWYWx1ZX1cbiAgICAgICogbWV0aG9kcy5cbiAgICAgICogKlxuICAgICAgKiAqKkxpc3RlbiB0byB2YWx1ZSoqOiBJZiB5b3Ugd2FudCB0byBsaXN0ZW4gdG8gY2hhbmdlcyBpbiB0aGUgdmFsdWUgb2YgdGhlIGFycmF5LCB5b3UgY2FuXG4gICAgICAqIHN1YnNjcmliZSB0byB0aGUge0BsaW5rIEZvcm1BcnJheX0ncyB7QGxpbmsgQWJzdHJhY3RDb250cm9sLnZhbHVlQ2hhbmdlc30gZXZlbnQuICBZb3UgY2FuIGFsc29cbiAgICAgICogbGlzdGVuIHRvIGl0cyB7QGxpbmsgQWJzdHJhY3RDb250cm9sLnN0YXR1c0NoYW5nZXN9IGV2ZW50IHRvIGJlIG5vdGlmaWVkIHdoZW4gdGhlIHZhbGlkYXRpb25cbiAgICAgICogc3RhdHVzIGlzIHJlLWNhbGN1bGF0ZWQuXG4gICAgICAqICpcbiAgICAgICogKipBZGQgbmV3IGNvbnRyb2xzKio6IFlvdSBjYW4gYWRkIG5ldyBjb250cm9scyB0byB0aGUge0BsaW5rIEZvcm1BcnJheX0gZHluYW1pY2FsbHkgYnlcbiAgICAgICogY2FsbGluZyBpdHMge0BsaW5rIEZvcm1BcnJheS5wdXNofSBtZXRob2QuXG4gICAgICAqIEV4OiBgdGhpcy5mb3JtLmdldCgnY2l0aWVzJykucHVzaChuZXcgRm9ybUNvbnRyb2woKSk7YFxuICAgICAgKiAqXG4gICAgICAqICMjIyBFeGFtcGxlXG4gICAgICAqICpcbiAgICAgICoge0BleGFtcGxlIGZvcm1zL3RzL25lc3RlZEZvcm1BcnJheS9uZXN0ZWRfZm9ybV9hcnJheV9leGFtcGxlLnRzIHJlZ2lvbj0nQ29tcG9uZW50J31cbiAgICAgICogKlxuICAgICAgKiAqICoqbnBtIHBhY2thZ2UqKjogYEBhbmd1bGFyL2Zvcm1zYFxuICAgICAgKiAqXG4gICAgICAqICogKipOZ01vZHVsZSoqOiBgUmVhY3RpdmVGb3Jtc01vZHVsZWBcbiAgICAgICogKlxuICAgICAqL1xuICAgIHZhciBGb3JtQXJyYXlOYW1lID0gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICAgICAgX19leHRlbmRzJDEyKEZvcm1BcnJheU5hbWUsIF9zdXBlcik7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IHBhcmVudFxuICAgICAgICAgKiBAcGFyYW0gez99IHZhbGlkYXRvcnNcbiAgICAgICAgICogQHBhcmFtIHs/fSBhc3luY1ZhbGlkYXRvcnNcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIEZvcm1BcnJheU5hbWUocGFyZW50LCB2YWxpZGF0b3JzLCBhc3luY1ZhbGlkYXRvcnMpIHtcbiAgICAgICAgICAgIF9zdXBlci5jYWxsKHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5fcGFyZW50ID0gcGFyZW50O1xuICAgICAgICAgICAgdGhpcy5fdmFsaWRhdG9ycyA9IHZhbGlkYXRvcnM7XG4gICAgICAgICAgICB0aGlzLl9hc3luY1ZhbGlkYXRvcnMgPSBhc3luY1ZhbGlkYXRvcnM7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtQXJyYXlOYW1lLnByb3RvdHlwZS5uZ09uSW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMuX2NoZWNrUGFyZW50VHlwZSgpO1xuICAgICAgICAgICAgdGhpcy5mb3JtRGlyZWN0aXZlLmFkZEZvcm1BcnJheSh0aGlzKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtQXJyYXlOYW1lLnByb3RvdHlwZS5uZ09uRGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmZvcm1EaXJlY3RpdmUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZvcm1EaXJlY3RpdmUucmVtb3ZlRm9ybUFycmF5KHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRm9ybUFycmF5TmFtZS5wcm90b3R5cGUsIFwiY29udHJvbFwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5mb3JtRGlyZWN0aXZlLmdldEZvcm1BcnJheSh0aGlzKTsgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShGb3JtQXJyYXlOYW1lLnByb3RvdHlwZSwgXCJmb3JtRGlyZWN0aXZlXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3BhcmVudCA/ICh0aGlzLl9wYXJlbnQuZm9ybURpcmVjdGl2ZSkgOiBudWxsO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShGb3JtQXJyYXlOYW1lLnByb3RvdHlwZSwgXCJwYXRoXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBjb250cm9sUGF0aCh0aGlzLm5hbWUsIHRoaXMuX3BhcmVudCk7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRm9ybUFycmF5TmFtZS5wcm90b3R5cGUsIFwidmFsaWRhdG9yXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBjb21wb3NlVmFsaWRhdG9ycyh0aGlzLl92YWxpZGF0b3JzKTsgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShGb3JtQXJyYXlOYW1lLnByb3RvdHlwZSwgXCJhc3luY1ZhbGlkYXRvclwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gY29tcG9zZUFzeW5jVmFsaWRhdG9ycyh0aGlzLl9hc3luY1ZhbGlkYXRvcnMpOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtQXJyYXlOYW1lLnByb3RvdHlwZS5fY2hlY2tQYXJlbnRUeXBlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKF9oYXNJbnZhbGlkUGFyZW50KHRoaXMuX3BhcmVudCkpIHtcbiAgICAgICAgICAgICAgICBSZWFjdGl2ZUVycm9ycy5hcnJheVBhcmVudEV4Y2VwdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBGb3JtQXJyYXlOYW1lLmRlY29yYXRvcnMgPSBbXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuRGlyZWN0aXZlLCBhcmdzOiBbeyBzZWxlY3RvcjogJ1tmb3JtQXJyYXlOYW1lXScsIHByb3ZpZGVyczogW2Zvcm1BcnJheU5hbWVQcm92aWRlcl0gfSxdIH0sXG4gICAgICAgIF07XG4gICAgICAgIC8qKiBAbm9jb2xsYXBzZSAqL1xuICAgICAgICBGb3JtQXJyYXlOYW1lLmN0b3JQYXJhbWV0ZXJzID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gW1xuICAgICAgICAgICAgeyB0eXBlOiBDb250cm9sQ29udGFpbmVyLCBkZWNvcmF0b3JzOiBbeyB0eXBlOiBfYW5ndWxhcl9jb3JlLk9wdGlvbmFsIH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5Ib3N0IH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5Ta2lwU2VsZiB9LF0gfSxcbiAgICAgICAgICAgIHsgdHlwZTogQXJyYXksIGRlY29yYXRvcnM6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuT3B0aW9uYWwgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLlNlbGYgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkluamVjdCwgYXJnczogW05HX1ZBTElEQVRPUlMsXSB9LF0gfSxcbiAgICAgICAgICAgIHsgdHlwZTogQXJyYXksIGRlY29yYXRvcnM6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuT3B0aW9uYWwgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLlNlbGYgfSwgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkluamVjdCwgYXJnczogW05HX0FTWU5DX1ZBTElEQVRPUlMsXSB9LF0gfSxcbiAgICAgICAgXTsgfTtcbiAgICAgICAgRm9ybUFycmF5TmFtZS5wcm9wRGVjb3JhdG9ycyA9IHtcbiAgICAgICAgICAgICduYW1lJzogW3sgdHlwZTogX2FuZ3VsYXJfY29yZS5JbnB1dCwgYXJnczogWydmb3JtQXJyYXlOYW1lJyxdIH0sXSxcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIEZvcm1BcnJheU5hbWU7XG4gICAgfShDb250cm9sQ29udGFpbmVyKSk7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIHs/fSBwYXJlbnRcbiAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIF9oYXNJbnZhbGlkUGFyZW50KHBhcmVudCkge1xuICAgICAgICByZXR1cm4gIShwYXJlbnQgaW5zdGFuY2VvZiBGb3JtR3JvdXBOYW1lKSAmJiAhKHBhcmVudCBpbnN0YW5jZW9mIEZvcm1Hcm91cERpcmVjdGl2ZSkgJiZcbiAgICAgICAgICAgICEocGFyZW50IGluc3RhbmNlb2YgRm9ybUFycmF5TmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGxpY2Vuc2VcbiAgICAgKiBDb3B5cmlnaHQgR29vZ2xlIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAgICAgKlxuICAgICAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gICAgICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICAgICAqL1xuICAgIHZhciBfX2V4dGVuZHMkMTAgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgICAgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbiAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBjb250cm9sTmFtZUJpbmRpbmcgPSB7XG4gICAgICAgIHByb3ZpZGU6IE5nQ29udHJvbCxcbiAgICAgICAgdXNlRXhpc3Rpbmc6IF9hbmd1bGFyX2NvcmUuZm9yd2FyZFJlZihmdW5jdGlvbiAoKSB7IHJldHVybiBGb3JtQ29udHJvbE5hbWU7IH0pXG4gICAgfTtcbiAgICAvKipcbiAgICAgKiAgZWxlbWVudCBieSBuYW1lLlxuICAgICAgKiAqXG4gICAgICAqIEluIG90aGVyIHdvcmRzLCB0aGlzIGRpcmVjdGl2ZSBlbnN1cmVzIHRoYXQgYW55IHZhbHVlcyB3cml0dGVuIHRvIHRoZSB7QGxpbmsgRm9ybUNvbnRyb2x9XG4gICAgICAqIGluc3RhbmNlIHByb2dyYW1tYXRpY2FsbHkgd2lsbCBiZSB3cml0dGVuIHRvIHRoZSBET00gZWxlbWVudCAobW9kZWwgLT4gdmlldykuIENvbnZlcnNlbHksXG4gICAgICAqIGFueSB2YWx1ZXMgd3JpdHRlbiB0byB0aGUgRE9NIGVsZW1lbnQgdGhyb3VnaCB1c2VyIGlucHV0IHdpbGwgYmUgcmVmbGVjdGVkIGluIHRoZVxuICAgICAgKiB7QGxpbmsgRm9ybUNvbnRyb2x9IGluc3RhbmNlICh2aWV3IC0+IG1vZGVsKS5cbiAgICAgICogKlxuICAgICAgKiAqXG4gICAgICAqIFRoaXMgZGlyZWN0aXZlIGlzIGRlc2lnbmVkIHRvIGJlIHVzZWQgd2l0aCBhIHBhcmVudCB7QGxpbmsgRm9ybUdyb3VwRGlyZWN0aXZlfSAoc2VsZWN0b3I6XG4gICAgICAqIGBbZm9ybUdyb3VwXWApLlxuICAgICAgKiAqXG4gICAgICAqIEl0IGFjY2VwdHMgdGhlIHN0cmluZyBuYW1lIG9mIHRoZSB7QGxpbmsgRm9ybUNvbnRyb2x9IGluc3RhbmNlIHlvdSB3YW50IHRvXG4gICAgICAqIGxpbmssIGFuZCB3aWxsIGxvb2sgZm9yIGEge0BsaW5rIEZvcm1Db250cm9sfSByZWdpc3RlcmVkIHdpdGggdGhhdCBuYW1lIGluIHRoZVxuICAgICAgKiBjbG9zZXN0IHtAbGluayBGb3JtR3JvdXB9IG9yIHtAbGluayBGb3JtQXJyYXl9IGFib3ZlIGl0LlxuICAgICAgKiAqXG4gICAgICAqICoqQWNjZXNzIHRoZSBjb250cm9sKio6IFlvdSBjYW4gYWNjZXNzIHRoZSB7QGxpbmsgRm9ybUNvbnRyb2x9IGFzc29jaWF0ZWQgd2l0aFxuICAgICAgKiB0aGlzIGRpcmVjdGl2ZSBieSB1c2luZyB0aGUge0BsaW5rIEFic3RyYWN0Q29udHJvbC5nZXR9IG1ldGhvZC5cbiAgICAgICogRXg6IGB0aGlzLmZvcm0uZ2V0KCdmaXJzdCcpO2BcbiAgICAgICogKlxuICAgICAgKiAqKkdldCB2YWx1ZSoqOiB0aGUgYHZhbHVlYCBwcm9wZXJ0eSBpcyBhbHdheXMgc3luY2VkIGFuZCBhdmFpbGFibGUgb24gdGhlIHtAbGluayBGb3JtQ29udHJvbH0uXG4gICAgICAqIFNlZSBhIGZ1bGwgbGlzdCBvZiBhdmFpbGFibGUgcHJvcGVydGllcyBpbiB7QGxpbmsgQWJzdHJhY3RDb250cm9sfS5cbiAgICAgICogKlxuICAgICAgKiAqKlNldCB2YWx1ZSoqOiBZb3UgY2FuIHNldCBhbiBpbml0aWFsIHZhbHVlIGZvciB0aGUgY29udHJvbCB3aGVuIGluc3RhbnRpYXRpbmcgdGhlXG4gICAgICAqIHtAbGluayBGb3JtQ29udHJvbH0sIG9yIHlvdSBjYW4gc2V0IGl0IHByb2dyYW1tYXRpY2FsbHkgbGF0ZXIgdXNpbmdcbiAgICAgICoge0BsaW5rIEFic3RyYWN0Q29udHJvbC5zZXRWYWx1ZX0gb3Ige0BsaW5rIEFic3RyYWN0Q29udHJvbC5wYXRjaFZhbHVlfS5cbiAgICAgICogKlxuICAgICAgKiAqKkxpc3RlbiB0byB2YWx1ZSoqOiBJZiB5b3Ugd2FudCB0byBsaXN0ZW4gdG8gY2hhbmdlcyBpbiB0aGUgdmFsdWUgb2YgdGhlIGNvbnRyb2wsIHlvdSBjYW5cbiAgICAgICogc3Vic2NyaWJlIHRvIHRoZSB7QGxpbmsgQWJzdHJhY3RDb250cm9sLnZhbHVlQ2hhbmdlc30gZXZlbnQuICBZb3UgY2FuIGFsc28gbGlzdGVuIHRvXG4gICAgICAqIHtAbGluayBBYnN0cmFjdENvbnRyb2wuc3RhdHVzQ2hhbmdlc30gdG8gYmUgbm90aWZpZWQgd2hlbiB0aGUgdmFsaWRhdGlvbiBzdGF0dXMgaXNcbiAgICAgICogcmUtY2FsY3VsYXRlZC5cbiAgICAgICogKlxuICAgICAgKiAjIyMgRXhhbXBsZVxuICAgICAgKiAqXG4gICAgICAqIEluIHRoaXMgZXhhbXBsZSwgd2UgY3JlYXRlIGZvcm0gY29udHJvbHMgZm9yIGZpcnN0IG5hbWUgYW5kIGxhc3QgbmFtZS5cbiAgICAgICogKlxuICAgICAgKiB7QGV4YW1wbGUgZm9ybXMvdHMvc2ltcGxlRm9ybUdyb3VwL3NpbXBsZV9mb3JtX2dyb3VwX2V4YW1wbGUudHMgcmVnaW9uPSdDb21wb25lbnQnfVxuICAgICAgKiAqXG4gICAgICAqIFRvIHNlZSBgZm9ybUNvbnRyb2xOYW1lYCBleGFtcGxlcyB3aXRoIGRpZmZlcmVudCBmb3JtIGNvbnRyb2wgdHlwZXMsIHNlZTpcbiAgICAgICogKlxuICAgICAgKiAqIFJhZGlvIGJ1dHRvbnM6IHtAbGluayBSYWRpb0NvbnRyb2xWYWx1ZUFjY2Vzc29yfVxuICAgICAgKiAqIFNlbGVjdHM6IHtAbGluayBTZWxlY3RDb250cm9sVmFsdWVBY2Nlc3Nvcn1cbiAgICAgICogKlxuICAgICAgKiAqKm5wbSBwYWNrYWdlKio6IGBAYW5ndWxhci9mb3Jtc2BcbiAgICAgICogKlxuICAgICAgKiAqKk5nTW9kdWxlKio6IHtAbGluayBSZWFjdGl2ZUZvcm1zTW9kdWxlfVxuICAgICAgKiAqXG4gICAgICAqIEBzdGFibGVcbiAgICAgKi9cbiAgICB2YXIgRm9ybUNvbnRyb2xOYW1lID0gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICAgICAgX19leHRlbmRzJDEwKEZvcm1Db250cm9sTmFtZSwgX3N1cGVyKTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gcGFyZW50XG4gICAgICAgICAqIEBwYXJhbSB7P30gdmFsaWRhdG9yc1xuICAgICAgICAgKiBAcGFyYW0gez99IGFzeW5jVmFsaWRhdG9yc1xuICAgICAgICAgKiBAcGFyYW0gez99IHZhbHVlQWNjZXNzb3JzXG4gICAgICAgICAqL1xuICAgICAgICBmdW5jdGlvbiBGb3JtQ29udHJvbE5hbWUocGFyZW50LCB2YWxpZGF0b3JzLCBhc3luY1ZhbGlkYXRvcnMsIHZhbHVlQWNjZXNzb3JzKSB7XG4gICAgICAgICAgICBfc3VwZXIuY2FsbCh0aGlzKTtcbiAgICAgICAgICAgIHRoaXMuX2FkZGVkID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICAgICAgICAgIHRoaXMuX3BhcmVudCA9IHBhcmVudDtcbiAgICAgICAgICAgIHRoaXMuX3Jhd1ZhbGlkYXRvcnMgPSB2YWxpZGF0b3JzIHx8IFtdO1xuICAgICAgICAgICAgdGhpcy5fcmF3QXN5bmNWYWxpZGF0b3JzID0gYXN5bmNWYWxpZGF0b3JzIHx8IFtdO1xuICAgICAgICAgICAgdGhpcy52YWx1ZUFjY2Vzc29yID0gc2VsZWN0VmFsdWVBY2Nlc3Nvcih0aGlzLCB2YWx1ZUFjY2Vzc29ycyk7XG4gICAgICAgIH1cbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEZvcm1Db250cm9sTmFtZS5wcm90b3R5cGUsIFwiaXNEaXNhYmxlZFwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEBwYXJhbSB7P30gaXNEaXNhYmxlZFxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgc2V0OiBmdW5jdGlvbiAoaXNEaXNhYmxlZCkgeyBSZWFjdGl2ZUVycm9ycy5kaXNhYmxlZEF0dHJXYXJuaW5nKCk7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBjaGFuZ2VzXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtQ29udHJvbE5hbWUucHJvdG90eXBlLm5nT25DaGFuZ2VzID0gZnVuY3Rpb24gKGNoYW5nZXMpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5fYWRkZWQpXG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0VXBDb250cm9sKCk7XG4gICAgICAgICAgICBpZiAoaXNQcm9wZXJ0eVVwZGF0ZWQoY2hhbmdlcywgdGhpcy52aWV3TW9kZWwpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWV3TW9kZWwgPSB0aGlzLm1vZGVsO1xuICAgICAgICAgICAgICAgIHRoaXMuZm9ybURpcmVjdGl2ZS51cGRhdGVNb2RlbCh0aGlzLCB0aGlzLm1vZGVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtQ29udHJvbE5hbWUucHJvdG90eXBlLm5nT25EZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuZm9ybURpcmVjdGl2ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZm9ybURpcmVjdGl2ZS5yZW1vdmVDb250cm9sKHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBuZXdWYWx1ZVxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUNvbnRyb2xOYW1lLnByb3RvdHlwZS52aWV3VG9Nb2RlbFVwZGF0ZSA9IGZ1bmN0aW9uIChuZXdWYWx1ZSkge1xuICAgICAgICAgICAgdGhpcy52aWV3TW9kZWwgPSBuZXdWYWx1ZTtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlLmVtaXQobmV3VmFsdWUpO1xuICAgICAgICB9O1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRm9ybUNvbnRyb2xOYW1lLnByb3RvdHlwZSwgXCJwYXRoXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiBjb250cm9sUGF0aCh0aGlzLm5hbWUsIHRoaXMuX3BhcmVudCk7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRm9ybUNvbnRyb2xOYW1lLnByb3RvdHlwZSwgXCJmb3JtRGlyZWN0aXZlXCIsIHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLl9wYXJlbnQgPyB0aGlzLl9wYXJlbnQuZm9ybURpcmVjdGl2ZSA6IG51bGw7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRm9ybUNvbnRyb2xOYW1lLnByb3RvdHlwZSwgXCJ2YWxpZGF0b3JcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGNvbXBvc2VWYWxpZGF0b3JzKHRoaXMuX3Jhd1ZhbGlkYXRvcnMpOyB9LFxuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEZvcm1Db250cm9sTmFtZS5wcm90b3R5cGUsIFwiYXN5bmNWYWxpZGF0b3JcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY29tcG9zZUFzeW5jVmFsaWRhdG9ycyh0aGlzLl9yYXdBc3luY1ZhbGlkYXRvcnMpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShGb3JtQ29udHJvbE5hbWUucHJvdG90eXBlLCBcImNvbnRyb2xcIiwge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXMuX2NvbnRyb2w7IH0sXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgICAgIH0pO1xuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1Db250cm9sTmFtZS5wcm90b3R5cGUuX2NoZWNrUGFyZW50VHlwZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICghKHRoaXMuX3BhcmVudCBpbnN0YW5jZW9mIEZvcm1Hcm91cE5hbWUpICYmXG4gICAgICAgICAgICAgICAgdGhpcy5fcGFyZW50IGluc3RhbmNlb2YgQWJzdHJhY3RGb3JtR3JvdXBEaXJlY3RpdmUpIHtcbiAgICAgICAgICAgICAgICBSZWFjdGl2ZUVycm9ycy5uZ01vZGVsR3JvdXBFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKCEodGhpcy5fcGFyZW50IGluc3RhbmNlb2YgRm9ybUdyb3VwTmFtZSkgJiYgISh0aGlzLl9wYXJlbnQgaW5zdGFuY2VvZiBGb3JtR3JvdXBEaXJlY3RpdmUpICYmXG4gICAgICAgICAgICAgICAgISh0aGlzLl9wYXJlbnQgaW5zdGFuY2VvZiBGb3JtQXJyYXlOYW1lKSkge1xuICAgICAgICAgICAgICAgIFJlYWN0aXZlRXJyb3JzLmNvbnRyb2xQYXJlbnRFeGNlcHRpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtQ29udHJvbE5hbWUucHJvdG90eXBlLl9zZXRVcENvbnRyb2wgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLl9jaGVja1BhcmVudFR5cGUoKTtcbiAgICAgICAgICAgIHRoaXMuX2NvbnRyb2wgPSB0aGlzLmZvcm1EaXJlY3RpdmUuYWRkQ29udHJvbCh0aGlzKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbnRyb2wuZGlzYWJsZWQgJiYgdGhpcy52YWx1ZUFjY2Vzc29yLnNldERpc2FibGVkU3RhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlQWNjZXNzb3Iuc2V0RGlzYWJsZWRTdGF0ZSh0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX2FkZGVkID0gdHJ1ZTtcbiAgICAgICAgfTtcbiAgICAgICAgRm9ybUNvbnRyb2xOYW1lLmRlY29yYXRvcnMgPSBbXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuRGlyZWN0aXZlLCBhcmdzOiBbeyBzZWxlY3RvcjogJ1tmb3JtQ29udHJvbE5hbWVdJywgcHJvdmlkZXJzOiBbY29udHJvbE5hbWVCaW5kaW5nXSB9LF0gfSxcbiAgICAgICAgXTtcbiAgICAgICAgLyoqIEBub2NvbGxhcHNlICovXG4gICAgICAgIEZvcm1Db250cm9sTmFtZS5jdG9yUGFyYW1ldGVycyA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIFtcbiAgICAgICAgICAgIHsgdHlwZTogQ29udHJvbENvbnRhaW5lciwgZGVjb3JhdG9yczogW3sgdHlwZTogX2FuZ3VsYXJfY29yZS5PcHRpb25hbCB9LCB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuSG9zdCB9LCB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuU2tpcFNlbGYgfSxdIH0sXG4gICAgICAgICAgICB7IHR5cGU6IEFycmF5LCBkZWNvcmF0b3JzOiBbeyB0eXBlOiBfYW5ndWxhcl9jb3JlLk9wdGlvbmFsIH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5TZWxmIH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5JbmplY3QsIGFyZ3M6IFtOR19WQUxJREFUT1JTLF0gfSxdIH0sXG4gICAgICAgICAgICB7IHR5cGU6IEFycmF5LCBkZWNvcmF0b3JzOiBbeyB0eXBlOiBfYW5ndWxhcl9jb3JlLk9wdGlvbmFsIH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5TZWxmIH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5JbmplY3QsIGFyZ3M6IFtOR19BU1lOQ19WQUxJREFUT1JTLF0gfSxdIH0sXG4gICAgICAgICAgICB7IHR5cGU6IEFycmF5LCBkZWNvcmF0b3JzOiBbeyB0eXBlOiBfYW5ndWxhcl9jb3JlLk9wdGlvbmFsIH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5TZWxmIH0sIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5JbmplY3QsIGFyZ3M6IFtOR19WQUxVRV9BQ0NFU1NPUixdIH0sXSB9LFxuICAgICAgICBdOyB9O1xuICAgICAgICBGb3JtQ29udHJvbE5hbWUucHJvcERlY29yYXRvcnMgPSB7XG4gICAgICAgICAgICAnbmFtZSc6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuSW5wdXQsIGFyZ3M6IFsnZm9ybUNvbnRyb2xOYW1lJyxdIH0sXSxcbiAgICAgICAgICAgICdtb2RlbCc6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuSW5wdXQsIGFyZ3M6IFsnbmdNb2RlbCcsXSB9LF0sXG4gICAgICAgICAgICAndXBkYXRlJzogW3sgdHlwZTogX2FuZ3VsYXJfY29yZS5PdXRwdXQsIGFyZ3M6IFsnbmdNb2RlbENoYW5nZScsXSB9LF0sXG4gICAgICAgICAgICAnaXNEaXNhYmxlZCc6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuSW5wdXQsIGFyZ3M6IFsnZGlzYWJsZWQnLF0gfSxdLFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gRm9ybUNvbnRyb2xOYW1lO1xuICAgIH0oTmdDb250cm9sKSk7XG5cbiAgICB2YXIgX19leHRlbmRzJDEzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG4gICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gUkVRVUlSRURfVkFMSURBVE9SID0ge1xuICAgICAgICBwcm92aWRlOiBOR19WQUxJREFUT1JTLFxuICAgICAgICB1c2VFeGlzdGluZzogX2FuZ3VsYXJfY29yZS5mb3J3YXJkUmVmKGZ1bmN0aW9uICgpIHsgcmV0dXJuIFJlcXVpcmVkVmFsaWRhdG9yOyB9KSxcbiAgICAgICAgbXVsdGk6IHRydWVcbiAgICB9O1xuICAgIHZhciAvKiogQHR5cGUgez99ICovIENIRUNLQk9YX1JFUVVJUkVEX1ZBTElEQVRPUiA9IHtcbiAgICAgICAgcHJvdmlkZTogTkdfVkFMSURBVE9SUyxcbiAgICAgICAgdXNlRXhpc3Rpbmc6IF9hbmd1bGFyX2NvcmUuZm9yd2FyZFJlZihmdW5jdGlvbiAoKSB7IHJldHVybiBDaGVja2JveFJlcXVpcmVkVmFsaWRhdG9yOyB9KSxcbiAgICAgICAgbXVsdGk6IHRydWVcbiAgICB9O1xuICAgIC8qKlxuICAgICAqICBBIERpcmVjdGl2ZSB0aGF0IGFkZHMgdGhlIGByZXF1aXJlZGAgdmFsaWRhdG9yIHRvIGFueSBjb250cm9scyBtYXJrZWQgd2l0aCB0aGVcbiAgICAgICogYHJlcXVpcmVkYCBhdHRyaWJ1dGUsIHZpYSB0aGUge0BsaW5rIE5HX1ZBTElEQVRPUlN9IGJpbmRpbmcuXG4gICAgICAqICpcbiAgICAgICogIyMjIEV4YW1wbGVcbiAgICAgICogKlxuICAgICAgKiBgYGBcbiAgICAgICogPGlucHV0IG5hbWU9XCJmdWxsTmFtZVwiIG5nTW9kZWwgcmVxdWlyZWQ+XG4gICAgICAqIGBgYFxuICAgICAgKiAqXG4gICAgICovXG4gICAgdmFyIFJlcXVpcmVkVmFsaWRhdG9yID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gUmVxdWlyZWRWYWxpZGF0b3IoKSB7XG4gICAgICAgIH1cbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlcXVpcmVkVmFsaWRhdG9yLnByb3RvdHlwZSwgXCJyZXF1aXJlZFwiLCB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpcy5fcmVxdWlyZWQ7IH0sXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEBwYXJhbSB7P30gdmFsdWVcbiAgICAgICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHNldDogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVxdWlyZWQgPSB2YWx1ZSAhPSBudWxsICYmIHZhbHVlICE9PSBmYWxzZSAmJiBcIlwiICsgdmFsdWUgIT09ICdmYWxzZSc7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX29uQ2hhbmdlKVxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9vbkNoYW5nZSgpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGNcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIFJlcXVpcmVkVmFsaWRhdG9yLnByb3RvdHlwZS52YWxpZGF0ZSA9IGZ1bmN0aW9uIChjKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yZXF1aXJlZCA/IFZhbGlkYXRvcnMucmVxdWlyZWQoYykgOiBudWxsO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBmblxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgUmVxdWlyZWRWYWxpZGF0b3IucHJvdG90eXBlLnJlZ2lzdGVyT25WYWxpZGF0b3JDaGFuZ2UgPSBmdW5jdGlvbiAoZm4pIHsgdGhpcy5fb25DaGFuZ2UgPSBmbjsgfTtcbiAgICAgICAgUmVxdWlyZWRWYWxpZGF0b3IuZGVjb3JhdG9ycyA9IFtcbiAgICAgICAgICAgIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5EaXJlY3RpdmUsIGFyZ3M6IFt7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RvcjogJzpub3QoW3R5cGU9Y2hlY2tib3hdKVtyZXF1aXJlZF1bZm9ybUNvbnRyb2xOYW1lXSw6bm90KFt0eXBlPWNoZWNrYm94XSlbcmVxdWlyZWRdW2Zvcm1Db250cm9sXSw6bm90KFt0eXBlPWNoZWNrYm94XSlbcmVxdWlyZWRdW25nTW9kZWxdJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3ZpZGVyczogW1JFUVVJUkVEX1ZBTElEQVRPUl0sXG4gICAgICAgICAgICAgICAgICAgICAgICBob3N0OiB7ICdbYXR0ci5yZXF1aXJlZF0nOiAncmVxdWlyZWQgPyBcIlwiIDogbnVsbCcgfVxuICAgICAgICAgICAgICAgICAgICB9LF0gfSxcbiAgICAgICAgXTtcbiAgICAgICAgLyoqIEBub2NvbGxhcHNlICovXG4gICAgICAgIFJlcXVpcmVkVmFsaWRhdG9yLmN0b3JQYXJhbWV0ZXJzID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gW107IH07XG4gICAgICAgIFJlcXVpcmVkVmFsaWRhdG9yLnByb3BEZWNvcmF0b3JzID0ge1xuICAgICAgICAgICAgJ3JlcXVpcmVkJzogW3sgdHlwZTogX2FuZ3VsYXJfY29yZS5JbnB1dCB9LF0sXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBSZXF1aXJlZFZhbGlkYXRvcjtcbiAgICB9KCkpO1xuICAgIC8qKlxuICAgICAqICBBIERpcmVjdGl2ZSB0aGF0IGFkZHMgdGhlIGByZXF1aXJlZGAgdmFsaWRhdG9yIHRvIGNoZWNrYm94IGNvbnRyb2xzIG1hcmtlZCB3aXRoIHRoZVxuICAgICAgKiBgcmVxdWlyZWRgIGF0dHJpYnV0ZSwgdmlhIHRoZSB7QGxpbmsgTkdfVkFMSURBVE9SU30gYmluZGluZy5cbiAgICAgICogKlxuICAgICAgKiAjIyMgRXhhbXBsZVxuICAgICAgKiAqXG4gICAgICAqIGBgYFxuICAgICAgKiA8aW5wdXQgdHlwZT1cImNoZWNrYm94XCIgbmFtZT1cImFjdGl2ZVwiIG5nTW9kZWwgcmVxdWlyZWQ+XG4gICAgICAqIGBgYFxuICAgICAgKiAqXG4gICAgICovXG4gICAgdmFyIENoZWNrYm94UmVxdWlyZWRWYWxpZGF0b3IgPSAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgICAgICBfX2V4dGVuZHMkMTMoQ2hlY2tib3hSZXF1aXJlZFZhbGlkYXRvciwgX3N1cGVyKTtcbiAgICAgICAgZnVuY3Rpb24gQ2hlY2tib3hSZXF1aXJlZFZhbGlkYXRvcigpIHtcbiAgICAgICAgICAgIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGNcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIENoZWNrYm94UmVxdWlyZWRWYWxpZGF0b3IucHJvdG90eXBlLnZhbGlkYXRlID0gZnVuY3Rpb24gKGMpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJlcXVpcmVkID8gVmFsaWRhdG9ycy5yZXF1aXJlZFRydWUoYykgOiBudWxsO1xuICAgICAgICB9O1xuICAgICAgICBDaGVja2JveFJlcXVpcmVkVmFsaWRhdG9yLmRlY29yYXRvcnMgPSBbXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuRGlyZWN0aXZlLCBhcmdzOiBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0b3I6ICdpbnB1dFt0eXBlPWNoZWNrYm94XVtyZXF1aXJlZF1bZm9ybUNvbnRyb2xOYW1lXSxpbnB1dFt0eXBlPWNoZWNrYm94XVtyZXF1aXJlZF1bZm9ybUNvbnRyb2xdLGlucHV0W3R5cGU9Y2hlY2tib3hdW3JlcXVpcmVkXVtuZ01vZGVsXScsXG4gICAgICAgICAgICAgICAgICAgICAgICBwcm92aWRlcnM6IFtDSEVDS0JPWF9SRVFVSVJFRF9WQUxJREFUT1JdLFxuICAgICAgICAgICAgICAgICAgICAgICAgaG9zdDogeyAnW2F0dHIucmVxdWlyZWRdJzogJ3JlcXVpcmVkID8gXCJcIiA6IG51bGwnIH1cbiAgICAgICAgICAgICAgICAgICAgfSxdIH0sXG4gICAgICAgIF07XG4gICAgICAgIC8qKiBAbm9jb2xsYXBzZSAqL1xuICAgICAgICBDaGVja2JveFJlcXVpcmVkVmFsaWRhdG9yLmN0b3JQYXJhbWV0ZXJzID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gW107IH07XG4gICAgICAgIHJldHVybiBDaGVja2JveFJlcXVpcmVkVmFsaWRhdG9yO1xuICAgIH0oUmVxdWlyZWRWYWxpZGF0b3IpKTtcbiAgICAvKipcbiAgICAgKiBQcm92aWRlciB3aGljaCBhZGRzIHtAbGluayBNaW5MZW5ndGhWYWxpZGF0b3J9IHRvIHtAbGluayBOR19WQUxJREFUT1JTfS5cbiAgICAgKlxuICAgICAqICMjIEV4YW1wbGU6XG4gICAgICpcbiAgICAgKiB7QGV4YW1wbGUgY29tbW9uL2Zvcm1zL3RzL3ZhbGlkYXRvcnMvdmFsaWRhdG9ycy50cyByZWdpb249J21pbid9XG4gICAgICovXG4gICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gTUlOX0xFTkdUSF9WQUxJREFUT1IgPSB7XG4gICAgICAgIHByb3ZpZGU6IE5HX1ZBTElEQVRPUlMsXG4gICAgICAgIHVzZUV4aXN0aW5nOiBfYW5ndWxhcl9jb3JlLmZvcndhcmRSZWYoZnVuY3Rpb24gKCkgeyByZXR1cm4gTWluTGVuZ3RoVmFsaWRhdG9yOyB9KSxcbiAgICAgICAgbXVsdGk6IHRydWVcbiAgICB9O1xuICAgIC8qKlxuICAgICAqICBBIGRpcmVjdGl2ZSB3aGljaCBpbnN0YWxscyB0aGUge0BsaW5rIE1pbkxlbmd0aFZhbGlkYXRvcn0gZm9yIGFueSBgZm9ybUNvbnRyb2xOYW1lYCxcbiAgICAgICogYGZvcm1Db250cm9sYCwgb3IgY29udHJvbCB3aXRoIGBuZ01vZGVsYCB0aGF0IGFsc28gaGFzIGEgYG1pbmxlbmd0aGAgYXR0cmlidXRlLlxuICAgICAgKiAqXG4gICAgICovXG4gICAgdmFyIE1pbkxlbmd0aFZhbGlkYXRvciA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIE1pbkxlbmd0aFZhbGlkYXRvcigpIHtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBjaGFuZ2VzXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBNaW5MZW5ndGhWYWxpZGF0b3IucHJvdG90eXBlLm5nT25DaGFuZ2VzID0gZnVuY3Rpb24gKGNoYW5nZXMpIHtcbiAgICAgICAgICAgIGlmICgnbWlubGVuZ3RoJyBpbiBjaGFuZ2VzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fY3JlYXRlVmFsaWRhdG9yKCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX29uQ2hhbmdlKVxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9vbkNoYW5nZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBjXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBNaW5MZW5ndGhWYWxpZGF0b3IucHJvdG90eXBlLnZhbGlkYXRlID0gZnVuY3Rpb24gKGMpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1pbmxlbmd0aCA9PSBudWxsID8gbnVsbCA6IHRoaXMuX3ZhbGlkYXRvcihjKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gZm5cbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIE1pbkxlbmd0aFZhbGlkYXRvci5wcm90b3R5cGUucmVnaXN0ZXJPblZhbGlkYXRvckNoYW5nZSA9IGZ1bmN0aW9uIChmbikgeyB0aGlzLl9vbkNoYW5nZSA9IGZuOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIE1pbkxlbmd0aFZhbGlkYXRvci5wcm90b3R5cGUuX2NyZWF0ZVZhbGlkYXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMuX3ZhbGlkYXRvciA9IFZhbGlkYXRvcnMubWluTGVuZ3RoKHBhcnNlSW50KHRoaXMubWlubGVuZ3RoLCAxMCkpO1xuICAgICAgICB9O1xuICAgICAgICBNaW5MZW5ndGhWYWxpZGF0b3IuZGVjb3JhdG9ycyA9IFtcbiAgICAgICAgICAgIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5EaXJlY3RpdmUsIGFyZ3M6IFt7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RvcjogJ1ttaW5sZW5ndGhdW2Zvcm1Db250cm9sTmFtZV0sW21pbmxlbmd0aF1bZm9ybUNvbnRyb2xdLFttaW5sZW5ndGhdW25nTW9kZWxdJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3ZpZGVyczogW01JTl9MRU5HVEhfVkFMSURBVE9SXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGhvc3Q6IHsgJ1thdHRyLm1pbmxlbmd0aF0nOiAnbWlubGVuZ3RoID8gbWlubGVuZ3RoIDogbnVsbCcgfVxuICAgICAgICAgICAgICAgICAgICB9LF0gfSxcbiAgICAgICAgXTtcbiAgICAgICAgLyoqIEBub2NvbGxhcHNlICovXG4gICAgICAgIE1pbkxlbmd0aFZhbGlkYXRvci5jdG9yUGFyYW1ldGVycyA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIFtdOyB9O1xuICAgICAgICBNaW5MZW5ndGhWYWxpZGF0b3IucHJvcERlY29yYXRvcnMgPSB7XG4gICAgICAgICAgICAnbWlubGVuZ3RoJzogW3sgdHlwZTogX2FuZ3VsYXJfY29yZS5JbnB1dCB9LF0sXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBNaW5MZW5ndGhWYWxpZGF0b3I7XG4gICAgfSgpKTtcbiAgICAvKipcbiAgICAgKiBQcm92aWRlciB3aGljaCBhZGRzIHtAbGluayBNYXhMZW5ndGhWYWxpZGF0b3J9IHRvIHtAbGluayBOR19WQUxJREFUT1JTfS5cbiAgICAgKlxuICAgICAqICMjIEV4YW1wbGU6XG4gICAgICpcbiAgICAgKiB7QGV4YW1wbGUgY29tbW9uL2Zvcm1zL3RzL3ZhbGlkYXRvcnMvdmFsaWRhdG9ycy50cyByZWdpb249J21heCd9XG4gICAgICovXG4gICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gTUFYX0xFTkdUSF9WQUxJREFUT1IgPSB7XG4gICAgICAgIHByb3ZpZGU6IE5HX1ZBTElEQVRPUlMsXG4gICAgICAgIHVzZUV4aXN0aW5nOiBfYW5ndWxhcl9jb3JlLmZvcndhcmRSZWYoZnVuY3Rpb24gKCkgeyByZXR1cm4gTWF4TGVuZ3RoVmFsaWRhdG9yOyB9KSxcbiAgICAgICAgbXVsdGk6IHRydWVcbiAgICB9O1xuICAgIC8qKlxuICAgICAqICBBIGRpcmVjdGl2ZSB3aGljaCBpbnN0YWxscyB0aGUge0BsaW5rIE1heExlbmd0aFZhbGlkYXRvcn0gZm9yIGFueSBgZm9ybUNvbnRyb2xOYW1lLFxuICAgICAgKiBgZm9ybUNvbnRyb2xgLFxuICAgICAgKiBvciBjb250cm9sIHdpdGggYG5nTW9kZWxgIHRoYXQgYWxzbyBoYXMgYSBgbWF4bGVuZ3RoYCBhdHRyaWJ1dGUuXG4gICAgICAqICpcbiAgICAgKi9cbiAgICB2YXIgTWF4TGVuZ3RoVmFsaWRhdG9yID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gTWF4TGVuZ3RoVmFsaWRhdG9yKCkge1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGNoYW5nZXNcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIE1heExlbmd0aFZhbGlkYXRvci5wcm90b3R5cGUubmdPbkNoYW5nZXMgPSBmdW5jdGlvbiAoY2hhbmdlcykge1xuICAgICAgICAgICAgaWYgKCdtYXhsZW5ndGgnIGluIGNoYW5nZXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9jcmVhdGVWYWxpZGF0b3IoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fb25DaGFuZ2UpXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX29uQ2hhbmdlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGNcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIE1heExlbmd0aFZhbGlkYXRvci5wcm90b3R5cGUudmFsaWRhdGUgPSBmdW5jdGlvbiAoYykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubWF4bGVuZ3RoICE9IG51bGwgPyB0aGlzLl92YWxpZGF0b3IoYykgOiBudWxsO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBmblxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgTWF4TGVuZ3RoVmFsaWRhdG9yLnByb3RvdHlwZS5yZWdpc3Rlck9uVmFsaWRhdG9yQ2hhbmdlID0gZnVuY3Rpb24gKGZuKSB7IHRoaXMuX29uQ2hhbmdlID0gZm47IH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgTWF4TGVuZ3RoVmFsaWRhdG9yLnByb3RvdHlwZS5fY3JlYXRlVmFsaWRhdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy5fdmFsaWRhdG9yID0gVmFsaWRhdG9ycy5tYXhMZW5ndGgocGFyc2VJbnQodGhpcy5tYXhsZW5ndGgsIDEwKSk7XG4gICAgICAgIH07XG4gICAgICAgIE1heExlbmd0aFZhbGlkYXRvci5kZWNvcmF0b3JzID0gW1xuICAgICAgICAgICAgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLkRpcmVjdGl2ZSwgYXJnczogW3tcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdG9yOiAnW21heGxlbmd0aF1bZm9ybUNvbnRyb2xOYW1lXSxbbWF4bGVuZ3RoXVtmb3JtQ29udHJvbF0sW21heGxlbmd0aF1bbmdNb2RlbF0nLFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJvdmlkZXJzOiBbTUFYX0xFTkdUSF9WQUxJREFUT1JdLFxuICAgICAgICAgICAgICAgICAgICAgICAgaG9zdDogeyAnW2F0dHIubWF4bGVuZ3RoXSc6ICdtYXhsZW5ndGggPyBtYXhsZW5ndGggOiBudWxsJyB9XG4gICAgICAgICAgICAgICAgICAgIH0sXSB9LFxuICAgICAgICBdO1xuICAgICAgICAvKiogQG5vY29sbGFwc2UgKi9cbiAgICAgICAgTWF4TGVuZ3RoVmFsaWRhdG9yLmN0b3JQYXJhbWV0ZXJzID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gW107IH07XG4gICAgICAgIE1heExlbmd0aFZhbGlkYXRvci5wcm9wRGVjb3JhdG9ycyA9IHtcbiAgICAgICAgICAgICdtYXhsZW5ndGgnOiBbeyB0eXBlOiBfYW5ndWxhcl9jb3JlLklucHV0IH0sXSxcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIE1heExlbmd0aFZhbGlkYXRvcjtcbiAgICB9KCkpO1xuICAgIHZhciAvKiogQHR5cGUgez99ICovIFBBVFRFUk5fVkFMSURBVE9SID0ge1xuICAgICAgICBwcm92aWRlOiBOR19WQUxJREFUT1JTLFxuICAgICAgICB1c2VFeGlzdGluZzogX2FuZ3VsYXJfY29yZS5mb3J3YXJkUmVmKGZ1bmN0aW9uICgpIHsgcmV0dXJuIFBhdHRlcm5WYWxpZGF0b3I7IH0pLFxuICAgICAgICBtdWx0aTogdHJ1ZVxuICAgIH07XG4gICAgLyoqXG4gICAgICogIEEgRGlyZWN0aXZlIHRoYXQgYWRkcyB0aGUgYHBhdHRlcm5gIHZhbGlkYXRvciB0byBhbnkgY29udHJvbHMgbWFya2VkIHdpdGggdGhlXG4gICAgICAqIGBwYXR0ZXJuYCBhdHRyaWJ1dGUsIHZpYSB0aGUge0BsaW5rIE5HX1ZBTElEQVRPUlN9IGJpbmRpbmcuIFVzZXMgYXR0cmlidXRlIHZhbHVlXG4gICAgICAqIGFzIHRoZSByZWdleCB0byB2YWxpZGF0ZSBDb250cm9sIHZhbHVlIGFnYWluc3QuICBGb2xsb3dzIHBhdHRlcm4gYXR0cmlidXRlXG4gICAgICAqIHNlbWFudGljczsgaS5lLiByZWdleCBtdXN0IG1hdGNoIGVudGlyZSBDb250cm9sIHZhbHVlLlxuICAgICAgKiAqXG4gICAgICAqICMjIyBFeGFtcGxlXG4gICAgICAqICpcbiAgICAgICogYGBgXG4gICAgICAqIDxpbnB1dCBbbmFtZV09XCJmdWxsTmFtZVwiIHBhdHRlcm49XCJbYS16QS1aIF0qXCIgbmdNb2RlbD5cbiAgICAgICogYGBgXG4gICAgICovXG4gICAgdmFyIFBhdHRlcm5WYWxpZGF0b3IgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICBmdW5jdGlvbiBQYXR0ZXJuVmFsaWRhdG9yKCkge1xuICAgICAgICB9XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGNoYW5nZXNcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIFBhdHRlcm5WYWxpZGF0b3IucHJvdG90eXBlLm5nT25DaGFuZ2VzID0gZnVuY3Rpb24gKGNoYW5nZXMpIHtcbiAgICAgICAgICAgIGlmICgncGF0dGVybicgaW4gY2hhbmdlcykge1xuICAgICAgICAgICAgICAgIHRoaXMuX2NyZWF0ZVZhbGlkYXRvcigpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vbkNoYW5nZSlcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fb25DaGFuZ2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gY1xuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgUGF0dGVyblZhbGlkYXRvci5wcm90b3R5cGUudmFsaWRhdGUgPSBmdW5jdGlvbiAoYykgeyByZXR1cm4gdGhpcy5fdmFsaWRhdG9yKGMpOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHs/fSBmblxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgUGF0dGVyblZhbGlkYXRvci5wcm90b3R5cGUucmVnaXN0ZXJPblZhbGlkYXRvckNoYW5nZSA9IGZ1bmN0aW9uIChmbikgeyB0aGlzLl9vbkNoYW5nZSA9IGZuOyB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIFBhdHRlcm5WYWxpZGF0b3IucHJvdG90eXBlLl9jcmVhdGVWYWxpZGF0b3IgPSBmdW5jdGlvbiAoKSB7IHRoaXMuX3ZhbGlkYXRvciA9IFZhbGlkYXRvcnMucGF0dGVybih0aGlzLnBhdHRlcm4pOyB9O1xuICAgICAgICBQYXR0ZXJuVmFsaWRhdG9yLmRlY29yYXRvcnMgPSBbXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuRGlyZWN0aXZlLCBhcmdzOiBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0b3I6ICdbcGF0dGVybl1bZm9ybUNvbnRyb2xOYW1lXSxbcGF0dGVybl1bZm9ybUNvbnRyb2xdLFtwYXR0ZXJuXVtuZ01vZGVsXScsXG4gICAgICAgICAgICAgICAgICAgICAgICBwcm92aWRlcnM6IFtQQVRURVJOX1ZBTElEQVRPUl0sXG4gICAgICAgICAgICAgICAgICAgICAgICBob3N0OiB7ICdbYXR0ci5wYXR0ZXJuXSc6ICdwYXR0ZXJuID8gcGF0dGVybiA6IG51bGwnIH1cbiAgICAgICAgICAgICAgICAgICAgfSxdIH0sXG4gICAgICAgIF07XG4gICAgICAgIC8qKiBAbm9jb2xsYXBzZSAqL1xuICAgICAgICBQYXR0ZXJuVmFsaWRhdG9yLmN0b3JQYXJhbWV0ZXJzID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gW107IH07XG4gICAgICAgIFBhdHRlcm5WYWxpZGF0b3IucHJvcERlY29yYXRvcnMgPSB7XG4gICAgICAgICAgICAncGF0dGVybic6IFt7IHR5cGU6IF9hbmd1bGFyX2NvcmUuSW5wdXQgfSxdLFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gUGF0dGVyblZhbGlkYXRvcjtcbiAgICB9KCkpO1xuXG4gICAgLyoqXG4gICAgICogICpcbiAgICAgICogSXQgaXMgZXNzZW50aWFsbHkgc3ludGFjdGljIHN1Z2FyIHRoYXQgc2hvcnRlbnMgdGhlIGBuZXcgRm9ybUdyb3VwKClgLFxuICAgICAgKiBgbmV3IEZvcm1Db250cm9sKClgLCBhbmQgYG5ldyBGb3JtQXJyYXkoKWAgYm9pbGVycGxhdGUgdGhhdCBjYW4gYnVpbGQgdXAgaW4gbGFyZ2VyXG4gICAgICAqIGZvcm1zLlxuICAgICAgKiAqXG4gICAgICAqICpcbiAgICAgICogVG8gdXNlLCBpbmplY3QgYEZvcm1CdWlsZGVyYCBpbnRvIHlvdXIgY29tcG9uZW50IGNsYXNzLiBZb3UgY2FuIHRoZW4gY2FsbCBpdHMgbWV0aG9kc1xuICAgICAgKiBkaXJlY3RseS5cbiAgICAgICogKlxuICAgICAgKiB7QGV4YW1wbGUgZm9ybXMvdHMvZm9ybUJ1aWxkZXIvZm9ybV9idWlsZGVyX2V4YW1wbGUudHMgcmVnaW9uPSdDb21wb25lbnQnfVxuICAgICAgKiAqXG4gICAgICAqICogKipucG0gcGFja2FnZSoqOiBgQGFuZ3VsYXIvZm9ybXNgXG4gICAgICAqICpcbiAgICAgICogKiAqKk5nTW9kdWxlKio6IHtAbGluayBSZWFjdGl2ZUZvcm1zTW9kdWxlfVxuICAgICAgKiAqXG4gICAgICovXG4gICAgdmFyIEZvcm1CdWlsZGVyID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gRm9ybUJ1aWxkZXIoKSB7XG4gICAgICAgIH1cbiAgICAgICAgLyoqXG4gICAgICAgICAqICBDb25zdHJ1Y3QgYSBuZXcge0BsaW5rIEZvcm1Hcm91cH0gd2l0aCB0aGUgZ2l2ZW4gbWFwIG9mIGNvbmZpZ3VyYXRpb24uXG4gICAgICAgICAgKiBWYWxpZCBrZXlzIGZvciB0aGUgYGV4dHJhYCBwYXJhbWV0ZXIgbWFwIGFyZSBgdmFsaWRhdG9yYCBhbmQgYGFzeW5jVmFsaWRhdG9yYC5cbiAgICAgICAgICAqICpcbiAgICAgICAgICAqIFNlZSB0aGUge0BsaW5rIEZvcm1Hcm91cH0gY29uc3RydWN0b3IgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgICAgICogQHBhcmFtIHs/fSBjb250cm9sc0NvbmZpZ1xuICAgICAgICAgKiBAcGFyYW0gez89fSBleHRyYVxuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUJ1aWxkZXIucHJvdG90eXBlLmdyb3VwID0gZnVuY3Rpb24gKGNvbnRyb2xzQ29uZmlnLCBleHRyYSkge1xuICAgICAgICAgICAgaWYgKGV4dHJhID09PSB2b2lkIDApIHsgZXh0cmEgPSBudWxsOyB9XG4gICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBjb250cm9scyA9IHRoaXMuX3JlZHVjZUNvbnRyb2xzKGNvbnRyb2xzQ29uZmlnKTtcbiAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIHZhbGlkYXRvciA9IGlzUHJlc2VudChleHRyYSkgPyBleHRyYVsndmFsaWRhdG9yJ10gOiBudWxsO1xuICAgICAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gYXN5bmNWYWxpZGF0b3IgPSBpc1ByZXNlbnQoZXh0cmEpID8gZXh0cmFbJ2FzeW5jVmFsaWRhdG9yJ10gOiBudWxsO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBGb3JtR3JvdXAoY29udHJvbHMsIHZhbGlkYXRvciwgYXN5bmNWYWxpZGF0b3IpO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogIENvbnN0cnVjdCBhIG5ldyB7QGxpbmsgRm9ybUNvbnRyb2x9IHdpdGggdGhlIGdpdmVuIGBmb3JtU3RhdGVgLGB2YWxpZGF0b3JgLCBhbmRcbiAgICAgICAgICAqIGBhc3luY1ZhbGlkYXRvcmAuXG4gICAgICAgICAgKiAqXG4gICAgICAgICAgKiBgZm9ybVN0YXRlYCBjYW4gZWl0aGVyIGJlIGEgc3RhbmRhbG9uZSB2YWx1ZSBmb3IgdGhlIGZvcm0gY29udHJvbCBvciBhbiBvYmplY3RcbiAgICAgICAgICAqIHRoYXQgY29udGFpbnMgYm90aCBhIHZhbHVlIGFuZCBhIGRpc2FibGVkIHN0YXR1cy5cbiAgICAgICAgICAqICpcbiAgICAgICAgICogQHBhcmFtIHs/fSBmb3JtU3RhdGVcbiAgICAgICAgICogQHBhcmFtIHs/PX0gdmFsaWRhdG9yXG4gICAgICAgICAqIEBwYXJhbSB7Pz19IGFzeW5jVmFsaWRhdG9yXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtQnVpbGRlci5wcm90b3R5cGUuY29udHJvbCA9IGZ1bmN0aW9uIChmb3JtU3RhdGUsIHZhbGlkYXRvciwgYXN5bmNWYWxpZGF0b3IpIHtcbiAgICAgICAgICAgIGlmICh2YWxpZGF0b3IgPT09IHZvaWQgMCkgeyB2YWxpZGF0b3IgPSBudWxsOyB9XG4gICAgICAgICAgICBpZiAoYXN5bmNWYWxpZGF0b3IgPT09IHZvaWQgMCkgeyBhc3luY1ZhbGlkYXRvciA9IG51bGw7IH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgRm9ybUNvbnRyb2woZm9ybVN0YXRlLCB2YWxpZGF0b3IsIGFzeW5jVmFsaWRhdG9yKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqICBDb25zdHJ1Y3QgYSB7QGxpbmsgRm9ybUFycmF5fSBmcm9tIHRoZSBnaXZlbiBgY29udHJvbHNDb25maWdgIGFycmF5IG9mXG4gICAgICAgICAgKiBjb25maWd1cmF0aW9uLCB3aXRoIHRoZSBnaXZlbiBvcHRpb25hbCBgdmFsaWRhdG9yYCBhbmQgYGFzeW5jVmFsaWRhdG9yYC5cbiAgICAgICAgICogQHBhcmFtIHs/fSBjb250cm9sc0NvbmZpZ1xuICAgICAgICAgKiBAcGFyYW0gez89fSB2YWxpZGF0b3JcbiAgICAgICAgICogQHBhcmFtIHs/PX0gYXN5bmNWYWxpZGF0b3JcbiAgICAgICAgICogQHJldHVybiB7P31cbiAgICAgICAgICovXG4gICAgICAgIEZvcm1CdWlsZGVyLnByb3RvdHlwZS5hcnJheSA9IGZ1bmN0aW9uIChjb250cm9sc0NvbmZpZywgdmFsaWRhdG9yLCBhc3luY1ZhbGlkYXRvcikge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgICAgIGlmICh2YWxpZGF0b3IgPT09IHZvaWQgMCkgeyB2YWxpZGF0b3IgPSBudWxsOyB9XG4gICAgICAgICAgICBpZiAoYXN5bmNWYWxpZGF0b3IgPT09IHZvaWQgMCkgeyBhc3luY1ZhbGlkYXRvciA9IG51bGw7IH1cbiAgICAgICAgICAgIHZhciAvKiogQHR5cGUgez99ICovIGNvbnRyb2xzID0gY29udHJvbHNDb25maWcubWFwKGZ1bmN0aW9uIChjKSB7IHJldHVybiBfdGhpcy5fY3JlYXRlQ29udHJvbChjKTsgfSk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEZvcm1BcnJheShjb250cm9scywgdmFsaWRhdG9yLCBhc3luY1ZhbGlkYXRvcik7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0gez99IGNvbnRyb2xzQ29uZmlnXG4gICAgICAgICAqIEByZXR1cm4gez99XG4gICAgICAgICAqL1xuICAgICAgICBGb3JtQnVpbGRlci5wcm90b3R5cGUuX3JlZHVjZUNvbnRyb2xzID0gZnVuY3Rpb24gKGNvbnRyb2xzQ29uZmlnKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gY29udHJvbHMgPSB7fTtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKGNvbnRyb2xzQ29uZmlnKS5mb3JFYWNoKGZ1bmN0aW9uIChjb250cm9sTmFtZSkge1xuICAgICAgICAgICAgICAgIGNvbnRyb2xzW2NvbnRyb2xOYW1lXSA9IF90aGlzLl9jcmVhdGVDb250cm9sKGNvbnRyb2xzQ29uZmlnW2NvbnRyb2xOYW1lXSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBjb250cm9scztcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7P30gY29udHJvbENvbmZpZ1xuICAgICAgICAgKiBAcmV0dXJuIHs/fVxuICAgICAgICAgKi9cbiAgICAgICAgRm9ybUJ1aWxkZXIucHJvdG90eXBlLl9jcmVhdGVDb250cm9sID0gZnVuY3Rpb24gKGNvbnRyb2xDb25maWcpIHtcbiAgICAgICAgICAgIGlmIChjb250cm9sQ29uZmlnIGluc3RhbmNlb2YgRm9ybUNvbnRyb2wgfHwgY29udHJvbENvbmZpZyBpbnN0YW5jZW9mIEZvcm1Hcm91cCB8fFxuICAgICAgICAgICAgICAgIGNvbnRyb2xDb25maWcgaW5zdGFuY2VvZiBGb3JtQXJyYXkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY29udHJvbENvbmZpZztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoY29udHJvbENvbmZpZykpIHtcbiAgICAgICAgICAgICAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyB2YWx1ZSA9IGNvbnRyb2xDb25maWdbMF07XG4gICAgICAgICAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gdmFsaWRhdG9yID0gY29udHJvbENvbmZpZy5sZW5ndGggPiAxID8gY29udHJvbENvbmZpZ1sxXSA6IG51bGw7XG4gICAgICAgICAgICAgICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gYXN5bmNWYWxpZGF0b3IgPSBjb250cm9sQ29uZmlnLmxlbmd0aCA+IDIgPyBjb250cm9sQ29uZmlnWzJdIDogbnVsbDtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jb250cm9sKHZhbHVlLCB2YWxpZGF0b3IsIGFzeW5jVmFsaWRhdG9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnRyb2woY29udHJvbENvbmZpZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIEZvcm1CdWlsZGVyLmRlY29yYXRvcnMgPSBbXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuSW5qZWN0YWJsZSB9LFxuICAgICAgICBdO1xuICAgICAgICAvKiogQG5vY29sbGFwc2UgKi9cbiAgICAgICAgRm9ybUJ1aWxkZXIuY3RvclBhcmFtZXRlcnMgPSBmdW5jdGlvbiAoKSB7IHJldHVybiBbXTsgfTtcbiAgICAgICAgcmV0dXJuIEZvcm1CdWlsZGVyO1xuICAgIH0oKSk7XG5cbiAgICAvKipcbiAgICAgKiBAc3RhYmxlXG4gICAgICovXG4gICAgdmFyIC8qKiBAdHlwZSB7P30gKi8gVkVSU0lPTiA9IG5ldyBfYW5ndWxhcl9jb3JlLlZlcnNpb24oJzIuNC4xJyk7XG5cbiAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBTSEFSRURfRk9STV9ESVJFQ1RJVkVTID0gW1xuICAgICAgICBOZ1NlbGVjdE9wdGlvbixcbiAgICAgICAgTmdTZWxlY3RNdWx0aXBsZU9wdGlvbixcbiAgICAgICAgRGVmYXVsdFZhbHVlQWNjZXNzb3IsXG4gICAgICAgIE51bWJlclZhbHVlQWNjZXNzb3IsXG4gICAgICAgIFJhbmdlVmFsdWVBY2Nlc3NvcixcbiAgICAgICAgQ2hlY2tib3hDb250cm9sVmFsdWVBY2Nlc3NvcixcbiAgICAgICAgU2VsZWN0Q29udHJvbFZhbHVlQWNjZXNzb3IsXG4gICAgICAgIFNlbGVjdE11bHRpcGxlQ29udHJvbFZhbHVlQWNjZXNzb3IsXG4gICAgICAgIFJhZGlvQ29udHJvbFZhbHVlQWNjZXNzb3IsXG4gICAgICAgIE5nQ29udHJvbFN0YXR1cyxcbiAgICAgICAgTmdDb250cm9sU3RhdHVzR3JvdXAsXG4gICAgICAgIFJlcXVpcmVkVmFsaWRhdG9yLFxuICAgICAgICBNaW5MZW5ndGhWYWxpZGF0b3IsXG4gICAgICAgIE1heExlbmd0aFZhbGlkYXRvcixcbiAgICAgICAgUGF0dGVyblZhbGlkYXRvcixcbiAgICAgICAgQ2hlY2tib3hSZXF1aXJlZFZhbGlkYXRvcixcbiAgICBdO1xuICAgIHZhciAvKiogQHR5cGUgez99ICovIFRFTVBMQVRFX0RSSVZFTl9ESVJFQ1RJVkVTID0gW05nTW9kZWwsIE5nTW9kZWxHcm91cCwgTmdGb3JtXTtcbiAgICB2YXIgLyoqIEB0eXBlIHs/fSAqLyBSRUFDVElWRV9EUklWRU5fRElSRUNUSVZFUyA9IFtGb3JtQ29udHJvbERpcmVjdGl2ZSwgRm9ybUdyb3VwRGlyZWN0aXZlLCBGb3JtQ29udHJvbE5hbWUsIEZvcm1Hcm91cE5hbWUsIEZvcm1BcnJheU5hbWVdO1xuICAgIC8qKlxuICAgICAqICBJbnRlcm5hbCBtb2R1bGUgdXNlZCBmb3Igc2hhcmluZyBkaXJlY3RpdmVzIGJldHdlZW4gRm9ybXNNb2R1bGUgYW5kIFJlYWN0aXZlRm9ybXNNb2R1bGVcbiAgICAgKi9cbiAgICB2YXIgSW50ZXJuYWxGb3Jtc1NoYXJlZE1vZHVsZSA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZ1bmN0aW9uIEludGVybmFsRm9ybXNTaGFyZWRNb2R1bGUoKSB7XG4gICAgICAgIH1cbiAgICAgICAgSW50ZXJuYWxGb3Jtc1NoYXJlZE1vZHVsZS5kZWNvcmF0b3JzID0gW1xuICAgICAgICAgICAgeyB0eXBlOiBfYW5ndWxhcl9jb3JlLk5nTW9kdWxlLCBhcmdzOiBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVjbGFyYXRpb25zOiBTSEFSRURfRk9STV9ESVJFQ1RJVkVTLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXhwb3J0czogU0hBUkVEX0ZPUk1fRElSRUNUSVZFUyxcbiAgICAgICAgICAgICAgICAgICAgfSxdIH0sXG4gICAgICAgIF07XG4gICAgICAgIC8qKiBAbm9jb2xsYXBzZSAqL1xuICAgICAgICBJbnRlcm5hbEZvcm1zU2hhcmVkTW9kdWxlLmN0b3JQYXJhbWV0ZXJzID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gW107IH07XG4gICAgICAgIHJldHVybiBJbnRlcm5hbEZvcm1zU2hhcmVkTW9kdWxlO1xuICAgIH0oKSk7XG5cbiAgICAvKipcbiAgICAgKiAgVGhlIG5nIG1vZHVsZSBmb3IgZm9ybXMuXG4gICAgICovXG4gICAgdmFyIEZvcm1zTW9kdWxlID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gRm9ybXNNb2R1bGUoKSB7XG4gICAgICAgIH1cbiAgICAgICAgRm9ybXNNb2R1bGUuZGVjb3JhdG9ycyA9IFtcbiAgICAgICAgICAgIHsgdHlwZTogX2FuZ3VsYXJfY29yZS5OZ01vZHVsZSwgYXJnczogW3tcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlY2xhcmF0aW9uczogVEVNUExBVEVfRFJJVkVOX0RJUkVDVElWRVMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwcm92aWRlcnM6IFtSYWRpb0NvbnRyb2xSZWdpc3RyeV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBleHBvcnRzOiBbSW50ZXJuYWxGb3Jtc1NoYXJlZE1vZHVsZSwgVEVNUExBVEVfRFJJVkVOX0RJUkVDVElWRVNdXG4gICAgICAgICAgICAgICAgICAgIH0sXSB9LFxuICAgICAgICBdO1xuICAgICAgICAvKiogQG5vY29sbGFwc2UgKi9cbiAgICAgICAgRm9ybXNNb2R1bGUuY3RvclBhcmFtZXRlcnMgPSBmdW5jdGlvbiAoKSB7IHJldHVybiBbXTsgfTtcbiAgICAgICAgcmV0dXJuIEZvcm1zTW9kdWxlO1xuICAgIH0oKSk7XG4gICAgLyoqXG4gICAgICogIFRoZSBuZyBtb2R1bGUgZm9yIHJlYWN0aXZlIGZvcm1zLlxuICAgICAqL1xuICAgIHZhciBSZWFjdGl2ZUZvcm1zTW9kdWxlID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gUmVhY3RpdmVGb3Jtc01vZHVsZSgpIHtcbiAgICAgICAgfVxuICAgICAgICBSZWFjdGl2ZUZvcm1zTW9kdWxlLmRlY29yYXRvcnMgPSBbXG4gICAgICAgICAgICB7IHR5cGU6IF9hbmd1bGFyX2NvcmUuTmdNb2R1bGUsIGFyZ3M6IFt7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWNsYXJhdGlvbnM6IFtSRUFDVElWRV9EUklWRU5fRElSRUNUSVZFU10sXG4gICAgICAgICAgICAgICAgICAgICAgICBwcm92aWRlcnM6IFtGb3JtQnVpbGRlciwgUmFkaW9Db250cm9sUmVnaXN0cnldLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXhwb3J0czogW0ludGVybmFsRm9ybXNTaGFyZWRNb2R1bGUsIFJFQUNUSVZFX0RSSVZFTl9ESVJFQ1RJVkVTXVxuICAgICAgICAgICAgICAgICAgICB9LF0gfSxcbiAgICAgICAgXTtcbiAgICAgICAgLyoqIEBub2NvbGxhcHNlICovXG4gICAgICAgIFJlYWN0aXZlRm9ybXNNb2R1bGUuY3RvclBhcmFtZXRlcnMgPSBmdW5jdGlvbiAoKSB7IHJldHVybiBbXTsgfTtcbiAgICAgICAgcmV0dXJuIFJlYWN0aXZlRm9ybXNNb2R1bGU7XG4gICAgfSgpKTtcblxuICAgIGV4cG9ydHMuQWJzdHJhY3RDb250cm9sRGlyZWN0aXZlID0gQWJzdHJhY3RDb250cm9sRGlyZWN0aXZlO1xuICAgIGV4cG9ydHMuQWJzdHJhY3RGb3JtR3JvdXBEaXJlY3RpdmUgPSBBYnN0cmFjdEZvcm1Hcm91cERpcmVjdGl2ZTtcbiAgICBleHBvcnRzLkNoZWNrYm94Q29udHJvbFZhbHVlQWNjZXNzb3IgPSBDaGVja2JveENvbnRyb2xWYWx1ZUFjY2Vzc29yO1xuICAgIGV4cG9ydHMuQ29udHJvbENvbnRhaW5lciA9IENvbnRyb2xDb250YWluZXI7XG4gICAgZXhwb3J0cy5OR19WQUxVRV9BQ0NFU1NPUiA9IE5HX1ZBTFVFX0FDQ0VTU09SO1xuICAgIGV4cG9ydHMuRGVmYXVsdFZhbHVlQWNjZXNzb3IgPSBEZWZhdWx0VmFsdWVBY2Nlc3NvcjtcbiAgICBleHBvcnRzLk5nQ29udHJvbCA9IE5nQ29udHJvbDtcbiAgICBleHBvcnRzLk5nQ29udHJvbFN0YXR1cyA9IE5nQ29udHJvbFN0YXR1cztcbiAgICBleHBvcnRzLk5nQ29udHJvbFN0YXR1c0dyb3VwID0gTmdDb250cm9sU3RhdHVzR3JvdXA7XG4gICAgZXhwb3J0cy5OZ0Zvcm0gPSBOZ0Zvcm07XG4gICAgZXhwb3J0cy5OZ01vZGVsID0gTmdNb2RlbDtcbiAgICBleHBvcnRzLk5nTW9kZWxHcm91cCA9IE5nTW9kZWxHcm91cDtcbiAgICBleHBvcnRzLlJhZGlvQ29udHJvbFZhbHVlQWNjZXNzb3IgPSBSYWRpb0NvbnRyb2xWYWx1ZUFjY2Vzc29yO1xuICAgIGV4cG9ydHMuRm9ybUNvbnRyb2xEaXJlY3RpdmUgPSBGb3JtQ29udHJvbERpcmVjdGl2ZTtcbiAgICBleHBvcnRzLkZvcm1Db250cm9sTmFtZSA9IEZvcm1Db250cm9sTmFtZTtcbiAgICBleHBvcnRzLkZvcm1Hcm91cERpcmVjdGl2ZSA9IEZvcm1Hcm91cERpcmVjdGl2ZTtcbiAgICBleHBvcnRzLkZvcm1BcnJheU5hbWUgPSBGb3JtQXJyYXlOYW1lO1xuICAgIGV4cG9ydHMuRm9ybUdyb3VwTmFtZSA9IEZvcm1Hcm91cE5hbWU7XG4gICAgZXhwb3J0cy5OZ1NlbGVjdE9wdGlvbiA9IE5nU2VsZWN0T3B0aW9uO1xuICAgIGV4cG9ydHMuU2VsZWN0Q29udHJvbFZhbHVlQWNjZXNzb3IgPSBTZWxlY3RDb250cm9sVmFsdWVBY2Nlc3NvcjtcbiAgICBleHBvcnRzLlNlbGVjdE11bHRpcGxlQ29udHJvbFZhbHVlQWNjZXNzb3IgPSBTZWxlY3RNdWx0aXBsZUNvbnRyb2xWYWx1ZUFjY2Vzc29yO1xuICAgIGV4cG9ydHMuQ2hlY2tib3hSZXF1aXJlZFZhbGlkYXRvciA9IENoZWNrYm94UmVxdWlyZWRWYWxpZGF0b3I7XG4gICAgZXhwb3J0cy5NYXhMZW5ndGhWYWxpZGF0b3IgPSBNYXhMZW5ndGhWYWxpZGF0b3I7XG4gICAgZXhwb3J0cy5NaW5MZW5ndGhWYWxpZGF0b3IgPSBNaW5MZW5ndGhWYWxpZGF0b3I7XG4gICAgZXhwb3J0cy5QYXR0ZXJuVmFsaWRhdG9yID0gUGF0dGVyblZhbGlkYXRvcjtcbiAgICBleHBvcnRzLlJlcXVpcmVkVmFsaWRhdG9yID0gUmVxdWlyZWRWYWxpZGF0b3I7XG4gICAgZXhwb3J0cy5Gb3JtQnVpbGRlciA9IEZvcm1CdWlsZGVyO1xuICAgIGV4cG9ydHMuQWJzdHJhY3RDb250cm9sID0gQWJzdHJhY3RDb250cm9sO1xuICAgIGV4cG9ydHMuRm9ybUFycmF5ID0gRm9ybUFycmF5O1xuICAgIGV4cG9ydHMuRm9ybUNvbnRyb2wgPSBGb3JtQ29udHJvbDtcbiAgICBleHBvcnRzLkZvcm1Hcm91cCA9IEZvcm1Hcm91cDtcbiAgICBleHBvcnRzLk5HX0FTWU5DX1ZBTElEQVRPUlMgPSBOR19BU1lOQ19WQUxJREFUT1JTO1xuICAgIGV4cG9ydHMuTkdfVkFMSURBVE9SUyA9IE5HX1ZBTElEQVRPUlM7XG4gICAgZXhwb3J0cy5WYWxpZGF0b3JzID0gVmFsaWRhdG9ycztcbiAgICBleHBvcnRzLlZFUlNJT04gPSBWRVJTSU9OO1xuICAgIGV4cG9ydHMuRm9ybXNNb2R1bGUgPSBGb3Jtc01vZHVsZTtcbiAgICBleHBvcnRzLlJlYWN0aXZlRm9ybXNNb2R1bGUgPSBSZWFjdGl2ZUZvcm1zTW9kdWxlO1xuXG59KSk7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L0Bhbmd1bGFyL2Zvcm1zL2J1bmRsZXMvZm9ybXMudW1kLmpzXG4vLyBtb2R1bGUgaWQgPSAyNVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ },
- /* 26 */,
- /* 27 */,
- /* 28 */,
- /* 29 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar core_1 = __webpack_require__(4);\nvar AppComponent = (function () {\n function AppComponent() {\n }\n AppComponent = __decorate([\n core_1.Component({\n selector: 'my-app',\n template: '<router-outlet></router-outlet>',\n styles: [__webpack_require__(30)]\n }), \n __metadata('design:paramtypes', [])\n ], AppComponent);\n return AppComponent;\n}());\nexports.AppComponent = AppComponent;\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMjkuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvYXBwL2FwcC5jb21wb25lbnQudHM/ZjA1MiJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ215LWFwcCcsXG4gIHRlbXBsYXRlOiAnPHJvdXRlci1vdXRsZXQ+PC9yb3V0ZXItb3V0bGV0PicsXG4gIHN0eWxlczogWyByZXF1aXJlKCcuL2FwcC5jb21wb25lbnQuY3NzJykgXVxufSlcbmV4cG9ydCBjbGFzcyBBcHBDb21wb25lbnQgeyB9XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gbm9kZV9tb2R1bGVzL2FuZ3VsYXIyLXRlbXBsYXRlLWxvYWRlciEuL3NyYy9hcHAvYXBwLmNvbXBvbmVudC50cyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQUFBO0FBTUE7QUFBQTtBQUFBO0FBTEE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUFBO0FBQ0E7QUFBQTtBQUFBOyIsInNvdXJjZVJvb3QiOiIifQ==");
- /***/ },
- /* 30 */
- /***/ function(module, exports) {
- eval("module.exports = \"\"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMzAuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvYXBwL2FwcC5jb21wb25lbnQuY3NzP2M2MjMiXSwic291cmNlc0NvbnRlbnQiOlsibW9kdWxlLmV4cG9ydHMgPSBcIlwiXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9zcmMvYXBwL2FwcC5jb21wb25lbnQuY3NzXG4vLyBtb2R1bGUgaWQgPSAzMFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiXSwibWFwcGluZ3MiOiJBQUFBIiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 31 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar core_1 = __webpack_require__(4);\nvar router_1 = __webpack_require__(32);\nvar home_component_1 = __webpack_require__(62);\nvar archive_component_1 = __webpack_require__(104);\nvar bin_component_1 = __webpack_require__(106);\nvar about_component_1 = __webpack_require__(108);\nexports.routes = [\n { path: '', redirectTo: '/notes', pathMatch: 'full' },\n { path: 'notes', component: home_component_1.HomeComponent },\n { path: 'archive-notes', component: archive_component_1.ArchiveComponent },\n { path: 'recycle-bin', component: bin_component_1.BinComponent },\n { path: 'about', component: about_component_1.AboutComponent }\n];\nvar AppRoutingModule = (function () {\n function AppRoutingModule() {\n }\n AppRoutingModule = __decorate([\n core_1.NgModule({\n imports: [router_1.RouterModule.forRoot(exports.routes)],\n exports: [router_1.RouterModule]\n }), \n __metadata('design:paramtypes', [])\n ], AppRoutingModule);\n return AppRoutingModule;\n}());\nexports.AppRoutingModule = AppRoutingModule;\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMzEuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvYXBwL2FwcC5yb3V0aW5nLnRzPzk0NWEiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTmdNb2R1bGUgfSAgICAgICBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFJvdXRlcyxcbiAgICAgICAgIFJvdXRlck1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBIb21lQ29tcG9uZW50IH0gZnJvbSAnLi9jb21wb25lbnRzL2hvbWUvaG9tZS5jb21wb25lbnQnO1xuaW1wb3J0IHsgQXJjaGl2ZUNvbXBvbmVudCB9IGZyb20gJy4vY29tcG9uZW50cy9hcmNoaXZlLW5vdGVzL2FyY2hpdmUuY29tcG9uZW50JztcbmltcG9ydCB7IEJpbkNvbXBvbmVudCB9IGZyb20gJy4vY29tcG9uZW50cy9iaW4vYmluLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBBYm91dENvbXBvbmVudCB9IGZyb20gJy4vY29tcG9uZW50cy9hYm91dC9hYm91dC5jb21wb25lbnQnO1xuXG5leHBvcnQgY29uc3Qgcm91dGVzOiBSb3V0ZXMgPSBbXG4gIHsgcGF0aDogJycsIHJlZGlyZWN0VG86ICcvbm90ZXMnLCBwYXRoTWF0Y2g6ICdmdWxsJ30sXG4gIHsgcGF0aDogJ25vdGVzJywgY29tcG9uZW50OiBIb21lQ29tcG9uZW50IH0sXG4gIHsgcGF0aDogJ2FyY2hpdmUtbm90ZXMnLCBjb21wb25lbnQ6IEFyY2hpdmVDb21wb25lbnQgfSxcbiAgeyBwYXRoOiAncmVjeWNsZS1iaW4nLCBjb21wb25lbnQ6IEJpbkNvbXBvbmVudCB9LFxuICB7IHBhdGg6ICdhYm91dCcsIGNvbXBvbmVudDogQWJvdXRDb21wb25lbnQgfVxuXTtcblxuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogWyBSb3V0ZXJNb2R1bGUuZm9yUm9vdChyb3V0ZXMpIF0sXG4gIGV4cG9ydHM6IFsgUm91dGVyTW9kdWxlIF1cbn0pXG5leHBvcnQgY2xhc3MgQXBwUm91dGluZ01vZHVsZSB7fVxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIG5vZGVfbW9kdWxlcy9hbmd1bGFyMi10ZW1wbGF0ZS1sb2FkZXIhLi9zcmMvYXBwL2FwcC5yb3V0aW5nLnRzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFNQTtBQUFBO0FBQUE7QUFKQTtBQUFBO0FBQ0E7QUFDQTtBQUNBOztBQUFBO0FBQ0E7QUFBQTtBQUFBOyIsInNvdXJjZVJvb3QiOiIifQ==");
- /***/ },
- /* 32 */,
- /* 33 */,
- /* 34 */,
- /* 35 */,
- /* 36 */,
- /* 37 */,
- /* 38 */,
- /* 39 */,
- /* 40 */,
- /* 41 */,
- /* 42 */,
- /* 43 */,
- /* 44 */,
- /* 45 */,
- /* 46 */,
- /* 47 */,
- /* 48 */,
- /* 49 */,
- /* 50 */,
- /* 51 */,
- /* 52 */,
- /* 53 */,
- /* 54 */,
- /* 55 */,
- /* 56 */,
- /* 57 */,
- /* 58 */,
- /* 59 */,
- /* 60 */,
- /* 61 */,
- /* 62 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar core_1 = __webpack_require__(4);\nvar angular2_notifications_1 = __webpack_require__(63);\nvar _ = __webpack_require__(74);\nvar dragula_1 = __webpack_require__(76);\nvar notes_table_service_1 = __webpack_require__(88);\nvar bin_table_service_1 = __webpack_require__(101);\nvar archive_table_service_1 = __webpack_require__(102);\nvar HomeComponent = (function () {\n function HomeComponent(dragulaService, _notesService, _archiveService, _binService, _notificationsService) {\n var _this = this;\n this.dragulaService = dragulaService;\n this._notesService = _notesService;\n this._archiveService = _archiveService;\n this._binService = _binService;\n this._notificationsService = _notificationsService;\n this.spinner = true;\n this.displayList = false;\n this.inputFocusClass = false;\n this.notes_table = NOTES_TABLE;\n this.emptyHtmlMsg = false;\n this.notes = [];\n this.draft = {};\n this.editNoteDraft = {};\n this.order = [];\n this.orderNotes = [];\n this.notificationOptions = {\n timeOut: 3000,\n lastOnBottom: true,\n clickToClose: true,\n showProgressBar: false,\n pauseOnHover: true,\n preventDuplicates: false,\n theClass: \"notes-notifications\",\n rtl: true\n };\n dragulaService.drag.subscribe(function (value) {\n _this.onDrag(value.slice(1));\n });\n dragulaService.dropModel.subscribe(function (value) {\n _this.onDropModel(value.slice(1));\n });\n dragulaService.drop.subscribe(function (value) {\n _this.onDrop(value);\n });\n dragulaService.removeModel.subscribe(function (value) {\n _this.onRemoveModel(value.slice(1));\n });\n this.displayList = localStorage.getItem(\"displayNotesTypeList\") == 'true' ? true : false;\n }\n HomeComponent.prototype.onDrag = function (args) {\n var e = args[0], el = args[1];\n };\n HomeComponent.prototype.ngOnInit = function () {\n var _this = this;\n this.subscription = this._notesService.notes_tables$.subscribe(function (notes_table) { return _this.notes_table = notes_table; });\n this.refreshNotesTables();\n };\n HomeComponent.prototype._setInputFocus = function (isFocus) {\n this.inputFocusClass = isFocus;\n };\n HomeComponent.prototype.onDropModel = function (args) {\n var el = args[0], target = args[1], source = args[2];\n // do something else\n var order = [];\n this.notes.forEach(function (row) {\n order.push(row.doc._id);\n });\n localStorage.setItem(\"order\", JSON.stringify(order));\n };\n HomeComponent.prototype.onRemoveModel = function (args) {\n var el = args[0], source = args[1];\n // do something else\n };\n HomeComponent.prototype.onDrop = function (args) {\n var e = args[0], el = args[1];\n };\n HomeComponent.prototype.ngOnDestroy = function () {\n this.subscription.unsubscribe();\n };\n HomeComponent.prototype.refreshNotesTables = function () {\n var _this = this;\n this._notesService.getNotes().then(function (alldoc) {\n _this.notes_table = alldoc.rows;\n var testNotes = [];\n testNotes = _this.notes_table;\n if (localStorage.getItem('order')) {\n _this.order = JSON.parse(localStorage.getItem(\"order\"));\n }\n _this.notes = [];\n _this.order.forEach(function (el) {\n testNotes.forEach(function (row) {\n if (String(row.doc._id) === String(el)) {\n _this.notes.push(row);\n }\n });\n });\n if (_.isEmpty(_this.notes)) {\n _this.emptyHtmlMsg = true;\n }\n else {\n _this.emptyHtmlMsg = false;\n }\n _this.spinner = false;\n }, function (err) {\n _this.spinner = false;\n });\n };\n HomeComponent.prototype.saveNote = function (e, notetextarea) {\n var _this = this;\n if (_.trim(this.draft.title) || _.trim(this.draft.note)) {\n this.draft._id = 'note_' + Math.floor(Date.now() / 1000);\n this.draft.color = \"label-default\";\n this.draft.time = new Date().toISOString();\n this.draft.label = \"\";\n this.draft.restore = \"note\";\n this._notesService.saveNote(this.draft)\n .then(function (res) {\n notetextarea.placeholder = \"Write a note\";\n notetextarea.style.height = \"auto\";\n notetextarea.style.height = \"48px\";\n _this.updateOrder(_this.draft);\n _this.inputFocusClass = false;\n _this.draft = {};\n _this.refreshNotesTables();\n }, function (err) {\n _this.draft = {};\n console.log(\"Error\", err);\n notetextarea.placeholder = \"Write a note\";\n notetextarea.style.height = \"auto\";\n notetextarea.style.height = \"48px\";\n });\n }\n else {\n notetextarea.placeholder = \"Write a note\";\n notetextarea.style.height = \"auto\";\n notetextarea.style.height = \"48px\";\n notetextarea.value = null;\n this.inputFocusClass = false;\n }\n };\n HomeComponent.prototype.deleteNote = function (note, noteRow) {\n var _this = this;\n noteRow.className += this.displayList ? \" animated bounceOutRight\" : \" animated zoomOut\";\n setTimeout(function () {\n _this._notesService.deleteNote(note.doc)\n .then(function (res) {\n _this._notificationsService.create(\"Done\", \"Note moved to Recycle Bin\", \"success\");\n _this.deleteFromOrder(note);\n _this.refreshNotesTables();\n }, function (err) {\n console.log(\"Error\", err);\n });\n var binNote = note.doc;\n delete binNote._rev;\n _this._binService.saveNote(binNote)\n .then(function (res) {\n }, function (err) {\n console.log(\"Error\", err);\n });\n }, 200);\n };\n HomeComponent.prototype.setNoteColor = function (color, note) {\n var _this = this;\n if (note.doc.color != color) {\n note.doc.color = color;\n this._notesService.updateNote(note.doc)\n .then(function (res) {\n _this.refreshNotesTables();\n }, function (err) {\n console.log(\"Error\", err);\n });\n }\n };\n HomeComponent.prototype.updateModalNote = function (note) {\n var _this = this;\n note.doc.note = this.editNoteDraft.note;\n note.doc.title = this.editNoteDraft.title;\n this._notesService.updateNote(note.doc)\n .then(function (res) {\n _this.editNoteDraft = {};\n _this.refreshNotesTables();\n }, function (err) {\n _this.editNoteDraft = {};\n console.log(\"Error\", err);\n });\n };\n HomeComponent.prototype.editModalNoteClick = function (note) {\n this.editNoteDraft.title = note.doc.title;\n this.editNoteDraft.note = note.doc.note;\n };\n HomeComponent.prototype.makeArchive = function (note, noteRow) {\n var _this = this;\n noteRow.className += this.displayList ? \" animated bounceOutLeft\" : \" animated flipOutY\";\n setTimeout(function () {\n _this._notesService.deleteNote(note.doc)\n .then(function (res) {\n _this._notificationsService.create(\"Done\", \"Note archived\", \"success\");\n _this.deleteFromOrder(note);\n _this.refreshNotesTables();\n }, function (err) {\n console.log(\"Error\", err);\n });\n var archive_note = note;\n delete archive_note.doc._rev;\n archive_note.doc.restore = \"archive\";\n _this._archiveService.saveNote(archive_note.doc)\n .then(function (res) {\n _this.updateArchiveOrder(archive_note.doc);\n }, function (err) { });\n }, 200);\n };\n HomeComponent.prototype.displayTypeChange = function () {\n this.displayList = this.displayList ? false : true;\n localStorage.setItem(\"displayNotesTypeList\", String(this.displayList));\n };\n HomeComponent.prototype.deleteFromOrder = function (note) {\n var index = this.order.indexOf(this.order.filter(function (row) {\n return String(row) === String(note.doc._id);\n })[0]);\n if (index !== -1) {\n this.order.splice(index, 1);\n localStorage.setItem(\"order\", JSON.stringify(this.order));\n }\n };\n HomeComponent.prototype.updateOrder = function (draft) {\n var newOrder = [];\n if (localStorage.getItem('order')) {\n newOrder = JSON.parse(localStorage.getItem('order'));\n newOrder.unshift(draft._id);\n }\n else {\n newOrder.push(draft._id);\n }\n localStorage.setItem(\"order\", JSON.stringify(newOrder));\n };\n HomeComponent.prototype.updateArchiveOrder = function (draft) {\n var newArchiveOrder = [];\n if (localStorage.getItem('archiveOrder')) {\n newArchiveOrder = JSON.parse(localStorage.getItem('archiveOrder'));\n newArchiveOrder.unshift(draft._id);\n }\n else {\n newArchiveOrder.push(draft._id);\n }\n localStorage.setItem(\"archiveOrder\", JSON.stringify(newArchiveOrder));\n };\n HomeComponent = __decorate([\n core_1.Component({\n selector: 'Home',\n template: __webpack_require__(103)\n }), \n __metadata('design:paramtypes', [(typeof (_a = typeof dragula_1.DragulaService !== 'undefined' && dragula_1.DragulaService) === 'function' && _a) || Object, (typeof (_b = typeof notes_table_service_1.NotesTableService !== 'undefined' && notes_table_service_1.NotesTableService) === 'function' && _b) || Object, (typeof (_c = typeof archive_table_service_1.ArchiveNotesTableService !== 'undefined' && archive_table_service_1.ArchiveNotesTableService) === 'function' && _c) || Object, (typeof (_d = typeof bin_table_service_1.BinNotesTableService !== 'undefined' && bin_table_service_1.BinNotesTableService) === 'function' && _d) || Object, (typeof (_e = typeof angular2_notifications_1.NotificationsService !== 'undefined' && angular2_notifications_1.NotificationsService) === 'function' && _e) || Object])\n ], HomeComponent);\n return HomeComponent;\n var _a, _b, _c, _d, _e;\n}());\nexports.HomeComponent = HomeComponent;\nvar NOTES_TABLE = [];\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNjIuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvYXBwL2NvbXBvbmVudHMvaG9tZS9ob21lLmNvbXBvbmVudC50cz9iZDdlIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBOb3RpZmljYXRpb25zU2VydmljZSB9IGZyb20gXCJhbmd1bGFyMi1ub3RpZmljYXRpb25zXCI7XG5cbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMvU3Vic2NyaXB0aW9uJztcbmltcG9ydCAqIGFzIF8gZnJvbSAnbG9kYXNoJztcblxuaW1wb3J0IHsgRHJhZ3VsYVNlcnZpY2UgfSBmcm9tICcuLi8uLi9wcm92aWRlcnMvZHJhZ3VsYSc7XG5cbmltcG9ydCB7IE5vdGVzVGFibGUgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9ub3Rlc190YWJsZSc7XG5pbXBvcnQgeyBOb3Rlc1RhYmxlU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL25vdGVzX3RhYmxlLnNlcnZpY2UnO1xuaW1wb3J0IHsgQmluTm90ZXNUYWJsZVNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9iaW5fdGFibGUuc2VydmljZSc7XG5pbXBvcnQgeyBBcmNoaXZlTm90ZXNUYWJsZVNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9hcmNoaXZlX3RhYmxlLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdIb21lJyxcbiAgdGVtcGxhdGU6IHJlcXVpcmUoJy4vaG9tZS5jb21wb25lbnQuaHRtbCcpXG59KVxuZXhwb3J0IGNsYXNzIEhvbWVDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBwdWJsaWMgb3JkZXI6YW55O1xuICBwdWJsaWMgbm90ZXM6IGFueTtcbiAgcHVibGljIGRyYWZ0OiBhbnk7XG4gIHB1YmxpYyBvcmRlck5vdGVzOiBhbnk7XG4gIHB1YmxpYyBlZGl0Tm90ZURyYWZ0OiBhbnk7XG4gIHB1YmxpYyBub3RpZmljYXRpb25PcHRpb25zOiBhbnk7XG4gIHB1YmxpYyBzcGlubmVyOiBib29sZWFuID0gdHJ1ZTtcbiAgcHVibGljIGRpc3BsYXlMaXN0OiBib29sZWFuID0gZmFsc2U7XG4gIHB1YmxpYyBpbnB1dEZvY3VzQ2xhc3M6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBwdWJsaWMgbm90ZXNfdGFibGUgPSBOT1RFU19UQUJMRTtcbiAgcHVibGljIHN1YnNjcmlwdGlvbjpTdWJzY3JpcHRpb247XG4gIHB1YmxpYyBlbXB0eUh0bWxNc2c6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBjb25zdHJ1Y3RvciAoXG4gICAgICBwcml2YXRlIGRyYWd1bGFTZXJ2aWNlOiBEcmFndWxhU2VydmljZSxcbiAgICAgIHByaXZhdGUgX25vdGVzU2VydmljZTogTm90ZXNUYWJsZVNlcnZpY2UsXG4gICAgICBwcml2YXRlIF9hcmNoaXZlU2VydmljZTogQXJjaGl2ZU5vdGVzVGFibGVTZXJ2aWNlLFxuICAgICAgcHJpdmF0ZSBfYmluU2VydmljZTogQmluTm90ZXNUYWJsZVNlcnZpY2UsXG4gICAgICBwcml2YXRlIF9ub3RpZmljYXRpb25zU2VydmljZTogTm90aWZpY2F0aW9uc1NlcnZpY2VcbiAgICApIHtcbiAgICB0aGlzLm5vdGVzID0gW107XG4gICAgdGhpcy5kcmFmdCA9IHt9O1xuICAgIHRoaXMuZWRpdE5vdGVEcmFmdCA9IHt9O1xuICAgIHRoaXMub3JkZXIgPSBbXTtcbiAgICB0aGlzLm9yZGVyTm90ZXMgPSBbXTtcbiAgICB0aGlzLm5vdGlmaWNhdGlvbk9wdGlvbnMgPSB7XG4gICAgICB0aW1lT3V0OiAzMDAwLFxuICAgICAgbGFzdE9uQm90dG9tOiB0cnVlLFxuICAgICAgY2xpY2tUb0Nsb3NlOiB0cnVlLFxuICAgICAgc2hvd1Byb2dyZXNzQmFyOiBmYWxzZSxcbiAgICAgIHBhdXNlT25Ib3ZlcjogdHJ1ZSxcbiAgICAgIHByZXZlbnREdXBsaWNhdGVzOiBmYWxzZSxcbiAgICAgIHRoZUNsYXNzOiBcIm5vdGVzLW5vdGlmaWNhdGlvbnNcIixcbiAgICAgIHJ0bDogdHJ1ZVxuICAgIH07XG4gICAgZHJhZ3VsYVNlcnZpY2UuZHJhZy5zdWJzY3JpYmUoKHZhbHVlOiBhbnkpID0+IHtcbiAgICAgIHRoaXMub25EcmFnKHZhbHVlLnNsaWNlKDEpKTtcbiAgICB9KTtcbiAgICBkcmFndWxhU2VydmljZS5kcm9wTW9kZWwuc3Vic2NyaWJlKCh2YWx1ZTogYW55KSA9PiB7XG4gICAgICB0aGlzLm9uRHJvcE1vZGVsKHZhbHVlLnNsaWNlKDEpKTtcbiAgICB9KTtcbiAgICBkcmFndWxhU2VydmljZS5kcm9wLnN1YnNjcmliZSgodmFsdWU6IGFueSkgPT4ge1xuICAgICAgdGhpcy5vbkRyb3AodmFsdWUpO1xuICAgIH0pO1xuICAgIGRyYWd1bGFTZXJ2aWNlLnJlbW92ZU1vZGVsLnN1YnNjcmliZSgodmFsdWU6IGFueSkgPT4ge1xuICAgICAgdGhpcy5vblJlbW92ZU1vZGVsKHZhbHVlLnNsaWNlKDEpKTtcbiAgICB9KTtcblxuICAgIHRoaXMuZGlzcGxheUxpc3QgPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbShcImRpc3BsYXlOb3Rlc1R5cGVMaXN0XCIpID09ICd0cnVlJyA/IHRydWUgOiBmYWxzZTtcblxuICB9XG5cblxuICBwcml2YXRlIG9uRHJhZyhhcmdzOiBhbnkpIHtcbiAgICBsZXQgW2UsIGVsXSA9IGFyZ3M7XG4gIH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbiA9IHRoaXMuX25vdGVzU2VydmljZS5ub3Rlc190YWJsZXMkLnN1YnNjcmliZShcbiAgICAgIG5vdGVzX3RhYmxlID0+IHRoaXMubm90ZXNfdGFibGUgPSBub3Rlc190YWJsZVxuICAgICk7XG4gICAgdGhpcy5yZWZyZXNoTm90ZXNUYWJsZXMoKTtcbiAgfVxuXG4gIF9zZXRJbnB1dEZvY3VzKGlzRm9jdXM6Ym9vbGVhbikge1xuICAgIHRoaXMuaW5wdXRGb2N1c0NsYXNzID0gaXNGb2N1cztcbiAgfVxuXG4gIHByaXZhdGUgb25Ecm9wTW9kZWwoYXJnczogYW55KSB7XG4gICAgbGV0IFtlbCwgdGFyZ2V0LCBzb3VyY2VdID0gYXJncztcbiAgICAvLyBkbyBzb21ldGhpbmcgZWxzZVxuXG4gICAgbGV0IG9yZGVyID0gW107XG4gICAgdGhpcy5ub3Rlcy5mb3JFYWNoKHJvdyA9PiB7XG4gICAgICBvcmRlci5wdXNoKHJvdy5kb2MuX2lkKTtcbiAgICB9KTtcblxuICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKFwib3JkZXJcIiwgSlNPTi5zdHJpbmdpZnkob3JkZXIpKTtcbiAgfVxuXG4gIHByaXZhdGUgb25SZW1vdmVNb2RlbChhcmdzOiBhbnkpIHtcbiAgICBsZXQgW2VsLCBzb3VyY2VdID0gYXJncztcbiAgICAvLyBkbyBzb21ldGhpbmcgZWxzZVxuICB9XG5cbiAgcHJpdmF0ZSBvbkRyb3AoYXJnczogYW55KSB7XG4gICAgbGV0IFtlLCBlbF0gPSBhcmdzO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIHJlZnJlc2hOb3Rlc1RhYmxlcygpIHtcbiAgICB0aGlzLl9ub3Rlc1NlcnZpY2UuZ2V0Tm90ZXMoKS50aGVuKFxuICAgICAgYWxsZG9jID0+IHtcbiAgICAgICAgdGhpcy5ub3Rlc190YWJsZSA9IGFsbGRvYy5yb3dzO1xuICAgICAgICBsZXQgdGVzdE5vdGVzID0gW107XG4gICAgICAgIHRlc3ROb3RlcyA9IHRoaXMubm90ZXNfdGFibGU7XG4gICAgICAgIGlmIChsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnb3JkZXInKSkge1xuICAgICAgICAgIHRoaXMub3JkZXIgPSBKU09OLnBhcnNlKGxvY2FsU3RvcmFnZS5nZXRJdGVtKFwib3JkZXJcIikpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubm90ZXMgPSBbXTtcbiAgICAgICAgdGhpcy5vcmRlci5mb3JFYWNoKGVsID0+IHtcbiAgICAgICAgICB0ZXN0Tm90ZXMuZm9yRWFjaChyb3cgPT4ge1xuICAgICAgICAgICAgaWYgKFN0cmluZyhyb3cuZG9jLl9pZCkgPT09IFN0cmluZyhlbCkpIHtcbiAgICAgICAgICAgICAgdGhpcy5ub3Rlcy5wdXNoKHJvdyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoXy5pc0VtcHR5KHRoaXMubm90ZXMpKSB7XG4gICAgICAgICAgdGhpcy5lbXB0eUh0bWxNc2cgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuZW1wdHlIdG1sTXNnID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zcGlubmVyID0gZmFsc2U7XG4gICAgICB9LFxuICAgICAgZXJyID0+IHtcbiAgICAgICAgdGhpcy5zcGlubmVyID0gZmFsc2U7XG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIHNhdmVOb3RlKGU6IEV2ZW50LCBub3RldGV4dGFyZWE6IGFueSkge1xuICAgIGlmIChfLnRyaW0odGhpcy5kcmFmdC50aXRsZSkgfHwgXy50cmltKHRoaXMuZHJhZnQubm90ZSkpIHtcbiAgICAgIHRoaXMuZHJhZnQuX2lkID0gJ25vdGVfJyArIE1hdGguZmxvb3IoRGF0ZS5ub3coKSAvIDEwMDApO1xuICAgICAgdGhpcy5kcmFmdC5jb2xvciA9IFwibGFiZWwtZGVmYXVsdFwiO1xuICAgICAgdGhpcy5kcmFmdC50aW1lID0gbmV3IERhdGUoKS50b0lTT1N0cmluZygpO1xuICAgICAgdGhpcy5kcmFmdC5sYWJlbCA9IFwiXCI7XG4gICAgICB0aGlzLmRyYWZ0LnJlc3RvcmUgPSBcIm5vdGVcIjtcbiAgICAgIHRoaXMuX25vdGVzU2VydmljZS5zYXZlTm90ZSh0aGlzLmRyYWZ0KVxuICAgICAgICAudGhlbihyZXMgPT4ge1xuICAgICAgICAgIG5vdGV0ZXh0YXJlYS5wbGFjZWhvbGRlciA9IFwiV3JpdGUgYSBub3RlXCI7XG4gICAgICAgICAgbm90ZXRleHRhcmVhLnN0eWxlLmhlaWdodCA9IFwiYXV0b1wiO1xuICAgICAgICAgIG5vdGV0ZXh0YXJlYS5zdHlsZS5oZWlnaHQgPSBcIjQ4cHhcIjtcbiAgICAgICAgICB0aGlzLnVwZGF0ZU9yZGVyKHRoaXMuZHJhZnQpO1xuICAgICAgICAgIHRoaXMuaW5wdXRGb2N1c0NsYXNzID0gZmFsc2U7XG4gICAgICAgICAgdGhpcy5kcmFmdCA9IHt9O1xuICAgICAgICAgIHRoaXMucmVmcmVzaE5vdGVzVGFibGVzKCk7XG4gICAgICAgIH0sIGVyciA9PiB7XG4gICAgICAgICAgdGhpcy5kcmFmdCA9IHt9O1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiRXJyb3JcIiwgZXJyKTtcbiAgICAgICAgICBub3RldGV4dGFyZWEucGxhY2Vob2xkZXIgPSBcIldyaXRlIGEgbm90ZVwiO1xuICAgICAgICAgIG5vdGV0ZXh0YXJlYS5zdHlsZS5oZWlnaHQgPSBcImF1dG9cIjtcbiAgICAgICAgICBub3RldGV4dGFyZWEuc3R5bGUuaGVpZ2h0ID0gXCI0OHB4XCI7XG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBub3RldGV4dGFyZWEucGxhY2Vob2xkZXIgPSBcIldyaXRlIGEgbm90ZVwiO1xuICAgICAgbm90ZXRleHRhcmVhLnN0eWxlLmhlaWdodCA9IFwiYXV0b1wiO1xuICAgICAgbm90ZXRleHRhcmVhLnN0eWxlLmhlaWdodCA9IFwiNDhweFwiO1xuICAgICAgbm90ZXRleHRhcmVhLnZhbHVlID0gbnVsbDtcbiAgICAgIHRoaXMuaW5wdXRGb2N1c0NsYXNzID0gZmFsc2U7XG4gICAgfVxuXG5cbiAgfVxuXG4gIGRlbGV0ZU5vdGUobm90ZSwgbm90ZVJvdykge1xuICAgIG5vdGVSb3cuY2xhc3NOYW1lICs9IHRoaXMuZGlzcGxheUxpc3QgPyBcIiBhbmltYXRlZCBib3VuY2VPdXRSaWdodFwiIDogXCIgYW5pbWF0ZWQgem9vbU91dFwiO1xuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5fbm90ZXNTZXJ2aWNlLmRlbGV0ZU5vdGUobm90ZS5kb2MpXG4gICAgICAgIC50aGVuKHJlcyA9PiB7XG4gICAgICAgICAgdGhpcy5fbm90aWZpY2F0aW9uc1NlcnZpY2UuY3JlYXRlKFwiRG9uZVwiLCBcIk5vdGUgbW92ZWQgdG8gUmVjeWNsZSBCaW5cIiwgXCJzdWNjZXNzXCIpO1xuICAgICAgICAgIHRoaXMuZGVsZXRlRnJvbU9yZGVyKG5vdGUpO1xuICAgICAgICAgIHRoaXMucmVmcmVzaE5vdGVzVGFibGVzKCk7XG4gICAgICAgIH0sIGVyciA9PiB7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJFcnJvclwiLCBlcnIpO1xuICAgICAgICB9KTtcbiAgICAgIGxldCBiaW5Ob3RlID0gbm90ZS5kb2M7XG4gICAgICBkZWxldGUgYmluTm90ZS5fcmV2O1xuICAgICAgdGhpcy5fYmluU2VydmljZS5zYXZlTm90ZShiaW5Ob3RlKVxuICAgICAgICAudGhlbihyZXMgPT4ge1xuXG4gICAgICAgIH0sIGVyciA9PiB7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJFcnJvclwiLCBlcnIpO1xuICAgICAgICB9KTtcbiAgICB9LCAyMDApO1xuICB9XG5cbiAgc2V0Tm90ZUNvbG9yKGNvbG9yLCBub3RlKSB7XG4gICAgaWYgKG5vdGUuZG9jLmNvbG9yICE9IGNvbG9yKSB7XG4gICAgICBub3RlLmRvYy5jb2xvciA9IGNvbG9yO1xuICAgICAgdGhpcy5fbm90ZXNTZXJ2aWNlLnVwZGF0ZU5vdGUobm90ZS5kb2MpXG4gICAgICAgIC50aGVuKHJlcyA9PiB7XG4gICAgICAgICAgdGhpcy5yZWZyZXNoTm90ZXNUYWJsZXMoKTtcbiAgICAgICAgfSwgZXJyID0+IHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkVycm9yXCIsIGVycik7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHVwZGF0ZU1vZGFsTm90ZShub3RlKSB7XG4gICAgbm90ZS5kb2Mubm90ZSA9IHRoaXMuZWRpdE5vdGVEcmFmdC5ub3RlO1xuICAgIG5vdGUuZG9jLnRpdGxlID0gdGhpcy5lZGl0Tm90ZURyYWZ0LnRpdGxlO1xuICAgIHRoaXMuX25vdGVzU2VydmljZS51cGRhdGVOb3RlKG5vdGUuZG9jKVxuICAgICAgLnRoZW4ocmVzID0+IHtcbiAgICAgICAgdGhpcy5lZGl0Tm90ZURyYWZ0ID0ge307XG4gICAgICAgIHRoaXMucmVmcmVzaE5vdGVzVGFibGVzKCk7XG4gICAgICB9LCBlcnIgPT4ge1xuICAgICAgICB0aGlzLmVkaXROb3RlRHJhZnQgPSB7fTtcbiAgICAgICAgY29uc29sZS5sb2coXCJFcnJvclwiLCBlcnIpO1xuICAgICAgfSk7XG4gIH1cblxuICBlZGl0TW9kYWxOb3RlQ2xpY2sobm90ZSkge1xuICAgIHRoaXMuZWRpdE5vdGVEcmFmdC50aXRsZSA9IG5vdGUuZG9jLnRpdGxlO1xuICAgIHRoaXMuZWRpdE5vdGVEcmFmdC5ub3RlID0gbm90ZS5kb2Mubm90ZTtcbiAgfVxuXG4gIG1ha2VBcmNoaXZlKG5vdGUsIG5vdGVSb3cpIHtcbiAgICBub3RlUm93LmNsYXNzTmFtZSArPSB0aGlzLmRpc3BsYXlMaXN0ID8gXCIgYW5pbWF0ZWQgYm91bmNlT3V0TGVmdFwiIDogXCIgYW5pbWF0ZWQgZmxpcE91dFlcIjtcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMuX25vdGVzU2VydmljZS5kZWxldGVOb3RlKG5vdGUuZG9jKVxuICAgICAgICAudGhlbihyZXMgPT4ge1xuICAgICAgICAgIHRoaXMuX25vdGlmaWNhdGlvbnNTZXJ2aWNlLmNyZWF0ZShcIkRvbmVcIiwgXCJOb3RlIGFyY2hpdmVkXCIsIFwic3VjY2Vzc1wiKTtcbiAgICAgICAgICB0aGlzLmRlbGV0ZUZyb21PcmRlcihub3RlKTtcbiAgICAgICAgICB0aGlzLnJlZnJlc2hOb3Rlc1RhYmxlcygpO1xuICAgICAgICB9LCBlcnIgPT4ge1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiRXJyb3JcIiwgZXJyKTtcbiAgICAgICAgfSk7XG4gICAgICBsZXQgYXJjaGl2ZV9ub3RlID0gbm90ZTtcbiAgICAgIGRlbGV0ZSBhcmNoaXZlX25vdGUuZG9jLl9yZXY7XG4gICAgICBhcmNoaXZlX25vdGUuZG9jLnJlc3RvcmUgPSBcImFyY2hpdmVcIjtcbiAgICAgIHRoaXMuX2FyY2hpdmVTZXJ2aWNlLnNhdmVOb3RlKGFyY2hpdmVfbm90ZS5kb2MpXG4gICAgICAgIC50aGVuKHJlcyA9PiB7XG4gICAgICAgICAgdGhpcy51cGRhdGVBcmNoaXZlT3JkZXIoYXJjaGl2ZV9ub3RlLmRvYyk7XG4gICAgICAgIH0sIGVyciA9PiB7fSk7XG4gICAgfSwgMjAwKTtcbiAgfVxuXG4gIGRpc3BsYXlUeXBlQ2hhbmdlKCkge1xuICAgIHRoaXMuZGlzcGxheUxpc3QgPSB0aGlzLmRpc3BsYXlMaXN0ID8gZmFsc2UgOiB0cnVlO1xuICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKFwiZGlzcGxheU5vdGVzVHlwZUxpc3RcIiwgU3RyaW5nKHRoaXMuZGlzcGxheUxpc3QpKTtcbiAgfVxuXG4gIGRlbGV0ZUZyb21PcmRlcihub3RlKSB7XG4gICAgbGV0IGluZGV4ID0gdGhpcy5vcmRlci5pbmRleE9mKHRoaXMub3JkZXIuZmlsdGVyKHJvdyA9PiB7XG4gICAgICByZXR1cm4gU3RyaW5nKHJvdykgPT09IFN0cmluZyhub3RlLmRvYy5faWQpO1xuICAgIH0pWzBdKTtcbiAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICB0aGlzLm9yZGVyLnNwbGljZShpbmRleCwgMSk7XG4gICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShcIm9yZGVyXCIsIEpTT04uc3RyaW5naWZ5KHRoaXMub3JkZXIpKTtcbiAgICB9XG4gIH1cblxuICB1cGRhdGVPcmRlcihkcmFmdCkge1xuICAgIGxldCBuZXdPcmRlciA9IFtdO1xuICAgIGlmIChsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnb3JkZXInKSkge1xuICAgICAgbmV3T3JkZXIgPSBKU09OLnBhcnNlKGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdvcmRlcicpKTtcbiAgICAgIG5ld09yZGVyLnVuc2hpZnQoZHJhZnQuX2lkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3T3JkZXIucHVzaChkcmFmdC5faWQpO1xuICAgIH1cbiAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShcIm9yZGVyXCIsIEpTT04uc3RyaW5naWZ5KG5ld09yZGVyKSk7XG4gIH1cblxuICB1cGRhdGVBcmNoaXZlT3JkZXIoZHJhZnQ6IGFueSkge1xuICAgIGxldCBuZXdBcmNoaXZlT3JkZXIgPSBbXTtcbiAgICBpZiAobG9jYWxTdG9yYWdlLmdldEl0ZW0oJ2FyY2hpdmVPcmRlcicpKSB7XG4gICAgICBuZXdBcmNoaXZlT3JkZXIgPSBKU09OLnBhcnNlKGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdhcmNoaXZlT3JkZXInKSk7XG4gICAgICBuZXdBcmNoaXZlT3JkZXIudW5zaGlmdChkcmFmdC5faWQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdBcmNoaXZlT3JkZXIucHVzaChkcmFmdC5faWQpO1xuICAgIH1cbiAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShcImFyY2hpdmVPcmRlclwiLCBKU09OLnN0cmluZ2lmeShuZXdBcmNoaXZlT3JkZXIpKTtcbiAgfVxufVxuXG5sZXQgTk9URVNfVEFCTEU6IE5vdGVzVGFibGVbXSA9IFtdXG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gbm9kZV9tb2R1bGVzL2FuZ3VsYXIyLXRlbXBsYXRlLWxvYWRlciEuL3NyYy9hcHAvY29tcG9uZW50cy9ob21lL2hvbWUuY29tcG9uZW50LnRzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUdBO0FBRUE7QUFHQTtBQUNBO0FBQ0E7QUFNQTtBQWVBO0FBZkE7QUFnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQWJBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBR0E7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQUNBO0FBR0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFFQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFFQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQS9RQTtBQUFBO0FBQ0E7QUFDQTtBQUNBOztBQUFBO0FBNlFBOztBQUFBO0FBNVFBO0FBOFFBOyIsInNvdXJjZVJvb3QiOiIifQ==");
- /***/ },
- /* 63 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\r\nvar simple_notifications_module_1 = __webpack_require__(64);\r\nexports.SimpleNotificationsModule = simple_notifications_module_1.SimpleNotificationsModule;\r\nvar simple_notifications_component_1 = __webpack_require__(67);\r\nexports.SimpleNotificationsComponent = simple_notifications_component_1.SimpleNotificationsComponent;\r\nvar notification_component_1 = __webpack_require__(69);\r\nexports.NotificationComponent = notification_component_1.NotificationComponent;\r\nvar notifications_service_1 = __webpack_require__(65);\r\nexports.NotificationsService = notifications_service_1.NotificationsService;\r\nvar max_pipe_1 = __webpack_require__(71);\r\nexports.MaxPipe = max_pipe_1.MaxPipe;\r\nvar push_notifications_module_1 = __webpack_require__(72);\r\nexports.PushNotificationsModule = push_notifications_module_1.PushNotificationsModule;\r\nvar push_notifications_service_1 = __webpack_require__(73);\r\nexports.PushNotificationsService = push_notifications_service_1.PushNotificationsService;\r\n//# sourceMappingURL=components.js.map//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNjMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2FuZ3VsYXIyLW5vdGlmaWNhdGlvbnMvY29tcG9uZW50cy5qcz81Y2Q4Il0sInNvdXJjZXNDb250ZW50IjpbIlwidXNlIHN0cmljdFwiO1xyXG52YXIgc2ltcGxlX25vdGlmaWNhdGlvbnNfbW9kdWxlXzEgPSByZXF1aXJlKCcuL3NyYy9zaW1wbGUtbm90aWZpY2F0aW9ucy5tb2R1bGUnKTtcclxuZXhwb3J0cy5TaW1wbGVOb3RpZmljYXRpb25zTW9kdWxlID0gc2ltcGxlX25vdGlmaWNhdGlvbnNfbW9kdWxlXzEuU2ltcGxlTm90aWZpY2F0aW9uc01vZHVsZTtcclxudmFyIHNpbXBsZV9ub3RpZmljYXRpb25zX2NvbXBvbmVudF8xID0gcmVxdWlyZSgnLi9zcmMvc2ltcGxlLW5vdGlmaWNhdGlvbnMuY29tcG9uZW50Jyk7XHJcbmV4cG9ydHMuU2ltcGxlTm90aWZpY2F0aW9uc0NvbXBvbmVudCA9IHNpbXBsZV9ub3RpZmljYXRpb25zX2NvbXBvbmVudF8xLlNpbXBsZU5vdGlmaWNhdGlvbnNDb21wb25lbnQ7XHJcbnZhciBub3RpZmljYXRpb25fY29tcG9uZW50XzEgPSByZXF1aXJlKCcuL3NyYy9ub3RpZmljYXRpb24uY29tcG9uZW50Jyk7XHJcbmV4cG9ydHMuTm90aWZpY2F0aW9uQ29tcG9uZW50ID0gbm90aWZpY2F0aW9uX2NvbXBvbmVudF8xLk5vdGlmaWNhdGlvbkNvbXBvbmVudDtcclxudmFyIG5vdGlmaWNhdGlvbnNfc2VydmljZV8xID0gcmVxdWlyZSgnLi9zcmMvbm90aWZpY2F0aW9ucy5zZXJ2aWNlJyk7XHJcbmV4cG9ydHMuTm90aWZpY2F0aW9uc1NlcnZpY2UgPSBub3RpZmljYXRpb25zX3NlcnZpY2VfMS5Ob3RpZmljYXRpb25zU2VydmljZTtcclxudmFyIG1heF9waXBlXzEgPSByZXF1aXJlKCcuL3NyYy9tYXgucGlwZScpO1xyXG5leHBvcnRzLk1heFBpcGUgPSBtYXhfcGlwZV8xLk1heFBpcGU7XHJcbnZhciBwdXNoX25vdGlmaWNhdGlvbnNfbW9kdWxlXzEgPSByZXF1aXJlKCcuL3NyYy9wdXNoLW5vdGlmaWNhdGlvbnMubW9kdWxlJyk7XHJcbmV4cG9ydHMuUHVzaE5vdGlmaWNhdGlvbnNNb2R1bGUgPSBwdXNoX25vdGlmaWNhdGlvbnNfbW9kdWxlXzEuUHVzaE5vdGlmaWNhdGlvbnNNb2R1bGU7XHJcbnZhciBwdXNoX25vdGlmaWNhdGlvbnNfc2VydmljZV8xID0gcmVxdWlyZSgnLi9zcmMvcHVzaC1ub3RpZmljYXRpb25zLnNlcnZpY2UnKTtcclxuZXhwb3J0cy5QdXNoTm90aWZpY2F0aW9uc1NlcnZpY2UgPSBwdXNoX25vdGlmaWNhdGlvbnNfc2VydmljZV8xLlB1c2hOb3RpZmljYXRpb25zU2VydmljZTtcclxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y29tcG9uZW50cy5qcy5tYXBcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vYW5ndWxhcjItbm90aWZpY2F0aW9ucy9jb21wb25lbnRzLmpzXG4vLyBtb2R1bGUgaWQgPSA2M1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 64 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar core_1 = __webpack_require__(4);\nvar common_1 = __webpack_require__(23);\nvar notifications_service_1 = __webpack_require__(65);\nvar simple_notifications_component_1 = __webpack_require__(67);\nvar notification_component_1 = __webpack_require__(69);\nvar max_pipe_1 = __webpack_require__(71);\nvar SimpleNotificationsModule = (function () {\n function SimpleNotificationsModule() {\n }\n SimpleNotificationsModule = __decorate([\n core_1.NgModule({\n imports: [common_1.CommonModule],\n declarations: [simple_notifications_component_1.SimpleNotificationsComponent, notification_component_1.NotificationComponent, max_pipe_1.MaxPipe],\n providers: [notifications_service_1.NotificationsService],\n exports: [simple_notifications_component_1.SimpleNotificationsComponent]\n }), \n __metadata('design:paramtypes', [])\n ], SimpleNotificationsModule);\n return SimpleNotificationsModule;\n}());\nexports.SimpleNotificationsModule = SimpleNotificationsModule;\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNjQuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2FuZ3VsYXIyLW5vdGlmaWNhdGlvbnMvc3JjL3NpbXBsZS1ub3RpZmljYXRpb25zLm1vZHVsZS50cz9kOTJlIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7TmdNb2R1bGV9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQge0NvbW1vbk1vZHVsZX0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcclxuaW1wb3J0IHtOb3RpZmljYXRpb25zU2VydmljZX0gZnJvbSAnLi9ub3RpZmljYXRpb25zLnNlcnZpY2UnO1xyXG5pbXBvcnQge1NpbXBsZU5vdGlmaWNhdGlvbnNDb21wb25lbnR9IGZyb20gJy4vc2ltcGxlLW5vdGlmaWNhdGlvbnMuY29tcG9uZW50JztcclxuaW1wb3J0IHtOb3RpZmljYXRpb25Db21wb25lbnR9IGZyb20gJy4vbm90aWZpY2F0aW9uLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7TWF4UGlwZX0gZnJvbSAnLi9tYXgucGlwZSc7XHJcblxyXG5ATmdNb2R1bGUoe1xyXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGVdLFxyXG4gIGRlY2xhcmF0aW9uczogW1NpbXBsZU5vdGlmaWNhdGlvbnNDb21wb25lbnQsIE5vdGlmaWNhdGlvbkNvbXBvbmVudCwgTWF4UGlwZV0sXHJcbiAgcHJvdmlkZXJzOiBbTm90aWZpY2F0aW9uc1NlcnZpY2VdLFxyXG4gIGV4cG9ydHM6IFtTaW1wbGVOb3RpZmljYXRpb25zQ29tcG9uZW50XVxyXG59KVxyXG5leHBvcnQgY2xhc3MgU2ltcGxlTm90aWZpY2F0aW9uc01vZHVsZSB7XHJcbn1cclxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIG5vZGVfbW9kdWxlcy9hbmd1bGFyMi10ZW1wbGF0ZS1sb2FkZXIhLi9+L2FuZ3VsYXIyLW5vdGlmaWNhdGlvbnMvc3JjL3NpbXBsZS1ub3RpZmljYXRpb25zLm1vZHVsZS50cyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVFBO0FBQUE7QUFDQTtBQVBBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUFBO0FBRUE7QUFBQTtBQURBOyIsInNvdXJjZVJvb3QiOiIifQ==");
- /***/ },
- /* 65 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar core_1 = __webpack_require__(4);\nvar Subject_1 = __webpack_require__(5);\nvar icons_1 = __webpack_require__(66);\nvar NotificationsService = (function () {\n function NotificationsService() {\n this.emitter = new Subject_1.Subject();\n this.icons = icons_1.defaultIcons;\n }\n NotificationsService.prototype.set = function (notification, to) {\n notification.id = notification.override && notification.override.id ? notification.override.id : Math.random().toString(36).substring(3);\n notification.click = new core_1.EventEmitter();\n this.emitter.next({ command: 'set', notification: notification, add: to });\n return notification;\n };\n ;\n NotificationsService.prototype.getChangeEmitter = function () {\n return this.emitter;\n };\n //// Access methods\n NotificationsService.prototype.success = function (title, content, override) {\n return this.set({\n title: title,\n content: content,\n type: 'success',\n icon: this.icons.success,\n override: override\n }, true);\n };\n NotificationsService.prototype.error = function (title, content, override) {\n return this.set({ title: title, content: content, type: 'error', icon: this.icons.error, override: override }, true);\n };\n NotificationsService.prototype.alert = function (title, content, override) {\n return this.set({ title: title, content: content, type: 'alert', icon: this.icons.alert, override: override }, true);\n };\n NotificationsService.prototype.info = function (title, content, override) {\n return this.set({ title: title, content: content, type: 'info', icon: this.icons.info, override: override }, true);\n };\n NotificationsService.prototype.bare = function (title, content, override) {\n return this.set({ title: title, content: content, type: 'bare', icon: 'bare', override: override }, true);\n };\n // With type method\n NotificationsService.prototype.create = function (title, content, type, override) {\n return this.set({ title: title, content: content, type: type, icon: 'bare', override: override }, true);\n };\n // HTML Notification method\n NotificationsService.prototype.html = function (html, type, override) {\n return this.set({ html: html, type: type, icon: 'bare', override: override, title: null, content: null }, true);\n };\n // Remove all notifications method\n NotificationsService.prototype.remove = function (id) {\n if (id)\n this.emitter.next({ command: 'clean', id: id });\n else\n this.emitter.next({ command: 'cleanAll' });\n };\n NotificationsService = __decorate([\n core_1.Injectable(), \n __metadata('design:paramtypes', [])\n ], NotificationsService);\n return NotificationsService;\n}());\nexports.NotificationsService = NotificationsService;\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNjUuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2FuZ3VsYXIyLW5vdGlmaWNhdGlvbnMvc3JjL25vdGlmaWNhdGlvbnMuc2VydmljZS50cz85MjY2Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7SW5qZWN0YWJsZSwgRXZlbnRFbWl0dGVyfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHtTdWJqZWN0fSBmcm9tICdyeGpzL1N1YmplY3QnO1xyXG5pbXBvcnQge05vdGlmaWNhdGlvbkV2ZW50fSBmcm9tICcuL25vdGlmaWNhdGlvbi1ldmVudC50eXBlJztcclxuaW1wb3J0IHtOb3RpZmljYXRpb259IGZyb20gJy4vbm90aWZpY2F0aW9uLnR5cGUnO1xyXG5pbXBvcnQge0ljb25zLCBkZWZhdWx0SWNvbnN9IGZyb20gJy4vaWNvbnMnO1xyXG5cclxuQEluamVjdGFibGUoKVxyXG5leHBvcnQgY2xhc3MgTm90aWZpY2F0aW9uc1NlcnZpY2Uge1xyXG5cclxuICBwcml2YXRlIGVtaXR0ZXI6IFN1YmplY3Q8Tm90aWZpY2F0aW9uRXZlbnQ+ID0gbmV3IFN1YmplY3Q8Tm90aWZpY2F0aW9uRXZlbnQ+KCk7XHJcbiAgcHJpdmF0ZSBpY29uczogSWNvbnMgPSBkZWZhdWx0SWNvbnM7XHJcblxyXG4gIHNldChub3RpZmljYXRpb246IE5vdGlmaWNhdGlvbiwgdG86IGJvb2xlYW4pIHtcclxuICAgIG5vdGlmaWNhdGlvbi5pZCA9IG5vdGlmaWNhdGlvbi5vdmVycmlkZSAmJiBub3RpZmljYXRpb24ub3ZlcnJpZGUuaWQgPyBub3RpZmljYXRpb24ub3ZlcnJpZGUuaWQgOiBNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zdWJzdHJpbmcoMyk7XHJcbiAgICBub3RpZmljYXRpb24uY2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyPHt9PigpO1xyXG4gICAgdGhpcy5lbWl0dGVyLm5leHQoe2NvbW1hbmQ6ICdzZXQnLCBub3RpZmljYXRpb246IG5vdGlmaWNhdGlvbiwgYWRkOiB0b30pO1xyXG4gICAgcmV0dXJuIG5vdGlmaWNhdGlvbjtcclxuICB9O1xyXG5cclxuICBnZXRDaGFuZ2VFbWl0dGVyKCkge1xyXG4gICAgcmV0dXJuIHRoaXMuZW1pdHRlcjtcclxuICB9XHJcblxyXG4gIC8vLy8gQWNjZXNzIG1ldGhvZHNcclxuICBzdWNjZXNzKHRpdGxlOiBzdHJpbmcsIGNvbnRlbnQ6IHN0cmluZywgb3ZlcnJpZGU/OiBhbnkpIHtcclxuICAgIHJldHVybiB0aGlzLnNldCh7XHJcbiAgICAgIHRpdGxlOiB0aXRsZSxcclxuICAgICAgY29udGVudDogY29udGVudCxcclxuICAgICAgdHlwZTogJ3N1Y2Nlc3MnLFxyXG4gICAgICBpY29uOiB0aGlzLmljb25zLnN1Y2Nlc3MsXHJcbiAgICAgIG92ZXJyaWRlOiBvdmVycmlkZVxyXG4gICAgfSwgdHJ1ZSk7XHJcbiAgfVxyXG5cclxuICBlcnJvcih0aXRsZTogc3RyaW5nLCBjb250ZW50OiBzdHJpbmcsIG92ZXJyaWRlPzogYW55KSB7XHJcbiAgICByZXR1cm4gdGhpcy5zZXQoe3RpdGxlOiB0aXRsZSwgY29udGVudDogY29udGVudCwgdHlwZTogJ2Vycm9yJywgaWNvbjogdGhpcy5pY29ucy5lcnJvciwgb3ZlcnJpZGU6IG92ZXJyaWRlfSwgdHJ1ZSk7XHJcbiAgfVxyXG5cclxuICBhbGVydCh0aXRsZTogc3RyaW5nLCBjb250ZW50OiBzdHJpbmcsIG92ZXJyaWRlPzogYW55KSB7XHJcbiAgICByZXR1cm4gdGhpcy5zZXQoe3RpdGxlOiB0aXRsZSwgY29udGVudDogY29udGVudCwgdHlwZTogJ2FsZXJ0JywgaWNvbjogdGhpcy5pY29ucy5hbGVydCwgb3ZlcnJpZGU6IG92ZXJyaWRlfSwgdHJ1ZSk7XHJcbiAgfVxyXG5cclxuICBpbmZvKHRpdGxlOiBzdHJpbmcsIGNvbnRlbnQ6IHN0cmluZywgb3ZlcnJpZGU/OiBhbnkpIHtcclxuICAgIHJldHVybiB0aGlzLnNldCh7dGl0bGU6IHRpdGxlLCBjb250ZW50OiBjb250ZW50LCB0eXBlOiAnaW5mbycsIGljb246IHRoaXMuaWNvbnMuaW5mbywgb3ZlcnJpZGU6IG92ZXJyaWRlfSwgdHJ1ZSk7XHJcbiAgfVxyXG5cclxuICBiYXJlKHRpdGxlOiBzdHJpbmcsIGNvbnRlbnQ6IHN0cmluZywgb3ZlcnJpZGU/OiBhbnkpIHtcclxuICAgIHJldHVybiB0aGlzLnNldCh7dGl0bGU6IHRpdGxlLCBjb250ZW50OiBjb250ZW50LCB0eXBlOiAnYmFyZScsIGljb246ICdiYXJlJywgb3ZlcnJpZGU6IG92ZXJyaWRlfSwgdHJ1ZSk7XHJcbiAgfVxyXG5cclxuICAvLyBXaXRoIHR5cGUgbWV0aG9kXHJcbiAgY3JlYXRlKHRpdGxlOiBzdHJpbmcsIGNvbnRlbnQ6IHN0cmluZywgdHlwZTogc3RyaW5nLCBvdmVycmlkZT86IGFueSkge1xyXG4gICAgcmV0dXJuIHRoaXMuc2V0KHt0aXRsZTogdGl0bGUsIGNvbnRlbnQ6IGNvbnRlbnQsIHR5cGU6IHR5cGUsIGljb246ICdiYXJlJywgb3ZlcnJpZGU6IG92ZXJyaWRlfSwgdHJ1ZSk7XHJcbiAgfVxyXG5cclxuICAvLyBIVE1MIE5vdGlmaWNhdGlvbiBtZXRob2RcclxuICBodG1sKGh0bWw6IGFueSwgdHlwZTogc3RyaW5nLCBvdmVycmlkZT86IGFueSkge1xyXG4gICAgcmV0dXJuIHRoaXMuc2V0KHtodG1sOiBodG1sLCB0eXBlOiB0eXBlLCBpY29uOiAnYmFyZScsIG92ZXJyaWRlOiBvdmVycmlkZSwgdGl0bGU6IG51bGwsIGNvbnRlbnQ6IG51bGx9LCB0cnVlKTtcclxuICB9XHJcblxyXG4gIC8vIFJlbW92ZSBhbGwgbm90aWZpY2F0aW9ucyBtZXRob2RcclxuICByZW1vdmUoaWQ/OiBzdHJpbmcpIHtcclxuICAgIGlmIChpZCkgdGhpcy5lbWl0dGVyLm5leHQoe2NvbW1hbmQ6ICdjbGVhbicsIGlkOiBpZH0pO1xyXG4gICAgZWxzZSB0aGlzLmVtaXR0ZXIubmV4dCh7Y29tbWFuZDogJ2NsZWFuQWxsJ30pO1xyXG4gIH1cclxuXHJcbn1cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gbm9kZV9tb2R1bGVzL2FuZ3VsYXIyLXRlbXBsYXRlLWxvYWRlciEuL34vYW5ndWxhcjItbm90aWZpY2F0aW9ucy9zcmMvbm90aWZpY2F0aW9ucy5zZXJ2aWNlLnRzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUdBO0FBR0E7QUFBQTtBQUVBO0FBQ0E7QUF3REE7QUF0REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBMURBO0FBQUE7O0FBQUE7QUE0REE7QUFBQTtBQTNEQTsiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ },
- /* 66 */
- /***/ function(module, exports) {
- eval("\"use strict\";\nexports.defaultIcons = {\n alert: \"\\n <svg class=\\\"simple-notification-svg\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"#000000\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" width=\\\"24\\\">\\n <path d=\\\"M0 0h24v24H0z\\\" fill=\\\"none\\\"/>\\n <path d=\\\"M22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM12.5 8H11v6l4.75 2.85.75-1.23-4-2.37V8zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z\\\"/>\\n </svg>\",\n error: \"\\n <svg class=\\\"simple-notification-svg\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"#000000\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" width=\\\"24\\\">\\n <path d=\\\"M0 0h24v24H0V0z\\\" fill=\\\"none\\\"/>\\n <path d=\\\"M11 15h2v2h-2zm0-8h2v6h-2zm.99-5C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z\\\"/>\\n </svg>\\n \",\n info: \"\\n <svg class=\\\"simple-notification-svg\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"#000000\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" width=\\\"24\\\">\\n <path d=\\\"M0 0h24v24H0z\\\" fill=\\\"none\\\"/>\\n <path d=\\\"M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 9h2V7h-2v2z\\\"/>\\n </svg>\\n \",\n success: \"\\n <svg class=\\\"simple-notification-svg\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"#000000\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" width=\\\"24\\\">\\n <path d=\\\"M0 0h24v24H0z\\\" fill=\\\"none\\\"/>\\n <path d=\\\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z\\\"/>\\n </svg>\\n \"\n};\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNjYuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2FuZ3VsYXIyLW5vdGlmaWNhdGlvbnMvc3JjL2ljb25zLnRzPzMwODUiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGludGVyZmFjZSBJY29ucyB7XHJcbiAgYWxlcnQ6IHN0cmluZztcclxuICBlcnJvcjogc3RyaW5nO1xyXG4gIGluZm86IHN0cmluZztcclxuICBzdWNjZXNzOiBzdHJpbmc7XHJcbn1cclxuXHJcbmV4cG9ydCBjb25zdCBkZWZhdWx0SWNvbnM6IEljb25zID0ge1xyXG4gIGFsZXJ0OiBgXHJcbiAgICAgICAgPHN2ZyBjbGFzcz1cInNpbXBsZS1ub3RpZmljYXRpb24tc3ZnXCIgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIGZpbGw9XCIjMDAwMDAwXCIgaGVpZ2h0PVwiMjRcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCIgd2lkdGg9XCIyNFwiPlxyXG4gICAgICAgICAgICA8cGF0aCBkPVwiTTAgMGgyNHYyNEgwelwiIGZpbGw9XCJub25lXCIvPlxyXG4gICAgICAgICAgICA8cGF0aCBkPVwiTTIyIDUuNzJsLTQuNi0zLjg2LTEuMjkgMS41MyA0LjYgMy44NkwyMiA1Ljcyek03Ljg4IDMuMzlMNi42IDEuODYgMiA1LjcxbDEuMjkgMS41MyA0LjU5LTMuODV6TTEyLjUgOEgxMXY2bDQuNzUgMi44NS43NS0xLjIzLTQtMi4zN1Y4ek0xMiA0Yy00Ljk3IDAtOSA0LjAzLTkgOXM0LjAyIDkgOSA5YzQuOTcgMCA5LTQuMDMgOS05cy00LjAzLTktOS05em0wIDE2Yy0zLjg3IDAtNy0zLjEzLTctN3MzLjEzLTcgNy03IDcgMy4xMyA3IDctMy4xMyA3LTcgN3pcIi8+XHJcbiAgICAgICAgPC9zdmc+YCxcclxuXHJcbiAgZXJyb3I6IGBcclxuICAgICAgICA8c3ZnIGNsYXNzPVwic2ltcGxlLW5vdGlmaWNhdGlvbi1zdmdcIiB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgZmlsbD1cIiMwMDAwMDBcIiBoZWlnaHQ9XCIyNFwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiB3aWR0aD1cIjI0XCI+XHJcbiAgICAgICAgICAgIDxwYXRoIGQ9XCJNMCAwaDI0djI0SDBWMHpcIiBmaWxsPVwibm9uZVwiLz5cclxuICAgICAgICAgICAgPHBhdGggZD1cIk0xMSAxNWgydjJoLTJ6bTAtOGgydjZoLTJ6bS45OS01QzYuNDcgMiAyIDYuNDggMiAxMnM0LjQ3IDEwIDkuOTkgMTBDMTcuNTIgMjIgMjIgMTcuNTIgMjIgMTJTMTcuNTIgMiAxMS45OSAyek0xMiAyMGMtNC40MiAwLTgtMy41OC04LThzMy41OC04IDgtOCA4IDMuNTggOCA4LTMuNTggOC04IDh6XCIvPlxyXG4gICAgICAgIDwvc3ZnPlxyXG4gICAgYCxcclxuICBpbmZvOiBgXHJcbiAgICAgICAgPHN2ZyBjbGFzcz1cInNpbXBsZS1ub3RpZmljYXRpb24tc3ZnXCIgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIGZpbGw9XCIjMDAwMDAwXCIgaGVpZ2h0PVwiMjRcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCIgd2lkdGg9XCIyNFwiPlxyXG4gICAgICAgICAgICA8cGF0aCBkPVwiTTAgMGgyNHYyNEgwelwiIGZpbGw9XCJub25lXCIvPlxyXG4gICAgICAgICAgICA8cGF0aCBkPVwiTTExIDE3aDJ2LTZoLTJ2NnptMS0xNUM2LjQ4IDIgMiA2LjQ4IDIgMTJzNC40OCAxMCAxMCAxMCAxMC00LjQ4IDEwLTEwUzE3LjUyIDIgMTIgMnptMCAxOGMtNC40MSAwLTgtMy41OS04LThzMy41OS04IDgtOCA4IDMuNTkgOCA4LTMuNTkgOC04IDh6TTExIDloMlY3aC0ydjJ6XCIvPlxyXG4gICAgICAgIDwvc3ZnPlxyXG4gICAgYCxcclxuICBzdWNjZXNzOiBgXHJcbiAgICAgICAgPHN2ZyBjbGFzcz1cInNpbXBsZS1ub3RpZmljYXRpb24tc3ZnXCIgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIGZpbGw9XCIjMDAwMDAwXCIgaGVpZ2h0PVwiMjRcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCIgd2lkdGg9XCIyNFwiPlxyXG4gICAgICAgICAgICA8cGF0aCBkPVwiTTAgMGgyNHYyNEgwelwiIGZpbGw9XCJub25lXCIvPlxyXG4gICAgICAgICAgICA8cGF0aCBkPVwiTTkgMTYuMkw0LjggMTJsLTEuNCAxLjRMOSAxOSAyMSA3bC0xLjQtMS40TDkgMTYuMnpcIi8+XHJcbiAgICAgICAgPC9zdmc+XHJcbiAgICBgXHJcbn07XHJcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyBub2RlX21vZHVsZXMvYW5ndWxhcjItdGVtcGxhdGUtbG9hZGVyIS4vfi9hbmd1bGFyMi1ub3RpZmljYXRpb25zL3NyYy9pY29ucy50cyJdLCJtYXBwaW5ncyI6IjtBQU9BO0FBQ0E7QUFNQTtBQU1BO0FBTUE7QUFNQTsiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ },
- /* 67 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar core_1 = __webpack_require__(4);\nvar notifications_service_1 = __webpack_require__(65);\nvar options_type_1 = __webpack_require__(68);\nvar SimpleNotificationsComponent = (function () {\n function SimpleNotificationsComponent(_service) {\n this._service = _service;\n this.onCreate = new core_1.EventEmitter();\n this.onDestroy = new core_1.EventEmitter();\n this.notifications = [];\n this.position = ['bottom', 'right'];\n // Received values\n this.lastOnBottom = true;\n this.maxStack = 8;\n this.preventLastDuplicates = false;\n this.preventDuplicates = false;\n // Sent values\n this.timeOut = 0;\n this.maxLength = 0;\n this.clickToClose = true;\n this.showProgressBar = true;\n this.pauseOnHover = true;\n this.theClass = '';\n this.rtl = false;\n this.animate = 'fromRight';\n }\n Object.defineProperty(SimpleNotificationsComponent.prototype, \"options\", {\n set: function (opt) {\n this.attachChanges(opt);\n },\n enumerable: true,\n configurable: true\n });\n SimpleNotificationsComponent.prototype.ngOnInit = function () {\n var _this = this;\n // Listen for changes in the service\n this.listener = this._service.getChangeEmitter()\n .subscribe(function (item) {\n switch (item.command) {\n case 'cleanAll':\n _this.notifications = [];\n break;\n case 'clean':\n _this.cleanSingle(item.id);\n break;\n case 'set':\n if (item.add)\n _this.add(item.notification);\n else\n _this.defaultBehavior(item);\n break;\n default:\n _this.defaultBehavior(item);\n break;\n }\n });\n };\n // Default behavior on event\n SimpleNotificationsComponent.prototype.defaultBehavior = function (value) {\n this.notifications.splice(this.notifications.indexOf(value.notification), 1);\n this.onDestroy.emit(this.buildEmit(value.notification, false));\n };\n // Add the new notification to the notification array\n SimpleNotificationsComponent.prototype.add = function (item) {\n item.createdOn = new Date();\n var toBlock = this.preventLastDuplicates || this.preventDuplicates ? this.block(item) : false;\n // Save this as the last created notification\n this.lastNotificationCreated = item;\n if (!toBlock) {\n // Check if the notification should be added at the start or the end of the array\n if (this.lastOnBottom) {\n if (this.notifications.length >= this.maxStack)\n this.notifications.splice(0, 1);\n this.notifications.push(item);\n }\n else {\n if (this.notifications.length >= this.maxStack)\n this.notifications.splice(this.notifications.length - 1, 1);\n this.notifications.splice(0, 0, item);\n }\n this.onCreate.emit(this.buildEmit(item, true));\n }\n };\n // Check if notifications should be prevented\n SimpleNotificationsComponent.prototype.block = function (item) {\n var toCheck = item.html ? this.checkHtml : this.checkStandard;\n if (this.preventDuplicates && this.notifications.length > 0) {\n for (var i = 0; i < this.notifications.length; i++) {\n if (toCheck(this.notifications[i], item)) {\n return true;\n }\n }\n }\n if (this.preventLastDuplicates) {\n var comp = void 0;\n if (this.preventLastDuplicates === 'visible' && this.notifications.length > 0) {\n if (this.lastOnBottom) {\n comp = this.notifications[this.notifications.length - 1];\n }\n else {\n comp = this.notifications[0];\n }\n }\n else if (this.preventLastDuplicates === 'all' && this.lastNotificationCreated) {\n comp = this.lastNotificationCreated;\n }\n else {\n return false;\n }\n return toCheck(comp, item);\n }\n return false;\n };\n SimpleNotificationsComponent.prototype.checkStandard = function (checker, item) {\n return checker.type === item.type && checker.title === item.title && checker.content === item.content;\n };\n SimpleNotificationsComponent.prototype.checkHtml = function (checker, item) {\n return checker.html ? checker.type === item.type && checker.title === item.title && checker.content === item.content && checker.html === item.html : false;\n };\n // Attach all the changes received in the options object\n SimpleNotificationsComponent.prototype.attachChanges = function (options) {\n var _this = this;\n Object.keys(options).forEach(function (a) {\n if (_this.hasOwnProperty(a)) {\n _this[a] = options[a];\n }\n });\n };\n SimpleNotificationsComponent.prototype.buildEmit = function (notification, to) {\n var toEmit = {\n createdOn: notification.createdOn,\n type: notification.type,\n icon: notification.icon,\n id: notification.id\n };\n if (notification.html) {\n toEmit.html = notification.html;\n }\n else {\n toEmit.title = notification.title;\n toEmit.content = notification.content;\n }\n if (!to) {\n toEmit.destroyedOn = new Date();\n }\n return toEmit;\n };\n SimpleNotificationsComponent.prototype.cleanSingle = function (id) {\n var indexOfDelete = 0;\n var doDelete = false;\n this.notifications.forEach(function (notification, idx) {\n if (notification.id === id) {\n indexOfDelete = idx;\n doDelete = true;\n }\n });\n if (doDelete) {\n this.notifications.splice(indexOfDelete, 1);\n }\n };\n SimpleNotificationsComponent.prototype.ngOnDestroy = function () {\n if (this.listener) {\n this.listener.unsubscribe();\n }\n };\n __decorate([\n core_1.Input(), \n __metadata('design:type', (typeof (_a = typeof options_type_1.Options !== 'undefined' && options_type_1.Options) === 'function' && _a) || Object), \n __metadata('design:paramtypes', [(typeof (_b = typeof options_type_1.Options !== 'undefined' && options_type_1.Options) === 'function' && _b) || Object])\n ], SimpleNotificationsComponent.prototype, \"options\", null);\n __decorate([\n core_1.Output(), \n __metadata('design:type', Object)\n ], SimpleNotificationsComponent.prototype, \"onCreate\", void 0);\n __decorate([\n core_1.Output(), \n __metadata('design:type', Object)\n ], SimpleNotificationsComponent.prototype, \"onDestroy\", void 0);\n SimpleNotificationsComponent = __decorate([\n core_1.Component({\n selector: 'simple-notifications',\n encapsulation: core_1.ViewEncapsulation.None,\n template: \"\\n <div class=\\\"simple-notification-wrapper\\\" [ngClass]=\\\"position\\\">\\n <simple-notification\\n *ngFor=\\\"let a of notifications; let i = index\\\"\\n [item]=\\\"a\\\"\\n [timeOut]=\\\"timeOut\\\"\\n [clickToClose]=\\\"clickToClose\\\"\\n [maxLength]=\\\"maxLength\\\"\\n [showProgressBar]=\\\"showProgressBar\\\"\\n [pauseOnHover]=\\\"pauseOnHover\\\"\\n [theClass]=\\\"theClass\\\"\\n [rtl]=\\\"rtl\\\"\\n [animate]=\\\"animate\\\"\\n [position]=\\\"i\\\"\\n >\\n </simple-notification>\\n </div>\\n \",\n styles: [\"\\n .simple-notification-wrapper {\\n position: fixed;\\n width: 300px;\\n z-index: 1000;\\n }\\n \\n .simple-notification-wrapper.left { left: 20px; }\\n .simple-notification-wrapper.top { top: 20px; }\\n .simple-notification-wrapper.right { right: 20px; }\\n .simple-notification-wrapper.bottom { bottom: 20px; }\\n \\n @media (max-width: 340px) {\\n .simple-notification-wrapper {\\n width: auto;\\n left: 20px;\\n right: 20px;\\n }\\n }\\n \"]\n }), \n __metadata('design:paramtypes', [(typeof (_c = typeof notifications_service_1.NotificationsService !== 'undefined' && notifications_service_1.NotificationsService) === 'function' && _c) || Object])\n ], SimpleNotificationsComponent);\n return SimpleNotificationsComponent;\n var _a, _b, _c;\n}());\nexports.SimpleNotificationsComponent = SimpleNotificationsComponent;\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNjcuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2FuZ3VsYXIyLW5vdGlmaWNhdGlvbnMvc3JjL3NpbXBsZS1ub3RpZmljYXRpb25zLmNvbXBvbmVudC50cz84ZjBlIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7Q29tcG9uZW50LCBFdmVudEVtaXR0ZXIsIE9uSW5pdCwgT25EZXN0cm95LCBWaWV3RW5jYXBzdWxhdGlvbiwgSW5wdXQsIE91dHB1dH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7Tm90aWZpY2F0aW9ufSBmcm9tICcuL25vdGlmaWNhdGlvbi50eXBlJztcclxuaW1wb3J0IHtOb3RpZmljYXRpb25zU2VydmljZX0gZnJvbSAnLi9ub3RpZmljYXRpb25zLnNlcnZpY2UnO1xyXG5pbXBvcnQge09wdGlvbnN9IGZyb20gJy4vb3B0aW9ucy50eXBlJztcclxuaW1wb3J0IHtTdWJzY3JpcHRpb259IGZyb20gJ3J4anMvU3Vic2NyaXB0aW9uJztcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gICAgc2VsZWN0b3I6ICdzaW1wbGUtbm90aWZpY2F0aW9ucycsXHJcbiAgICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxyXG4gICAgdGVtcGxhdGU6IGBcclxuICAgICAgICA8ZGl2IGNsYXNzPVwic2ltcGxlLW5vdGlmaWNhdGlvbi13cmFwcGVyXCIgW25nQ2xhc3NdPVwicG9zaXRpb25cIj5cclxuICAgICAgICAgICAgPHNpbXBsZS1ub3RpZmljYXRpb25cclxuICAgICAgICAgICAgICAgICpuZ0Zvcj1cImxldCBhIG9mIG5vdGlmaWNhdGlvbnM7IGxldCBpID0gaW5kZXhcIlxyXG4gICAgICAgICAgICAgICAgW2l0ZW1dPVwiYVwiXHJcbiAgICAgICAgICAgICAgICBbdGltZU91dF09XCJ0aW1lT3V0XCJcclxuICAgICAgICAgICAgICAgIFtjbGlja1RvQ2xvc2VdPVwiY2xpY2tUb0Nsb3NlXCJcclxuICAgICAgICAgICAgICAgIFttYXhMZW5ndGhdPVwibWF4TGVuZ3RoXCJcclxuICAgICAgICAgICAgICAgIFtzaG93UHJvZ3Jlc3NCYXJdPVwic2hvd1Byb2dyZXNzQmFyXCJcclxuICAgICAgICAgICAgICAgIFtwYXVzZU9uSG92ZXJdPVwicGF1c2VPbkhvdmVyXCJcclxuICAgICAgICAgICAgICAgIFt0aGVDbGFzc109XCJ0aGVDbGFzc1wiXHJcbiAgICAgICAgICAgICAgICBbcnRsXT1cInJ0bFwiXHJcbiAgICAgICAgICAgICAgICBbYW5pbWF0ZV09XCJhbmltYXRlXCJcclxuICAgICAgICAgICAgICAgIFtwb3NpdGlvbl09XCJpXCJcclxuICAgICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgPC9zaW1wbGUtbm90aWZpY2F0aW9uPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgYCxcclxuICAgIHN0eWxlczogW2BcclxuICAgICAgICAuc2ltcGxlLW5vdGlmaWNhdGlvbi13cmFwcGVyIHtcclxuICAgICAgICAgICAgcG9zaXRpb246IGZpeGVkO1xyXG4gICAgICAgICAgICB3aWR0aDogMzAwcHg7XHJcbiAgICAgICAgICAgIHotaW5kZXg6IDEwMDA7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIFxyXG4gICAgICAgIC5zaW1wbGUtbm90aWZpY2F0aW9uLXdyYXBwZXIubGVmdCB7IGxlZnQ6IDIwcHg7IH1cclxuICAgICAgICAuc2ltcGxlLW5vdGlmaWNhdGlvbi13cmFwcGVyLnRvcCB7IHRvcDogMjBweDsgfVxyXG4gICAgICAgIC5zaW1wbGUtbm90aWZpY2F0aW9uLXdyYXBwZXIucmlnaHQgeyByaWdodDogMjBweDsgfVxyXG4gICAgICAgIC5zaW1wbGUtbm90aWZpY2F0aW9uLXdyYXBwZXIuYm90dG9tIHsgYm90dG9tOiAyMHB4OyB9XHJcbiAgICAgICAgXHJcbiAgICAgICAgQG1lZGlhIChtYXgtd2lkdGg6IDM0MHB4KSB7XHJcbiAgICAgICAgICAgIC5zaW1wbGUtbm90aWZpY2F0aW9uLXdyYXBwZXIge1xyXG4gICAgICAgICAgICAgICAgd2lkdGg6IGF1dG87XHJcbiAgICAgICAgICAgICAgICBsZWZ0OiAyMHB4O1xyXG4gICAgICAgICAgICAgICAgcmlnaHQ6IDIwcHg7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICBgXVxyXG59KVxyXG5cclxuZXhwb3J0IGNsYXNzIFNpbXBsZU5vdGlmaWNhdGlvbnNDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XHJcblxyXG4gICAgQElucHV0KCkgc2V0IG9wdGlvbnMob3B0OiBPcHRpb25zKSB7XHJcbiAgICAgICAgdGhpcy5hdHRhY2hDaGFuZ2VzKG9wdCk7XHJcbiAgICB9XHJcblxyXG4gICAgQE91dHB1dCgpIG9uQ3JlYXRlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xyXG4gICAgQE91dHB1dCgpIG9uRGVzdHJveSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcclxuXHJcbiAgICBwdWJsaWMgbm90aWZpY2F0aW9uczogTm90aWZpY2F0aW9uW10gPSBbXTtcclxuICAgIHB1YmxpYyBwb3NpdGlvbjogWyd0b3AnIHwgJ2JvdHRvbScsICdyaWdodCcgfCAnbGVmdCddID0gWydib3R0b20nLCAncmlnaHQnXTtcclxuXHJcbiAgICBwcml2YXRlIGxhc3ROb3RpZmljYXRpb25DcmVhdGVkOiBOb3RpZmljYXRpb247XHJcbiAgICBwcml2YXRlIGxpc3RlbmVyOiBTdWJzY3JpcHRpb247XHJcblxyXG4gICAgLy8gUmVjZWl2ZWQgdmFsdWVzXHJcbiAgICBwcml2YXRlIGxhc3RPbkJvdHRvbTogYm9vbGVhbiA9IHRydWU7XHJcbiAgICBwcml2YXRlIG1heFN0YWNrOiBudW1iZXIgPSA4O1xyXG4gICAgcHJpdmF0ZSBwcmV2ZW50TGFzdER1cGxpY2F0ZXM6IGFueSA9IGZhbHNlO1xyXG4gICAgcHJpdmF0ZSBwcmV2ZW50RHVwbGljYXRlczogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAgIC8vIFNlbnQgdmFsdWVzXHJcbiAgICBwcml2YXRlIHRpbWVPdXQ6IG51bWJlciA9IDA7XHJcbiAgICBwcml2YXRlIG1heExlbmd0aDogbnVtYmVyID0gMDtcclxuICAgIHByaXZhdGUgY2xpY2tUb0Nsb3NlOiBib29sZWFuID0gdHJ1ZTtcclxuICAgIHByaXZhdGUgc2hvd1Byb2dyZXNzQmFyOiBib29sZWFuID0gdHJ1ZTtcclxuICAgIHByaXZhdGUgcGF1c2VPbkhvdmVyOiBib29sZWFuID0gdHJ1ZTtcclxuICAgIHByaXZhdGUgdGhlQ2xhc3M6IHN0cmluZyA9ICcnO1xyXG4gICAgcHJpdmF0ZSBydGw6IGJvb2xlYW4gPSBmYWxzZTtcclxuICAgIHByaXZhdGUgYW5pbWF0ZTogJ2Zyb21SaWdodCcgfCAnZnJvbUxlZnQnIHwgJ3JvdGF0ZScgfCAnc2NhbGUnID0gJ2Zyb21SaWdodCc7XHJcblxyXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBfc2VydmljZTogTm90aWZpY2F0aW9uc1NlcnZpY2UpIHt9XHJcblxyXG4gICAgbmdPbkluaXQoKTogdm9pZCB7XHJcbiAgICAgICAgLy8gTGlzdGVuIGZvciBjaGFuZ2VzIGluIHRoZSBzZXJ2aWNlXHJcbiAgICAgICAgdGhpcy5saXN0ZW5lciA9IHRoaXMuX3NlcnZpY2UuZ2V0Q2hhbmdlRW1pdHRlcigpXHJcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoaXRlbSA9PiB7XHJcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKGl0ZW0uY29tbWFuZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2NsZWFuQWxsJzpcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5ub3RpZmljYXRpb25zID0gW107XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBjYXNlICdjbGVhbic6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYW5TaW5nbGUoaXRlbS5pZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBjYXNlICdzZXQnOlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXRlbS5hZGQpIHRoaXMuYWRkKGl0ZW0ubm90aWZpY2F0aW9uKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB0aGlzLmRlZmF1bHRCZWhhdmlvcihpdGVtKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGVmYXVsdEJlaGF2aW9yKGl0ZW0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gRGVmYXVsdCBiZWhhdmlvciBvbiBldmVudFxyXG4gICAgZGVmYXVsdEJlaGF2aW9yKHZhbHVlOiBhbnkpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLm5vdGlmaWNhdGlvbnMuc3BsaWNlKHRoaXMubm90aWZpY2F0aW9ucy5pbmRleE9mKHZhbHVlLm5vdGlmaWNhdGlvbiksIDEpO1xyXG4gICAgICAgIHRoaXMub25EZXN0cm95LmVtaXQodGhpcy5idWlsZEVtaXQodmFsdWUubm90aWZpY2F0aW9uLCBmYWxzZSkpO1xyXG4gICAgfVxyXG5cclxuXHJcbiAgICAvLyBBZGQgdGhlIG5ldyBub3RpZmljYXRpb24gdG8gdGhlIG5vdGlmaWNhdGlvbiBhcnJheVxyXG4gICAgYWRkKGl0ZW06IE5vdGlmaWNhdGlvbik6IHZvaWQge1xyXG4gICAgICAgIGl0ZW0uY3JlYXRlZE9uID0gbmV3IERhdGUoKTtcclxuXHJcbiAgICAgICAgbGV0IHRvQmxvY2s6IGJvb2xlYW4gPSB0aGlzLnByZXZlbnRMYXN0RHVwbGljYXRlcyB8fCB0aGlzLnByZXZlbnREdXBsaWNhdGVzID8gdGhpcy5ibG9jayhpdGVtKSA6IGZhbHNlO1xyXG5cclxuICAgICAgICAvLyBTYXZlIHRoaXMgYXMgdGhlIGxhc3QgY3JlYXRlZCBub3RpZmljYXRpb25cclxuICAgICAgICB0aGlzLmxhc3ROb3RpZmljYXRpb25DcmVhdGVkID0gaXRlbTtcclxuXHJcbiAgICAgICAgaWYgKCF0b0Jsb2NrKSB7XHJcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHRoZSBub3RpZmljYXRpb24gc2hvdWxkIGJlIGFkZGVkIGF0IHRoZSBzdGFydCBvciB0aGUgZW5kIG9mIHRoZSBhcnJheVxyXG4gICAgICAgICAgICBpZiAodGhpcy5sYXN0T25Cb3R0b20pIHtcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLm5vdGlmaWNhdGlvbnMubGVuZ3RoID49IHRoaXMubWF4U3RhY2spIHRoaXMubm90aWZpY2F0aW9ucy5zcGxpY2UoMCwgMSk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLm5vdGlmaWNhdGlvbnMucHVzaChpdGVtKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLm5vdGlmaWNhdGlvbnMubGVuZ3RoID49IHRoaXMubWF4U3RhY2spIHRoaXMubm90aWZpY2F0aW9ucy5zcGxpY2UodGhpcy5ub3RpZmljYXRpb25zLmxlbmd0aCAtIDEsIDEpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5ub3RpZmljYXRpb25zLnNwbGljZSgwLCAwLCBpdGVtKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgdGhpcy5vbkNyZWF0ZS5lbWl0KHRoaXMuYnVpbGRFbWl0KGl0ZW0sIHRydWUpKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQ2hlY2sgaWYgbm90aWZpY2F0aW9ucyBzaG91bGQgYmUgcHJldmVudGVkXHJcbiAgICBibG9jayhpdGVtOiBOb3RpZmljYXRpb24pOiBib29sZWFuIHtcclxuXHJcbiAgICAgICAgbGV0IHRvQ2hlY2sgPSBpdGVtLmh0bWwgPyB0aGlzLmNoZWNrSHRtbCA6IHRoaXMuY2hlY2tTdGFuZGFyZDtcclxuXHJcbiAgICAgICAgaWYgKHRoaXMucHJldmVudER1cGxpY2F0ZXMgJiYgdGhpcy5ub3RpZmljYXRpb25zLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm5vdGlmaWNhdGlvbnMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgIGlmICh0b0NoZWNrKHRoaXMubm90aWZpY2F0aW9uc1tpXSwgaXRlbSkpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRoaXMucHJldmVudExhc3REdXBsaWNhdGVzKSB7XHJcblxyXG4gICAgICAgICAgICBsZXQgY29tcDogTm90aWZpY2F0aW9uO1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMucHJldmVudExhc3REdXBsaWNhdGVzID09PSAndmlzaWJsZScgJiYgdGhpcy5ub3RpZmljYXRpb25zLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmxhc3RPbkJvdHRvbSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbXAgPSB0aGlzLm5vdGlmaWNhdGlvbnNbdGhpcy5ub3RpZmljYXRpb25zLmxlbmd0aCAtIDFdO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBjb21wID0gdGhpcy5ub3RpZmljYXRpb25zWzBdO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMucHJldmVudExhc3REdXBsaWNhdGVzID09PSAnYWxsJyAmJiB0aGlzLmxhc3ROb3RpZmljYXRpb25DcmVhdGVkKSB7XHJcbiAgICAgICAgICAgICAgICBjb21wID0gdGhpcy5sYXN0Tm90aWZpY2F0aW9uQ3JlYXRlZDtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gdG9DaGVjayhjb21wLCBpdGVtKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICBjaGVja1N0YW5kYXJkKGNoZWNrZXI6IE5vdGlmaWNhdGlvbiwgaXRlbTogTm90aWZpY2F0aW9uKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuIGNoZWNrZXIudHlwZSA9PT0gaXRlbS50eXBlICYmIGNoZWNrZXIudGl0bGUgPT09IGl0ZW0udGl0bGUgJiYgY2hlY2tlci5jb250ZW50ID09PSBpdGVtLmNvbnRlbnQ7XHJcbiAgICB9XHJcblxyXG4gICAgY2hlY2tIdG1sKGNoZWNrZXI6IE5vdGlmaWNhdGlvbiwgaXRlbTogTm90aWZpY2F0aW9uKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuIGNoZWNrZXIuaHRtbCA/IGNoZWNrZXIudHlwZSA9PT0gaXRlbS50eXBlICYmIGNoZWNrZXIudGl0bGUgPT09IGl0ZW0udGl0bGUgJiYgY2hlY2tlci5jb250ZW50ID09PSBpdGVtLmNvbnRlbnQgJiYgY2hlY2tlci5odG1sID09PSBpdGVtLmh0bWwgOiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBBdHRhY2ggYWxsIHRoZSBjaGFuZ2VzIHJlY2VpdmVkIGluIHRoZSBvcHRpb25zIG9iamVjdFxyXG4gICAgYXR0YWNoQ2hhbmdlcyhvcHRpb25zOiBhbnkpOiB2b2lkIHtcclxuICAgICAgICBPYmplY3Qua2V5cyhvcHRpb25zKS5mb3JFYWNoKGEgPT4ge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5oYXNPd25Qcm9wZXJ0eShhKSkge1xyXG4gICAgICAgICAgICAgICAgKDxhbnk+dGhpcylbYV0gPSBvcHRpb25zW2FdO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgYnVpbGRFbWl0KG5vdGlmaWNhdGlvbjogTm90aWZpY2F0aW9uLCB0bzogYm9vbGVhbikge1xyXG4gICAgICAgIGxldCB0b0VtaXQ6IE5vdGlmaWNhdGlvbiA9IHtcclxuICAgICAgICAgICAgY3JlYXRlZE9uOiBub3RpZmljYXRpb24uY3JlYXRlZE9uLFxyXG4gICAgICAgICAgICB0eXBlOiBub3RpZmljYXRpb24udHlwZSxcclxuICAgICAgICAgICAgaWNvbjogbm90aWZpY2F0aW9uLmljb24sXHJcbiAgICAgICAgICAgIGlkOiBub3RpZmljYXRpb24uaWRcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBpZiAobm90aWZpY2F0aW9uLmh0bWwpIHtcclxuICAgICAgICAgICAgdG9FbWl0Lmh0bWwgPSBub3RpZmljYXRpb24uaHRtbDtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0b0VtaXQudGl0bGUgPSBub3RpZmljYXRpb24udGl0bGU7XHJcbiAgICAgICAgICAgIHRvRW1pdC5jb250ZW50ID0gbm90aWZpY2F0aW9uLmNvbnRlbnQ7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIXRvKSB7XHJcbiAgICAgICAgICAgIHRvRW1pdC5kZXN0cm95ZWRPbiA9IG5ldyBEYXRlKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gdG9FbWl0O1xyXG4gICAgfVxyXG5cclxuICAgIGNsZWFuU2luZ2xlKGlkOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICBsZXQgaW5kZXhPZkRlbGV0ZTogbnVtYmVyID0gMDtcclxuICAgICAgICBsZXQgZG9EZWxldGU6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgICAgICAgdGhpcy5ub3RpZmljYXRpb25zLmZvckVhY2goKG5vdGlmaWNhdGlvbiwgaWR4KSA9PiB7XHJcbiAgICAgICAgICAgIGlmIChub3RpZmljYXRpb24uaWQgPT09IGlkKSB7XHJcbiAgICAgICAgICAgICAgICBpbmRleE9mRGVsZXRlID0gaWR4O1xyXG4gICAgICAgICAgICAgICAgZG9EZWxldGUgPSB0cnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIGlmIChkb0RlbGV0ZSkge1xyXG4gICAgICAgICAgICB0aGlzLm5vdGlmaWNhdGlvbnMuc3BsaWNlKGluZGV4T2ZEZWxldGUsIDEpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgICAgICBpZiAodGhpcy5saXN0ZW5lcikge1xyXG4gICAgICAgICAgICB0aGlzLmxpc3RlbmVyLnVuc3Vic2NyaWJlKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyBub2RlX21vZHVsZXMvYW5ndWxhcjItdGVtcGxhdGUtbG9hZGVyIS4vfi9hbmd1bGFyMi1ub3RpZmljYXRpb25zL3NyYy9zaW1wbGUtbm90aWZpY2F0aW9ucy5jb21wb25lbnQudHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQTtBQUVBO0FBQ0E7QUE4Q0E7QUErQkE7QUFBQTtBQXpCQTtBQUNBO0FBRUE7QUFDQTtBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQTdCQTtBQUFBO0FBQ0E7QUFDQTs7O0FBQUE7QUE2QkE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBbkxBO0FBQUE7OztBQUFBO0FBSUE7QUFBQTs7QUFBQTtBQUNBO0FBQUE7O0FBQUE7QUFsREE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQWtCQTtBQW9CQTs7QUFBQTtBQXdMQTs7QUFBQTtBQXRMQTsiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ },
- /* 68 */
- /***/ function(module, exports) {
- eval("\"use strict\";\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNjguanMiLCJzb3VyY2VzIjpbXSwibWFwcGluZ3MiOiI7Iiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 69 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar core_1 = __webpack_require__(4);\nvar platform_browser_1 = __webpack_require__(22);\nvar notification_type_1 = __webpack_require__(70);\nvar notifications_service_1 = __webpack_require__(65);\nvar NotificationComponent = (function () {\n function NotificationComponent(notificationService, domSanitizer, zone) {\n var _this = this;\n this.notificationService = notificationService;\n this.domSanitizer = domSanitizer;\n this.zone = zone;\n // Progress bar variables\n this.progressWidth = 0;\n this.stopTime = false;\n this.count = 0;\n this.instance = function () {\n _this.zone.runOutsideAngular(function () {\n _this.zone.run(function () { return _this.diff = (new Date().getTime() - _this.start) - (_this.count * _this.speed); });\n if (_this.count++ === _this.steps)\n _this.zone.run(function () { return _this.remove(); });\n else if (!_this.stopTime) {\n if (_this.showProgressBar)\n _this.zone.run(function () { return _this.progressWidth += 100 / _this.steps; });\n _this.timer = setTimeout(_this.instance, (_this.speed - _this.diff));\n }\n });\n };\n }\n NotificationComponent.prototype.ngOnInit = function () {\n if (this.animate) {\n this.item.state = this.animate;\n }\n if (this.item.override) {\n this.attachOverrides();\n }\n if (this.timeOut !== 0) {\n this.startTimeOut();\n }\n this.safeSvg = this.domSanitizer.bypassSecurityTrustHtml(this.item.icon);\n };\n NotificationComponent.prototype.startTimeOut = function () {\n var _this = this;\n this.steps = this.timeOut / 10;\n this.speed = this.timeOut / this.steps;\n this.start = new Date().getTime();\n this.zone.runOutsideAngular(function () { return _this.timer = setTimeout(_this.instance, _this.speed); });\n };\n NotificationComponent.prototype.onEnter = function () {\n if (this.pauseOnHover) {\n this.stopTime = true;\n }\n };\n NotificationComponent.prototype.onLeave = function () {\n if (this.pauseOnHover) {\n this.stopTime = false;\n setTimeout(this.instance, (this.speed - this.diff));\n }\n };\n NotificationComponent.prototype.setPosition = function () {\n return this.position !== 0 ? this.position * 90 : 0;\n };\n NotificationComponent.prototype.onClick = function ($e) {\n this.item.click.emit($e);\n if (this.clickToClose) {\n this.remove();\n }\n };\n // Attach all the overrides\n NotificationComponent.prototype.attachOverrides = function () {\n var _this = this;\n Object.keys(this.item.override).forEach(function (a) {\n if (_this.hasOwnProperty(a)) {\n _this[a] = _this.item.override[a];\n }\n });\n };\n NotificationComponent.prototype.ngOnDestroy = function () {\n clearTimeout(this.timer);\n };\n NotificationComponent.prototype.remove = function () {\n var _this = this;\n if (this.animate) {\n this.item.state = this.animate + 'Out';\n this.zone.runOutsideAngular(function () {\n setTimeout(function () {\n _this.zone.run(function () { return _this.notificationService.set(_this.item, false); });\n }, 310);\n });\n }\n else {\n this.notificationService.set(this.item, false);\n }\n };\n __decorate([\n core_1.Input(), \n __metadata('design:type', Number)\n ], NotificationComponent.prototype, \"timeOut\", void 0);\n __decorate([\n core_1.Input(), \n __metadata('design:type', Boolean)\n ], NotificationComponent.prototype, \"showProgressBar\", void 0);\n __decorate([\n core_1.Input(), \n __metadata('design:type', Boolean)\n ], NotificationComponent.prototype, \"pauseOnHover\", void 0);\n __decorate([\n core_1.Input(), \n __metadata('design:type', Boolean)\n ], NotificationComponent.prototype, \"clickToClose\", void 0);\n __decorate([\n core_1.Input(), \n __metadata('design:type', Number)\n ], NotificationComponent.prototype, \"maxLength\", void 0);\n __decorate([\n core_1.Input(), \n __metadata('design:type', String)\n ], NotificationComponent.prototype, \"theClass\", void 0);\n __decorate([\n core_1.Input(), \n __metadata('design:type', Boolean)\n ], NotificationComponent.prototype, \"rtl\", void 0);\n __decorate([\n core_1.Input(), \n __metadata('design:type', String)\n ], NotificationComponent.prototype, \"animate\", void 0);\n __decorate([\n core_1.Input(), \n __metadata('design:type', Number)\n ], NotificationComponent.prototype, \"position\", void 0);\n __decorate([\n core_1.Input(), \n __metadata('design:type', (typeof (_a = typeof notification_type_1.Notification !== 'undefined' && notification_type_1.Notification) === 'function' && _a) || Object)\n ], NotificationComponent.prototype, \"item\", void 0);\n NotificationComponent = __decorate([\n core_1.Component({\n selector: 'simple-notification',\n encapsulation: core_1.ViewEncapsulation.None,\n animations: [\n core_1.trigger('enterLeave', [\n // Enter from right\n core_1.state('fromRight', core_1.style({ opacity: 1, transform: 'translateX(0)' })),\n core_1.transition('* => fromRight', [\n core_1.style({ opacity: 0, transform: 'translateX(5%)' }),\n core_1.animate('400ms ease-in-out')\n ]),\n core_1.state('fromRightOut', core_1.style({ opacity: 0, transform: 'translateX(-5%)' })),\n core_1.transition('fromRight => fromRightOut', [\n core_1.style({ opacity: 1, transform: 'translateX(0)' }),\n core_1.animate('300ms ease-in-out')\n ]),\n // Enter from left\n core_1.state('fromLeft', core_1.style({ opacity: 1, transform: 'translateX(0)' })),\n core_1.transition('* => fromLeft', [\n core_1.style({ opacity: 0, transform: 'translateX(-5%)' }),\n core_1.animate('400ms ease-in-out')\n ]),\n core_1.state('fromLeftOut', core_1.style({ opacity: 0, transform: 'translateX(5%)' })),\n core_1.transition('fromLeft => fromLeftOut', [\n core_1.style({ opacity: 1, transform: 'translateX(0)' }),\n core_1.animate('300ms ease-in-out')\n ]),\n // Rotate\n core_1.state('scale', core_1.style({ opacity: 1, transform: 'scale(1)' })),\n core_1.transition('* => scale', [\n core_1.style({ opacity: 0, transform: 'scale(0)' }),\n core_1.animate('400ms ease-in-out')\n ]),\n core_1.state('scaleOut', core_1.style({ opacity: 0, transform: 'scale(0)' })),\n core_1.transition('scale => scaleOut', [\n core_1.style({ opacity: 1, transform: 'scale(1)' }),\n core_1.animate('400ms ease-in-out')\n ]),\n // Scale\n core_1.state('rotate', core_1.style({ opacity: 1, transform: 'rotate(0deg)' })),\n core_1.transition('* => rotate', [\n core_1.style({ opacity: 0, transform: 'rotate(5deg)' }),\n core_1.animate('400ms ease-in-out')\n ]),\n core_1.state('rotateOut', core_1.style({ opacity: 0, transform: 'rotate(-5deg)' })),\n core_1.transition('rotate => rotateOut', [\n core_1.style({ opacity: 1, transform: 'rotate(0deg)' }),\n core_1.animate('400ms ease-in-out')\n ])\n ])\n ],\n template: \"\\n <div class=\\\"simple-notification\\\"\\n [@enterLeave]=\\\"item.state\\\"\\n (click)=\\\"onClick($event)\\\"\\n [class]=\\\"theClass\\\"\\n\\n [ngClass]=\\\"{\\n 'alert': item.type === 'alert',\\n 'error': item.type === 'error',\\n 'success': item.type === 'success',\\n 'info': item.type === 'info',\\n 'bare': item.type === 'bare',\\n 'rtl-mode': rtl\\n }\\\"\\n\\n (mouseenter)=\\\"onEnter()\\\"\\n (mouseleave)=\\\"onLeave()\\\">\\n\\n <div *ngIf=\\\"!item.html\\\">\\n <div class=\\\"sn-title\\\">{{item.title}}</div>\\n <div class=\\\"sn-content\\\">{{item.content | max:maxLength}}</div>\\n\\n <div *ngIf=\\\"item.type !== 'bare'\\\" [innerHTML]=\\\"safeSvg\\\"></div>\\n </div>\\n <div *ngIf=\\\"item.html\\\" [innerHTML]=\\\"item.html\\\"></div>\\n\\n <div class=\\\"sn-progress-loader\\\" *ngIf=\\\"showProgressBar\\\">\\n <span [ngStyle]=\\\"{'width': progressWidth + '%'}\\\"></span>\\n </div>\\n\\n </div>\\n \",\n styles: [\"\\n .simple-notification {\\n width: 100%;\\n padding: 10px 20px;\\n box-sizing: border-box;\\n position: relative;\\n float: left;\\n margin-bottom: 10px;\\n color: #fff;\\n cursor: pointer;\\n transition: all 0.5s;\\n }\\n\\n .simple-notification .sn-title {\\n margin: 0;\\n padding: 0 50px 0 0;\\n line-height: 30px;\\n font-size: 20px;\\n }\\n\\n .simple-notification .sn-content {\\n margin: 0;\\n font-size: 16px;\\n padding: 0 50px 0 0;\\n line-height: 20px;\\n }\\n\\n .simple-notification svg {\\n position: absolute;\\n box-sizing: border-box;\\n top: 0;\\n right: 0;\\n width: 70px;\\n height: 70px;\\n padding: 10px;\\n fill: #fff;\\n }\\n\\n .simple-notification.rtl-mode {\\n direction: rtl;\\n }\\n\\n .simple-notification.rtl-mode .sn-content {\\n padding: 0 0 0 50px;\\n }\\n\\n .simple-notification.rtl-mode svg {\\n left: 0;\\n right: auto;\\n }\\n\\n .simple-notification.error { background: #F44336; }\\n .simple-notification.success { background: #8BC34A; }\\n .simple-notification.alert { background: #ffdb5b; }\\n .simple-notification.info { background: #03A9F4; }\\n\\n .simple-notification .sn-progress-loader {\\n position: absolute;\\n top: 0;\\n left: 0;\\n width: 100%;\\n height: 5px;\\n }\\n\\n .simple-notification .sn-progress-loader span {\\n float: left;\\n height: 100%;\\n }\\n\\n .simple-notification.success .sn-progress-loader span { background: #689F38; }\\n .simple-notification.error .sn-progress-loader span { background: #D32F2F; }\\n .simple-notification.alert .sn-progress-loader span { background: #edc242; }\\n .simple-notification.info .sn-progress-loader span { background: #0288D1; }\\n .simple-notification.bare .sn-progress-loader span { background: #ccc; }\\n \"]\n }), \n __metadata('design:paramtypes', [(typeof (_b = typeof notifications_service_1.NotificationsService !== 'undefined' && notifications_service_1.NotificationsService) === 'function' && _b) || Object, (typeof (_c = typeof platform_browser_1.DomSanitizer !== 'undefined' && platform_browser_1.DomSanitizer) === 'function' && _c) || Object, (typeof (_d = typeof core_1.NgZone !== 'undefined' && core_1.NgZone) === 'function' && _d) || Object])\n ], NotificationComponent);\n return NotificationComponent;\n var _a, _b, _c, _d;\n}());\nexports.NotificationComponent = NotificationComponent;\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNjkuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2FuZ3VsYXIyLW5vdGlmaWNhdGlvbnMvc3JjL25vdGlmaWNhdGlvbi5jb21wb25lbnQudHM/NzI5NyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0NvbXBvbmVudCwgT25Jbml0LCBPbkRlc3Ryb3ksIHRyaWdnZXIsIHN0YXRlLCBzdHlsZSwgdHJhbnNpdGlvbiwgYW5pbWF0ZSwgSW5wdXQsIFZpZXdFbmNhcHN1bGF0aW9uLCBOZ1pvbmV9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQge0RvbVNhbml0aXplciwgU2FmZUh0bWx9IGZyb20gJ0Bhbmd1bGFyL3BsYXRmb3JtLWJyb3dzZXInO1xyXG5pbXBvcnQge05vdGlmaWNhdGlvbn0gZnJvbSAnLi9ub3RpZmljYXRpb24udHlwZSc7XHJcbmltcG9ydCB7Tm90aWZpY2F0aW9uc1NlcnZpY2V9IGZyb20gJy4vbm90aWZpY2F0aW9ucy5zZXJ2aWNlJztcclxuQENvbXBvbmVudCh7XHJcbiAgICBzZWxlY3RvcjogJ3NpbXBsZS1ub3RpZmljYXRpb24nLFxyXG4gICAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcclxuICAgIGFuaW1hdGlvbnM6IFtcclxuICAgICAgICB0cmlnZ2VyKCdlbnRlckxlYXZlJywgW1xyXG5cclxuICAgICAgICAgICAgLy8gRW50ZXIgZnJvbSByaWdodFxyXG4gICAgICAgICAgICBzdGF0ZSgnZnJvbVJpZ2h0Jywgc3R5bGUoe29wYWNpdHk6IDEsIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZVgoMCknfSkpLFxyXG4gICAgICAgICAgICB0cmFuc2l0aW9uKCcqID0+IGZyb21SaWdodCcsIFtcclxuICAgICAgICAgICAgICAgIHN0eWxlKHtvcGFjaXR5OiAwLCB0cmFuc2Zvcm06ICd0cmFuc2xhdGVYKDUlKSd9KSxcclxuICAgICAgICAgICAgICAgIGFuaW1hdGUoJzQwMG1zIGVhc2UtaW4tb3V0JylcclxuICAgICAgICAgICAgXSksXHJcbiAgICAgICAgICAgIHN0YXRlKCdmcm9tUmlnaHRPdXQnLCBzdHlsZSh7b3BhY2l0eTogMCwgdHJhbnNmb3JtOiAndHJhbnNsYXRlWCgtNSUpJ30pKSxcclxuICAgICAgICAgICAgdHJhbnNpdGlvbignZnJvbVJpZ2h0ID0+IGZyb21SaWdodE91dCcsIFtcclxuICAgICAgICAgICAgICAgIHN0eWxlKHtvcGFjaXR5OiAxLCB0cmFuc2Zvcm06ICd0cmFuc2xhdGVYKDApJ30pLFxyXG4gICAgICAgICAgICAgICAgYW5pbWF0ZSgnMzAwbXMgZWFzZS1pbi1vdXQnKVxyXG4gICAgICAgICAgICBdKSxcclxuXHJcbiAgICAgICAgICAgIC8vIEVudGVyIGZyb20gbGVmdFxyXG4gICAgICAgICAgICBzdGF0ZSgnZnJvbUxlZnQnLCBzdHlsZSh7b3BhY2l0eTogMSwgdHJhbnNmb3JtOiAndHJhbnNsYXRlWCgwKSd9KSksXHJcbiAgICAgICAgICAgIHRyYW5zaXRpb24oJyogPT4gZnJvbUxlZnQnLCBbXHJcbiAgICAgICAgICAgICAgICBzdHlsZSh7b3BhY2l0eTogMCwgdHJhbnNmb3JtOiAndHJhbnNsYXRlWCgtNSUpJ30pLFxyXG4gICAgICAgICAgICAgICAgYW5pbWF0ZSgnNDAwbXMgZWFzZS1pbi1vdXQnKVxyXG4gICAgICAgICAgICBdKSxcclxuICAgICAgICAgICAgc3RhdGUoJ2Zyb21MZWZ0T3V0Jywgc3R5bGUoe29wYWNpdHk6IDAsIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZVgoNSUpJ30pKSxcclxuICAgICAgICAgICAgdHJhbnNpdGlvbignZnJvbUxlZnQgPT4gZnJvbUxlZnRPdXQnLCBbXHJcbiAgICAgICAgICAgICAgICBzdHlsZSh7b3BhY2l0eTogMSwgdHJhbnNmb3JtOiAndHJhbnNsYXRlWCgwKSd9KSxcclxuICAgICAgICAgICAgICAgIGFuaW1hdGUoJzMwMG1zIGVhc2UtaW4tb3V0JylcclxuICAgICAgICAgICAgXSksXHJcblxyXG4gICAgICAgICAgICAvLyBSb3RhdGVcclxuICAgICAgICAgICAgc3RhdGUoJ3NjYWxlJywgc3R5bGUoe29wYWNpdHk6IDEsIHRyYW5zZm9ybTogJ3NjYWxlKDEpJ30pKSxcclxuICAgICAgICAgICAgdHJhbnNpdGlvbignKiA9PiBzY2FsZScsIFtcclxuICAgICAgICAgICAgICAgIHN0eWxlKHtvcGFjaXR5OiAwLCB0cmFuc2Zvcm06ICdzY2FsZSgwKSd9KSxcclxuICAgICAgICAgICAgICAgIGFuaW1hdGUoJzQwMG1zIGVhc2UtaW4tb3V0JylcclxuICAgICAgICAgICAgXSksXHJcbiAgICAgICAgICAgIHN0YXRlKCdzY2FsZU91dCcsIHN0eWxlKHtvcGFjaXR5OiAwLCB0cmFuc2Zvcm06ICdzY2FsZSgwKSd9KSksXHJcbiAgICAgICAgICAgIHRyYW5zaXRpb24oJ3NjYWxlID0+IHNjYWxlT3V0JywgW1xyXG4gICAgICAgICAgICAgICAgc3R5bGUoe29wYWNpdHk6IDEsIHRyYW5zZm9ybTogJ3NjYWxlKDEpJ30pLFxyXG4gICAgICAgICAgICAgICAgYW5pbWF0ZSgnNDAwbXMgZWFzZS1pbi1vdXQnKVxyXG4gICAgICAgICAgICBdKSxcclxuXHJcbiAgICAgICAgICAgIC8vIFNjYWxlXHJcbiAgICAgICAgICAgIHN0YXRlKCdyb3RhdGUnLCBzdHlsZSh7b3BhY2l0eTogMSwgdHJhbnNmb3JtOiAncm90YXRlKDBkZWcpJ30pKSxcclxuICAgICAgICAgICAgdHJhbnNpdGlvbignKiA9PiByb3RhdGUnLCBbXHJcbiAgICAgICAgICAgICAgICBzdHlsZSh7b3BhY2l0eTogMCwgdHJhbnNmb3JtOiAncm90YXRlKDVkZWcpJ30pLFxyXG4gICAgICAgICAgICAgICAgYW5pbWF0ZSgnNDAwbXMgZWFzZS1pbi1vdXQnKVxyXG4gICAgICAgICAgICBdKSxcclxuICAgICAgICAgICAgc3RhdGUoJ3JvdGF0ZU91dCcsIHN0eWxlKHtvcGFjaXR5OiAwLCB0cmFuc2Zvcm06ICdyb3RhdGUoLTVkZWcpJ30pKSxcclxuICAgICAgICAgICAgdHJhbnNpdGlvbigncm90YXRlID0+IHJvdGF0ZU91dCcsIFtcclxuICAgICAgICAgICAgICAgIHN0eWxlKHtvcGFjaXR5OiAxLCB0cmFuc2Zvcm06ICdyb3RhdGUoMGRlZyknfSksXHJcbiAgICAgICAgICAgICAgICBhbmltYXRlKCc0MDBtcyBlYXNlLWluLW91dCcpXHJcbiAgICAgICAgICAgIF0pXHJcbiAgICAgICAgXSlcclxuICAgIF0sXHJcbiAgICB0ZW1wbGF0ZTogYFxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJzaW1wbGUtbm90aWZpY2F0aW9uXCJcclxuICAgICAgICAgICAgW0BlbnRlckxlYXZlXT1cIml0ZW0uc3RhdGVcIlxyXG4gICAgICAgICAgICAoY2xpY2spPVwib25DbGljaygkZXZlbnQpXCJcclxuICAgICAgICAgICAgW2NsYXNzXT1cInRoZUNsYXNzXCJcclxuXHJcbiAgICAgICAgICAgIFtuZ0NsYXNzXT1cIntcclxuICAgICAgICAgICAgICAgICdhbGVydCc6IGl0ZW0udHlwZSA9PT0gJ2FsZXJ0JyxcclxuICAgICAgICAgICAgICAgICdlcnJvcic6IGl0ZW0udHlwZSA9PT0gJ2Vycm9yJyxcclxuICAgICAgICAgICAgICAgICdzdWNjZXNzJzogaXRlbS50eXBlID09PSAnc3VjY2VzcycsXHJcbiAgICAgICAgICAgICAgICAnaW5mbyc6IGl0ZW0udHlwZSA9PT0gJ2luZm8nLFxyXG4gICAgICAgICAgICAgICAgJ2JhcmUnOiBpdGVtLnR5cGUgPT09ICdiYXJlJyxcclxuICAgICAgICAgICAgICAgICdydGwtbW9kZSc6IHJ0bFxyXG4gICAgICAgICAgICB9XCJcclxuXHJcbiAgICAgICAgICAgIChtb3VzZWVudGVyKT1cIm9uRW50ZXIoKVwiXHJcbiAgICAgICAgICAgIChtb3VzZWxlYXZlKT1cIm9uTGVhdmUoKVwiPlxyXG5cclxuICAgICAgICAgICAgPGRpdiAqbmdJZj1cIiFpdGVtLmh0bWxcIj5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzbi10aXRsZVwiPnt7aXRlbS50aXRsZX19PC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic24tY29udGVudFwiPnt7aXRlbS5jb250ZW50IHwgbWF4Om1heExlbmd0aH19PC9kaXY+XHJcblxyXG4gICAgICAgICAgICAgICAgPGRpdiAqbmdJZj1cIml0ZW0udHlwZSAhPT0gJ2JhcmUnXCIgW2lubmVySFRNTF09XCJzYWZlU3ZnXCI+PC9kaXY+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiaXRlbS5odG1sXCIgW2lubmVySFRNTF09XCJpdGVtLmh0bWxcIj48L2Rpdj5cclxuXHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzbi1wcm9ncmVzcy1sb2FkZXJcIiAqbmdJZj1cInNob3dQcm9ncmVzc0JhclwiPlxyXG4gICAgICAgICAgICAgICAgPHNwYW4gW25nU3R5bGVdPVwieyd3aWR0aCc6IHByb2dyZXNzV2lkdGggKyAnJSd9XCI+PC9zcGFuPlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICBgLFxyXG4gICAgc3R5bGVzOiBbYFxyXG4gICAgICAgIC5zaW1wbGUtbm90aWZpY2F0aW9uIHtcclxuICAgICAgICAgICAgd2lkdGg6IDEwMCU7XHJcbiAgICAgICAgICAgIHBhZGRpbmc6IDEwcHggMjBweDtcclxuICAgICAgICAgICAgYm94LXNpemluZzogYm9yZGVyLWJveDtcclxuICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gICAgICAgICAgICBmbG9hdDogbGVmdDtcclxuICAgICAgICAgICAgbWFyZ2luLWJvdHRvbTogMTBweDtcclxuICAgICAgICAgICAgY29sb3I6ICNmZmY7XHJcbiAgICAgICAgICAgIGN1cnNvcjogcG9pbnRlcjtcclxuICAgICAgICAgICAgdHJhbnNpdGlvbjogYWxsIDAuNXM7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAuc2ltcGxlLW5vdGlmaWNhdGlvbiAuc24tdGl0bGUge1xyXG4gICAgICAgICAgICBtYXJnaW46IDA7XHJcbiAgICAgICAgICAgIHBhZGRpbmc6IDAgNTBweCAwIDA7XHJcbiAgICAgICAgICAgIGxpbmUtaGVpZ2h0OiAzMHB4O1xyXG4gICAgICAgICAgICBmb250LXNpemU6IDIwcHg7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAuc2ltcGxlLW5vdGlmaWNhdGlvbiAuc24tY29udGVudCB7XHJcbiAgICAgICAgICAgIG1hcmdpbjogMDtcclxuICAgICAgICAgICAgZm9udC1zaXplOiAxNnB4O1xyXG4gICAgICAgICAgICBwYWRkaW5nOiAwIDUwcHggMCAwO1xyXG4gICAgICAgICAgICBsaW5lLWhlaWdodDogMjBweDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5zaW1wbGUtbm90aWZpY2F0aW9uIHN2ZyB7XHJcbiAgICAgICAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgICAgICAgYm94LXNpemluZzogYm9yZGVyLWJveDtcclxuICAgICAgICAgICAgdG9wOiAwO1xyXG4gICAgICAgICAgICByaWdodDogMDtcclxuICAgICAgICAgICAgd2lkdGg6IDcwcHg7XHJcbiAgICAgICAgICAgIGhlaWdodDogNzBweDtcclxuICAgICAgICAgICAgcGFkZGluZzogMTBweDtcclxuICAgICAgICAgICAgZmlsbDogI2ZmZjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5zaW1wbGUtbm90aWZpY2F0aW9uLnJ0bC1tb2RlIHtcclxuICAgICAgICAgICAgZGlyZWN0aW9uOiBydGw7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAuc2ltcGxlLW5vdGlmaWNhdGlvbi5ydGwtbW9kZSAuc24tY29udGVudCB7XHJcbiAgICAgICAgICAgIHBhZGRpbmc6IDAgMCAwIDUwcHg7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAuc2ltcGxlLW5vdGlmaWNhdGlvbi5ydGwtbW9kZSBzdmcge1xyXG4gICAgICAgICAgICBsZWZ0OiAwO1xyXG4gICAgICAgICAgICByaWdodDogYXV0bztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5zaW1wbGUtbm90aWZpY2F0aW9uLmVycm9yIHsgYmFja2dyb3VuZDogI0Y0NDMzNjsgfVxyXG4gICAgICAgIC5zaW1wbGUtbm90aWZpY2F0aW9uLnN1Y2Nlc3MgeyBiYWNrZ3JvdW5kOiAjOEJDMzRBOyB9XHJcbiAgICAgICAgLnNpbXBsZS1ub3RpZmljYXRpb24uYWxlcnQgeyBiYWNrZ3JvdW5kOiAjZmZkYjViOyB9XHJcbiAgICAgICAgLnNpbXBsZS1ub3RpZmljYXRpb24uaW5mbyB7IGJhY2tncm91bmQ6ICMwM0E5RjQ7IH1cclxuXHJcbiAgICAgICAgLnNpbXBsZS1ub3RpZmljYXRpb24gLnNuLXByb2dyZXNzLWxvYWRlciB7XHJcbiAgICAgICAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcclxuICAgICAgICAgICAgdG9wOiAwO1xyXG4gICAgICAgICAgICBsZWZ0OiAwO1xyXG4gICAgICAgICAgICB3aWR0aDogMTAwJTtcclxuICAgICAgICAgICAgaGVpZ2h0OiA1cHg7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAuc2ltcGxlLW5vdGlmaWNhdGlvbiAuc24tcHJvZ3Jlc3MtbG9hZGVyIHNwYW4ge1xyXG4gICAgICAgICAgICBmbG9hdDogbGVmdDtcclxuICAgICAgICAgICAgaGVpZ2h0OiAxMDAlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLnNpbXBsZS1ub3RpZmljYXRpb24uc3VjY2VzcyAuc24tcHJvZ3Jlc3MtbG9hZGVyIHNwYW4geyBiYWNrZ3JvdW5kOiAjNjg5RjM4OyB9XHJcbiAgICAgICAgLnNpbXBsZS1ub3RpZmljYXRpb24uZXJyb3IgLnNuLXByb2dyZXNzLWxvYWRlciBzcGFuIHsgYmFja2dyb3VuZDogI0QzMkYyRjsgfVxyXG4gICAgICAgIC5zaW1wbGUtbm90aWZpY2F0aW9uLmFsZXJ0IC5zbi1wcm9ncmVzcy1sb2FkZXIgc3BhbiB7IGJhY2tncm91bmQ6ICNlZGMyNDI7IH1cclxuICAgICAgICAuc2ltcGxlLW5vdGlmaWNhdGlvbi5pbmZvIC5zbi1wcm9ncmVzcy1sb2FkZXIgc3BhbiB7IGJhY2tncm91bmQ6ICMwMjg4RDE7IH1cclxuICAgICAgICAuc2ltcGxlLW5vdGlmaWNhdGlvbi5iYXJlIC5zbi1wcm9ncmVzcy1sb2FkZXIgc3BhbiB7IGJhY2tncm91bmQ6ICNjY2M7IH1cclxuICAgIGBdXHJcbn0pXHJcblxyXG5leHBvcnQgY2xhc3MgTm90aWZpY2F0aW9uQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xyXG5cclxuICAgIEBJbnB1dCgpIHB1YmxpYyB0aW1lT3V0OiBudW1iZXI7XHJcbiAgICBASW5wdXQoKSBwdWJsaWMgc2hvd1Byb2dyZXNzQmFyOiBib29sZWFuO1xyXG4gICAgQElucHV0KCkgcHVibGljIHBhdXNlT25Ib3ZlcjogYm9vbGVhbjtcclxuICAgIEBJbnB1dCgpIHB1YmxpYyBjbGlja1RvQ2xvc2U6IGJvb2xlYW47XHJcbiAgICBASW5wdXQoKSBwdWJsaWMgbWF4TGVuZ3RoOiBudW1iZXI7XHJcbiAgICBASW5wdXQoKSBwdWJsaWMgdGhlQ2xhc3M6IHN0cmluZztcclxuICAgIEBJbnB1dCgpIHB1YmxpYyBydGw6IGJvb2xlYW47XHJcbiAgICBASW5wdXQoKSBwdWJsaWMgYW5pbWF0ZTogc3RyaW5nO1xyXG4gICAgQElucHV0KCkgcHVibGljIHBvc2l0aW9uOiBudW1iZXI7XHJcbiAgICBASW5wdXQoKSBwdWJsaWMgaXRlbTogTm90aWZpY2F0aW9uO1xyXG5cclxuXHJcbiAgICAvLyBQcm9ncmVzcyBiYXIgdmFyaWFibGVzXHJcbiAgICBwdWJsaWMgcHJvZ3Jlc3NXaWR0aDogbnVtYmVyID0gMDtcclxuICAgIHByaXZhdGUgc3RvcFRpbWU6IGJvb2xlYW4gPSBmYWxzZTtcclxuICAgIHByaXZhdGUgdGltZXI6IGFueTtcclxuICAgIHByaXZhdGUgc3RlcHM6IG51bWJlcjtcclxuICAgIHByaXZhdGUgc3BlZWQ6IG51bWJlcjtcclxuICAgIHByaXZhdGUgY291bnQ6IG51bWJlciA9IDA7XHJcbiAgICBwcml2YXRlIHN0YXJ0OiBhbnk7XHJcbiAgICBwcml2YXRlIGRpZmY6IGFueTtcclxuXHJcbiAgICBwcml2YXRlIHNhZmVTdmc6IFNhZmVIdG1sO1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKFxyXG4gICAgICAgIHByaXZhdGUgbm90aWZpY2F0aW9uU2VydmljZTogTm90aWZpY2F0aW9uc1NlcnZpY2UsXHJcbiAgICAgICAgcHJpdmF0ZSBkb21TYW5pdGl6ZXI6IERvbVNhbml0aXplcixcclxuICAgICAgICBwcml2YXRlIHpvbmU6IE5nWm9uZVxyXG4gICAgKSB7fVxyXG5cclxuICAgIG5nT25Jbml0KCk6IHZvaWQge1xyXG4gICAgICAgIGlmICh0aGlzLmFuaW1hdGUpIHtcclxuICAgICAgICAgICAgdGhpcy5pdGVtLnN0YXRlID0gdGhpcy5hbmltYXRlO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAodGhpcy5pdGVtLm92ZXJyaWRlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuYXR0YWNoT3ZlcnJpZGVzKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmICh0aGlzLnRpbWVPdXQgIT09IDApIHtcclxuICAgICAgICAgICAgdGhpcy5zdGFydFRpbWVPdXQoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuc2FmZVN2ZyA9IHRoaXMuZG9tU2FuaXRpemVyLmJ5cGFzc1NlY3VyaXR5VHJ1c3RIdG1sKHRoaXMuaXRlbS5pY29uKTtcclxuICAgIH1cclxuXHJcbiAgICBzdGFydFRpbWVPdXQoKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5zdGVwcyA9IHRoaXMudGltZU91dCAvIDEwO1xyXG4gICAgICAgIHRoaXMuc3BlZWQgPSB0aGlzLnRpbWVPdXQgLyB0aGlzLnN0ZXBzO1xyXG4gICAgICAgIHRoaXMuc3RhcnQgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcclxuICAgICAgICB0aGlzLnpvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4gdGhpcy50aW1lciA9IHNldFRpbWVvdXQodGhpcy5pbnN0YW5jZSwgdGhpcy5zcGVlZCkpO1xyXG4gICAgfVxyXG5cclxuICAgIG9uRW50ZXIoKTogdm9pZCB7XHJcbiAgICAgICAgaWYgKHRoaXMucGF1c2VPbkhvdmVyKSB7XHJcbiAgICAgICAgICAgIHRoaXMuc3RvcFRpbWUgPSB0cnVlO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBvbkxlYXZlKCk6IHZvaWQge1xyXG4gICAgICAgIGlmICh0aGlzLnBhdXNlT25Ib3Zlcikge1xyXG4gICAgICAgICAgICB0aGlzLnN0b3BUaW1lID0gZmFsc2U7XHJcbiAgICAgICAgICAgIHNldFRpbWVvdXQodGhpcy5pbnN0YW5jZSwgKHRoaXMuc3BlZWQgLSB0aGlzLmRpZmYpKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgc2V0UG9zaXRpb24oKTogbnVtYmVyIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5wb3NpdGlvbiAhPT0gMCA/IHRoaXMucG9zaXRpb24gKiA5MCA6IDA7XHJcbiAgICB9XHJcblxyXG4gICAgb25DbGljaygkZTogYW55KTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5pdGVtLmNsaWNrLmVtaXQoJGUpO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5jbGlja1RvQ2xvc2UpIHtcclxuICAgICAgICAgICAgdGhpcy5yZW1vdmUoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQXR0YWNoIGFsbCB0aGUgb3ZlcnJpZGVzXHJcbiAgICBhdHRhY2hPdmVycmlkZXMoKTogdm9pZCB7XHJcbiAgICAgICAgT2JqZWN0LmtleXModGhpcy5pdGVtLm92ZXJyaWRlKS5mb3JFYWNoKGEgPT4ge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5oYXNPd25Qcm9wZXJ0eShhKSkge1xyXG4gICAgICAgICAgICAgICAgKDxhbnk+dGhpcylbYV0gPSB0aGlzLml0ZW0ub3ZlcnJpZGVbYV07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy50aW1lcik7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBpbnN0YW5jZSA9ICgpID0+IHtcclxuICAgICAgICB0aGlzLnpvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLnpvbmUucnVuKCgpID0+IHRoaXMuZGlmZiA9IChuZXcgRGF0ZSgpLmdldFRpbWUoKSAtIHRoaXMuc3RhcnQpIC0gKHRoaXMuY291bnQgKiB0aGlzLnNwZWVkKSk7XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5jb3VudCsrID09PSB0aGlzLnN0ZXBzKSB0aGlzLnpvbmUucnVuKCgpID0+IHRoaXMucmVtb3ZlKCkpO1xyXG4gICAgICAgICAgICBlbHNlIGlmICghdGhpcy5zdG9wVGltZSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2hvd1Byb2dyZXNzQmFyKSB0aGlzLnpvbmUucnVuKCgpID0+IHRoaXMucHJvZ3Jlc3NXaWR0aCArPSAxMDAgLyB0aGlzLnN0ZXBzKTtcclxuXHJcbiAgICAgICAgICAgICAgICB0aGlzLnRpbWVyID0gc2V0VGltZW91dCh0aGlzLmluc3RhbmNlLCAodGhpcy5zcGVlZCAtIHRoaXMuZGlmZikpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSlcclxuICAgIH07XHJcblxyXG4gICAgcHJpdmF0ZSByZW1vdmUoKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuYW5pbWF0ZSkge1xyXG4gICAgICAgICAgICB0aGlzLml0ZW0uc3RhdGUgPSB0aGlzLmFuaW1hdGUgKyAnT3V0JztcclxuICAgICAgICAgICAgdGhpcy56b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcclxuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuem9uZS5ydW4oKCkgPT4gdGhpcy5ub3RpZmljYXRpb25TZXJ2aWNlLnNldCh0aGlzLml0ZW0sIGZhbHNlKSlcclxuICAgICAgICAgICAgICAgIH0sIDMxMCk7XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhpcy5ub3RpZmljYXRpb25TZXJ2aWNlLnNldCh0aGlzLml0ZW0sIGZhbHNlKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIG5vZGVfbW9kdWxlcy9hbmd1bGFyMi10ZW1wbGF0ZS1sb2FkZXIhLi9+L2FuZ3VsYXIyLW5vdGlmaWNhdGlvbnMvc3JjL25vdGlmaWNhdGlvbi5jb21wb25lbnQudHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQXFLQTtBQTBCQTtBQTFCQTtBQTJCQTtBQUNBO0FBQ0E7QUFmQTtBQUNBO0FBQ0E7QUFJQTtBQXVFQTtBQUNBO0FBQ0E7QUFFQTtBQUFBO0FBQ0E7QUFDQTtBQUFBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUF4RUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFlQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBakhBO0FBQUE7O0FBQUE7QUFDQTtBQUFBOztBQUFBO0FBQ0E7QUFBQTs7QUFBQTtBQUNBO0FBQUE7O0FBQUE7QUFDQTtBQUFBOztBQUFBO0FBQ0E7QUFBQTs7QUFBQTtBQUNBO0FBQUE7O0FBQUE7QUFDQTtBQUFBOztBQUFBO0FBQ0E7QUFBQTs7QUFBQTtBQUNBO0FBQUE7O0FBQUE7QUEvS0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQWdDQTtBQTJFQTs7QUFBQTtBQXNIQTs7QUFBQTtBQXBIQTsiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ },
- /* 70 */
- /***/ function(module, exports) {
- eval("\"use strict\";\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNzAuanMiLCJzb3VyY2VzIjpbXSwibWFwcGluZ3MiOiI7Iiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 71 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar core_1 = __webpack_require__(4);\nvar MaxPipe = (function () {\n function MaxPipe() {\n }\n MaxPipe.prototype.transform = function (value) {\n var args = [];\n for (var _i = 1; _i < arguments.length; _i++) {\n args[_i - 1] = arguments[_i];\n }\n var allowed = args[0];\n var received = value.length;\n if (received > allowed && allowed !== 0) {\n var toCut = allowed - received;\n return value.slice(0, toCut);\n }\n return value;\n };\n MaxPipe = __decorate([\n core_1.Pipe({ name: 'max' }), \n __metadata('design:paramtypes', [])\n ], MaxPipe);\n return MaxPipe;\n}());\nexports.MaxPipe = MaxPipe;\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNzEuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2FuZ3VsYXIyLW5vdGlmaWNhdGlvbnMvc3JjL21heC5waXBlLnRzP2Y3MjUiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtQaXBlLCBQaXBlVHJhbnNmb3JtfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuXHJcbkBQaXBlKHtuYW1lOiAnbWF4J30pXHJcbmV4cG9ydCBjbGFzcyBNYXhQaXBlIGltcGxlbWVudHMgUGlwZVRyYW5zZm9ybSB7XHJcbiAgdHJhbnNmb3JtKHZhbHVlOiBzdHJpbmcsIC4uLmFyZ3M6IGFueVtdKTogYW55IHtcclxuICAgIGxldCBhbGxvd2VkID0gYXJnc1swXTtcclxuICAgIGxldCByZWNlaXZlZCA9IHZhbHVlLmxlbmd0aDtcclxuXHJcbiAgICBpZiAocmVjZWl2ZWQgPiBhbGxvd2VkICYmIGFsbG93ZWQgIT09IDApIHtcclxuICAgICAgbGV0IHRvQ3V0ID0gYWxsb3dlZCAtIHJlY2VpdmVkO1xyXG4gICAgICByZXR1cm4gdmFsdWUuc2xpY2UoMCwgdG9DdXQpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB2YWx1ZTtcclxuICB9XHJcbn1cclxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIG5vZGVfbW9kdWxlcy9hbmd1bGFyMi10ZW1wbGF0ZS1sb2FkZXIhLi9+L2FuZ3VsYXIyLW5vdGlmaWNhdGlvbnMvc3JjL21heC5waXBlLnRzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUE7QUFHQTtBQUFBO0FBWUE7QUFYQTtBQUFBO0FBQUE7QUFBQTs7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBWkE7QUFBQTs7QUFBQTtBQWFBO0FBQUE7QUFaQTsiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ },
- /* 72 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar core_1 = __webpack_require__(4);\nvar push_notifications_service_1 = __webpack_require__(73);\nvar PushNotificationsModule = (function () {\n function PushNotificationsModule() {\n }\n PushNotificationsModule = __decorate([\n core_1.NgModule({\n providers: [push_notifications_service_1.PushNotificationsService]\n }), \n __metadata('design:paramtypes', [])\n ], PushNotificationsModule);\n return PushNotificationsModule;\n}());\nexports.PushNotificationsModule = PushNotificationsModule;\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNzIuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2FuZ3VsYXIyLW5vdGlmaWNhdGlvbnMvc3JjL3B1c2gtbm90aWZpY2F0aW9ucy5tb2R1bGUudHM/ZmRiOSJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge05nTW9kdWxlfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHtQdXNoTm90aWZpY2F0aW9uc1NlcnZpY2V9IGZyb20gJy4vcHVzaC1ub3RpZmljYXRpb25zLnNlcnZpY2UnO1xyXG5cclxuQE5nTW9kdWxlKHtcclxuICAgIHByb3ZpZGVyczogW1B1c2hOb3RpZmljYXRpb25zU2VydmljZV1cclxufSlcclxuZXhwb3J0IGNsYXNzIFB1c2hOb3RpZmljYXRpb25zTW9kdWxlIHt9XG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIG5vZGVfbW9kdWxlcy9hbmd1bGFyMi10ZW1wbGF0ZS1sb2FkZXIhLi9+L2FuZ3VsYXIyLW5vdGlmaWNhdGlvbnMvc3JjL3B1c2gtbm90aWZpY2F0aW9ucy5tb2R1bGUudHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBS0E7QUFBQTtBQUFBO0FBSEE7QUFBQTtBQUNBO0FBQ0E7O0FBQUE7QUFDQTtBQUFBO0FBQUE7Iiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 73 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar core_1 = __webpack_require__(4);\nvar Observable_1 = __webpack_require__(6);\nvar PushNotificationsService = (function () {\n function PushNotificationsService() {\n this.permission = this.isSupported() ? Notification.permission : 'denied';\n }\n PushNotificationsService.prototype.requestPermission = function () {\n var _this = this;\n if ('Notification' in window)\n Notification.requestPermission(function (status) { return _this.permission = status; });\n };\n PushNotificationsService.prototype.isSupported = function () {\n return 'Notification' in window;\n };\n PushNotificationsService.prototype.create = function (title, options) {\n var _this = this;\n return new Observable_1.Observable(function (obs) {\n if (!('Notification' in window)) {\n obs.error('Notifications are not available in this environment');\n obs.complete();\n }\n if (_this.permission !== 'granted') {\n obs.error(\"The user hasn't granted you permission to send push notifications\");\n obs.complete();\n }\n var n = new Notification(title, options);\n n.onshow = function (e) { return obs.next({ notification: n, event: e }); };\n n.onclick = function (e) { return obs.next({ notification: n, event: e }); };\n n.onerror = function (e) { return obs.error({ notification: n, event: e }); };\n n.onclose = function () { return obs.complete(); };\n });\n };\n PushNotificationsService = __decorate([\n core_1.Injectable(), \n __metadata('design:paramtypes', [])\n ], PushNotificationsService);\n return PushNotificationsService;\n}());\nexports.PushNotificationsService = PushNotificationsService;\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNzMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2FuZ3VsYXIyLW5vdGlmaWNhdGlvbnMvc3JjL3B1c2gtbm90aWZpY2F0aW9ucy5zZXJ2aWNlLnRzP2EwZWQiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtJbmplY3RhYmxlfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHtPYnNlcnZhYmxlfSBmcm9tICdyeGpzL09ic2VydmFibGUnO1xyXG5pbXBvcnQge1B1c2hOb3RpZmljYXRpb24sIFBlcm1pc3Npb259IGZyb20gJy4vcHVzaC1ub3RpZmljYXRpb24udHlwZSc7XHJcblxyXG5kZWNsYXJlIGNvbnN0IE5vdGlmaWNhdGlvbjogYW55O1xyXG5cclxuQEluamVjdGFibGUoKVxyXG5leHBvcnQgY2xhc3MgUHVzaE5vdGlmaWNhdGlvbnNTZXJ2aWNlIHtcclxuXHJcbiAgICBwZXJtaXNzaW9uOiBQZXJtaXNzaW9uO1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKCkge1xyXG4gICAgICAgIHRoaXMucGVybWlzc2lvbiAgPSB0aGlzLmlzU3VwcG9ydGVkKCkgPyBOb3RpZmljYXRpb24ucGVybWlzc2lvbiA6ICdkZW5pZWQnO1xyXG4gICAgfVxyXG5cclxuICAgIHJlcXVlc3RQZXJtaXNzaW9uKCkge1xyXG4gICAgICAgIGlmICgnTm90aWZpY2F0aW9uJyBpbiB3aW5kb3cpXHJcbiAgICAgICAgICAgIE5vdGlmaWNhdGlvbi5yZXF1ZXN0UGVybWlzc2lvbigoc3RhdHVzOiBhbnkpID0+IHRoaXMucGVybWlzc2lvbiA9IHN0YXR1cyk7XHJcbiAgICB9XHJcblxyXG4gICAgaXNTdXBwb3J0ZWQoKSB7XHJcbiAgICAgICAgcmV0dXJuICdOb3RpZmljYXRpb24nIGluIHdpbmRvdztcclxuICAgIH1cclxuXHJcbiAgICBjcmVhdGUodGl0bGU6IHN0cmluZywgb3B0aW9ucz86IFB1c2hOb3RpZmljYXRpb24pOiBhbnkge1xyXG5cclxuICAgICAgICByZXR1cm4gbmV3IE9ic2VydmFibGUoKG9iczogYW55KSA9PiB7XHJcblxyXG4gICAgICAgICAgICBpZiAoISgnTm90aWZpY2F0aW9uJyBpbiB3aW5kb3cpKSB7XHJcbiAgICAgICAgICAgICAgICBvYnMuZXJyb3IoJ05vdGlmaWNhdGlvbnMgYXJlIG5vdCBhdmFpbGFibGUgaW4gdGhpcyBlbnZpcm9ubWVudCcpO1xyXG4gICAgICAgICAgICAgICAgb2JzLmNvbXBsZXRlKCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLnBlcm1pc3Npb24gIT09ICdncmFudGVkJykge1xyXG4gICAgICAgICAgICAgICAgb2JzLmVycm9yKGBUaGUgdXNlciBoYXNuJ3QgZ3JhbnRlZCB5b3UgcGVybWlzc2lvbiB0byBzZW5kIHB1c2ggbm90aWZpY2F0aW9uc2ApO1xyXG4gICAgICAgICAgICAgICAgb2JzLmNvbXBsZXRlKCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGNvbnN0IG4gPSBuZXcgTm90aWZpY2F0aW9uKHRpdGxlLCBvcHRpb25zKTtcclxuXHJcbiAgICAgICAgICAgIG4ub25zaG93ID0gKGU6IGFueSkgPT4gb2JzLm5leHQoe25vdGlmaWNhdGlvbjogbiwgZXZlbnQ6IGV9KTtcclxuICAgICAgICAgICAgbi5vbmNsaWNrID0gKGU6IGFueSkgPT4gb2JzLm5leHQoe25vdGlmaWNhdGlvbjogbiwgZXZlbnQ6IGV9KTtcclxuICAgICAgICAgICAgbi5vbmVycm9yID0gKGU6IGFueSkgPT4gb2JzLmVycm9yKHtub3RpZmljYXRpb246IG4sIGV2ZW50OiBlfSk7XHJcbiAgICAgICAgICAgIG4ub25jbG9zZSA9ICgpID0+IG9icy5jb21wbGV0ZSgpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxufVxyXG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gbm9kZV9tb2R1bGVzL2FuZ3VsYXIyLXRlbXBsYXRlLWxvYWRlciEuL34vYW5ndWxhcjItbm90aWZpY2F0aW9ucy9zcmMvcHVzaC1ub3RpZmljYXRpb25zLnNlcnZpY2UudHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBTUE7QUFJQTtBQUNBO0FBQ0E7QUFFQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBdkNBO0FBQUE7O0FBQUE7QUF5Q0E7QUFBQTtBQXhDQTsiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ },
- /* 74 */
- /***/ function(module, exports, __webpack_require__) {
- eval("var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(global, module) {/**\n * @license\n * Lodash <https://lodash.com/>\n * Copyright JS Foundation and other contributors <https://js.foundation/>\n * Released under MIT license <https://lodash.com/license>\n * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>\n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n */\n;(function() {\n\n /** Used as a safe reference for `undefined` in pre-ES5 environments. */\n var undefined;\n\n /** Used as the semantic version number. */\n var VERSION = '4.17.3';\n\n /** Used as the size to enable large array optimizations. */\n var LARGE_ARRAY_SIZE = 200;\n\n /** Error message constants. */\n var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',\n FUNC_ERROR_TEXT = 'Expected a function';\n\n /** Used to stand-in for `undefined` hash values. */\n var HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n /** Used as the maximum memoize cache size. */\n var MAX_MEMOIZE_SIZE = 500;\n\n /** Used as the internal argument placeholder. */\n var PLACEHOLDER = '__lodash_placeholder__';\n\n /** Used to compose bitmasks for cloning. */\n var CLONE_DEEP_FLAG = 1,\n CLONE_FLAT_FLAG = 2,\n CLONE_SYMBOLS_FLAG = 4;\n\n /** Used to compose bitmasks for value comparisons. */\n var COMPARE_PARTIAL_FLAG = 1,\n COMPARE_UNORDERED_FLAG = 2;\n\n /** Used to compose bitmasks for function metadata. */\n var WRAP_BIND_FLAG = 1,\n WRAP_BIND_KEY_FLAG = 2,\n WRAP_CURRY_BOUND_FLAG = 4,\n WRAP_CURRY_FLAG = 8,\n WRAP_CURRY_RIGHT_FLAG = 16,\n WRAP_PARTIAL_FLAG = 32,\n WRAP_PARTIAL_RIGHT_FLAG = 64,\n WRAP_ARY_FLAG = 128,\n WRAP_REARG_FLAG = 256,\n WRAP_FLIP_FLAG = 512;\n\n /** Used as default options for `_.truncate`. */\n var DEFAULT_TRUNC_LENGTH = 30,\n DEFAULT_TRUNC_OMISSION = '...';\n\n /** Used to detect hot functions by number of calls within a span of milliseconds. */\n var HOT_COUNT = 800,\n HOT_SPAN = 16;\n\n /** Used to indicate the type of lazy iteratees. */\n var LAZY_FILTER_FLAG = 1,\n LAZY_MAP_FLAG = 2,\n LAZY_WHILE_FLAG = 3;\n\n /** Used as references for various `Number` constants. */\n var INFINITY = 1 / 0,\n MAX_SAFE_INTEGER = 9007199254740991,\n MAX_INTEGER = 1.7976931348623157e+308,\n NAN = 0 / 0;\n\n /** Used as references for the maximum length and index of an array. */\n var MAX_ARRAY_LENGTH = 4294967295,\n MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,\n HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;\n\n /** Used to associate wrap methods with their bit flags. */\n var wrapFlags = [\n ['ary', WRAP_ARY_FLAG],\n ['bind', WRAP_BIND_FLAG],\n ['bindKey', WRAP_BIND_KEY_FLAG],\n ['curry', WRAP_CURRY_FLAG],\n ['curryRight', WRAP_CURRY_RIGHT_FLAG],\n ['flip', WRAP_FLIP_FLAG],\n ['partial', WRAP_PARTIAL_FLAG],\n ['partialRight', WRAP_PARTIAL_RIGHT_FLAG],\n ['rearg', WRAP_REARG_FLAG]\n ];\n\n /** `Object#toString` result references. */\n var argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n asyncTag = '[object AsyncFunction]',\n boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n domExcTag = '[object DOMException]',\n errorTag = '[object Error]',\n funcTag = '[object Function]',\n genTag = '[object GeneratorFunction]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n nullTag = '[object Null]',\n objectTag = '[object Object]',\n promiseTag = '[object Promise]',\n proxyTag = '[object Proxy]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n symbolTag = '[object Symbol]',\n undefinedTag = '[object Undefined]',\n weakMapTag = '[object WeakMap]',\n weakSetTag = '[object WeakSet]';\n\n var arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]',\n float32Tag = '[object Float32Array]',\n float64Tag = '[object Float64Array]',\n int8Tag = '[object Int8Array]',\n int16Tag = '[object Int16Array]',\n int32Tag = '[object Int32Array]',\n uint8Tag = '[object Uint8Array]',\n uint8ClampedTag = '[object Uint8ClampedArray]',\n uint16Tag = '[object Uint16Array]',\n uint32Tag = '[object Uint32Array]';\n\n /** Used to match empty string literals in compiled template source. */\n var reEmptyStringLeading = /\\b__p \\+= '';/g,\n reEmptyStringMiddle = /\\b(__p \\+=) '' \\+/g,\n reEmptyStringTrailing = /(__e\\(.*?\\)|\\b__t\\)) \\+\\n'';/g;\n\n /** Used to match HTML entities and HTML characters. */\n var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g,\n reUnescapedHtml = /[&<>\"']/g,\n reHasEscapedHtml = RegExp(reEscapedHtml.source),\n reHasUnescapedHtml = RegExp(reUnescapedHtml.source);\n\n /** Used to match template delimiters. */\n var reEscape = /<%-([\\s\\S]+?)%>/g,\n reEvaluate = /<%([\\s\\S]+?)%>/g,\n reInterpolate = /<%=([\\s\\S]+?)%>/g;\n\n /** Used to match property names within property paths. */\n var reIsDeepProp = /\\.|\\[(?:[^[\\]]*|([\"'])(?:(?!\\1)[^\\\\]|\\\\.)*?\\1)\\]/,\n reIsPlainProp = /^\\w*$/,\n reLeadingDot = /^\\./,\n rePropName = /[^.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2)\\]|(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))/g;\n\n /**\n * Used to match `RegExp`\n * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).\n */\n var reRegExpChar = /[\\\\^$.*+?()[\\]{}|]/g,\n reHasRegExpChar = RegExp(reRegExpChar.source);\n\n /** Used to match leading and trailing whitespace. */\n var reTrim = /^\\s+|\\s+$/g,\n reTrimStart = /^\\s+/,\n reTrimEnd = /\\s+$/;\n\n /** Used to match wrap detail comments. */\n var reWrapComment = /\\{(?:\\n\\/\\* \\[wrapped with .+\\] \\*\\/)?\\n?/,\n reWrapDetails = /\\{\\n\\/\\* \\[wrapped with (.+)\\] \\*/,\n reSplitDetails = /,? & /;\n\n /** Used to match words composed of alphanumeric characters. */\n var reAsciiWord = /[^\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\x7f]+/g;\n\n /** Used to match backslashes in property paths. */\n var reEscapeChar = /\\\\(\\\\)?/g;\n\n /**\n * Used to match\n * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components).\n */\n var reEsTemplate = /\\$\\{([^\\\\}]*(?:\\\\.[^\\\\}]*)*)\\}/g;\n\n /** Used to match `RegExp` flags from their coerced string values. */\n var reFlags = /\\w*$/;\n\n /** Used to detect bad signed hexadecimal string values. */\n var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;\n\n /** Used to detect binary string values. */\n var reIsBinary = /^0b[01]+$/i;\n\n /** Used to detect host constructors (Safari). */\n var reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n /** Used to detect octal string values. */\n var reIsOctal = /^0o[0-7]+$/i;\n\n /** Used to detect unsigned integer values. */\n var reIsUint = /^(?:0|[1-9]\\d*)$/;\n\n /** Used to match Latin Unicode letters (excluding mathematical operators). */\n var reLatin = /[\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\xff\\u0100-\\u017f]/g;\n\n /** Used to ensure capturing order of template delimiters. */\n var reNoMatch = /($^)/;\n\n /** Used to match unescaped characters in compiled string literals. */\n var reUnescapedString = /['\\n\\r\\u2028\\u2029\\\\]/g;\n\n /** Used to compose unicode character classes. */\n var rsAstralRange = '\\\\ud800-\\\\udfff',\n rsComboMarksRange = '\\\\u0300-\\\\u036f',\n reComboHalfMarksRange = '\\\\ufe20-\\\\ufe2f',\n rsComboSymbolsRange = '\\\\u20d0-\\\\u20ff',\n rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,\n rsDingbatRange = '\\\\u2700-\\\\u27bf',\n rsLowerRange = 'a-z\\\\xdf-\\\\xf6\\\\xf8-\\\\xff',\n rsMathOpRange = '\\\\xac\\\\xb1\\\\xd7\\\\xf7',\n rsNonCharRange = '\\\\x00-\\\\x2f\\\\x3a-\\\\x40\\\\x5b-\\\\x60\\\\x7b-\\\\xbf',\n rsPunctuationRange = '\\\\u2000-\\\\u206f',\n rsSpaceRange = ' \\\\t\\\\x0b\\\\f\\\\xa0\\\\ufeff\\\\n\\\\r\\\\u2028\\\\u2029\\\\u1680\\\\u180e\\\\u2000\\\\u2001\\\\u2002\\\\u2003\\\\u2004\\\\u2005\\\\u2006\\\\u2007\\\\u2008\\\\u2009\\\\u200a\\\\u202f\\\\u205f\\\\u3000',\n rsUpperRange = 'A-Z\\\\xc0-\\\\xd6\\\\xd8-\\\\xde',\n rsVarRange = '\\\\ufe0e\\\\ufe0f',\n rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;\n\n /** Used to compose unicode capture groups. */\n var rsApos = \"['\\u2019]\",\n rsAstral = '[' + rsAstralRange + ']',\n rsBreak = '[' + rsBreakRange + ']',\n rsCombo = '[' + rsComboRange + ']',\n rsDigits = '\\\\d+',\n rsDingbat = '[' + rsDingbatRange + ']',\n rsLower = '[' + rsLowerRange + ']',\n rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',\n rsFitz = '\\\\ud83c[\\\\udffb-\\\\udfff]',\n rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',\n rsNonAstral = '[^' + rsAstralRange + ']',\n rsRegional = '(?:\\\\ud83c[\\\\udde6-\\\\uddff]){2}',\n rsSurrPair = '[\\\\ud800-\\\\udbff][\\\\udc00-\\\\udfff]',\n rsUpper = '[' + rsUpperRange + ']',\n rsZWJ = '\\\\u200d';\n\n /** Used to compose unicode regexes. */\n var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')',\n rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')',\n rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',\n rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',\n reOptMod = rsModifier + '?',\n rsOptVar = '[' + rsVarRange + ']?',\n rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',\n rsOrdLower = '\\\\d*(?:(?:1st|2nd|3rd|(?![123])\\\\dth)\\\\b)',\n rsOrdUpper = '\\\\d*(?:(?:1ST|2ND|3RD|(?![123])\\\\dTH)\\\\b)',\n rsSeq = rsOptVar + reOptMod + rsOptJoin,\n rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq,\n rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';\n\n /** Used to match apostrophes. */\n var reApos = RegExp(rsApos, 'g');\n\n /**\n * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and\n * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).\n */\n var reComboMark = RegExp(rsCombo, 'g');\n\n /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */\n var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');\n\n /** Used to match complex or compound words. */\n var reUnicodeWord = RegExp([\n rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',\n rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')',\n rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower,\n rsUpper + '+' + rsOptContrUpper,\n rsOrdUpper,\n rsOrdLower,\n rsDigits,\n rsEmoji\n ].join('|'), 'g');\n\n /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */\n var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');\n\n /** Used to detect strings that need a more robust regexp to match words. */\n var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;\n\n /** Used to assign default `context` object properties. */\n var contextProps = [\n 'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array',\n 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object',\n 'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array',\n 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap',\n '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout'\n ];\n\n /** Used to make template sourceURLs easier to identify. */\n var templateCounter = -1;\n\n /** Used to identify `toStringTag` values of typed arrays. */\n var typedArrayTags = {};\n typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =\n typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =\n typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =\n typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =\n typedArrayTags[uint32Tag] = true;\n typedArrayTags[argsTag] = typedArrayTags[arrayTag] =\n typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =\n typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =\n typedArrayTags[errorTag] = typedArrayTags[funcTag] =\n typedArrayTags[mapTag] = typedArrayTags[numberTag] =\n typedArrayTags[objectTag] = typedArrayTags[regexpTag] =\n typedArrayTags[setTag] = typedArrayTags[stringTag] =\n typedArrayTags[weakMapTag] = false;\n\n /** Used to identify `toStringTag` values supported by `_.clone`. */\n var cloneableTags = {};\n cloneableTags[argsTag] = cloneableTags[arrayTag] =\n cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =\n cloneableTags[boolTag] = cloneableTags[dateTag] =\n cloneableTags[float32Tag] = cloneableTags[float64Tag] =\n cloneableTags[int8Tag] = cloneableTags[int16Tag] =\n cloneableTags[int32Tag] = cloneableTags[mapTag] =\n cloneableTags[numberTag] = cloneableTags[objectTag] =\n cloneableTags[regexpTag] = cloneableTags[setTag] =\n cloneableTags[stringTag] = cloneableTags[symbolTag] =\n cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =\n cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;\n cloneableTags[errorTag] = cloneableTags[funcTag] =\n cloneableTags[weakMapTag] = false;\n\n /** Used to map Latin Unicode letters to basic Latin letters. */\n var deburredLetters = {\n // Latin-1 Supplement block.\n '\\xc0': 'A', '\\xc1': 'A', '\\xc2': 'A', '\\xc3': 'A', '\\xc4': 'A', '\\xc5': 'A',\n '\\xe0': 'a', '\\xe1': 'a', '\\xe2': 'a', '\\xe3': 'a', '\\xe4': 'a', '\\xe5': 'a',\n '\\xc7': 'C', '\\xe7': 'c',\n '\\xd0': 'D', '\\xf0': 'd',\n '\\xc8': 'E', '\\xc9': 'E', '\\xca': 'E', '\\xcb': 'E',\n '\\xe8': 'e', '\\xe9': 'e', '\\xea': 'e', '\\xeb': 'e',\n '\\xcc': 'I', '\\xcd': 'I', '\\xce': 'I', '\\xcf': 'I',\n '\\xec': 'i', '\\xed': 'i', '\\xee': 'i', '\\xef': 'i',\n '\\xd1': 'N', '\\xf1': 'n',\n '\\xd2': 'O', '\\xd3': 'O', '\\xd4': 'O', '\\xd5': 'O', '\\xd6': 'O', '\\xd8': 'O',\n '\\xf2': 'o', '\\xf3': 'o', '\\xf4': 'o', '\\xf5': 'o', '\\xf6': 'o', '\\xf8': 'o',\n '\\xd9': 'U', '\\xda': 'U', '\\xdb': 'U', '\\xdc': 'U',\n '\\xf9': 'u', '\\xfa': 'u', '\\xfb': 'u', '\\xfc': 'u',\n '\\xdd': 'Y', '\\xfd': 'y', '\\xff': 'y',\n '\\xc6': 'Ae', '\\xe6': 'ae',\n '\\xde': 'Th', '\\xfe': 'th',\n '\\xdf': 'ss',\n // Latin Extended-A block.\n '\\u0100': 'A', '\\u0102': 'A', '\\u0104': 'A',\n '\\u0101': 'a', '\\u0103': 'a', '\\u0105': 'a',\n '\\u0106': 'C', '\\u0108': 'C', '\\u010a': 'C', '\\u010c': 'C',\n '\\u0107': 'c', '\\u0109': 'c', '\\u010b': 'c', '\\u010d': 'c',\n '\\u010e': 'D', '\\u0110': 'D', '\\u010f': 'd', '\\u0111': 'd',\n '\\u0112': 'E', '\\u0114': 'E', '\\u0116': 'E', '\\u0118': 'E', '\\u011a': 'E',\n '\\u0113': 'e', '\\u0115': 'e', '\\u0117': 'e', '\\u0119': 'e', '\\u011b': 'e',\n '\\u011c': 'G', '\\u011e': 'G', '\\u0120': 'G', '\\u0122': 'G',\n '\\u011d': 'g', '\\u011f': 'g', '\\u0121': 'g', '\\u0123': 'g',\n '\\u0124': 'H', '\\u0126': 'H', '\\u0125': 'h', '\\u0127': 'h',\n '\\u0128': 'I', '\\u012a': 'I', '\\u012c': 'I', '\\u012e': 'I', '\\u0130': 'I',\n '\\u0129': 'i', '\\u012b': 'i', '\\u012d': 'i', '\\u012f': 'i', '\\u0131': 'i',\n '\\u0134': 'J', '\\u0135': 'j',\n '\\u0136': 'K', '\\u0137': 'k', '\\u0138': 'k',\n '\\u0139': 'L', '\\u013b': 'L', '\\u013d': 'L', '\\u013f': 'L', '\\u0141': 'L',\n '\\u013a': 'l', '\\u013c': 'l', '\\u013e': 'l', '\\u0140': 'l', '\\u0142': 'l',\n '\\u0143': 'N', '\\u0145': 'N', '\\u0147': 'N', '\\u014a': 'N',\n '\\u0144': 'n', '\\u0146': 'n', '\\u0148': 'n', '\\u014b': 'n',\n '\\u014c': 'O', '\\u014e': 'O', '\\u0150': 'O',\n '\\u014d': 'o', '\\u014f': 'o', '\\u0151': 'o',\n '\\u0154': 'R', '\\u0156': 'R', '\\u0158': 'R',\n '\\u0155': 'r', '\\u0157': 'r', '\\u0159': 'r',\n '\\u015a': 'S', '\\u015c': 'S', '\\u015e': 'S', '\\u0160': 'S',\n '\\u015b': 's', '\\u015d': 's', '\\u015f': 's', '\\u0161': 's',\n '\\u0162': 'T', '\\u0164': 'T', '\\u0166': 'T',\n '\\u0163': 't', '\\u0165': 't', '\\u0167': 't',\n '\\u0168': 'U', '\\u016a': 'U', '\\u016c': 'U', '\\u016e': 'U', '\\u0170': 'U', '\\u0172': 'U',\n '\\u0169': 'u', '\\u016b': 'u', '\\u016d': 'u', '\\u016f': 'u', '\\u0171': 'u', '\\u0173': 'u',\n '\\u0174': 'W', '\\u0175': 'w',\n '\\u0176': 'Y', '\\u0177': 'y', '\\u0178': 'Y',\n '\\u0179': 'Z', '\\u017b': 'Z', '\\u017d': 'Z',\n '\\u017a': 'z', '\\u017c': 'z', '\\u017e': 'z',\n '\\u0132': 'IJ', '\\u0133': 'ij',\n '\\u0152': 'Oe', '\\u0153': 'oe',\n '\\u0149': \"'n\", '\\u017f': 's'\n };\n\n /** Used to map characters to HTML entities. */\n var htmlEscapes = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n\n /** Used to map HTML entities to characters. */\n var htmlUnescapes = {\n '&': '&',\n '<': '<',\n '>': '>',\n '"': '\"',\n ''': \"'\"\n };\n\n /** Used to escape characters for inclusion in compiled string literals. */\n var stringEscapes = {\n '\\\\': '\\\\',\n \"'\": \"'\",\n '\\n': 'n',\n '\\r': 'r',\n '\\u2028': 'u2028',\n '\\u2029': 'u2029'\n };\n\n /** Built-in method references without a dependency on `root`. */\n var freeParseFloat = parseFloat,\n freeParseInt = parseInt;\n\n /** Detect free variable `global` from Node.js. */\n var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\n /** Detect free variable `self`. */\n var freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n /** Used as a reference to the global object. */\n var root = freeGlobal || freeSelf || Function('return this')();\n\n /** Detect free variable `exports`. */\n var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n /** Detect free variable `module`. */\n var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n /** Detect the popular CommonJS extension `module.exports`. */\n var moduleExports = freeModule && freeModule.exports === freeExports;\n\n /** Detect free variable `process` from Node.js. */\n var freeProcess = moduleExports && freeGlobal.process;\n\n /** Used to access faster Node.js helpers. */\n var nodeUtil = (function() {\n try {\n return freeProcess && freeProcess.binding && freeProcess.binding('util');\n } catch (e) {}\n }());\n\n /* Node.js helper references. */\n var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer,\n nodeIsDate = nodeUtil && nodeUtil.isDate,\n nodeIsMap = nodeUtil && nodeUtil.isMap,\n nodeIsRegExp = nodeUtil && nodeUtil.isRegExp,\n nodeIsSet = nodeUtil && nodeUtil.isSet,\n nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;\n\n /*--------------------------------------------------------------------------*/\n\n /**\n * Adds the key-value `pair` to `map`.\n *\n * @private\n * @param {Object} map The map to modify.\n * @param {Array} pair The key-value pair to add.\n * @returns {Object} Returns `map`.\n */\n function addMapEntry(map, pair) {\n // Don't return `map.set` because it's not chainable in IE 11.\n map.set(pair[0], pair[1]);\n return map;\n }\n\n /**\n * Adds `value` to `set`.\n *\n * @private\n * @param {Object} set The set to modify.\n * @param {*} value The value to add.\n * @returns {Object} Returns `set`.\n */\n function addSetEntry(set, value) {\n // Don't return `set.add` because it's not chainable in IE 11.\n set.add(value);\n return set;\n }\n\n /**\n * A faster alternative to `Function#apply`, this function invokes `func`\n * with the `this` binding of `thisArg` and the arguments of `args`.\n *\n * @private\n * @param {Function} func The function to invoke.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} args The arguments to invoke `func` with.\n * @returns {*} Returns the result of `func`.\n */\n function apply(func, thisArg, args) {\n switch (args.length) {\n case 0: return func.call(thisArg);\n case 1: return func.call(thisArg, args[0]);\n case 2: return func.call(thisArg, args[0], args[1]);\n case 3: return func.call(thisArg, args[0], args[1], args[2]);\n }\n return func.apply(thisArg, args);\n }\n\n /**\n * A specialized version of `baseAggregator` for arrays.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} setter The function to set `accumulator` values.\n * @param {Function} iteratee The iteratee to transform keys.\n * @param {Object} accumulator The initial aggregated object.\n * @returns {Function} Returns `accumulator`.\n */\n function arrayAggregator(array, setter, iteratee, accumulator) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n var value = array[index];\n setter(accumulator, value, iteratee(value), array);\n }\n return accumulator;\n }\n\n /**\n * A specialized version of `_.forEach` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns `array`.\n */\n function arrayEach(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (iteratee(array[index], index, array) === false) {\n break;\n }\n }\n return array;\n }\n\n /**\n * A specialized version of `_.forEachRight` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns `array`.\n */\n function arrayEachRight(array, iteratee) {\n var length = array == null ? 0 : array.length;\n\n while (length--) {\n if (iteratee(array[length], length, array) === false) {\n break;\n }\n }\n return array;\n }\n\n /**\n * A specialized version of `_.every` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {boolean} Returns `true` if all elements pass the predicate check,\n * else `false`.\n */\n function arrayEvery(array, predicate) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (!predicate(array[index], index, array)) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * A specialized version of `_.filter` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {Array} Returns the new filtered array.\n */\n function arrayFilter(array, predicate) {\n var index = -1,\n length = array == null ? 0 : array.length,\n resIndex = 0,\n result = [];\n\n while (++index < length) {\n var value = array[index];\n if (predicate(value, index, array)) {\n result[resIndex++] = value;\n }\n }\n return result;\n }\n\n /**\n * A specialized version of `_.includes` for arrays without support for\n * specifying an index to search from.\n *\n * @private\n * @param {Array} [array] The array to inspect.\n * @param {*} target The value to search for.\n * @returns {boolean} Returns `true` if `target` is found, else `false`.\n */\n function arrayIncludes(array, value) {\n var length = array == null ? 0 : array.length;\n return !!length && baseIndexOf(array, value, 0) > -1;\n }\n\n /**\n * This function is like `arrayIncludes` except that it accepts a comparator.\n *\n * @private\n * @param {Array} [array] The array to inspect.\n * @param {*} target The value to search for.\n * @param {Function} comparator The comparator invoked per element.\n * @returns {boolean} Returns `true` if `target` is found, else `false`.\n */\n function arrayIncludesWith(array, value, comparator) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (comparator(value, array[index])) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\n function arrayMap(array, iteratee) {\n var index = -1,\n length = array == null ? 0 : array.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iteratee(array[index], index, array);\n }\n return result;\n }\n\n /**\n * Appends the elements of `values` to `array`.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {Array} values The values to append.\n * @returns {Array} Returns `array`.\n */\n function arrayPush(array, values) {\n var index = -1,\n length = values.length,\n offset = array.length;\n\n while (++index < length) {\n array[offset + index] = values[index];\n }\n return array;\n }\n\n /**\n * A specialized version of `_.reduce` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {*} [accumulator] The initial value.\n * @param {boolean} [initAccum] Specify using the first element of `array` as\n * the initial value.\n * @returns {*} Returns the accumulated value.\n */\n function arrayReduce(array, iteratee, accumulator, initAccum) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n if (initAccum && length) {\n accumulator = array[++index];\n }\n while (++index < length) {\n accumulator = iteratee(accumulator, array[index], index, array);\n }\n return accumulator;\n }\n\n /**\n * A specialized version of `_.reduceRight` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {*} [accumulator] The initial value.\n * @param {boolean} [initAccum] Specify using the last element of `array` as\n * the initial value.\n * @returns {*} Returns the accumulated value.\n */\n function arrayReduceRight(array, iteratee, accumulator, initAccum) {\n var length = array == null ? 0 : array.length;\n if (initAccum && length) {\n accumulator = array[--length];\n }\n while (length--) {\n accumulator = iteratee(accumulator, array[length], length, array);\n }\n return accumulator;\n }\n\n /**\n * A specialized version of `_.some` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {boolean} Returns `true` if any element passes the predicate check,\n * else `false`.\n */\n function arraySome(array, predicate) {\n var index = -1,\n length = array == null ? 0 : array.length;\n\n while (++index < length) {\n if (predicate(array[index], index, array)) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Gets the size of an ASCII `string`.\n *\n * @private\n * @param {string} string The string inspect.\n * @returns {number} Returns the string size.\n */\n var asciiSize = baseProperty('length');\n\n /**\n * Converts an ASCII `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\n function asciiToArray(string) {\n return string.split('');\n }\n\n /**\n * Splits an ASCII `string` into an array of its words.\n *\n * @private\n * @param {string} The string to inspect.\n * @returns {Array} Returns the words of `string`.\n */\n function asciiWords(string) {\n return string.match(reAsciiWord) || [];\n }\n\n /**\n * The base implementation of methods like `_.findKey` and `_.findLastKey`,\n * without support for iteratee shorthands, which iterates over `collection`\n * using `eachFunc`.\n *\n * @private\n * @param {Array|Object} collection The collection to inspect.\n * @param {Function} predicate The function invoked per iteration.\n * @param {Function} eachFunc The function to iterate over `collection`.\n * @returns {*} Returns the found element or its key, else `undefined`.\n */\n function baseFindKey(collection, predicate, eachFunc) {\n var result;\n eachFunc(collection, function(value, key, collection) {\n if (predicate(value, key, collection)) {\n result = key;\n return false;\n }\n });\n return result;\n }\n\n /**\n * The base implementation of `_.findIndex` and `_.findLastIndex` without\n * support for iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Function} predicate The function invoked per iteration.\n * @param {number} fromIndex The index to search from.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\n function baseFindIndex(array, predicate, fromIndex, fromRight) {\n var length = array.length,\n index = fromIndex + (fromRight ? 1 : -1);\n\n while ((fromRight ? index-- : ++index < length)) {\n if (predicate(array[index], index, array)) {\n return index;\n }\n }\n return -1;\n }\n\n /**\n * The base implementation of `_.indexOf` without `fromIndex` bounds checks.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\n function baseIndexOf(array, value, fromIndex) {\n return value === value\n ? strictIndexOf(array, value, fromIndex)\n : baseFindIndex(array, baseIsNaN, fromIndex);\n }\n\n /**\n * This function is like `baseIndexOf` except that it accepts a comparator.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @param {Function} comparator The comparator invoked per element.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\n function baseIndexOfWith(array, value, fromIndex, comparator) {\n var index = fromIndex - 1,\n length = array.length;\n\n while (++index < length) {\n if (comparator(array[index], value)) {\n return index;\n }\n }\n return -1;\n }\n\n /**\n * The base implementation of `_.isNaN` without support for number objects.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.\n */\n function baseIsNaN(value) {\n return value !== value;\n }\n\n /**\n * The base implementation of `_.mean` and `_.meanBy` without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {number} Returns the mean.\n */\n function baseMean(array, iteratee) {\n var length = array == null ? 0 : array.length;\n return length ? (baseSum(array, iteratee) / length) : NAN;\n }\n\n /**\n * The base implementation of `_.property` without support for deep paths.\n *\n * @private\n * @param {string} key The key of the property to get.\n * @returns {Function} Returns the new accessor function.\n */\n function baseProperty(key) {\n return function(object) {\n return object == null ? undefined : object[key];\n };\n }\n\n /**\n * The base implementation of `_.propertyOf` without support for deep paths.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Function} Returns the new accessor function.\n */\n function basePropertyOf(object) {\n return function(key) {\n return object == null ? undefined : object[key];\n };\n }\n\n /**\n * The base implementation of `_.reduce` and `_.reduceRight`, without support\n * for iteratee shorthands, which iterates over `collection` using `eachFunc`.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {*} accumulator The initial value.\n * @param {boolean} initAccum Specify using the first or last element of\n * `collection` as the initial value.\n * @param {Function} eachFunc The function to iterate over `collection`.\n * @returns {*} Returns the accumulated value.\n */\n function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {\n eachFunc(collection, function(value, index, collection) {\n accumulator = initAccum\n ? (initAccum = false, value)\n : iteratee(accumulator, value, index, collection);\n });\n return accumulator;\n }\n\n /**\n * The base implementation of `_.sortBy` which uses `comparer` to define the\n * sort order of `array` and replaces criteria objects with their corresponding\n * values.\n *\n * @private\n * @param {Array} array The array to sort.\n * @param {Function} comparer The function to define sort order.\n * @returns {Array} Returns `array`.\n */\n function baseSortBy(array, comparer) {\n var length = array.length;\n\n array.sort(comparer);\n while (length--) {\n array[length] = array[length].value;\n }\n return array;\n }\n\n /**\n * The base implementation of `_.sum` and `_.sumBy` without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {number} Returns the sum.\n */\n function baseSum(array, iteratee) {\n var result,\n index = -1,\n length = array.length;\n\n while (++index < length) {\n var current = iteratee(array[index]);\n if (current !== undefined) {\n result = result === undefined ? current : (result + current);\n }\n }\n return result;\n }\n\n /**\n * The base implementation of `_.times` without support for iteratee shorthands\n * or max array length checks.\n *\n * @private\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n */\n function baseTimes(n, iteratee) {\n var index = -1,\n result = Array(n);\n\n while (++index < n) {\n result[index] = iteratee(index);\n }\n return result;\n }\n\n /**\n * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array\n * of key-value pairs for `object` corresponding to the property names of `props`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array} props The property names to get values for.\n * @returns {Object} Returns the key-value pairs.\n */\n function baseToPairs(object, props) {\n return arrayMap(props, function(key) {\n return [key, object[key]];\n });\n }\n\n /**\n * The base implementation of `_.unary` without support for storing metadata.\n *\n * @private\n * @param {Function} func The function to cap arguments for.\n * @returns {Function} Returns the new capped function.\n */\n function baseUnary(func) {\n return function(value) {\n return func(value);\n };\n }\n\n /**\n * The base implementation of `_.values` and `_.valuesIn` which creates an\n * array of `object` property values corresponding to the property names\n * of `props`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array} props The property names to get values for.\n * @returns {Object} Returns the array of property values.\n */\n function baseValues(object, props) {\n return arrayMap(props, function(key) {\n return object[key];\n });\n }\n\n /**\n * Checks if a `cache` value for `key` exists.\n *\n * @private\n * @param {Object} cache The cache to query.\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\n function cacheHas(cache, key) {\n return cache.has(key);\n }\n\n /**\n * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol\n * that is not found in the character symbols.\n *\n * @private\n * @param {Array} strSymbols The string symbols to inspect.\n * @param {Array} chrSymbols The character symbols to find.\n * @returns {number} Returns the index of the first unmatched string symbol.\n */\n function charsStartIndex(strSymbols, chrSymbols) {\n var index = -1,\n length = strSymbols.length;\n\n while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}\n return index;\n }\n\n /**\n * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol\n * that is not found in the character symbols.\n *\n * @private\n * @param {Array} strSymbols The string symbols to inspect.\n * @param {Array} chrSymbols The character symbols to find.\n * @returns {number} Returns the index of the last unmatched string symbol.\n */\n function charsEndIndex(strSymbols, chrSymbols) {\n var index = strSymbols.length;\n\n while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}\n return index;\n }\n\n /**\n * Gets the number of `placeholder` occurrences in `array`.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} placeholder The placeholder to search for.\n * @returns {number} Returns the placeholder count.\n */\n function countHolders(array, placeholder) {\n var length = array.length,\n result = 0;\n\n while (length--) {\n if (array[length] === placeholder) {\n ++result;\n }\n }\n return result;\n }\n\n /**\n * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A\n * letters to basic Latin letters.\n *\n * @private\n * @param {string} letter The matched letter to deburr.\n * @returns {string} Returns the deburred letter.\n */\n var deburrLetter = basePropertyOf(deburredLetters);\n\n /**\n * Used by `_.escape` to convert characters to HTML entities.\n *\n * @private\n * @param {string} chr The matched character to escape.\n * @returns {string} Returns the escaped character.\n */\n var escapeHtmlChar = basePropertyOf(htmlEscapes);\n\n /**\n * Used by `_.template` to escape characters for inclusion in compiled string literals.\n *\n * @private\n * @param {string} chr The matched character to escape.\n * @returns {string} Returns the escaped character.\n */\n function escapeStringChar(chr) {\n return '\\\\' + stringEscapes[chr];\n }\n\n /**\n * Gets the value at `key` of `object`.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\n function getValue(object, key) {\n return object == null ? undefined : object[key];\n }\n\n /**\n * Checks if `string` contains Unicode symbols.\n *\n * @private\n * @param {string} string The string to inspect.\n * @returns {boolean} Returns `true` if a symbol is found, else `false`.\n */\n function hasUnicode(string) {\n return reHasUnicode.test(string);\n }\n\n /**\n * Checks if `string` contains a word composed of Unicode symbols.\n *\n * @private\n * @param {string} string The string to inspect.\n * @returns {boolean} Returns `true` if a word is found, else `false`.\n */\n function hasUnicodeWord(string) {\n return reHasUnicodeWord.test(string);\n }\n\n /**\n * Converts `iterator` to an array.\n *\n * @private\n * @param {Object} iterator The iterator to convert.\n * @returns {Array} Returns the converted array.\n */\n function iteratorToArray(iterator) {\n var data,\n result = [];\n\n while (!(data = iterator.next()).done) {\n result.push(data.value);\n }\n return result;\n }\n\n /**\n * Converts `map` to its key-value pairs.\n *\n * @private\n * @param {Object} map The map to convert.\n * @returns {Array} Returns the key-value pairs.\n */\n function mapToArray(map) {\n var index = -1,\n result = Array(map.size);\n\n map.forEach(function(value, key) {\n result[++index] = [key, value];\n });\n return result;\n }\n\n /**\n * Creates a unary function that invokes `func` with its argument transformed.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {Function} transform The argument transform.\n * @returns {Function} Returns the new function.\n */\n function overArg(func, transform) {\n return function(arg) {\n return func(transform(arg));\n };\n }\n\n /**\n * Replaces all `placeholder` elements in `array` with an internal placeholder\n * and returns an array of their indexes.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {*} placeholder The placeholder to replace.\n * @returns {Array} Returns the new array of placeholder indexes.\n */\n function replaceHolders(array, placeholder) {\n var index = -1,\n length = array.length,\n resIndex = 0,\n result = [];\n\n while (++index < length) {\n var value = array[index];\n if (value === placeholder || value === PLACEHOLDER) {\n array[index] = PLACEHOLDER;\n result[resIndex++] = index;\n }\n }\n return result;\n }\n\n /**\n * Converts `set` to an array of its values.\n *\n * @private\n * @param {Object} set The set to convert.\n * @returns {Array} Returns the values.\n */\n function setToArray(set) {\n var index = -1,\n result = Array(set.size);\n\n set.forEach(function(value) {\n result[++index] = value;\n });\n return result;\n }\n\n /**\n * Converts `set` to its value-value pairs.\n *\n * @private\n * @param {Object} set The set to convert.\n * @returns {Array} Returns the value-value pairs.\n */\n function setToPairs(set) {\n var index = -1,\n result = Array(set.size);\n\n set.forEach(function(value) {\n result[++index] = [value, value];\n });\n return result;\n }\n\n /**\n * A specialized version of `_.indexOf` which performs strict equality\n * comparisons of values, i.e. `===`.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\n function strictIndexOf(array, value, fromIndex) {\n var index = fromIndex - 1,\n length = array.length;\n\n while (++index < length) {\n if (array[index] === value) {\n return index;\n }\n }\n return -1;\n }\n\n /**\n * A specialized version of `_.lastIndexOf` which performs strict equality\n * comparisons of values, i.e. `===`.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\n function strictLastIndexOf(array, value, fromIndex) {\n var index = fromIndex + 1;\n while (index--) {\n if (array[index] === value) {\n return index;\n }\n }\n return index;\n }\n\n /**\n * Gets the number of symbols in `string`.\n *\n * @private\n * @param {string} string The string to inspect.\n * @returns {number} Returns the string size.\n */\n function stringSize(string) {\n return hasUnicode(string)\n ? unicodeSize(string)\n : asciiSize(string);\n }\n\n /**\n * Converts `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\n function stringToArray(string) {\n return hasUnicode(string)\n ? unicodeToArray(string)\n : asciiToArray(string);\n }\n\n /**\n * Used by `_.unescape` to convert HTML entities to characters.\n *\n * @private\n * @param {string} chr The matched character to unescape.\n * @returns {string} Returns the unescaped character.\n */\n var unescapeHtmlChar = basePropertyOf(htmlUnescapes);\n\n /**\n * Gets the size of a Unicode `string`.\n *\n * @private\n * @param {string} string The string inspect.\n * @returns {number} Returns the string size.\n */\n function unicodeSize(string) {\n var result = reUnicode.lastIndex = 0;\n while (reUnicode.test(string)) {\n ++result;\n }\n return result;\n }\n\n /**\n * Converts a Unicode `string` to an array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the converted array.\n */\n function unicodeToArray(string) {\n return string.match(reUnicode) || [];\n }\n\n /**\n * Splits a Unicode `string` into an array of its words.\n *\n * @private\n * @param {string} The string to inspect.\n * @returns {Array} Returns the words of `string`.\n */\n function unicodeWords(string) {\n return string.match(reUnicodeWord) || [];\n }\n\n /*--------------------------------------------------------------------------*/\n\n /**\n * Create a new pristine `lodash` function using the `context` object.\n *\n * @static\n * @memberOf _\n * @since 1.1.0\n * @category Util\n * @param {Object} [context=root] The context object.\n * @returns {Function} Returns a new `lodash` function.\n * @example\n *\n * _.mixin({ 'foo': _.constant('foo') });\n *\n * var lodash = _.runInContext();\n * lodash.mixin({ 'bar': lodash.constant('bar') });\n *\n * _.isFunction(_.foo);\n * // => true\n * _.isFunction(_.bar);\n * // => false\n *\n * lodash.isFunction(lodash.foo);\n * // => false\n * lodash.isFunction(lodash.bar);\n * // => true\n *\n * // Create a suped-up `defer` in Node.js.\n * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;\n */\n var runInContext = (function runInContext(context) {\n context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps));\n\n /** Built-in constructor references. */\n var Array = context.Array,\n Date = context.Date,\n Error = context.Error,\n Function = context.Function,\n Math = context.Math,\n Object = context.Object,\n RegExp = context.RegExp,\n String = context.String,\n TypeError = context.TypeError;\n\n /** Used for built-in method references. */\n var arrayProto = Array.prototype,\n funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n /** Used to detect overreaching core-js shims. */\n var coreJsData = context['__core-js_shared__'];\n\n /** Used to resolve the decompiled source of functions. */\n var funcToString = funcProto.toString;\n\n /** Used to check objects for own properties. */\n var hasOwnProperty = objectProto.hasOwnProperty;\n\n /** Used to generate unique IDs. */\n var idCounter = 0;\n\n /** Used to detect methods masquerading as native. */\n var maskSrcKey = (function() {\n var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');\n return uid ? ('Symbol(src)_1.' + uid) : '';\n }());\n\n /**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\n var nativeObjectToString = objectProto.toString;\n\n /** Used to infer the `Object` constructor. */\n var objectCtorString = funcToString.call(Object);\n\n /** Used to restore the original `_` reference in `_.noConflict`. */\n var oldDash = root._;\n\n /** Used to detect if a method is native. */\n var reIsNative = RegExp('^' +\n funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\\\$&')\n .replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n );\n\n /** Built-in value references. */\n var Buffer = moduleExports ? context.Buffer : undefined,\n Symbol = context.Symbol,\n Uint8Array = context.Uint8Array,\n allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined,\n getPrototype = overArg(Object.getPrototypeOf, Object),\n objectCreate = Object.create,\n propertyIsEnumerable = objectProto.propertyIsEnumerable,\n splice = arrayProto.splice,\n spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined,\n symIterator = Symbol ? Symbol.iterator : undefined,\n symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n var defineProperty = (function() {\n try {\n var func = getNative(Object, 'defineProperty');\n func({}, '', {});\n return func;\n } catch (e) {}\n }());\n\n /** Mocked built-ins. */\n var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout,\n ctxNow = Date && Date.now !== root.Date.now && Date.now,\n ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout;\n\n /* Built-in method references for those with the same name as other `lodash` methods. */\n var nativeCeil = Math.ceil,\n nativeFloor = Math.floor,\n nativeGetSymbols = Object.getOwnPropertySymbols,\n nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,\n nativeIsFinite = context.isFinite,\n nativeJoin = arrayProto.join,\n nativeKeys = overArg(Object.keys, Object),\n nativeMax = Math.max,\n nativeMin = Math.min,\n nativeNow = Date.now,\n nativeParseInt = context.parseInt,\n nativeRandom = Math.random,\n nativeReverse = arrayProto.reverse;\n\n /* Built-in method references that are verified to be native. */\n var DataView = getNative(context, 'DataView'),\n Map = getNative(context, 'Map'),\n Promise = getNative(context, 'Promise'),\n Set = getNative(context, 'Set'),\n WeakMap = getNative(context, 'WeakMap'),\n nativeCreate = getNative(Object, 'create');\n\n /** Used to store function metadata. */\n var metaMap = WeakMap && new WeakMap;\n\n /** Used to lookup unminified function names. */\n var realNames = {};\n\n /** Used to detect maps, sets, and weakmaps. */\n var dataViewCtorString = toSource(DataView),\n mapCtorString = toSource(Map),\n promiseCtorString = toSource(Promise),\n setCtorString = toSource(Set),\n weakMapCtorString = toSource(WeakMap);\n\n /** Used to convert symbols to primitives and strings. */\n var symbolProto = Symbol ? Symbol.prototype : undefined,\n symbolValueOf = symbolProto ? symbolProto.valueOf : undefined,\n symbolToString = symbolProto ? symbolProto.toString : undefined;\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Creates a `lodash` object which wraps `value` to enable implicit method\n * chain sequences. Methods that operate on and return arrays, collections,\n * and functions can be chained together. Methods that retrieve a single value\n * or may return a primitive value will automatically end the chain sequence\n * and return the unwrapped value. Otherwise, the value must be unwrapped\n * with `_#value`.\n *\n * Explicit chain sequences, which must be unwrapped with `_#value`, may be\n * enabled using `_.chain`.\n *\n * The execution of chained methods is lazy, that is, it's deferred until\n * `_#value` is implicitly or explicitly called.\n *\n * Lazy evaluation allows several methods to support shortcut fusion.\n * Shortcut fusion is an optimization to merge iteratee calls; this avoids\n * the creation of intermediate arrays and can greatly reduce the number of\n * iteratee executions. Sections of a chain sequence qualify for shortcut\n * fusion if the section is applied to an array and iteratees accept only\n * one argument. The heuristic for whether a section qualifies for shortcut\n * fusion is subject to change.\n *\n * Chaining is supported in custom builds as long as the `_#value` method is\n * directly or indirectly included in the build.\n *\n * In addition to lodash methods, wrappers have `Array` and `String` methods.\n *\n * The wrapper `Array` methods are:\n * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`\n *\n * The wrapper `String` methods are:\n * `replace` and `split`\n *\n * The wrapper methods that support shortcut fusion are:\n * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,\n * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,\n * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`\n *\n * The chainable wrapper methods are:\n * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,\n * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,\n * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,\n * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,\n * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,\n * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,\n * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,\n * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,\n * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,\n * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,\n * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,\n * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,\n * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,\n * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,\n * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,\n * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,\n * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,\n * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,\n * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,\n * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,\n * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,\n * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,\n * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,\n * `zipObject`, `zipObjectDeep`, and `zipWith`\n *\n * The wrapper methods that are **not** chainable by default are:\n * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,\n * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`,\n * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`,\n * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,\n * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`,\n * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`,\n * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`,\n * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`,\n * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`,\n * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`,\n * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`,\n * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`,\n * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`,\n * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`,\n * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`,\n * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`,\n * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`,\n * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`,\n * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`,\n * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`,\n * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`,\n * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`,\n * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`,\n * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`,\n * `upperFirst`, `value`, and `words`\n *\n * @name _\n * @constructor\n * @category Seq\n * @param {*} value The value to wrap in a `lodash` instance.\n * @returns {Object} Returns the new `lodash` wrapper instance.\n * @example\n *\n * function square(n) {\n * return n * n;\n * }\n *\n * var wrapped = _([1, 2, 3]);\n *\n * // Returns an unwrapped value.\n * wrapped.reduce(_.add);\n * // => 6\n *\n * // Returns a wrapped value.\n * var squares = wrapped.map(square);\n *\n * _.isArray(squares);\n * // => false\n *\n * _.isArray(squares.value());\n * // => true\n */\n function lodash(value) {\n if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {\n if (value instanceof LodashWrapper) {\n return value;\n }\n if (hasOwnProperty.call(value, '__wrapped__')) {\n return wrapperClone(value);\n }\n }\n return new LodashWrapper(value);\n }\n\n /**\n * The base implementation of `_.create` without support for assigning\n * properties to the created object.\n *\n * @private\n * @param {Object} proto The object to inherit from.\n * @returns {Object} Returns the new object.\n */\n var baseCreate = (function() {\n function object() {}\n return function(proto) {\n if (!isObject(proto)) {\n return {};\n }\n if (objectCreate) {\n return objectCreate(proto);\n }\n object.prototype = proto;\n var result = new object;\n object.prototype = undefined;\n return result;\n };\n }());\n\n /**\n * The function whose prototype chain sequence wrappers inherit from.\n *\n * @private\n */\n function baseLodash() {\n // No operation performed.\n }\n\n /**\n * The base constructor for creating `lodash` wrapper objects.\n *\n * @private\n * @param {*} value The value to wrap.\n * @param {boolean} [chainAll] Enable explicit method chain sequences.\n */\n function LodashWrapper(value, chainAll) {\n this.__wrapped__ = value;\n this.__actions__ = [];\n this.__chain__ = !!chainAll;\n this.__index__ = 0;\n this.__values__ = undefined;\n }\n\n /**\n * By default, the template delimiters used by lodash are like those in\n * embedded Ruby (ERB) as well as ES2015 template strings. Change the\n * following template settings to use alternative delimiters.\n *\n * @static\n * @memberOf _\n * @type {Object}\n */\n lodash.templateSettings = {\n\n /**\n * Used to detect `data` property values to be HTML-escaped.\n *\n * @memberOf _.templateSettings\n * @type {RegExp}\n */\n 'escape': reEscape,\n\n /**\n * Used to detect code to be evaluated.\n *\n * @memberOf _.templateSettings\n * @type {RegExp}\n */\n 'evaluate': reEvaluate,\n\n /**\n * Used to detect `data` property values to inject.\n *\n * @memberOf _.templateSettings\n * @type {RegExp}\n */\n 'interpolate': reInterpolate,\n\n /**\n * Used to reference the data object in the template text.\n *\n * @memberOf _.templateSettings\n * @type {string}\n */\n 'variable': '',\n\n /**\n * Used to import variables into the compiled template.\n *\n * @memberOf _.templateSettings\n * @type {Object}\n */\n 'imports': {\n\n /**\n * A reference to the `lodash` function.\n *\n * @memberOf _.templateSettings.imports\n * @type {Function}\n */\n '_': lodash\n }\n };\n\n // Ensure wrappers are instances of `baseLodash`.\n lodash.prototype = baseLodash.prototype;\n lodash.prototype.constructor = lodash;\n\n LodashWrapper.prototype = baseCreate(baseLodash.prototype);\n LodashWrapper.prototype.constructor = LodashWrapper;\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.\n *\n * @private\n * @constructor\n * @param {*} value The value to wrap.\n */\n function LazyWrapper(value) {\n this.__wrapped__ = value;\n this.__actions__ = [];\n this.__dir__ = 1;\n this.__filtered__ = false;\n this.__iteratees__ = [];\n this.__takeCount__ = MAX_ARRAY_LENGTH;\n this.__views__ = [];\n }\n\n /**\n * Creates a clone of the lazy wrapper object.\n *\n * @private\n * @name clone\n * @memberOf LazyWrapper\n * @returns {Object} Returns the cloned `LazyWrapper` object.\n */\n function lazyClone() {\n var result = new LazyWrapper(this.__wrapped__);\n result.__actions__ = copyArray(this.__actions__);\n result.__dir__ = this.__dir__;\n result.__filtered__ = this.__filtered__;\n result.__iteratees__ = copyArray(this.__iteratees__);\n result.__takeCount__ = this.__takeCount__;\n result.__views__ = copyArray(this.__views__);\n return result;\n }\n\n /**\n * Reverses the direction of lazy iteration.\n *\n * @private\n * @name reverse\n * @memberOf LazyWrapper\n * @returns {Object} Returns the new reversed `LazyWrapper` object.\n */\n function lazyReverse() {\n if (this.__filtered__) {\n var result = new LazyWrapper(this);\n result.__dir__ = -1;\n result.__filtered__ = true;\n } else {\n result = this.clone();\n result.__dir__ *= -1;\n }\n return result;\n }\n\n /**\n * Extracts the unwrapped value from its lazy wrapper.\n *\n * @private\n * @name value\n * @memberOf LazyWrapper\n * @returns {*} Returns the unwrapped value.\n */\n function lazyValue() {\n var array = this.__wrapped__.value(),\n dir = this.__dir__,\n isArr = isArray(array),\n isRight = dir < 0,\n arrLength = isArr ? array.length : 0,\n view = getView(0, arrLength, this.__views__),\n start = view.start,\n end = view.end,\n length = end - start,\n index = isRight ? end : (start - 1),\n iteratees = this.__iteratees__,\n iterLength = iteratees.length,\n resIndex = 0,\n takeCount = nativeMin(length, this.__takeCount__);\n\n if (!isArr || (!isRight && arrLength == length && takeCount == length)) {\n return baseWrapperValue(array, this.__actions__);\n }\n var result = [];\n\n outer:\n while (length-- && resIndex < takeCount) {\n index += dir;\n\n var iterIndex = -1,\n value = array[index];\n\n while (++iterIndex < iterLength) {\n var data = iteratees[iterIndex],\n iteratee = data.iteratee,\n type = data.type,\n computed = iteratee(value);\n\n if (type == LAZY_MAP_FLAG) {\n value = computed;\n } else if (!computed) {\n if (type == LAZY_FILTER_FLAG) {\n continue outer;\n } else {\n break outer;\n }\n }\n }\n result[resIndex++] = value;\n }\n return result;\n }\n\n // Ensure `LazyWrapper` is an instance of `baseLodash`.\n LazyWrapper.prototype = baseCreate(baseLodash.prototype);\n LazyWrapper.prototype.constructor = LazyWrapper;\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Creates a hash object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\n function Hash(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n }\n\n /**\n * Removes all key-value entries from the hash.\n *\n * @private\n * @name clear\n * @memberOf Hash\n */\n function hashClear() {\n this.__data__ = nativeCreate ? nativeCreate(null) : {};\n this.size = 0;\n }\n\n /**\n * Removes `key` and its value from the hash.\n *\n * @private\n * @name delete\n * @memberOf Hash\n * @param {Object} hash The hash to modify.\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\n function hashDelete(key) {\n var result = this.has(key) && delete this.__data__[key];\n this.size -= result ? 1 : 0;\n return result;\n }\n\n /**\n * Gets the hash value for `key`.\n *\n * @private\n * @name get\n * @memberOf Hash\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\n function hashGet(key) {\n var data = this.__data__;\n if (nativeCreate) {\n var result = data[key];\n return result === HASH_UNDEFINED ? undefined : result;\n }\n return hasOwnProperty.call(data, key) ? data[key] : undefined;\n }\n\n /**\n * Checks if a hash value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Hash\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\n function hashHas(key) {\n var data = this.__data__;\n return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);\n }\n\n /**\n * Sets the hash `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Hash\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the hash instance.\n */\n function hashSet(key, value) {\n var data = this.__data__;\n this.size += this.has(key) ? 0 : 1;\n data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;\n return this;\n }\n\n // Add methods to `Hash`.\n Hash.prototype.clear = hashClear;\n Hash.prototype['delete'] = hashDelete;\n Hash.prototype.get = hashGet;\n Hash.prototype.has = hashHas;\n Hash.prototype.set = hashSet;\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Creates an list cache object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\n function ListCache(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n }\n\n /**\n * Removes all key-value entries from the list cache.\n *\n * @private\n * @name clear\n * @memberOf ListCache\n */\n function listCacheClear() {\n this.__data__ = [];\n this.size = 0;\n }\n\n /**\n * Removes `key` and its value from the list cache.\n *\n * @private\n * @name delete\n * @memberOf ListCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\n function listCacheDelete(key) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n if (index < 0) {\n return false;\n }\n var lastIndex = data.length - 1;\n if (index == lastIndex) {\n data.pop();\n } else {\n splice.call(data, index, 1);\n }\n --this.size;\n return true;\n }\n\n /**\n * Gets the list cache value for `key`.\n *\n * @private\n * @name get\n * @memberOf ListCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\n function listCacheGet(key) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n return index < 0 ? undefined : data[index][1];\n }\n\n /**\n * Checks if a list cache value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf ListCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\n function listCacheHas(key) {\n return assocIndexOf(this.__data__, key) > -1;\n }\n\n /**\n * Sets the list cache `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf ListCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the list cache instance.\n */\n function listCacheSet(key, value) {\n var data = this.__data__,\n index = assocIndexOf(data, key);\n\n if (index < 0) {\n ++this.size;\n data.push([key, value]);\n } else {\n data[index][1] = value;\n }\n return this;\n }\n\n // Add methods to `ListCache`.\n ListCache.prototype.clear = listCacheClear;\n ListCache.prototype['delete'] = listCacheDelete;\n ListCache.prototype.get = listCacheGet;\n ListCache.prototype.has = listCacheHas;\n ListCache.prototype.set = listCacheSet;\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Creates a map cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\n function MapCache(entries) {\n var index = -1,\n length = entries == null ? 0 : entries.length;\n\n this.clear();\n while (++index < length) {\n var entry = entries[index];\n this.set(entry[0], entry[1]);\n }\n }\n\n /**\n * Removes all key-value entries from the map.\n *\n * @private\n * @name clear\n * @memberOf MapCache\n */\n function mapCacheClear() {\n this.size = 0;\n this.__data__ = {\n 'hash': new Hash,\n 'map': new (Map || ListCache),\n 'string': new Hash\n };\n }\n\n /**\n * Removes `key` and its value from the map.\n *\n * @private\n * @name delete\n * @memberOf MapCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\n function mapCacheDelete(key) {\n var result = getMapData(this, key)['delete'](key);\n this.size -= result ? 1 : 0;\n return result;\n }\n\n /**\n * Gets the map value for `key`.\n *\n * @private\n * @name get\n * @memberOf MapCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\n function mapCacheGet(key) {\n return getMapData(this, key).get(key);\n }\n\n /**\n * Checks if a map value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf MapCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\n function mapCacheHas(key) {\n return getMapData(this, key).has(key);\n }\n\n /**\n * Sets the map `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf MapCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the map cache instance.\n */\n function mapCacheSet(key, value) {\n var data = getMapData(this, key),\n size = data.size;\n\n data.set(key, value);\n this.size += data.size == size ? 0 : 1;\n return this;\n }\n\n // Add methods to `MapCache`.\n MapCache.prototype.clear = mapCacheClear;\n MapCache.prototype['delete'] = mapCacheDelete;\n MapCache.prototype.get = mapCacheGet;\n MapCache.prototype.has = mapCacheHas;\n MapCache.prototype.set = mapCacheSet;\n\n /*------------------------------------------------------------------------*/\n\n /**\n *\n * Creates an array cache object to store unique values.\n *\n * @private\n * @constructor\n * @param {Array} [values] The values to cache.\n */\n function SetCache(values) {\n var index = -1,\n length = values == null ? 0 : values.length;\n\n this.__data__ = new MapCache;\n while (++index < length) {\n this.add(values[index]);\n }\n }\n\n /**\n * Adds `value` to the array cache.\n *\n * @private\n * @name add\n * @memberOf SetCache\n * @alias push\n * @param {*} value The value to cache.\n * @returns {Object} Returns the cache instance.\n */\n function setCacheAdd(value) {\n this.__data__.set(value, HASH_UNDEFINED);\n return this;\n }\n\n /**\n * Checks if `value` is in the array cache.\n *\n * @private\n * @name has\n * @memberOf SetCache\n * @param {*} value The value to search for.\n * @returns {number} Returns `true` if `value` is found, else `false`.\n */\n function setCacheHas(value) {\n return this.__data__.has(value);\n }\n\n // Add methods to `SetCache`.\n SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;\n SetCache.prototype.has = setCacheHas;\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Creates a stack cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\n function Stack(entries) {\n var data = this.__data__ = new ListCache(entries);\n this.size = data.size;\n }\n\n /**\n * Removes all key-value entries from the stack.\n *\n * @private\n * @name clear\n * @memberOf Stack\n */\n function stackClear() {\n this.__data__ = new ListCache;\n this.size = 0;\n }\n\n /**\n * Removes `key` and its value from the stack.\n *\n * @private\n * @name delete\n * @memberOf Stack\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\n function stackDelete(key) {\n var data = this.__data__,\n result = data['delete'](key);\n\n this.size = data.size;\n return result;\n }\n\n /**\n * Gets the stack value for `key`.\n *\n * @private\n * @name get\n * @memberOf Stack\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\n function stackGet(key) {\n return this.__data__.get(key);\n }\n\n /**\n * Checks if a stack value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Stack\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\n function stackHas(key) {\n return this.__data__.has(key);\n }\n\n /**\n * Sets the stack `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Stack\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the stack cache instance.\n */\n function stackSet(key, value) {\n var data = this.__data__;\n if (data instanceof ListCache) {\n var pairs = data.__data__;\n if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {\n pairs.push([key, value]);\n this.size = ++data.size;\n return this;\n }\n data = this.__data__ = new MapCache(pairs);\n }\n data.set(key, value);\n this.size = data.size;\n return this;\n }\n\n // Add methods to `Stack`.\n Stack.prototype.clear = stackClear;\n Stack.prototype['delete'] = stackDelete;\n Stack.prototype.get = stackGet;\n Stack.prototype.has = stackHas;\n Stack.prototype.set = stackSet;\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Creates an array of the enumerable property names of the array-like `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @param {boolean} inherited Specify returning inherited property names.\n * @returns {Array} Returns the array of property names.\n */\n function arrayLikeKeys(value, inherited) {\n var isArr = isArray(value),\n isArg = !isArr && isArguments(value),\n isBuff = !isArr && !isArg && isBuffer(value),\n isType = !isArr && !isArg && !isBuff && isTypedArray(value),\n skipIndexes = isArr || isArg || isBuff || isType,\n result = skipIndexes ? baseTimes(value.length, String) : [],\n length = result.length;\n\n for (var key in value) {\n if ((inherited || hasOwnProperty.call(value, key)) &&\n !(skipIndexes && (\n // Safari 9 has enumerable `arguments.length` in strict mode.\n key == 'length' ||\n // Node.js 0.10 has enumerable non-index properties on buffers.\n (isBuff && (key == 'offset' || key == 'parent')) ||\n // PhantomJS 2 has enumerable non-index properties on typed arrays.\n (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||\n // Skip index properties.\n isIndex(key, length)\n ))) {\n result.push(key);\n }\n }\n return result;\n }\n\n /**\n * A specialized version of `_.sample` for arrays.\n *\n * @private\n * @param {Array} array The array to sample.\n * @returns {*} Returns the random element.\n */\n function arraySample(array) {\n var length = array.length;\n return length ? array[baseRandom(0, length - 1)] : undefined;\n }\n\n /**\n * A specialized version of `_.sampleSize` for arrays.\n *\n * @private\n * @param {Array} array The array to sample.\n * @param {number} n The number of elements to sample.\n * @returns {Array} Returns the random elements.\n */\n function arraySampleSize(array, n) {\n return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));\n }\n\n /**\n * A specialized version of `_.shuffle` for arrays.\n *\n * @private\n * @param {Array} array The array to shuffle.\n * @returns {Array} Returns the new shuffled array.\n */\n function arrayShuffle(array) {\n return shuffleSelf(copyArray(array));\n }\n\n /**\n * This function is like `assignValue` except that it doesn't assign\n * `undefined` values.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\n function assignMergeValue(object, key, value) {\n if ((value !== undefined && !eq(object[key], value)) ||\n (value === undefined && !(key in object))) {\n baseAssignValue(object, key, value);\n }\n }\n\n /**\n * Assigns `value` to `key` of `object` if the existing value is not equivalent\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\n function assignValue(object, key, value) {\n var objValue = object[key];\n if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||\n (value === undefined && !(key in object))) {\n baseAssignValue(object, key, value);\n }\n }\n\n /**\n * Gets the index at which the `key` is found in `array` of key-value pairs.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} key The key to search for.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\n function assocIndexOf(array, key) {\n var length = array.length;\n while (length--) {\n if (eq(array[length][0], key)) {\n return length;\n }\n }\n return -1;\n }\n\n /**\n * Aggregates elements of `collection` on `accumulator` with keys transformed\n * by `iteratee` and values set by `setter`.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} setter The function to set `accumulator` values.\n * @param {Function} iteratee The iteratee to transform keys.\n * @param {Object} accumulator The initial aggregated object.\n * @returns {Function} Returns `accumulator`.\n */\n function baseAggregator(collection, setter, iteratee, accumulator) {\n baseEach(collection, function(value, key, collection) {\n setter(accumulator, value, iteratee(value), collection);\n });\n return accumulator;\n }\n\n /**\n * The base implementation of `_.assign` without support for multiple sources\n * or `customizer` functions.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @returns {Object} Returns `object`.\n */\n function baseAssign(object, source) {\n return object && copyObject(source, keys(source), object);\n }\n\n /**\n * The base implementation of `_.assignIn` without support for multiple sources\n * or `customizer` functions.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @returns {Object} Returns `object`.\n */\n function baseAssignIn(object, source) {\n return object && copyObject(source, keysIn(source), object);\n }\n\n /**\n * The base implementation of `assignValue` and `assignMergeValue` without\n * value checks.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\n function baseAssignValue(object, key, value) {\n if (key == '__proto__' && defineProperty) {\n defineProperty(object, key, {\n 'configurable': true,\n 'enumerable': true,\n 'value': value,\n 'writable': true\n });\n } else {\n object[key] = value;\n }\n }\n\n /**\n * The base implementation of `_.at` without support for individual paths.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {string[]} paths The property paths to pick.\n * @returns {Array} Returns the picked elements.\n */\n function baseAt(object, paths) {\n var index = -1,\n length = paths.length,\n result = Array(length),\n skip = object == null;\n\n while (++index < length) {\n result[index] = skip ? undefined : get(object, paths[index]);\n }\n return result;\n }\n\n /**\n * The base implementation of `_.clamp` which doesn't coerce arguments.\n *\n * @private\n * @param {number} number The number to clamp.\n * @param {number} [lower] The lower bound.\n * @param {number} upper The upper bound.\n * @returns {number} Returns the clamped number.\n */\n function baseClamp(number, lower, upper) {\n if (number === number) {\n if (upper !== undefined) {\n number = number <= upper ? number : upper;\n }\n if (lower !== undefined) {\n number = number >= lower ? number : lower;\n }\n }\n return number;\n }\n\n /**\n * The base implementation of `_.clone` and `_.cloneDeep` which tracks\n * traversed objects.\n *\n * @private\n * @param {*} value The value to clone.\n * @param {boolean} bitmask The bitmask flags.\n * 1 - Deep clone\n * 2 - Flatten inherited properties\n * 4 - Clone symbols\n * @param {Function} [customizer] The function to customize cloning.\n * @param {string} [key] The key of `value`.\n * @param {Object} [object] The parent object of `value`.\n * @param {Object} [stack] Tracks traversed objects and their clone counterparts.\n * @returns {*} Returns the cloned value.\n */\n function baseClone(value, bitmask, customizer, key, object, stack) {\n var result,\n isDeep = bitmask & CLONE_DEEP_FLAG,\n isFlat = bitmask & CLONE_FLAT_FLAG,\n isFull = bitmask & CLONE_SYMBOLS_FLAG;\n\n if (customizer) {\n result = object ? customizer(value, key, object, stack) : customizer(value);\n }\n if (result !== undefined) {\n return result;\n }\n if (!isObject(value)) {\n return value;\n }\n var isArr = isArray(value);\n if (isArr) {\n result = initCloneArray(value);\n if (!isDeep) {\n return copyArray(value, result);\n }\n } else {\n var tag = getTag(value),\n isFunc = tag == funcTag || tag == genTag;\n\n if (isBuffer(value)) {\n return cloneBuffer(value, isDeep);\n }\n if (tag == objectTag || tag == argsTag || (isFunc && !object)) {\n result = (isFlat || isFunc) ? {} : initCloneObject(value);\n if (!isDeep) {\n return isFlat\n ? copySymbolsIn(value, baseAssignIn(result, value))\n : copySymbols(value, baseAssign(result, value));\n }\n } else {\n if (!cloneableTags[tag]) {\n return object ? value : {};\n }\n result = initCloneByTag(value, tag, baseClone, isDeep);\n }\n }\n // Check for circular references and return its corresponding clone.\n stack || (stack = new Stack);\n var stacked = stack.get(value);\n if (stacked) {\n return stacked;\n }\n stack.set(value, result);\n\n var keysFunc = isFull\n ? (isFlat ? getAllKeysIn : getAllKeys)\n : (isFlat ? keysIn : keys);\n\n var props = isArr ? undefined : keysFunc(value);\n arrayEach(props || value, function(subValue, key) {\n if (props) {\n key = subValue;\n subValue = value[key];\n }\n // Recursively populate clone (susceptible to call stack limits).\n assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));\n });\n return result;\n }\n\n /**\n * The base implementation of `_.conforms` which doesn't clone `source`.\n *\n * @private\n * @param {Object} source The object of property predicates to conform to.\n * @returns {Function} Returns the new spec function.\n */\n function baseConforms(source) {\n var props = keys(source);\n return function(object) {\n return baseConformsTo(object, source, props);\n };\n }\n\n /**\n * The base implementation of `_.conformsTo` which accepts `props` to check.\n *\n * @private\n * @param {Object} object The object to inspect.\n * @param {Object} source The object of property predicates to conform to.\n * @returns {boolean} Returns `true` if `object` conforms, else `false`.\n */\n function baseConformsTo(object, source, props) {\n var length = props.length;\n if (object == null) {\n return !length;\n }\n object = Object(object);\n while (length--) {\n var key = props[length],\n predicate = source[key],\n value = object[key];\n\n if ((value === undefined && !(key in object)) || !predicate(value)) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * The base implementation of `_.delay` and `_.defer` which accepts `args`\n * to provide to `func`.\n *\n * @private\n * @param {Function} func The function to delay.\n * @param {number} wait The number of milliseconds to delay invocation.\n * @param {Array} args The arguments to provide to `func`.\n * @returns {number|Object} Returns the timer id or timeout object.\n */\n function baseDelay(func, wait, args) {\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n return setTimeout(function() { func.apply(undefined, args); }, wait);\n }\n\n /**\n * The base implementation of methods like `_.difference` without support\n * for excluding multiple arrays or iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Array} values The values to exclude.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of filtered values.\n */\n function baseDifference(array, values, iteratee, comparator) {\n var index = -1,\n includes = arrayIncludes,\n isCommon = true,\n length = array.length,\n result = [],\n valuesLength = values.length;\n\n if (!length) {\n return result;\n }\n if (iteratee) {\n values = arrayMap(values, baseUnary(iteratee));\n }\n if (comparator) {\n includes = arrayIncludesWith;\n isCommon = false;\n }\n else if (values.length >= LARGE_ARRAY_SIZE) {\n includes = cacheHas;\n isCommon = false;\n values = new SetCache(values);\n }\n outer:\n while (++index < length) {\n var value = array[index],\n computed = iteratee == null ? value : iteratee(value);\n\n value = (comparator || value !== 0) ? value : 0;\n if (isCommon && computed === computed) {\n var valuesIndex = valuesLength;\n while (valuesIndex--) {\n if (values[valuesIndex] === computed) {\n continue outer;\n }\n }\n result.push(value);\n }\n else if (!includes(values, computed, comparator)) {\n result.push(value);\n }\n }\n return result;\n }\n\n /**\n * The base implementation of `_.forEach` without support for iteratee shorthands.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array|Object} Returns `collection`.\n */\n var baseEach = createBaseEach(baseForOwn);\n\n /**\n * The base implementation of `_.forEachRight` without support for iteratee shorthands.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array|Object} Returns `collection`.\n */\n var baseEachRight = createBaseEach(baseForOwnRight, true);\n\n /**\n * The base implementation of `_.every` without support for iteratee shorthands.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {boolean} Returns `true` if all elements pass the predicate check,\n * else `false`\n */\n function baseEvery(collection, predicate) {\n var result = true;\n baseEach(collection, function(value, index, collection) {\n result = !!predicate(value, index, collection);\n return result;\n });\n return result;\n }\n\n /**\n * The base implementation of methods like `_.max` and `_.min` which accepts a\n * `comparator` to determine the extremum value.\n *\n * @private\n * @param {Array} array The array to iterate over.\n * @param {Function} iteratee The iteratee invoked per iteration.\n * @param {Function} comparator The comparator used to compare values.\n * @returns {*} Returns the extremum value.\n */\n function baseExtremum(array, iteratee, comparator) {\n var index = -1,\n length = array.length;\n\n while (++index < length) {\n var value = array[index],\n current = iteratee(value);\n\n if (current != null && (computed === undefined\n ? (current === current && !isSymbol(current))\n : comparator(current, computed)\n )) {\n var computed = current,\n result = value;\n }\n }\n return result;\n }\n\n /**\n * The base implementation of `_.fill` without an iteratee call guard.\n *\n * @private\n * @param {Array} array The array to fill.\n * @param {*} value The value to fill `array` with.\n * @param {number} [start=0] The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns `array`.\n */\n function baseFill(array, value, start, end) {\n var length = array.length;\n\n start = toInteger(start);\n if (start < 0) {\n start = -start > length ? 0 : (length + start);\n }\n end = (end === undefined || end > length) ? length : toInteger(end);\n if (end < 0) {\n end += length;\n }\n end = start > end ? 0 : toLength(end);\n while (start < end) {\n array[start++] = value;\n }\n return array;\n }\n\n /**\n * The base implementation of `_.filter` without support for iteratee shorthands.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {Array} Returns the new filtered array.\n */\n function baseFilter(collection, predicate) {\n var result = [];\n baseEach(collection, function(value, index, collection) {\n if (predicate(value, index, collection)) {\n result.push(value);\n }\n });\n return result;\n }\n\n /**\n * The base implementation of `_.flatten` with support for restricting flattening.\n *\n * @private\n * @param {Array} array The array to flatten.\n * @param {number} depth The maximum recursion depth.\n * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.\n * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.\n * @param {Array} [result=[]] The initial result value.\n * @returns {Array} Returns the new flattened array.\n */\n function baseFlatten(array, depth, predicate, isStrict, result) {\n var index = -1,\n length = array.length;\n\n predicate || (predicate = isFlattenable);\n result || (result = []);\n\n while (++index < length) {\n var value = array[index];\n if (depth > 0 && predicate(value)) {\n if (depth > 1) {\n // Recursively flatten arrays (susceptible to call stack limits).\n baseFlatten(value, depth - 1, predicate, isStrict, result);\n } else {\n arrayPush(result, value);\n }\n } else if (!isStrict) {\n result[result.length] = value;\n }\n }\n return result;\n }\n\n /**\n * The base implementation of `baseForOwn` which iterates over `object`\n * properties returned by `keysFunc` and invokes `iteratee` for each property.\n * Iteratee functions may exit iteration early by explicitly returning `false`.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {Function} keysFunc The function to get the keys of `object`.\n * @returns {Object} Returns `object`.\n */\n var baseFor = createBaseFor();\n\n /**\n * This function is like `baseFor` except that it iterates over properties\n * in the opposite order.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {Function} keysFunc The function to get the keys of `object`.\n * @returns {Object} Returns `object`.\n */\n var baseForRight = createBaseFor(true);\n\n /**\n * The base implementation of `_.forOwn` without support for iteratee shorthands.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Object} Returns `object`.\n */\n function baseForOwn(object, iteratee) {\n return object && baseFor(object, iteratee, keys);\n }\n\n /**\n * The base implementation of `_.forOwnRight` without support for iteratee shorthands.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Object} Returns `object`.\n */\n function baseForOwnRight(object, iteratee) {\n return object && baseForRight(object, iteratee, keys);\n }\n\n /**\n * The base implementation of `_.functions` which creates an array of\n * `object` function property names filtered from `props`.\n *\n * @private\n * @param {Object} object The object to inspect.\n * @param {Array} props The property names to filter.\n * @returns {Array} Returns the function names.\n */\n function baseFunctions(object, props) {\n return arrayFilter(props, function(key) {\n return isFunction(object[key]);\n });\n }\n\n /**\n * The base implementation of `_.get` without support for default values.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the property to get.\n * @returns {*} Returns the resolved value.\n */\n function baseGet(object, path) {\n path = castPath(path, object);\n\n var index = 0,\n length = path.length;\n\n while (object != null && index < length) {\n object = object[toKey(path[index++])];\n }\n return (index && index == length) ? object : undefined;\n }\n\n /**\n * The base implementation of `getAllKeys` and `getAllKeysIn` which uses\n * `keysFunc` and `symbolsFunc` to get the enumerable property names and\n * symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Function} keysFunc The function to get the keys of `object`.\n * @param {Function} symbolsFunc The function to get the symbols of `object`.\n * @returns {Array} Returns the array of property names and symbols.\n */\n function baseGetAllKeys(object, keysFunc, symbolsFunc) {\n var result = keysFunc(object);\n return isArray(object) ? result : arrayPush(result, symbolsFunc(object));\n }\n\n /**\n * The base implementation of `getTag` without fallbacks for buggy environments.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\n function baseGetTag(value) {\n if (value == null) {\n return value === undefined ? undefinedTag : nullTag;\n }\n return (symToStringTag && symToStringTag in Object(value))\n ? getRawTag(value)\n : objectToString(value);\n }\n\n /**\n * The base implementation of `_.gt` which doesn't coerce arguments.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if `value` is greater than `other`,\n * else `false`.\n */\n function baseGt(value, other) {\n return value > other;\n }\n\n /**\n * The base implementation of `_.has` without support for deep paths.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {Array|string} key The key to check.\n * @returns {boolean} Returns `true` if `key` exists, else `false`.\n */\n function baseHas(object, key) {\n return object != null && hasOwnProperty.call(object, key);\n }\n\n /**\n * The base implementation of `_.hasIn` without support for deep paths.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {Array|string} key The key to check.\n * @returns {boolean} Returns `true` if `key` exists, else `false`.\n */\n function baseHasIn(object, key) {\n return object != null && key in Object(object);\n }\n\n /**\n * The base implementation of `_.inRange` which doesn't coerce arguments.\n *\n * @private\n * @param {number} number The number to check.\n * @param {number} start The start of the range.\n * @param {number} end The end of the range.\n * @returns {boolean} Returns `true` if `number` is in the range, else `false`.\n */\n function baseInRange(number, start, end) {\n return number >= nativeMin(start, end) && number < nativeMax(start, end);\n }\n\n /**\n * The base implementation of methods like `_.intersection`, without support\n * for iteratee shorthands, that accepts an array of arrays to inspect.\n *\n * @private\n * @param {Array} arrays The arrays to inspect.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of shared values.\n */\n function baseIntersection(arrays, iteratee, comparator) {\n var includes = comparator ? arrayIncludesWith : arrayIncludes,\n length = arrays[0].length,\n othLength = arrays.length,\n othIndex = othLength,\n caches = Array(othLength),\n maxLength = Infinity,\n result = [];\n\n while (othIndex--) {\n var array = arrays[othIndex];\n if (othIndex && iteratee) {\n array = arrayMap(array, baseUnary(iteratee));\n }\n maxLength = nativeMin(array.length, maxLength);\n caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120))\n ? new SetCache(othIndex && array)\n : undefined;\n }\n array = arrays[0];\n\n var index = -1,\n seen = caches[0];\n\n outer:\n while (++index < length && result.length < maxLength) {\n var value = array[index],\n computed = iteratee ? iteratee(value) : value;\n\n value = (comparator || value !== 0) ? value : 0;\n if (!(seen\n ? cacheHas(seen, computed)\n : includes(result, computed, comparator)\n )) {\n othIndex = othLength;\n while (--othIndex) {\n var cache = caches[othIndex];\n if (!(cache\n ? cacheHas(cache, computed)\n : includes(arrays[othIndex], computed, comparator))\n ) {\n continue outer;\n }\n }\n if (seen) {\n seen.push(computed);\n }\n result.push(value);\n }\n }\n return result;\n }\n\n /**\n * The base implementation of `_.invert` and `_.invertBy` which inverts\n * `object` with values transformed by `iteratee` and set by `setter`.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} setter The function to set `accumulator` values.\n * @param {Function} iteratee The iteratee to transform values.\n * @param {Object} accumulator The initial inverted object.\n * @returns {Function} Returns `accumulator`.\n */\n function baseInverter(object, setter, iteratee, accumulator) {\n baseForOwn(object, function(value, key, object) {\n setter(accumulator, iteratee(value), key, object);\n });\n return accumulator;\n }\n\n /**\n * The base implementation of `_.invoke` without support for individual\n * method arguments.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the method to invoke.\n * @param {Array} args The arguments to invoke the method with.\n * @returns {*} Returns the result of the invoked method.\n */\n function baseInvoke(object, path, args) {\n path = castPath(path, object);\n object = parent(object, path);\n var func = object == null ? object : object[toKey(last(path))];\n return func == null ? undefined : apply(func, object, args);\n }\n\n /**\n * The base implementation of `_.isArguments`.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n */\n function baseIsArguments(value) {\n return isObjectLike(value) && baseGetTag(value) == argsTag;\n }\n\n /**\n * The base implementation of `_.isArrayBuffer` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.\n */\n function baseIsArrayBuffer(value) {\n return isObjectLike(value) && baseGetTag(value) == arrayBufferTag;\n }\n\n /**\n * The base implementation of `_.isDate` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a date object, else `false`.\n */\n function baseIsDate(value) {\n return isObjectLike(value) && baseGetTag(value) == dateTag;\n }\n\n /**\n * The base implementation of `_.isEqual` which supports partial comparisons\n * and tracks traversed objects.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @param {boolean} bitmask The bitmask flags.\n * 1 - Unordered comparison\n * 2 - Partial comparison\n * @param {Function} [customizer] The function to customize comparisons.\n * @param {Object} [stack] Tracks traversed `value` and `other` objects.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n */\n function baseIsEqual(value, other, bitmask, customizer, stack) {\n if (value === other) {\n return true;\n }\n if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {\n return value !== value && other !== other;\n }\n return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);\n }\n\n /**\n * A specialized version of `baseIsEqual` for arrays and objects which performs\n * deep comparisons and tracks traversed objects enabling objects with circular\n * references to be compared.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} [stack] Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\n function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {\n var objIsArr = isArray(object),\n othIsArr = isArray(other),\n objTag = objIsArr ? arrayTag : getTag(object),\n othTag = othIsArr ? arrayTag : getTag(other);\n\n objTag = objTag == argsTag ? objectTag : objTag;\n othTag = othTag == argsTag ? objectTag : othTag;\n\n var objIsObj = objTag == objectTag,\n othIsObj = othTag == objectTag,\n isSameTag = objTag == othTag;\n\n if (isSameTag && isBuffer(object)) {\n if (!isBuffer(other)) {\n return false;\n }\n objIsArr = true;\n objIsObj = false;\n }\n if (isSameTag && !objIsObj) {\n stack || (stack = new Stack);\n return (objIsArr || isTypedArray(object))\n ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)\n : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);\n }\n if (!(bitmask & COMPARE_PARTIAL_FLAG)) {\n var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),\n othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');\n\n if (objIsWrapped || othIsWrapped) {\n var objUnwrapped = objIsWrapped ? object.value() : object,\n othUnwrapped = othIsWrapped ? other.value() : other;\n\n stack || (stack = new Stack);\n return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);\n }\n }\n if (!isSameTag) {\n return false;\n }\n stack || (stack = new Stack);\n return equalObjects(object, other, bitmask, customizer, equalFunc, stack);\n }\n\n /**\n * The base implementation of `_.isMap` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a map, else `false`.\n */\n function baseIsMap(value) {\n return isObjectLike(value) && getTag(value) == mapTag;\n }\n\n /**\n * The base implementation of `_.isMatch` without support for iteratee shorthands.\n *\n * @private\n * @param {Object} object The object to inspect.\n * @param {Object} source The object of property values to match.\n * @param {Array} matchData The property names, values, and compare flags to match.\n * @param {Function} [customizer] The function to customize comparisons.\n * @returns {boolean} Returns `true` if `object` is a match, else `false`.\n */\n function baseIsMatch(object, source, matchData, customizer) {\n var index = matchData.length,\n length = index,\n noCustomizer = !customizer;\n\n if (object == null) {\n return !length;\n }\n object = Object(object);\n while (index--) {\n var data = matchData[index];\n if ((noCustomizer && data[2])\n ? data[1] !== object[data[0]]\n : !(data[0] in object)\n ) {\n return false;\n }\n }\n while (++index < length) {\n data = matchData[index];\n var key = data[0],\n objValue = object[key],\n srcValue = data[1];\n\n if (noCustomizer && data[2]) {\n if (objValue === undefined && !(key in object)) {\n return false;\n }\n } else {\n var stack = new Stack;\n if (customizer) {\n var result = customizer(objValue, srcValue, key, object, source, stack);\n }\n if (!(result === undefined\n ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)\n : result\n )) {\n return false;\n }\n }\n }\n return true;\n }\n\n /**\n * The base implementation of `_.isNative` without bad shim checks.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function,\n * else `false`.\n */\n function baseIsNative(value) {\n if (!isObject(value) || isMasked(value)) {\n return false;\n }\n var pattern = isFunction(value) ? reIsNative : reIsHostCtor;\n return pattern.test(toSource(value));\n }\n\n /**\n * The base implementation of `_.isRegExp` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.\n */\n function baseIsRegExp(value) {\n return isObjectLike(value) && baseGetTag(value) == regexpTag;\n }\n\n /**\n * The base implementation of `_.isSet` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a set, else `false`.\n */\n function baseIsSet(value) {\n return isObjectLike(value) && getTag(value) == setTag;\n }\n\n /**\n * The base implementation of `_.isTypedArray` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n */\n function baseIsTypedArray(value) {\n return isObjectLike(value) &&\n isLength(value.length) && !!typedArrayTags[baseGetTag(value)];\n }\n\n /**\n * The base implementation of `_.iteratee`.\n *\n * @private\n * @param {*} [value=_.identity] The value to convert to an iteratee.\n * @returns {Function} Returns the iteratee.\n */\n function baseIteratee(value) {\n // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.\n // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.\n if (typeof value == 'function') {\n return value;\n }\n if (value == null) {\n return identity;\n }\n if (typeof value == 'object') {\n return isArray(value)\n ? baseMatchesProperty(value[0], value[1])\n : baseMatches(value);\n }\n return property(value);\n }\n\n /**\n * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\n function baseKeys(object) {\n if (!isPrototype(object)) {\n return nativeKeys(object);\n }\n var result = [];\n for (var key in Object(object)) {\n if (hasOwnProperty.call(object, key) && key != 'constructor') {\n result.push(key);\n }\n }\n return result;\n }\n\n /**\n * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\n function baseKeysIn(object) {\n if (!isObject(object)) {\n return nativeKeysIn(object);\n }\n var isProto = isPrototype(object),\n result = [];\n\n for (var key in object) {\n if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {\n result.push(key);\n }\n }\n return result;\n }\n\n /**\n * The base implementation of `_.lt` which doesn't coerce arguments.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if `value` is less than `other`,\n * else `false`.\n */\n function baseLt(value, other) {\n return value < other;\n }\n\n /**\n * The base implementation of `_.map` without support for iteratee shorthands.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\n function baseMap(collection, iteratee) {\n var index = -1,\n result = isArrayLike(collection) ? Array(collection.length) : [];\n\n baseEach(collection, function(value, key, collection) {\n result[++index] = iteratee(value, key, collection);\n });\n return result;\n }\n\n /**\n * The base implementation of `_.matches` which doesn't clone `source`.\n *\n * @private\n * @param {Object} source The object of property values to match.\n * @returns {Function} Returns the new spec function.\n */\n function baseMatches(source) {\n var matchData = getMatchData(source);\n if (matchData.length == 1 && matchData[0][2]) {\n return matchesStrictComparable(matchData[0][0], matchData[0][1]);\n }\n return function(object) {\n return object === source || baseIsMatch(object, source, matchData);\n };\n }\n\n /**\n * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.\n *\n * @private\n * @param {string} path The path of the property to get.\n * @param {*} srcValue The value to match.\n * @returns {Function} Returns the new spec function.\n */\n function baseMatchesProperty(path, srcValue) {\n if (isKey(path) && isStrictComparable(srcValue)) {\n return matchesStrictComparable(toKey(path), srcValue);\n }\n return function(object) {\n var objValue = get(object, path);\n return (objValue === undefined && objValue === srcValue)\n ? hasIn(object, path)\n : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);\n };\n }\n\n /**\n * The base implementation of `_.merge` without support for multiple sources.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @param {number} srcIndex The index of `source`.\n * @param {Function} [customizer] The function to customize merged values.\n * @param {Object} [stack] Tracks traversed source values and their merged\n * counterparts.\n */\n function baseMerge(object, source, srcIndex, customizer, stack) {\n if (object === source) {\n return;\n }\n baseFor(source, function(srcValue, key) {\n if (isObject(srcValue)) {\n stack || (stack = new Stack);\n baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);\n }\n else {\n var newValue = customizer\n ? customizer(object[key], srcValue, (key + ''), object, source, stack)\n : undefined;\n\n if (newValue === undefined) {\n newValue = srcValue;\n }\n assignMergeValue(object, key, newValue);\n }\n }, keysIn);\n }\n\n /**\n * A specialized version of `baseMerge` for arrays and objects which performs\n * deep merges and tracks traversed objects enabling objects with circular\n * references to be merged.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @param {string} key The key of the value to merge.\n * @param {number} srcIndex The index of `source`.\n * @param {Function} mergeFunc The function to merge values.\n * @param {Function} [customizer] The function to customize assigned values.\n * @param {Object} [stack] Tracks traversed source values and their merged\n * counterparts.\n */\n function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {\n var objValue = object[key],\n srcValue = source[key],\n stacked = stack.get(srcValue);\n\n if (stacked) {\n assignMergeValue(object, key, stacked);\n return;\n }\n var newValue = customizer\n ? customizer(objValue, srcValue, (key + ''), object, source, stack)\n : undefined;\n\n var isCommon = newValue === undefined;\n\n if (isCommon) {\n var isArr = isArray(srcValue),\n isBuff = !isArr && isBuffer(srcValue),\n isTyped = !isArr && !isBuff && isTypedArray(srcValue);\n\n newValue = srcValue;\n if (isArr || isBuff || isTyped) {\n if (isArray(objValue)) {\n newValue = objValue;\n }\n else if (isArrayLikeObject(objValue)) {\n newValue = copyArray(objValue);\n }\n else if (isBuff) {\n isCommon = false;\n newValue = cloneBuffer(srcValue, true);\n }\n else if (isTyped) {\n isCommon = false;\n newValue = cloneTypedArray(srcValue, true);\n }\n else {\n newValue = [];\n }\n }\n else if (isPlainObject(srcValue) || isArguments(srcValue)) {\n newValue = objValue;\n if (isArguments(objValue)) {\n newValue = toPlainObject(objValue);\n }\n else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) {\n newValue = initCloneObject(srcValue);\n }\n }\n else {\n isCommon = false;\n }\n }\n if (isCommon) {\n // Recursively merge objects and arrays (susceptible to call stack limits).\n stack.set(srcValue, newValue);\n mergeFunc(newValue, srcValue, srcIndex, customizer, stack);\n stack['delete'](srcValue);\n }\n assignMergeValue(object, key, newValue);\n }\n\n /**\n * The base implementation of `_.nth` which doesn't coerce arguments.\n *\n * @private\n * @param {Array} array The array to query.\n * @param {number} n The index of the element to return.\n * @returns {*} Returns the nth element of `array`.\n */\n function baseNth(array, n) {\n var length = array.length;\n if (!length) {\n return;\n }\n n += n < 0 ? length : 0;\n return isIndex(n, length) ? array[n] : undefined;\n }\n\n /**\n * The base implementation of `_.orderBy` without param guards.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.\n * @param {string[]} orders The sort orders of `iteratees`.\n * @returns {Array} Returns the new sorted array.\n */\n function baseOrderBy(collection, iteratees, orders) {\n var index = -1;\n iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(getIteratee()));\n\n var result = baseMap(collection, function(value, key, collection) {\n var criteria = arrayMap(iteratees, function(iteratee) {\n return iteratee(value);\n });\n return { 'criteria': criteria, 'index': ++index, 'value': value };\n });\n\n return baseSortBy(result, function(object, other) {\n return compareMultiple(object, other, orders);\n });\n }\n\n /**\n * The base implementation of `_.pick` without support for individual\n * property identifiers.\n *\n * @private\n * @param {Object} object The source object.\n * @param {string[]} paths The property paths to pick.\n * @returns {Object} Returns the new object.\n */\n function basePick(object, paths) {\n return basePickBy(object, paths, function(value, path) {\n return hasIn(object, path);\n });\n }\n\n /**\n * The base implementation of `_.pickBy` without support for iteratee shorthands.\n *\n * @private\n * @param {Object} object The source object.\n * @param {string[]} paths The property paths to pick.\n * @param {Function} predicate The function invoked per property.\n * @returns {Object} Returns the new object.\n */\n function basePickBy(object, paths, predicate) {\n var index = -1,\n length = paths.length,\n result = {};\n\n while (++index < length) {\n var path = paths[index],\n value = baseGet(object, path);\n\n if (predicate(value, path)) {\n baseSet(result, castPath(path, object), value);\n }\n }\n return result;\n }\n\n /**\n * A specialized version of `baseProperty` which supports deep paths.\n *\n * @private\n * @param {Array|string} path The path of the property to get.\n * @returns {Function} Returns the new accessor function.\n */\n function basePropertyDeep(path) {\n return function(object) {\n return baseGet(object, path);\n };\n }\n\n /**\n * The base implementation of `_.pullAllBy` without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {Array} values The values to remove.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns `array`.\n */\n function basePullAll(array, values, iteratee, comparator) {\n var indexOf = comparator ? baseIndexOfWith : baseIndexOf,\n index = -1,\n length = values.length,\n seen = array;\n\n if (array === values) {\n values = copyArray(values);\n }\n if (iteratee) {\n seen = arrayMap(array, baseUnary(iteratee));\n }\n while (++index < length) {\n var fromIndex = 0,\n value = values[index],\n computed = iteratee ? iteratee(value) : value;\n\n while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {\n if (seen !== array) {\n splice.call(seen, fromIndex, 1);\n }\n splice.call(array, fromIndex, 1);\n }\n }\n return array;\n }\n\n /**\n * The base implementation of `_.pullAt` without support for individual\n * indexes or capturing the removed elements.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {number[]} indexes The indexes of elements to remove.\n * @returns {Array} Returns `array`.\n */\n function basePullAt(array, indexes) {\n var length = array ? indexes.length : 0,\n lastIndex = length - 1;\n\n while (length--) {\n var index = indexes[length];\n if (length == lastIndex || index !== previous) {\n var previous = index;\n if (isIndex(index)) {\n splice.call(array, index, 1);\n } else {\n baseUnset(array, index);\n }\n }\n }\n return array;\n }\n\n /**\n * The base implementation of `_.random` without support for returning\n * floating-point numbers.\n *\n * @private\n * @param {number} lower The lower bound.\n * @param {number} upper The upper bound.\n * @returns {number} Returns the random number.\n */\n function baseRandom(lower, upper) {\n return lower + nativeFloor(nativeRandom() * (upper - lower + 1));\n }\n\n /**\n * The base implementation of `_.range` and `_.rangeRight` which doesn't\n * coerce arguments.\n *\n * @private\n * @param {number} start The start of the range.\n * @param {number} end The end of the range.\n * @param {number} step The value to increment or decrement by.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Array} Returns the range of numbers.\n */\n function baseRange(start, end, step, fromRight) {\n var index = -1,\n length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),\n result = Array(length);\n\n while (length--) {\n result[fromRight ? length : ++index] = start;\n start += step;\n }\n return result;\n }\n\n /**\n * The base implementation of `_.repeat` which doesn't coerce arguments.\n *\n * @private\n * @param {string} string The string to repeat.\n * @param {number} n The number of times to repeat the string.\n * @returns {string} Returns the repeated string.\n */\n function baseRepeat(string, n) {\n var result = '';\n if (!string || n < 1 || n > MAX_SAFE_INTEGER) {\n return result;\n }\n // Leverage the exponentiation by squaring algorithm for a faster repeat.\n // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.\n do {\n if (n % 2) {\n result += string;\n }\n n = nativeFloor(n / 2);\n if (n) {\n string += string;\n }\n } while (n);\n\n return result;\n }\n\n /**\n * The base implementation of `_.rest` which doesn't validate or coerce arguments.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @returns {Function} Returns the new function.\n */\n function baseRest(func, start) {\n return setToString(overRest(func, start, identity), func + '');\n }\n\n /**\n * The base implementation of `_.sample`.\n *\n * @private\n * @param {Array|Object} collection The collection to sample.\n * @returns {*} Returns the random element.\n */\n function baseSample(collection) {\n return arraySample(values(collection));\n }\n\n /**\n * The base implementation of `_.sampleSize` without param guards.\n *\n * @private\n * @param {Array|Object} collection The collection to sample.\n * @param {number} n The number of elements to sample.\n * @returns {Array} Returns the random elements.\n */\n function baseSampleSize(collection, n) {\n var array = values(collection);\n return shuffleSelf(array, baseClamp(n, 0, array.length));\n }\n\n /**\n * The base implementation of `_.set`.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to set.\n * @param {*} value The value to set.\n * @param {Function} [customizer] The function to customize path creation.\n * @returns {Object} Returns `object`.\n */\n function baseSet(object, path, value, customizer) {\n if (!isObject(object)) {\n return object;\n }\n path = castPath(path, object);\n\n var index = -1,\n length = path.length,\n lastIndex = length - 1,\n nested = object;\n\n while (nested != null && ++index < length) {\n var key = toKey(path[index]),\n newValue = value;\n\n if (index != lastIndex) {\n var objValue = nested[key];\n newValue = customizer ? customizer(objValue, key, nested) : undefined;\n if (newValue === undefined) {\n newValue = isObject(objValue)\n ? objValue\n : (isIndex(path[index + 1]) ? [] : {});\n }\n }\n assignValue(nested, key, newValue);\n nested = nested[key];\n }\n return object;\n }\n\n /**\n * The base implementation of `setData` without support for hot loop shorting.\n *\n * @private\n * @param {Function} func The function to associate metadata with.\n * @param {*} data The metadata.\n * @returns {Function} Returns `func`.\n */\n var baseSetData = !metaMap ? identity : function(func, data) {\n metaMap.set(func, data);\n return func;\n };\n\n /**\n * The base implementation of `setToString` without support for hot loop shorting.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\n var baseSetToString = !defineProperty ? identity : function(func, string) {\n return defineProperty(func, 'toString', {\n 'configurable': true,\n 'enumerable': false,\n 'value': constant(string),\n 'writable': true\n });\n };\n\n /**\n * The base implementation of `_.shuffle`.\n *\n * @private\n * @param {Array|Object} collection The collection to shuffle.\n * @returns {Array} Returns the new shuffled array.\n */\n function baseShuffle(collection) {\n return shuffleSelf(values(collection));\n }\n\n /**\n * The base implementation of `_.slice` without an iteratee call guard.\n *\n * @private\n * @param {Array} array The array to slice.\n * @param {number} [start=0] The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns the slice of `array`.\n */\n function baseSlice(array, start, end) {\n var index = -1,\n length = array.length;\n\n if (start < 0) {\n start = -start > length ? 0 : (length + start);\n }\n end = end > length ? length : end;\n if (end < 0) {\n end += length;\n }\n length = start > end ? 0 : ((end - start) >>> 0);\n start >>>= 0;\n\n var result = Array(length);\n while (++index < length) {\n result[index] = array[index + start];\n }\n return result;\n }\n\n /**\n * The base implementation of `_.some` without support for iteratee shorthands.\n *\n * @private\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {boolean} Returns `true` if any element passes the predicate check,\n * else `false`.\n */\n function baseSome(collection, predicate) {\n var result;\n\n baseEach(collection, function(value, index, collection) {\n result = predicate(value, index, collection);\n return !result;\n });\n return !!result;\n }\n\n /**\n * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which\n * performs a binary search of `array` to determine the index at which `value`\n * should be inserted into `array` in order to maintain its sort order.\n *\n * @private\n * @param {Array} array The sorted array to inspect.\n * @param {*} value The value to evaluate.\n * @param {boolean} [retHighest] Specify returning the highest qualified index.\n * @returns {number} Returns the index at which `value` should be inserted\n * into `array`.\n */\n function baseSortedIndex(array, value, retHighest) {\n var low = 0,\n high = array == null ? low : array.length;\n\n if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {\n while (low < high) {\n var mid = (low + high) >>> 1,\n computed = array[mid];\n\n if (computed !== null && !isSymbol(computed) &&\n (retHighest ? (computed <= value) : (computed < value))) {\n low = mid + 1;\n } else {\n high = mid;\n }\n }\n return high;\n }\n return baseSortedIndexBy(array, value, identity, retHighest);\n }\n\n /**\n * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`\n * which invokes `iteratee` for `value` and each element of `array` to compute\n * their sort ranking. The iteratee is invoked with one argument; (value).\n *\n * @private\n * @param {Array} array The sorted array to inspect.\n * @param {*} value The value to evaluate.\n * @param {Function} iteratee The iteratee invoked per element.\n * @param {boolean} [retHighest] Specify returning the highest qualified index.\n * @returns {number} Returns the index at which `value` should be inserted\n * into `array`.\n */\n function baseSortedIndexBy(array, value, iteratee, retHighest) {\n value = iteratee(value);\n\n var low = 0,\n high = array == null ? 0 : array.length,\n valIsNaN = value !== value,\n valIsNull = value === null,\n valIsSymbol = isSymbol(value),\n valIsUndefined = value === undefined;\n\n while (low < high) {\n var mid = nativeFloor((low + high) / 2),\n computed = iteratee(array[mid]),\n othIsDefined = computed !== undefined,\n othIsNull = computed === null,\n othIsReflexive = computed === computed,\n othIsSymbol = isSymbol(computed);\n\n if (valIsNaN) {\n var setLow = retHighest || othIsReflexive;\n } else if (valIsUndefined) {\n setLow = othIsReflexive && (retHighest || othIsDefined);\n } else if (valIsNull) {\n setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);\n } else if (valIsSymbol) {\n setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);\n } else if (othIsNull || othIsSymbol) {\n setLow = false;\n } else {\n setLow = retHighest ? (computed <= value) : (computed < value);\n }\n if (setLow) {\n low = mid + 1;\n } else {\n high = mid;\n }\n }\n return nativeMin(high, MAX_ARRAY_INDEX);\n }\n\n /**\n * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without\n * support for iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n */\n function baseSortedUniq(array, iteratee) {\n var index = -1,\n length = array.length,\n resIndex = 0,\n result = [];\n\n while (++index < length) {\n var value = array[index],\n computed = iteratee ? iteratee(value) : value;\n\n if (!index || !eq(computed, seen)) {\n var seen = computed;\n result[resIndex++] = value === 0 ? 0 : value;\n }\n }\n return result;\n }\n\n /**\n * The base implementation of `_.toNumber` which doesn't ensure correct\n * conversions of binary, hexadecimal, or octal string values.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {number} Returns the number.\n */\n function baseToNumber(value) {\n if (typeof value == 'number') {\n return value;\n }\n if (isSymbol(value)) {\n return NAN;\n }\n return +value;\n }\n\n /**\n * The base implementation of `_.toString` which doesn't convert nullish\n * values to empty strings.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {string} Returns the string.\n */\n function baseToString(value) {\n // Exit early for strings to avoid a performance hit in some environments.\n if (typeof value == 'string') {\n return value;\n }\n if (isArray(value)) {\n // Recursively convert values (susceptible to call stack limits).\n return arrayMap(value, baseToString) + '';\n }\n if (isSymbol(value)) {\n return symbolToString ? symbolToString.call(value) : '';\n }\n var result = (value + '');\n return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;\n }\n\n /**\n * The base implementation of `_.uniqBy` without support for iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n */\n function baseUniq(array, iteratee, comparator) {\n var index = -1,\n includes = arrayIncludes,\n length = array.length,\n isCommon = true,\n result = [],\n seen = result;\n\n if (comparator) {\n isCommon = false;\n includes = arrayIncludesWith;\n }\n else if (length >= LARGE_ARRAY_SIZE) {\n var set = iteratee ? null : createSet(array);\n if (set) {\n return setToArray(set);\n }\n isCommon = false;\n includes = cacheHas;\n seen = new SetCache;\n }\n else {\n seen = iteratee ? [] : result;\n }\n outer:\n while (++index < length) {\n var value = array[index],\n computed = iteratee ? iteratee(value) : value;\n\n value = (comparator || value !== 0) ? value : 0;\n if (isCommon && computed === computed) {\n var seenIndex = seen.length;\n while (seenIndex--) {\n if (seen[seenIndex] === computed) {\n continue outer;\n }\n }\n if (iteratee) {\n seen.push(computed);\n }\n result.push(value);\n }\n else if (!includes(seen, computed, comparator)) {\n if (seen !== result) {\n seen.push(computed);\n }\n result.push(value);\n }\n }\n return result;\n }\n\n /**\n * The base implementation of `_.unset`.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {Array|string} path The property path to unset.\n * @returns {boolean} Returns `true` if the property is deleted, else `false`.\n */\n function baseUnset(object, path) {\n path = castPath(path, object);\n object = parent(object, path);\n return object == null || delete object[toKey(last(path))];\n }\n\n /**\n * The base implementation of `_.update`.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to update.\n * @param {Function} updater The function to produce the updated value.\n * @param {Function} [customizer] The function to customize path creation.\n * @returns {Object} Returns `object`.\n */\n function baseUpdate(object, path, updater, customizer) {\n return baseSet(object, path, updater(baseGet(object, path)), customizer);\n }\n\n /**\n * The base implementation of methods like `_.dropWhile` and `_.takeWhile`\n * without support for iteratee shorthands.\n *\n * @private\n * @param {Array} array The array to query.\n * @param {Function} predicate The function invoked per iteration.\n * @param {boolean} [isDrop] Specify dropping elements instead of taking them.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Array} Returns the slice of `array`.\n */\n function baseWhile(array, predicate, isDrop, fromRight) {\n var length = array.length,\n index = fromRight ? length : -1;\n\n while ((fromRight ? index-- : ++index < length) &&\n predicate(array[index], index, array)) {}\n\n return isDrop\n ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))\n : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));\n }\n\n /**\n * The base implementation of `wrapperValue` which returns the result of\n * performing a sequence of actions on the unwrapped `value`, where each\n * successive action is supplied the return value of the previous.\n *\n * @private\n * @param {*} value The unwrapped value.\n * @param {Array} actions Actions to perform to resolve the unwrapped value.\n * @returns {*} Returns the resolved value.\n */\n function baseWrapperValue(value, actions) {\n var result = value;\n if (result instanceof LazyWrapper) {\n result = result.value();\n }\n return arrayReduce(actions, function(result, action) {\n return action.func.apply(action.thisArg, arrayPush([result], action.args));\n }, result);\n }\n\n /**\n * The base implementation of methods like `_.xor`, without support for\n * iteratee shorthands, that accepts an array of arrays to inspect.\n *\n * @private\n * @param {Array} arrays The arrays to inspect.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of values.\n */\n function baseXor(arrays, iteratee, comparator) {\n var length = arrays.length;\n if (length < 2) {\n return length ? baseUniq(arrays[0]) : [];\n }\n var index = -1,\n result = Array(length);\n\n while (++index < length) {\n var array = arrays[index],\n othIndex = -1;\n\n while (++othIndex < length) {\n if (othIndex != index) {\n result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);\n }\n }\n }\n return baseUniq(baseFlatten(result, 1), iteratee, comparator);\n }\n\n /**\n * This base implementation of `_.zipObject` which assigns values using `assignFunc`.\n *\n * @private\n * @param {Array} props The property identifiers.\n * @param {Array} values The property values.\n * @param {Function} assignFunc The function to assign values.\n * @returns {Object} Returns the new object.\n */\n function baseZipObject(props, values, assignFunc) {\n var index = -1,\n length = props.length,\n valsLength = values.length,\n result = {};\n\n while (++index < length) {\n var value = index < valsLength ? values[index] : undefined;\n assignFunc(result, props[index], value);\n }\n return result;\n }\n\n /**\n * Casts `value` to an empty array if it's not an array like object.\n *\n * @private\n * @param {*} value The value to inspect.\n * @returns {Array|Object} Returns the cast array-like object.\n */\n function castArrayLikeObject(value) {\n return isArrayLikeObject(value) ? value : [];\n }\n\n /**\n * Casts `value` to `identity` if it's not a function.\n *\n * @private\n * @param {*} value The value to inspect.\n * @returns {Function} Returns cast function.\n */\n function castFunction(value) {\n return typeof value == 'function' ? value : identity;\n }\n\n /**\n * Casts `value` to a path array if it's not one.\n *\n * @private\n * @param {*} value The value to inspect.\n * @param {Object} [object] The object to query keys on.\n * @returns {Array} Returns the cast property path array.\n */\n function castPath(value, object) {\n if (isArray(value)) {\n return value;\n }\n return isKey(value, object) ? [value] : stringToPath(toString(value));\n }\n\n /**\n * A `baseRest` alias which can be replaced with `identity` by module\n * replacement plugins.\n *\n * @private\n * @type {Function}\n * @param {Function} func The function to apply a rest parameter to.\n * @returns {Function} Returns the new function.\n */\n var castRest = baseRest;\n\n /**\n * Casts `array` to a slice if it's needed.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {number} start The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns the cast slice.\n */\n function castSlice(array, start, end) {\n var length = array.length;\n end = end === undefined ? length : end;\n return (!start && end >= length) ? array : baseSlice(array, start, end);\n }\n\n /**\n * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout).\n *\n * @private\n * @param {number|Object} id The timer id or timeout object of the timer to clear.\n */\n var clearTimeout = ctxClearTimeout || function(id) {\n return root.clearTimeout(id);\n };\n\n /**\n * Creates a clone of `buffer`.\n *\n * @private\n * @param {Buffer} buffer The buffer to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Buffer} Returns the cloned buffer.\n */\n function cloneBuffer(buffer, isDeep) {\n if (isDeep) {\n return buffer.slice();\n }\n var length = buffer.length,\n result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);\n\n buffer.copy(result);\n return result;\n }\n\n /**\n * Creates a clone of `arrayBuffer`.\n *\n * @private\n * @param {ArrayBuffer} arrayBuffer The array buffer to clone.\n * @returns {ArrayBuffer} Returns the cloned array buffer.\n */\n function cloneArrayBuffer(arrayBuffer) {\n var result = new arrayBuffer.constructor(arrayBuffer.byteLength);\n new Uint8Array(result).set(new Uint8Array(arrayBuffer));\n return result;\n }\n\n /**\n * Creates a clone of `dataView`.\n *\n * @private\n * @param {Object} dataView The data view to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned data view.\n */\n function cloneDataView(dataView, isDeep) {\n var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;\n return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);\n }\n\n /**\n * Creates a clone of `map`.\n *\n * @private\n * @param {Object} map The map to clone.\n * @param {Function} cloneFunc The function to clone values.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned map.\n */\n function cloneMap(map, isDeep, cloneFunc) {\n var array = isDeep ? cloneFunc(mapToArray(map), CLONE_DEEP_FLAG) : mapToArray(map);\n return arrayReduce(array, addMapEntry, new map.constructor);\n }\n\n /**\n * Creates a clone of `regexp`.\n *\n * @private\n * @param {Object} regexp The regexp to clone.\n * @returns {Object} Returns the cloned regexp.\n */\n function cloneRegExp(regexp) {\n var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));\n result.lastIndex = regexp.lastIndex;\n return result;\n }\n\n /**\n * Creates a clone of `set`.\n *\n * @private\n * @param {Object} set The set to clone.\n * @param {Function} cloneFunc The function to clone values.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned set.\n */\n function cloneSet(set, isDeep, cloneFunc) {\n var array = isDeep ? cloneFunc(setToArray(set), CLONE_DEEP_FLAG) : setToArray(set);\n return arrayReduce(array, addSetEntry, new set.constructor);\n }\n\n /**\n * Creates a clone of the `symbol` object.\n *\n * @private\n * @param {Object} symbol The symbol object to clone.\n * @returns {Object} Returns the cloned symbol object.\n */\n function cloneSymbol(symbol) {\n return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};\n }\n\n /**\n * Creates a clone of `typedArray`.\n *\n * @private\n * @param {Object} typedArray The typed array to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned typed array.\n */\n function cloneTypedArray(typedArray, isDeep) {\n var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;\n return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);\n }\n\n /**\n * Compares values to sort them in ascending order.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {number} Returns the sort order indicator for `value`.\n */\n function compareAscending(value, other) {\n if (value !== other) {\n var valIsDefined = value !== undefined,\n valIsNull = value === null,\n valIsReflexive = value === value,\n valIsSymbol = isSymbol(value);\n\n var othIsDefined = other !== undefined,\n othIsNull = other === null,\n othIsReflexive = other === other,\n othIsSymbol = isSymbol(other);\n\n if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||\n (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||\n (valIsNull && othIsDefined && othIsReflexive) ||\n (!valIsDefined && othIsReflexive) ||\n !valIsReflexive) {\n return 1;\n }\n if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||\n (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||\n (othIsNull && valIsDefined && valIsReflexive) ||\n (!othIsDefined && valIsReflexive) ||\n !othIsReflexive) {\n return -1;\n }\n }\n return 0;\n }\n\n /**\n * Used by `_.orderBy` to compare multiple properties of a value to another\n * and stable sort them.\n *\n * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,\n * specify an order of \"desc\" for descending or \"asc\" for ascending sort order\n * of corresponding values.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {boolean[]|string[]} orders The order to sort by for each property.\n * @returns {number} Returns the sort order indicator for `object`.\n */\n function compareMultiple(object, other, orders) {\n var index = -1,\n objCriteria = object.criteria,\n othCriteria = other.criteria,\n length = objCriteria.length,\n ordersLength = orders.length;\n\n while (++index < length) {\n var result = compareAscending(objCriteria[index], othCriteria[index]);\n if (result) {\n if (index >= ordersLength) {\n return result;\n }\n var order = orders[index];\n return result * (order == 'desc' ? -1 : 1);\n }\n }\n // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications\n // that causes it, under certain circumstances, to provide the same value for\n // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247\n // for more details.\n //\n // This also ensures a stable sort in V8 and other engines.\n // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.\n return object.index - other.index;\n }\n\n /**\n * Creates an array that is the composition of partially applied arguments,\n * placeholders, and provided arguments into a single array of arguments.\n *\n * @private\n * @param {Array} args The provided arguments.\n * @param {Array} partials The arguments to prepend to those provided.\n * @param {Array} holders The `partials` placeholder indexes.\n * @params {boolean} [isCurried] Specify composing for a curried function.\n * @returns {Array} Returns the new array of composed arguments.\n */\n function composeArgs(args, partials, holders, isCurried) {\n var argsIndex = -1,\n argsLength = args.length,\n holdersLength = holders.length,\n leftIndex = -1,\n leftLength = partials.length,\n rangeLength = nativeMax(argsLength - holdersLength, 0),\n result = Array(leftLength + rangeLength),\n isUncurried = !isCurried;\n\n while (++leftIndex < leftLength) {\n result[leftIndex] = partials[leftIndex];\n }\n while (++argsIndex < holdersLength) {\n if (isUncurried || argsIndex < argsLength) {\n result[holders[argsIndex]] = args[argsIndex];\n }\n }\n while (rangeLength--) {\n result[leftIndex++] = args[argsIndex++];\n }\n return result;\n }\n\n /**\n * This function is like `composeArgs` except that the arguments composition\n * is tailored for `_.partialRight`.\n *\n * @private\n * @param {Array} args The provided arguments.\n * @param {Array} partials The arguments to append to those provided.\n * @param {Array} holders The `partials` placeholder indexes.\n * @params {boolean} [isCurried] Specify composing for a curried function.\n * @returns {Array} Returns the new array of composed arguments.\n */\n function composeArgsRight(args, partials, holders, isCurried) {\n var argsIndex = -1,\n argsLength = args.length,\n holdersIndex = -1,\n holdersLength = holders.length,\n rightIndex = -1,\n rightLength = partials.length,\n rangeLength = nativeMax(argsLength - holdersLength, 0),\n result = Array(rangeLength + rightLength),\n isUncurried = !isCurried;\n\n while (++argsIndex < rangeLength) {\n result[argsIndex] = args[argsIndex];\n }\n var offset = argsIndex;\n while (++rightIndex < rightLength) {\n result[offset + rightIndex] = partials[rightIndex];\n }\n while (++holdersIndex < holdersLength) {\n if (isUncurried || argsIndex < argsLength) {\n result[offset + holders[holdersIndex]] = args[argsIndex++];\n }\n }\n return result;\n }\n\n /**\n * Copies the values of `source` to `array`.\n *\n * @private\n * @param {Array} source The array to copy values from.\n * @param {Array} [array=[]] The array to copy values to.\n * @returns {Array} Returns `array`.\n */\n function copyArray(source, array) {\n var index = -1,\n length = source.length;\n\n array || (array = Array(length));\n while (++index < length) {\n array[index] = source[index];\n }\n return array;\n }\n\n /**\n * Copies properties of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy properties from.\n * @param {Array} props The property identifiers to copy.\n * @param {Object} [object={}] The object to copy properties to.\n * @param {Function} [customizer] The function to customize copied values.\n * @returns {Object} Returns `object`.\n */\n function copyObject(source, props, object, customizer) {\n var isNew = !object;\n object || (object = {});\n\n var index = -1,\n length = props.length;\n\n while (++index < length) {\n var key = props[index];\n\n var newValue = customizer\n ? customizer(object[key], source[key], key, object, source)\n : undefined;\n\n if (newValue === undefined) {\n newValue = source[key];\n }\n if (isNew) {\n baseAssignValue(object, key, newValue);\n } else {\n assignValue(object, key, newValue);\n }\n }\n return object;\n }\n\n /**\n * Copies own symbols of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy symbols from.\n * @param {Object} [object={}] The object to copy symbols to.\n * @returns {Object} Returns `object`.\n */\n function copySymbols(source, object) {\n return copyObject(source, getSymbols(source), object);\n }\n\n /**\n * Copies own and inherited symbols of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy symbols from.\n * @param {Object} [object={}] The object to copy symbols to.\n * @returns {Object} Returns `object`.\n */\n function copySymbolsIn(source, object) {\n return copyObject(source, getSymbolsIn(source), object);\n }\n\n /**\n * Creates a function like `_.groupBy`.\n *\n * @private\n * @param {Function} setter The function to set accumulator values.\n * @param {Function} [initializer] The accumulator object initializer.\n * @returns {Function} Returns the new aggregator function.\n */\n function createAggregator(setter, initializer) {\n return function(collection, iteratee) {\n var func = isArray(collection) ? arrayAggregator : baseAggregator,\n accumulator = initializer ? initializer() : {};\n\n return func(collection, setter, getIteratee(iteratee, 2), accumulator);\n };\n }\n\n /**\n * Creates a function like `_.assign`.\n *\n * @private\n * @param {Function} assigner The function to assign values.\n * @returns {Function} Returns the new assigner function.\n */\n function createAssigner(assigner) {\n return baseRest(function(object, sources) {\n var index = -1,\n length = sources.length,\n customizer = length > 1 ? sources[length - 1] : undefined,\n guard = length > 2 ? sources[2] : undefined;\n\n customizer = (assigner.length > 3 && typeof customizer == 'function')\n ? (length--, customizer)\n : undefined;\n\n if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n customizer = length < 3 ? undefined : customizer;\n length = 1;\n }\n object = Object(object);\n while (++index < length) {\n var source = sources[index];\n if (source) {\n assigner(object, source, index, customizer);\n }\n }\n return object;\n });\n }\n\n /**\n * Creates a `baseEach` or `baseEachRight` function.\n *\n * @private\n * @param {Function} eachFunc The function to iterate over a collection.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new base function.\n */\n function createBaseEach(eachFunc, fromRight) {\n return function(collection, iteratee) {\n if (collection == null) {\n return collection;\n }\n if (!isArrayLike(collection)) {\n return eachFunc(collection, iteratee);\n }\n var length = collection.length,\n index = fromRight ? length : -1,\n iterable = Object(collection);\n\n while ((fromRight ? index-- : ++index < length)) {\n if (iteratee(iterable[index], index, iterable) === false) {\n break;\n }\n }\n return collection;\n };\n }\n\n /**\n * Creates a base function for methods like `_.forIn` and `_.forOwn`.\n *\n * @private\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new base function.\n */\n function createBaseFor(fromRight) {\n return function(object, iteratee, keysFunc) {\n var index = -1,\n iterable = Object(object),\n props = keysFunc(object),\n length = props.length;\n\n while (length--) {\n var key = props[fromRight ? length : ++index];\n if (iteratee(iterable[key], key, iterable) === false) {\n break;\n }\n }\n return object;\n };\n }\n\n /**\n * Creates a function that wraps `func` to invoke it with the optional `this`\n * binding of `thisArg`.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n * @param {*} [thisArg] The `this` binding of `func`.\n * @returns {Function} Returns the new wrapped function.\n */\n function createBind(func, bitmask, thisArg) {\n var isBind = bitmask & WRAP_BIND_FLAG,\n Ctor = createCtor(func);\n\n function wrapper() {\n var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;\n return fn.apply(isBind ? thisArg : this, arguments);\n }\n return wrapper;\n }\n\n /**\n * Creates a function like `_.lowerFirst`.\n *\n * @private\n * @param {string} methodName The name of the `String` case method to use.\n * @returns {Function} Returns the new case function.\n */\n function createCaseFirst(methodName) {\n return function(string) {\n string = toString(string);\n\n var strSymbols = hasUnicode(string)\n ? stringToArray(string)\n : undefined;\n\n var chr = strSymbols\n ? strSymbols[0]\n : string.charAt(0);\n\n var trailing = strSymbols\n ? castSlice(strSymbols, 1).join('')\n : string.slice(1);\n\n return chr[methodName]() + trailing;\n };\n }\n\n /**\n * Creates a function like `_.camelCase`.\n *\n * @private\n * @param {Function} callback The function to combine each word.\n * @returns {Function} Returns the new compounder function.\n */\n function createCompounder(callback) {\n return function(string) {\n return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');\n };\n }\n\n /**\n * Creates a function that produces an instance of `Ctor` regardless of\n * whether it was invoked as part of a `new` expression or by `call` or `apply`.\n *\n * @private\n * @param {Function} Ctor The constructor to wrap.\n * @returns {Function} Returns the new wrapped function.\n */\n function createCtor(Ctor) {\n return function() {\n // Use a `switch` statement to work with class constructors. See\n // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist\n // for more details.\n var args = arguments;\n switch (args.length) {\n case 0: return new Ctor;\n case 1: return new Ctor(args[0]);\n case 2: return new Ctor(args[0], args[1]);\n case 3: return new Ctor(args[0], args[1], args[2]);\n case 4: return new Ctor(args[0], args[1], args[2], args[3]);\n case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);\n case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);\n case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n }\n var thisBinding = baseCreate(Ctor.prototype),\n result = Ctor.apply(thisBinding, args);\n\n // Mimic the constructor's `return` behavior.\n // See https://es5.github.io/#x13.2.2 for more details.\n return isObject(result) ? result : thisBinding;\n };\n }\n\n /**\n * Creates a function that wraps `func` to enable currying.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n * @param {number} arity The arity of `func`.\n * @returns {Function} Returns the new wrapped function.\n */\n function createCurry(func, bitmask, arity) {\n var Ctor = createCtor(func);\n\n function wrapper() {\n var length = arguments.length,\n args = Array(length),\n index = length,\n placeholder = getHolder(wrapper);\n\n while (index--) {\n args[index] = arguments[index];\n }\n var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)\n ? []\n : replaceHolders(args, placeholder);\n\n length -= holders.length;\n if (length < arity) {\n return createRecurry(\n func, bitmask, createHybrid, wrapper.placeholder, undefined,\n args, holders, undefined, undefined, arity - length);\n }\n var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;\n return apply(fn, this, args);\n }\n return wrapper;\n }\n\n /**\n * Creates a `_.find` or `_.findLast` function.\n *\n * @private\n * @param {Function} findIndexFunc The function to find the collection index.\n * @returns {Function} Returns the new find function.\n */\n function createFind(findIndexFunc) {\n return function(collection, predicate, fromIndex) {\n var iterable = Object(collection);\n if (!isArrayLike(collection)) {\n var iteratee = getIteratee(predicate, 3);\n collection = keys(collection);\n predicate = function(key) { return iteratee(iterable[key], key, iterable); };\n }\n var index = findIndexFunc(collection, predicate, fromIndex);\n return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined;\n };\n }\n\n /**\n * Creates a `_.flow` or `_.flowRight` function.\n *\n * @private\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new flow function.\n */\n function createFlow(fromRight) {\n return flatRest(function(funcs) {\n var length = funcs.length,\n index = length,\n prereq = LodashWrapper.prototype.thru;\n\n if (fromRight) {\n funcs.reverse();\n }\n while (index--) {\n var func = funcs[index];\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n if (prereq && !wrapper && getFuncName(func) == 'wrapper') {\n var wrapper = new LodashWrapper([], true);\n }\n }\n index = wrapper ? index : length;\n while (++index < length) {\n func = funcs[index];\n\n var funcName = getFuncName(func),\n data = funcName == 'wrapper' ? getData(func) : undefined;\n\n if (data && isLaziable(data[0]) &&\n data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) &&\n !data[4].length && data[9] == 1\n ) {\n wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);\n } else {\n wrapper = (func.length == 1 && isLaziable(func))\n ? wrapper[funcName]()\n : wrapper.thru(func);\n }\n }\n return function() {\n var args = arguments,\n value = args[0];\n\n if (wrapper && args.length == 1 && isArray(value)) {\n return wrapper.plant(value).value();\n }\n var index = 0,\n result = length ? funcs[index].apply(this, args) : value;\n\n while (++index < length) {\n result = funcs[index].call(this, result);\n }\n return result;\n };\n });\n }\n\n /**\n * Creates a function that wraps `func` to invoke it with optional `this`\n * binding of `thisArg`, partial application, and currying.\n *\n * @private\n * @param {Function|string} func The function or method name to wrap.\n * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n * @param {*} [thisArg] The `this` binding of `func`.\n * @param {Array} [partials] The arguments to prepend to those provided to\n * the new function.\n * @param {Array} [holders] The `partials` placeholder indexes.\n * @param {Array} [partialsRight] The arguments to append to those provided\n * to the new function.\n * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.\n * @param {Array} [argPos] The argument positions of the new function.\n * @param {number} [ary] The arity cap of `func`.\n * @param {number} [arity] The arity of `func`.\n * @returns {Function} Returns the new wrapped function.\n */\n function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {\n var isAry = bitmask & WRAP_ARY_FLAG,\n isBind = bitmask & WRAP_BIND_FLAG,\n isBindKey = bitmask & WRAP_BIND_KEY_FLAG,\n isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),\n isFlip = bitmask & WRAP_FLIP_FLAG,\n Ctor = isBindKey ? undefined : createCtor(func);\n\n function wrapper() {\n var length = arguments.length,\n args = Array(length),\n index = length;\n\n while (index--) {\n args[index] = arguments[index];\n }\n if (isCurried) {\n var placeholder = getHolder(wrapper),\n holdersCount = countHolders(args, placeholder);\n }\n if (partials) {\n args = composeArgs(args, partials, holders, isCurried);\n }\n if (partialsRight) {\n args = composeArgsRight(args, partialsRight, holdersRight, isCurried);\n }\n length -= holdersCount;\n if (isCurried && length < arity) {\n var newHolders = replaceHolders(args, placeholder);\n return createRecurry(\n func, bitmask, createHybrid, wrapper.placeholder, thisArg,\n args, newHolders, argPos, ary, arity - length\n );\n }\n var thisBinding = isBind ? thisArg : this,\n fn = isBindKey ? thisBinding[func] : func;\n\n length = args.length;\n if (argPos) {\n args = reorder(args, argPos);\n } else if (isFlip && length > 1) {\n args.reverse();\n }\n if (isAry && ary < length) {\n args.length = ary;\n }\n if (this && this !== root && this instanceof wrapper) {\n fn = Ctor || createCtor(fn);\n }\n return fn.apply(thisBinding, args);\n }\n return wrapper;\n }\n\n /**\n * Creates a function like `_.invertBy`.\n *\n * @private\n * @param {Function} setter The function to set accumulator values.\n * @param {Function} toIteratee The function to resolve iteratees.\n * @returns {Function} Returns the new inverter function.\n */\n function createInverter(setter, toIteratee) {\n return function(object, iteratee) {\n return baseInverter(object, setter, toIteratee(iteratee), {});\n };\n }\n\n /**\n * Creates a function that performs a mathematical operation on two values.\n *\n * @private\n * @param {Function} operator The function to perform the operation.\n * @param {number} [defaultValue] The value used for `undefined` arguments.\n * @returns {Function} Returns the new mathematical operation function.\n */\n function createMathOperation(operator, defaultValue) {\n return function(value, other) {\n var result;\n if (value === undefined && other === undefined) {\n return defaultValue;\n }\n if (value !== undefined) {\n result = value;\n }\n if (other !== undefined) {\n if (result === undefined) {\n return other;\n }\n if (typeof value == 'string' || typeof other == 'string') {\n value = baseToString(value);\n other = baseToString(other);\n } else {\n value = baseToNumber(value);\n other = baseToNumber(other);\n }\n result = operator(value, other);\n }\n return result;\n };\n }\n\n /**\n * Creates a function like `_.over`.\n *\n * @private\n * @param {Function} arrayFunc The function to iterate over iteratees.\n * @returns {Function} Returns the new over function.\n */\n function createOver(arrayFunc) {\n return flatRest(function(iteratees) {\n iteratees = arrayMap(iteratees, baseUnary(getIteratee()));\n return baseRest(function(args) {\n var thisArg = this;\n return arrayFunc(iteratees, function(iteratee) {\n return apply(iteratee, thisArg, args);\n });\n });\n });\n }\n\n /**\n * Creates the padding for `string` based on `length`. The `chars` string\n * is truncated if the number of characters exceeds `length`.\n *\n * @private\n * @param {number} length The padding length.\n * @param {string} [chars=' '] The string used as padding.\n * @returns {string} Returns the padding for `string`.\n */\n function createPadding(length, chars) {\n chars = chars === undefined ? ' ' : baseToString(chars);\n\n var charsLength = chars.length;\n if (charsLength < 2) {\n return charsLength ? baseRepeat(chars, length) : chars;\n }\n var result = baseRepeat(chars, nativeCeil(length / stringSize(chars)));\n return hasUnicode(chars)\n ? castSlice(stringToArray(result), 0, length).join('')\n : result.slice(0, length);\n }\n\n /**\n * Creates a function that wraps `func` to invoke it with the `this` binding\n * of `thisArg` and `partials` prepended to the arguments it receives.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} partials The arguments to prepend to those provided to\n * the new function.\n * @returns {Function} Returns the new wrapped function.\n */\n function createPartial(func, bitmask, thisArg, partials) {\n var isBind = bitmask & WRAP_BIND_FLAG,\n Ctor = createCtor(func);\n\n function wrapper() {\n var argsIndex = -1,\n argsLength = arguments.length,\n leftIndex = -1,\n leftLength = partials.length,\n args = Array(leftLength + argsLength),\n fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;\n\n while (++leftIndex < leftLength) {\n args[leftIndex] = partials[leftIndex];\n }\n while (argsLength--) {\n args[leftIndex++] = arguments[++argsIndex];\n }\n return apply(fn, isBind ? thisArg : this, args);\n }\n return wrapper;\n }\n\n /**\n * Creates a `_.range` or `_.rangeRight` function.\n *\n * @private\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new range function.\n */\n function createRange(fromRight) {\n return function(start, end, step) {\n if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {\n end = step = undefined;\n }\n // Ensure the sign of `-0` is preserved.\n start = toFinite(start);\n if (end === undefined) {\n end = start;\n start = 0;\n } else {\n end = toFinite(end);\n }\n step = step === undefined ? (start < end ? 1 : -1) : toFinite(step);\n return baseRange(start, end, step, fromRight);\n };\n }\n\n /**\n * Creates a function that performs a relational operation on two values.\n *\n * @private\n * @param {Function} operator The function to perform the operation.\n * @returns {Function} Returns the new relational operation function.\n */\n function createRelationalOperation(operator) {\n return function(value, other) {\n if (!(typeof value == 'string' && typeof other == 'string')) {\n value = toNumber(value);\n other = toNumber(other);\n }\n return operator(value, other);\n };\n }\n\n /**\n * Creates a function that wraps `func` to continue currying.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n * @param {Function} wrapFunc The function to create the `func` wrapper.\n * @param {*} placeholder The placeholder value.\n * @param {*} [thisArg] The `this` binding of `func`.\n * @param {Array} [partials] The arguments to prepend to those provided to\n * the new function.\n * @param {Array} [holders] The `partials` placeholder indexes.\n * @param {Array} [argPos] The argument positions of the new function.\n * @param {number} [ary] The arity cap of `func`.\n * @param {number} [arity] The arity of `func`.\n * @returns {Function} Returns the new wrapped function.\n */\n function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {\n var isCurry = bitmask & WRAP_CURRY_FLAG,\n newHolders = isCurry ? holders : undefined,\n newHoldersRight = isCurry ? undefined : holders,\n newPartials = isCurry ? partials : undefined,\n newPartialsRight = isCurry ? undefined : partials;\n\n bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG);\n bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);\n\n if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {\n bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);\n }\n var newData = [\n func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,\n newHoldersRight, argPos, ary, arity\n ];\n\n var result = wrapFunc.apply(undefined, newData);\n if (isLaziable(func)) {\n setData(result, newData);\n }\n result.placeholder = placeholder;\n return setWrapToString(result, func, bitmask);\n }\n\n /**\n * Creates a function like `_.round`.\n *\n * @private\n * @param {string} methodName The name of the `Math` method to use when rounding.\n * @returns {Function} Returns the new round function.\n */\n function createRound(methodName) {\n var func = Math[methodName];\n return function(number, precision) {\n number = toNumber(number);\n precision = precision == null ? 0 : nativeMin(toInteger(precision), 292);\n if (precision) {\n // Shift with exponential notation to avoid floating-point issues.\n // See [MDN](https://mdn.io/round#Examples) for more details.\n var pair = (toString(number) + 'e').split('e'),\n value = func(pair[0] + 'e' + (+pair[1] + precision));\n\n pair = (toString(value) + 'e').split('e');\n return +(pair[0] + 'e' + (+pair[1] - precision));\n }\n return func(number);\n };\n }\n\n /**\n * Creates a set object of `values`.\n *\n * @private\n * @param {Array} values The values to add to the set.\n * @returns {Object} Returns the new set.\n */\n var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {\n return new Set(values);\n };\n\n /**\n * Creates a `_.toPairs` or `_.toPairsIn` function.\n *\n * @private\n * @param {Function} keysFunc The function to get the keys of a given object.\n * @returns {Function} Returns the new pairs function.\n */\n function createToPairs(keysFunc) {\n return function(object) {\n var tag = getTag(object);\n if (tag == mapTag) {\n return mapToArray(object);\n }\n if (tag == setTag) {\n return setToPairs(object);\n }\n return baseToPairs(object, keysFunc(object));\n };\n }\n\n /**\n * Creates a function that either curries or invokes `func` with optional\n * `this` binding and partially applied arguments.\n *\n * @private\n * @param {Function|string} func The function or method name to wrap.\n * @param {number} bitmask The bitmask flags.\n * 1 - `_.bind`\n * 2 - `_.bindKey`\n * 4 - `_.curry` or `_.curryRight` of a bound function\n * 8 - `_.curry`\n * 16 - `_.curryRight`\n * 32 - `_.partial`\n * 64 - `_.partialRight`\n * 128 - `_.rearg`\n * 256 - `_.ary`\n * 512 - `_.flip`\n * @param {*} [thisArg] The `this` binding of `func`.\n * @param {Array} [partials] The arguments to be partially applied.\n * @param {Array} [holders] The `partials` placeholder indexes.\n * @param {Array} [argPos] The argument positions of the new function.\n * @param {number} [ary] The arity cap of `func`.\n * @param {number} [arity] The arity of `func`.\n * @returns {Function} Returns the new wrapped function.\n */\n function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {\n var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;\n if (!isBindKey && typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n var length = partials ? partials.length : 0;\n if (!length) {\n bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);\n partials = holders = undefined;\n }\n ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);\n arity = arity === undefined ? arity : toInteger(arity);\n length -= holders ? holders.length : 0;\n\n if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {\n var partialsRight = partials,\n holdersRight = holders;\n\n partials = holders = undefined;\n }\n var data = isBindKey ? undefined : getData(func);\n\n var newData = [\n func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,\n argPos, ary, arity\n ];\n\n if (data) {\n mergeData(newData, data);\n }\n func = newData[0];\n bitmask = newData[1];\n thisArg = newData[2];\n partials = newData[3];\n holders = newData[4];\n arity = newData[9] = newData[9] === undefined\n ? (isBindKey ? 0 : func.length)\n : nativeMax(newData[9] - length, 0);\n\n if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {\n bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);\n }\n if (!bitmask || bitmask == WRAP_BIND_FLAG) {\n var result = createBind(func, bitmask, thisArg);\n } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {\n result = createCurry(func, bitmask, arity);\n } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {\n result = createPartial(func, bitmask, thisArg, partials);\n } else {\n result = createHybrid.apply(undefined, newData);\n }\n var setter = data ? baseSetData : setData;\n return setWrapToString(setter(result, newData), func, bitmask);\n }\n\n /**\n * Used by `_.defaults` to customize its `_.assignIn` use to assign properties\n * of source objects to the destination object for all destination properties\n * that resolve to `undefined`.\n *\n * @private\n * @param {*} objValue The destination value.\n * @param {*} srcValue The source value.\n * @param {string} key The key of the property to assign.\n * @param {Object} object The parent object of `objValue`.\n * @returns {*} Returns the value to assign.\n */\n function customDefaultsAssignIn(objValue, srcValue, key, object) {\n if (objValue === undefined ||\n (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {\n return srcValue;\n }\n return objValue;\n }\n\n /**\n * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source\n * objects into destination objects that are passed thru.\n *\n * @private\n * @param {*} objValue The destination value.\n * @param {*} srcValue The source value.\n * @param {string} key The key of the property to merge.\n * @param {Object} object The parent object of `objValue`.\n * @param {Object} source The parent object of `srcValue`.\n * @param {Object} [stack] Tracks traversed source values and their merged\n * counterparts.\n * @returns {*} Returns the value to assign.\n */\n function customDefaultsMerge(objValue, srcValue, key, object, source, stack) {\n if (isObject(objValue) && isObject(srcValue)) {\n // Recursively merge objects and arrays (susceptible to call stack limits).\n stack.set(srcValue, objValue);\n baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack);\n stack['delete'](srcValue);\n }\n return objValue;\n }\n\n /**\n * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain\n * objects.\n *\n * @private\n * @param {*} value The value to inspect.\n * @param {string} key The key of the property to inspect.\n * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`.\n */\n function customOmitClone(value, key) {\n return (key !== undefined && isPlainObject(value)) ? undefined : value;\n }\n\n /**\n * A specialized version of `baseIsEqualDeep` for arrays with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Array} array The array to compare.\n * @param {Array} other The other array to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `array` and `other` objects.\n * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.\n */\n function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {\n var isPartial = bitmask & COMPARE_PARTIAL_FLAG,\n arrLength = array.length,\n othLength = other.length;\n\n if (arrLength != othLength && !(isPartial && othLength > arrLength)) {\n return false;\n }\n // Assume cyclic values are equal.\n var stacked = stack.get(array);\n if (stacked && stack.get(other)) {\n return stacked == other;\n }\n var index = -1,\n result = true,\n seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;\n\n stack.set(array, other);\n stack.set(other, array);\n\n // Ignore non-index properties.\n while (++index < arrLength) {\n var arrValue = array[index],\n othValue = other[index];\n\n if (customizer) {\n var compared = isPartial\n ? customizer(othValue, arrValue, index, other, array, stack)\n : customizer(arrValue, othValue, index, array, other, stack);\n }\n if (compared !== undefined) {\n if (compared) {\n continue;\n }\n result = false;\n break;\n }\n // Recursively compare arrays (susceptible to call stack limits).\n if (seen) {\n if (!arraySome(other, function(othValue, othIndex) {\n if (!cacheHas(seen, othIndex) &&\n (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {\n return seen.push(othIndex);\n }\n })) {\n result = false;\n break;\n }\n } else if (!(\n arrValue === othValue ||\n equalFunc(arrValue, othValue, bitmask, customizer, stack)\n )) {\n result = false;\n break;\n }\n }\n stack['delete'](array);\n stack['delete'](other);\n return result;\n }\n\n /**\n * A specialized version of `baseIsEqualDeep` for comparing objects of\n * the same `toStringTag`.\n *\n * **Note:** This function only supports comparing values with tags of\n * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {string} tag The `toStringTag` of the objects to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\n function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {\n switch (tag) {\n case dataViewTag:\n if ((object.byteLength != other.byteLength) ||\n (object.byteOffset != other.byteOffset)) {\n return false;\n }\n object = object.buffer;\n other = other.buffer;\n\n case arrayBufferTag:\n if ((object.byteLength != other.byteLength) ||\n !equalFunc(new Uint8Array(object), new Uint8Array(other))) {\n return false;\n }\n return true;\n\n case boolTag:\n case dateTag:\n case numberTag:\n // Coerce booleans to `1` or `0` and dates to milliseconds.\n // Invalid dates are coerced to `NaN`.\n return eq(+object, +other);\n\n case errorTag:\n return object.name == other.name && object.message == other.message;\n\n case regexpTag:\n case stringTag:\n // Coerce regexes to strings and treat strings, primitives and objects,\n // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring\n // for more details.\n return object == (other + '');\n\n case mapTag:\n var convert = mapToArray;\n\n case setTag:\n var isPartial = bitmask & COMPARE_PARTIAL_FLAG;\n convert || (convert = setToArray);\n\n if (object.size != other.size && !isPartial) {\n return false;\n }\n // Assume cyclic values are equal.\n var stacked = stack.get(object);\n if (stacked) {\n return stacked == other;\n }\n bitmask |= COMPARE_UNORDERED_FLAG;\n\n // Recursively compare objects (susceptible to call stack limits).\n stack.set(object, other);\n var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);\n stack['delete'](object);\n return result;\n\n case symbolTag:\n if (symbolValueOf) {\n return symbolValueOf.call(object) == symbolValueOf.call(other);\n }\n }\n return false;\n }\n\n /**\n * A specialized version of `baseIsEqualDeep` for objects with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\n function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {\n var isPartial = bitmask & COMPARE_PARTIAL_FLAG,\n objProps = getAllKeys(object),\n objLength = objProps.length,\n othProps = getAllKeys(other),\n othLength = othProps.length;\n\n if (objLength != othLength && !isPartial) {\n return false;\n }\n var index = objLength;\n while (index--) {\n var key = objProps[index];\n if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {\n return false;\n }\n }\n // Assume cyclic values are equal.\n var stacked = stack.get(object);\n if (stacked && stack.get(other)) {\n return stacked == other;\n }\n var result = true;\n stack.set(object, other);\n stack.set(other, object);\n\n var skipCtor = isPartial;\n while (++index < objLength) {\n key = objProps[index];\n var objValue = object[key],\n othValue = other[key];\n\n if (customizer) {\n var compared = isPartial\n ? customizer(othValue, objValue, key, other, object, stack)\n : customizer(objValue, othValue, key, object, other, stack);\n }\n // Recursively compare objects (susceptible to call stack limits).\n if (!(compared === undefined\n ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))\n : compared\n )) {\n result = false;\n break;\n }\n skipCtor || (skipCtor = key == 'constructor');\n }\n if (result && !skipCtor) {\n var objCtor = object.constructor,\n othCtor = other.constructor;\n\n // Non `Object` object instances with different constructors are not equal.\n if (objCtor != othCtor &&\n ('constructor' in object && 'constructor' in other) &&\n !(typeof objCtor == 'function' && objCtor instanceof objCtor &&\n typeof othCtor == 'function' && othCtor instanceof othCtor)) {\n result = false;\n }\n }\n stack['delete'](object);\n stack['delete'](other);\n return result;\n }\n\n /**\n * A specialized version of `baseRest` which flattens the rest array.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @returns {Function} Returns the new function.\n */\n function flatRest(func) {\n return setToString(overRest(func, undefined, flatten), func + '');\n }\n\n /**\n * Creates an array of own enumerable property names and symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names and symbols.\n */\n function getAllKeys(object) {\n return baseGetAllKeys(object, keys, getSymbols);\n }\n\n /**\n * Creates an array of own and inherited enumerable property names and\n * symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names and symbols.\n */\n function getAllKeysIn(object) {\n return baseGetAllKeys(object, keysIn, getSymbolsIn);\n }\n\n /**\n * Gets metadata for `func`.\n *\n * @private\n * @param {Function} func The function to query.\n * @returns {*} Returns the metadata for `func`.\n */\n var getData = !metaMap ? noop : function(func) {\n return metaMap.get(func);\n };\n\n /**\n * Gets the name of `func`.\n *\n * @private\n * @param {Function} func The function to query.\n * @returns {string} Returns the function name.\n */\n function getFuncName(func) {\n var result = (func.name + ''),\n array = realNames[result],\n length = hasOwnProperty.call(realNames, result) ? array.length : 0;\n\n while (length--) {\n var data = array[length],\n otherFunc = data.func;\n if (otherFunc == null || otherFunc == func) {\n return data.name;\n }\n }\n return result;\n }\n\n /**\n * Gets the argument placeholder value for `func`.\n *\n * @private\n * @param {Function} func The function to inspect.\n * @returns {*} Returns the placeholder value.\n */\n function getHolder(func) {\n var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;\n return object.placeholder;\n }\n\n /**\n * Gets the appropriate \"iteratee\" function. If `_.iteratee` is customized,\n * this function returns the custom method, otherwise it returns `baseIteratee`.\n * If arguments are provided, the chosen function is invoked with them and\n * its result is returned.\n *\n * @private\n * @param {*} [value] The value to convert to an iteratee.\n * @param {number} [arity] The arity of the created iteratee.\n * @returns {Function} Returns the chosen function or its result.\n */\n function getIteratee() {\n var result = lodash.iteratee || iteratee;\n result = result === iteratee ? baseIteratee : result;\n return arguments.length ? result(arguments[0], arguments[1]) : result;\n }\n\n /**\n * Gets the data for `map`.\n *\n * @private\n * @param {Object} map The map to query.\n * @param {string} key The reference key.\n * @returns {*} Returns the map data.\n */\n function getMapData(map, key) {\n var data = map.__data__;\n return isKeyable(key)\n ? data[typeof key == 'string' ? 'string' : 'hash']\n : data.map;\n }\n\n /**\n * Gets the property names, values, and compare flags of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the match data of `object`.\n */\n function getMatchData(object) {\n var result = keys(object),\n length = result.length;\n\n while (length--) {\n var key = result[length],\n value = object[key];\n\n result[length] = [key, value, isStrictComparable(value)];\n }\n return result;\n }\n\n /**\n * Gets the native function at `key` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the method to get.\n * @returns {*} Returns the function if it's native, else `undefined`.\n */\n function getNative(object, key) {\n var value = getValue(object, key);\n return baseIsNative(value) ? value : undefined;\n }\n\n /**\n * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the raw `toStringTag`.\n */\n function getRawTag(value) {\n var isOwn = hasOwnProperty.call(value, symToStringTag),\n tag = value[symToStringTag];\n\n try {\n value[symToStringTag] = undefined;\n var unmasked = true;\n } catch (e) {}\n\n var result = nativeObjectToString.call(value);\n if (unmasked) {\n if (isOwn) {\n value[symToStringTag] = tag;\n } else {\n delete value[symToStringTag];\n }\n }\n return result;\n }\n\n /**\n * Creates an array of the own enumerable symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of symbols.\n */\n var getSymbols = !nativeGetSymbols ? stubArray : function(object) {\n if (object == null) {\n return [];\n }\n object = Object(object);\n return arrayFilter(nativeGetSymbols(object), function(symbol) {\n return propertyIsEnumerable.call(object, symbol);\n });\n };\n\n /**\n * Creates an array of the own and inherited enumerable symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of symbols.\n */\n var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {\n var result = [];\n while (object) {\n arrayPush(result, getSymbols(object));\n object = getPrototype(object);\n }\n return result;\n };\n\n /**\n * Gets the `toStringTag` of `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\n var getTag = baseGetTag;\n\n // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.\n if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||\n (Map && getTag(new Map) != mapTag) ||\n (Promise && getTag(Promise.resolve()) != promiseTag) ||\n (Set && getTag(new Set) != setTag) ||\n (WeakMap && getTag(new WeakMap) != weakMapTag)) {\n getTag = function(value) {\n var result = baseGetTag(value),\n Ctor = result == objectTag ? value.constructor : undefined,\n ctorString = Ctor ? toSource(Ctor) : '';\n\n if (ctorString) {\n switch (ctorString) {\n case dataViewCtorString: return dataViewTag;\n case mapCtorString: return mapTag;\n case promiseCtorString: return promiseTag;\n case setCtorString: return setTag;\n case weakMapCtorString: return weakMapTag;\n }\n }\n return result;\n };\n }\n\n /**\n * Gets the view, applying any `transforms` to the `start` and `end` positions.\n *\n * @private\n * @param {number} start The start of the view.\n * @param {number} end The end of the view.\n * @param {Array} transforms The transformations to apply to the view.\n * @returns {Object} Returns an object containing the `start` and `end`\n * positions of the view.\n */\n function getView(start, end, transforms) {\n var index = -1,\n length = transforms.length;\n\n while (++index < length) {\n var data = transforms[index],\n size = data.size;\n\n switch (data.type) {\n case 'drop': start += size; break;\n case 'dropRight': end -= size; break;\n case 'take': end = nativeMin(end, start + size); break;\n case 'takeRight': start = nativeMax(start, end - size); break;\n }\n }\n return { 'start': start, 'end': end };\n }\n\n /**\n * Extracts wrapper details from the `source` body comment.\n *\n * @private\n * @param {string} source The source to inspect.\n * @returns {Array} Returns the wrapper details.\n */\n function getWrapDetails(source) {\n var match = source.match(reWrapDetails);\n return match ? match[1].split(reSplitDetails) : [];\n }\n\n /**\n * Checks if `path` exists on `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array|string} path The path to check.\n * @param {Function} hasFunc The function to check properties.\n * @returns {boolean} Returns `true` if `path` exists, else `false`.\n */\n function hasPath(object, path, hasFunc) {\n path = castPath(path, object);\n\n var index = -1,\n length = path.length,\n result = false;\n\n while (++index < length) {\n var key = toKey(path[index]);\n if (!(result = object != null && hasFunc(object, key))) {\n break;\n }\n object = object[key];\n }\n if (result || ++index != length) {\n return result;\n }\n length = object == null ? 0 : object.length;\n return !!length && isLength(length) && isIndex(key, length) &&\n (isArray(object) || isArguments(object));\n }\n\n /**\n * Initializes an array clone.\n *\n * @private\n * @param {Array} array The array to clone.\n * @returns {Array} Returns the initialized clone.\n */\n function initCloneArray(array) {\n var length = array.length,\n result = array.constructor(length);\n\n // Add properties assigned by `RegExp#exec`.\n if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {\n result.index = array.index;\n result.input = array.input;\n }\n return result;\n }\n\n /**\n * Initializes an object clone.\n *\n * @private\n * @param {Object} object The object to clone.\n * @returns {Object} Returns the initialized clone.\n */\n function initCloneObject(object) {\n return (typeof object.constructor == 'function' && !isPrototype(object))\n ? baseCreate(getPrototype(object))\n : {};\n }\n\n /**\n * Initializes an object clone based on its `toStringTag`.\n *\n * **Note:** This function only supports cloning values with tags of\n * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.\n *\n * @private\n * @param {Object} object The object to clone.\n * @param {string} tag The `toStringTag` of the object to clone.\n * @param {Function} cloneFunc The function to clone values.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the initialized clone.\n */\n function initCloneByTag(object, tag, cloneFunc, isDeep) {\n var Ctor = object.constructor;\n switch (tag) {\n case arrayBufferTag:\n return cloneArrayBuffer(object);\n\n case boolTag:\n case dateTag:\n return new Ctor(+object);\n\n case dataViewTag:\n return cloneDataView(object, isDeep);\n\n case float32Tag: case float64Tag:\n case int8Tag: case int16Tag: case int32Tag:\n case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:\n return cloneTypedArray(object, isDeep);\n\n case mapTag:\n return cloneMap(object, isDeep, cloneFunc);\n\n case numberTag:\n case stringTag:\n return new Ctor(object);\n\n case regexpTag:\n return cloneRegExp(object);\n\n case setTag:\n return cloneSet(object, isDeep, cloneFunc);\n\n case symbolTag:\n return cloneSymbol(object);\n }\n }\n\n /**\n * Inserts wrapper `details` in a comment at the top of the `source` body.\n *\n * @private\n * @param {string} source The source to modify.\n * @returns {Array} details The details to insert.\n * @returns {string} Returns the modified source.\n */\n function insertWrapDetails(source, details) {\n var length = details.length;\n if (!length) {\n return source;\n }\n var lastIndex = length - 1;\n details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];\n details = details.join(length > 2 ? ', ' : ' ');\n return source.replace(reWrapComment, '{\\n/* [wrapped with ' + details + '] */\\n');\n }\n\n /**\n * Checks if `value` is a flattenable `arguments` object or array.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.\n */\n function isFlattenable(value) {\n return isArray(value) || isArguments(value) ||\n !!(spreadableSymbol && value && value[spreadableSymbol]);\n }\n\n /**\n * Checks if `value` is a valid array-like index.\n *\n * @private\n * @param {*} value The value to check.\n * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.\n * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.\n */\n function isIndex(value, length) {\n length = length == null ? MAX_SAFE_INTEGER : length;\n return !!length &&\n (typeof value == 'number' || reIsUint.test(value)) &&\n (value > -1 && value % 1 == 0 && value < length);\n }\n\n /**\n * Checks if the given arguments are from an iteratee call.\n *\n * @private\n * @param {*} value The potential iteratee value argument.\n * @param {*} index The potential iteratee index or key argument.\n * @param {*} object The potential iteratee object argument.\n * @returns {boolean} Returns `true` if the arguments are from an iteratee call,\n * else `false`.\n */\n function isIterateeCall(value, index, object) {\n if (!isObject(object)) {\n return false;\n }\n var type = typeof index;\n if (type == 'number'\n ? (isArrayLike(object) && isIndex(index, object.length))\n : (type == 'string' && index in object)\n ) {\n return eq(object[index], value);\n }\n return false;\n }\n\n /**\n * Checks if `value` is a property name and not a property path.\n *\n * @private\n * @param {*} value The value to check.\n * @param {Object} [object] The object to query keys on.\n * @returns {boolean} Returns `true` if `value` is a property name, else `false`.\n */\n function isKey(value, object) {\n if (isArray(value)) {\n return false;\n }\n var type = typeof value;\n if (type == 'number' || type == 'symbol' || type == 'boolean' ||\n value == null || isSymbol(value)) {\n return true;\n }\n return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||\n (object != null && value in Object(object));\n }\n\n /**\n * Checks if `value` is suitable for use as unique object key.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is suitable, else `false`.\n */\n function isKeyable(value) {\n var type = typeof value;\n return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')\n ? (value !== '__proto__')\n : (value === null);\n }\n\n /**\n * Checks if `func` has a lazy counterpart.\n *\n * @private\n * @param {Function} func The function to check.\n * @returns {boolean} Returns `true` if `func` has a lazy counterpart,\n * else `false`.\n */\n function isLaziable(func) {\n var funcName = getFuncName(func),\n other = lodash[funcName];\n\n if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {\n return false;\n }\n if (func === other) {\n return true;\n }\n var data = getData(other);\n return !!data && func === data[0];\n }\n\n /**\n * Checks if `func` has its source masked.\n *\n * @private\n * @param {Function} func The function to check.\n * @returns {boolean} Returns `true` if `func` is masked, else `false`.\n */\n function isMasked(func) {\n return !!maskSrcKey && (maskSrcKey in func);\n }\n\n /**\n * Checks if `func` is capable of being masked.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `func` is maskable, else `false`.\n */\n var isMaskable = coreJsData ? isFunction : stubFalse;\n\n /**\n * Checks if `value` is likely a prototype object.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.\n */\n function isPrototype(value) {\n var Ctor = value && value.constructor,\n proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;\n\n return value === proto;\n }\n\n /**\n * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` if suitable for strict\n * equality comparisons, else `false`.\n */\n function isStrictComparable(value) {\n return value === value && !isObject(value);\n }\n\n /**\n * A specialized version of `matchesProperty` for source values suitable\n * for strict equality comparisons, i.e. `===`.\n *\n * @private\n * @param {string} key The key of the property to get.\n * @param {*} srcValue The value to match.\n * @returns {Function} Returns the new spec function.\n */\n function matchesStrictComparable(key, srcValue) {\n return function(object) {\n if (object == null) {\n return false;\n }\n return object[key] === srcValue &&\n (srcValue !== undefined || (key in Object(object)));\n };\n }\n\n /**\n * A specialized version of `_.memoize` which clears the memoized function's\n * cache when it exceeds `MAX_MEMOIZE_SIZE`.\n *\n * @private\n * @param {Function} func The function to have its output memoized.\n * @returns {Function} Returns the new memoized function.\n */\n function memoizeCapped(func) {\n var result = memoize(func, function(key) {\n if (cache.size === MAX_MEMOIZE_SIZE) {\n cache.clear();\n }\n return key;\n });\n\n var cache = result.cache;\n return result;\n }\n\n /**\n * Merges the function metadata of `source` into `data`.\n *\n * Merging metadata reduces the number of wrappers used to invoke a function.\n * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`\n * may be applied regardless of execution order. Methods like `_.ary` and\n * `_.rearg` modify function arguments, making the order in which they are\n * executed important, preventing the merging of metadata. However, we make\n * an exception for a safe combined case where curried functions have `_.ary`\n * and or `_.rearg` applied.\n *\n * @private\n * @param {Array} data The destination metadata.\n * @param {Array} source The source metadata.\n * @returns {Array} Returns `data`.\n */\n function mergeData(data, source) {\n var bitmask = data[1],\n srcBitmask = source[1],\n newBitmask = bitmask | srcBitmask,\n isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);\n\n var isCombo =\n ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) ||\n ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) ||\n ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG));\n\n // Exit early if metadata can't be merged.\n if (!(isCommon || isCombo)) {\n return data;\n }\n // Use source `thisArg` if available.\n if (srcBitmask & WRAP_BIND_FLAG) {\n data[2] = source[2];\n // Set when currying a bound function.\n newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;\n }\n // Compose partial arguments.\n var value = source[3];\n if (value) {\n var partials = data[3];\n data[3] = partials ? composeArgs(partials, value, source[4]) : value;\n data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];\n }\n // Compose partial right arguments.\n value = source[5];\n if (value) {\n partials = data[5];\n data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;\n data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];\n }\n // Use source `argPos` if available.\n value = source[7];\n if (value) {\n data[7] = value;\n }\n // Use source `ary` if it's smaller.\n if (srcBitmask & WRAP_ARY_FLAG) {\n data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);\n }\n // Use source `arity` if one is not provided.\n if (data[9] == null) {\n data[9] = source[9];\n }\n // Use source `func` and merge bitmasks.\n data[0] = source[0];\n data[1] = newBitmask;\n\n return data;\n }\n\n /**\n * This function is like\n * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * except that it includes inherited enumerable properties.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\n function nativeKeysIn(object) {\n var result = [];\n if (object != null) {\n for (var key in Object(object)) {\n result.push(key);\n }\n }\n return result;\n }\n\n /**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\n function objectToString(value) {\n return nativeObjectToString.call(value);\n }\n\n /**\n * A specialized version of `baseRest` which transforms the rest array.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @param {Function} transform The rest array transform.\n * @returns {Function} Returns the new function.\n */\n function overRest(func, start, transform) {\n start = nativeMax(start === undefined ? (func.length - 1) : start, 0);\n return function() {\n var args = arguments,\n index = -1,\n length = nativeMax(args.length - start, 0),\n array = Array(length);\n\n while (++index < length) {\n array[index] = args[start + index];\n }\n index = -1;\n var otherArgs = Array(start + 1);\n while (++index < start) {\n otherArgs[index] = args[index];\n }\n otherArgs[start] = transform(array);\n return apply(func, this, otherArgs);\n };\n }\n\n /**\n * Gets the parent value at `path` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array} path The path to get the parent value of.\n * @returns {*} Returns the parent value.\n */\n function parent(object, path) {\n return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));\n }\n\n /**\n * Reorder `array` according to the specified indexes where the element at\n * the first index is assigned as the first element, the element at\n * the second index is assigned as the second element, and so on.\n *\n * @private\n * @param {Array} array The array to reorder.\n * @param {Array} indexes The arranged array indexes.\n * @returns {Array} Returns `array`.\n */\n function reorder(array, indexes) {\n var arrLength = array.length,\n length = nativeMin(indexes.length, arrLength),\n oldArray = copyArray(array);\n\n while (length--) {\n var index = indexes[length];\n array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;\n }\n return array;\n }\n\n /**\n * Sets metadata for `func`.\n *\n * **Note:** If this function becomes hot, i.e. is invoked a lot in a short\n * period of time, it will trip its breaker and transition to an identity\n * function to avoid garbage collection pauses in V8. See\n * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)\n * for more details.\n *\n * @private\n * @param {Function} func The function to associate metadata with.\n * @param {*} data The metadata.\n * @returns {Function} Returns `func`.\n */\n var setData = shortOut(baseSetData);\n\n /**\n * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout).\n *\n * @private\n * @param {Function} func The function to delay.\n * @param {number} wait The number of milliseconds to delay invocation.\n * @returns {number|Object} Returns the timer id or timeout object.\n */\n var setTimeout = ctxSetTimeout || function(func, wait) {\n return root.setTimeout(func, wait);\n };\n\n /**\n * Sets the `toString` method of `func` to return `string`.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\n var setToString = shortOut(baseSetToString);\n\n /**\n * Sets the `toString` method of `wrapper` to mimic the source of `reference`\n * with wrapper details in a comment at the top of the source body.\n *\n * @private\n * @param {Function} wrapper The function to modify.\n * @param {Function} reference The reference function.\n * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n * @returns {Function} Returns `wrapper`.\n */\n function setWrapToString(wrapper, reference, bitmask) {\n var source = (reference + '');\n return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));\n }\n\n /**\n * Creates a function that'll short out and invoke `identity` instead\n * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`\n * milliseconds.\n *\n * @private\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new shortable function.\n */\n function shortOut(func) {\n var count = 0,\n lastCalled = 0;\n\n return function() {\n var stamp = nativeNow(),\n remaining = HOT_SPAN - (stamp - lastCalled);\n\n lastCalled = stamp;\n if (remaining > 0) {\n if (++count >= HOT_COUNT) {\n return arguments[0];\n }\n } else {\n count = 0;\n }\n return func.apply(undefined, arguments);\n };\n }\n\n /**\n * A specialized version of `_.shuffle` which mutates and sets the size of `array`.\n *\n * @private\n * @param {Array} array The array to shuffle.\n * @param {number} [size=array.length] The size of `array`.\n * @returns {Array} Returns `array`.\n */\n function shuffleSelf(array, size) {\n var index = -1,\n length = array.length,\n lastIndex = length - 1;\n\n size = size === undefined ? length : size;\n while (++index < size) {\n var rand = baseRandom(index, lastIndex),\n value = array[rand];\n\n array[rand] = array[index];\n array[index] = value;\n }\n array.length = size;\n return array;\n }\n\n /**\n * Converts `string` to a property path array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the property path array.\n */\n var stringToPath = memoizeCapped(function(string) {\n var result = [];\n if (reLeadingDot.test(string)) {\n result.push('');\n }\n string.replace(rePropName, function(match, number, quote, string) {\n result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));\n });\n return result;\n });\n\n /**\n * Converts `value` to a string key if it's not a string or symbol.\n *\n * @private\n * @param {*} value The value to inspect.\n * @returns {string|symbol} Returns the key.\n */\n function toKey(value) {\n if (typeof value == 'string' || isSymbol(value)) {\n return value;\n }\n var result = (value + '');\n return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;\n }\n\n /**\n * Converts `func` to its source code.\n *\n * @private\n * @param {Function} func The function to convert.\n * @returns {string} Returns the source code.\n */\n function toSource(func) {\n if (func != null) {\n try {\n return funcToString.call(func);\n } catch (e) {}\n try {\n return (func + '');\n } catch (e) {}\n }\n return '';\n }\n\n /**\n * Updates wrapper `details` based on `bitmask` flags.\n *\n * @private\n * @returns {Array} details The details to modify.\n * @param {number} bitmask The bitmask flags. See `createWrap` for more details.\n * @returns {Array} Returns `details`.\n */\n function updateWrapDetails(details, bitmask) {\n arrayEach(wrapFlags, function(pair) {\n var value = '_.' + pair[0];\n if ((bitmask & pair[1]) && !arrayIncludes(details, value)) {\n details.push(value);\n }\n });\n return details.sort();\n }\n\n /**\n * Creates a clone of `wrapper`.\n *\n * @private\n * @param {Object} wrapper The wrapper to clone.\n * @returns {Object} Returns the cloned wrapper.\n */\n function wrapperClone(wrapper) {\n if (wrapper instanceof LazyWrapper) {\n return wrapper.clone();\n }\n var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);\n result.__actions__ = copyArray(wrapper.__actions__);\n result.__index__ = wrapper.__index__;\n result.__values__ = wrapper.__values__;\n return result;\n }\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Creates an array of elements split into groups the length of `size`.\n * If `array` can't be split evenly, the final chunk will be the remaining\n * elements.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to process.\n * @param {number} [size=1] The length of each chunk\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Array} Returns the new array of chunks.\n * @example\n *\n * _.chunk(['a', 'b', 'c', 'd'], 2);\n * // => [['a', 'b'], ['c', 'd']]\n *\n * _.chunk(['a', 'b', 'c', 'd'], 3);\n * // => [['a', 'b', 'c'], ['d']]\n */\n function chunk(array, size, guard) {\n if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) {\n size = 1;\n } else {\n size = nativeMax(toInteger(size), 0);\n }\n var length = array == null ? 0 : array.length;\n if (!length || size < 1) {\n return [];\n }\n var index = 0,\n resIndex = 0,\n result = Array(nativeCeil(length / size));\n\n while (index < length) {\n result[resIndex++] = baseSlice(array, index, (index += size));\n }\n return result;\n }\n\n /**\n * Creates an array with all falsey values removed. The values `false`, `null`,\n * `0`, `\"\"`, `undefined`, and `NaN` are falsey.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to compact.\n * @returns {Array} Returns the new array of filtered values.\n * @example\n *\n * _.compact([0, 1, false, 2, '', 3]);\n * // => [1, 2, 3]\n */\n function compact(array) {\n var index = -1,\n length = array == null ? 0 : array.length,\n resIndex = 0,\n result = [];\n\n while (++index < length) {\n var value = array[index];\n if (value) {\n result[resIndex++] = value;\n }\n }\n return result;\n }\n\n /**\n * Creates a new array concatenating `array` with any additional arrays\n * and/or values.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to concatenate.\n * @param {...*} [values] The values to concatenate.\n * @returns {Array} Returns the new concatenated array.\n * @example\n *\n * var array = [1];\n * var other = _.concat(array, 2, [3], [[4]]);\n *\n * console.log(other);\n * // => [1, 2, 3, [4]]\n *\n * console.log(array);\n * // => [1]\n */\n function concat() {\n var length = arguments.length;\n if (!length) {\n return [];\n }\n var args = Array(length - 1),\n array = arguments[0],\n index = length;\n\n while (index--) {\n args[index - 1] = arguments[index];\n }\n return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));\n }\n\n /**\n * Creates an array of `array` values not included in the other given arrays\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons. The order and references of result values are\n * determined by the first array.\n *\n * **Note:** Unlike `_.pullAll`, this method returns a new array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {...Array} [values] The values to exclude.\n * @returns {Array} Returns the new array of filtered values.\n * @see _.without, _.xor\n * @example\n *\n * _.difference([2, 1], [2, 3]);\n * // => [1]\n */\n var difference = baseRest(function(array, values) {\n return isArrayLikeObject(array)\n ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))\n : [];\n });\n\n /**\n * This method is like `_.difference` except that it accepts `iteratee` which\n * is invoked for each element of `array` and `values` to generate the criterion\n * by which they're compared. The order and references of result values are\n * determined by the first array. The iteratee is invoked with one argument:\n * (value).\n *\n * **Note:** Unlike `_.pullAllBy`, this method returns a new array.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {...Array} [values] The values to exclude.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {Array} Returns the new array of filtered values.\n * @example\n *\n * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor);\n * // => [1.2]\n *\n * // The `_.property` iteratee shorthand.\n * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');\n * // => [{ 'x': 2 }]\n */\n var differenceBy = baseRest(function(array, values) {\n var iteratee = last(values);\n if (isArrayLikeObject(iteratee)) {\n iteratee = undefined;\n }\n return isArrayLikeObject(array)\n ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2))\n : [];\n });\n\n /**\n * This method is like `_.difference` except that it accepts `comparator`\n * which is invoked to compare elements of `array` to `values`. The order and\n * references of result values are determined by the first array. The comparator\n * is invoked with two arguments: (arrVal, othVal).\n *\n * **Note:** Unlike `_.pullAllWith`, this method returns a new array.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {...Array} [values] The values to exclude.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of filtered values.\n * @example\n *\n * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];\n *\n * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);\n * // => [{ 'x': 2, 'y': 1 }]\n */\n var differenceWith = baseRest(function(array, values) {\n var comparator = last(values);\n if (isArrayLikeObject(comparator)) {\n comparator = undefined;\n }\n return isArrayLikeObject(array)\n ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator)\n : [];\n });\n\n /**\n * Creates a slice of `array` with `n` elements dropped from the beginning.\n *\n * @static\n * @memberOf _\n * @since 0.5.0\n * @category Array\n * @param {Array} array The array to query.\n * @param {number} [n=1] The number of elements to drop.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Array} Returns the slice of `array`.\n * @example\n *\n * _.drop([1, 2, 3]);\n * // => [2, 3]\n *\n * _.drop([1, 2, 3], 2);\n * // => [3]\n *\n * _.drop([1, 2, 3], 5);\n * // => []\n *\n * _.drop([1, 2, 3], 0);\n * // => [1, 2, 3]\n */\n function drop(array, n, guard) {\n var length = array == null ? 0 : array.length;\n if (!length) {\n return [];\n }\n n = (guard || n === undefined) ? 1 : toInteger(n);\n return baseSlice(array, n < 0 ? 0 : n, length);\n }\n\n /**\n * Creates a slice of `array` with `n` elements dropped from the end.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to query.\n * @param {number} [n=1] The number of elements to drop.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Array} Returns the slice of `array`.\n * @example\n *\n * _.dropRight([1, 2, 3]);\n * // => [1, 2]\n *\n * _.dropRight([1, 2, 3], 2);\n * // => [1]\n *\n * _.dropRight([1, 2, 3], 5);\n * // => []\n *\n * _.dropRight([1, 2, 3], 0);\n * // => [1, 2, 3]\n */\n function dropRight(array, n, guard) {\n var length = array == null ? 0 : array.length;\n if (!length) {\n return [];\n }\n n = (guard || n === undefined) ? 1 : toInteger(n);\n n = length - n;\n return baseSlice(array, 0, n < 0 ? 0 : n);\n }\n\n /**\n * Creates a slice of `array` excluding elements dropped from the end.\n * Elements are dropped until `predicate` returns falsey. The predicate is\n * invoked with three arguments: (value, index, array).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to query.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the slice of `array`.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'active': true },\n * { 'user': 'fred', 'active': false },\n * { 'user': 'pebbles', 'active': false }\n * ];\n *\n * _.dropRightWhile(users, function(o) { return !o.active; });\n * // => objects for ['barney']\n *\n * // The `_.matches` iteratee shorthand.\n * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });\n * // => objects for ['barney', 'fred']\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.dropRightWhile(users, ['active', false]);\n * // => objects for ['barney']\n *\n * // The `_.property` iteratee shorthand.\n * _.dropRightWhile(users, 'active');\n * // => objects for ['barney', 'fred', 'pebbles']\n */\n function dropRightWhile(array, predicate) {\n return (array && array.length)\n ? baseWhile(array, getIteratee(predicate, 3), true, true)\n : [];\n }\n\n /**\n * Creates a slice of `array` excluding elements dropped from the beginning.\n * Elements are dropped until `predicate` returns falsey. The predicate is\n * invoked with three arguments: (value, index, array).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to query.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the slice of `array`.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'active': false },\n * { 'user': 'fred', 'active': false },\n * { 'user': 'pebbles', 'active': true }\n * ];\n *\n * _.dropWhile(users, function(o) { return !o.active; });\n * // => objects for ['pebbles']\n *\n * // The `_.matches` iteratee shorthand.\n * _.dropWhile(users, { 'user': 'barney', 'active': false });\n * // => objects for ['fred', 'pebbles']\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.dropWhile(users, ['active', false]);\n * // => objects for ['pebbles']\n *\n * // The `_.property` iteratee shorthand.\n * _.dropWhile(users, 'active');\n * // => objects for ['barney', 'fred', 'pebbles']\n */\n function dropWhile(array, predicate) {\n return (array && array.length)\n ? baseWhile(array, getIteratee(predicate, 3), true)\n : [];\n }\n\n /**\n * Fills elements of `array` with `value` from `start` up to, but not\n * including, `end`.\n *\n * **Note:** This method mutates `array`.\n *\n * @static\n * @memberOf _\n * @since 3.2.0\n * @category Array\n * @param {Array} array The array to fill.\n * @param {*} value The value to fill `array` with.\n * @param {number} [start=0] The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns `array`.\n * @example\n *\n * var array = [1, 2, 3];\n *\n * _.fill(array, 'a');\n * console.log(array);\n * // => ['a', 'a', 'a']\n *\n * _.fill(Array(3), 2);\n * // => [2, 2, 2]\n *\n * _.fill([4, 6, 8, 10], '*', 1, 3);\n * // => [4, '*', '*', 10]\n */\n function fill(array, value, start, end) {\n var length = array == null ? 0 : array.length;\n if (!length) {\n return [];\n }\n if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {\n start = 0;\n end = length;\n }\n return baseFill(array, value, start, end);\n }\n\n /**\n * This method is like `_.find` except that it returns the index of the first\n * element `predicate` returns truthy for instead of the element itself.\n *\n * @static\n * @memberOf _\n * @since 1.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @param {number} [fromIndex=0] The index to search from.\n * @returns {number} Returns the index of the found element, else `-1`.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'active': false },\n * { 'user': 'fred', 'active': false },\n * { 'user': 'pebbles', 'active': true }\n * ];\n *\n * _.findIndex(users, function(o) { return o.user == 'barney'; });\n * // => 0\n *\n * // The `_.matches` iteratee shorthand.\n * _.findIndex(users, { 'user': 'fred', 'active': false });\n * // => 1\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.findIndex(users, ['active', false]);\n * // => 0\n *\n * // The `_.property` iteratee shorthand.\n * _.findIndex(users, 'active');\n * // => 2\n */\n function findIndex(array, predicate, fromIndex) {\n var length = array == null ? 0 : array.length;\n if (!length) {\n return -1;\n }\n var index = fromIndex == null ? 0 : toInteger(fromIndex);\n if (index < 0) {\n index = nativeMax(length + index, 0);\n }\n return baseFindIndex(array, getIteratee(predicate, 3), index);\n }\n\n /**\n * This method is like `_.findIndex` except that it iterates over elements\n * of `collection` from right to left.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @param {number} [fromIndex=array.length-1] The index to search from.\n * @returns {number} Returns the index of the found element, else `-1`.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'active': true },\n * { 'user': 'fred', 'active': false },\n * { 'user': 'pebbles', 'active': false }\n * ];\n *\n * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });\n * // => 2\n *\n * // The `_.matches` iteratee shorthand.\n * _.findLastIndex(users, { 'user': 'barney', 'active': true });\n * // => 0\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.findLastIndex(users, ['active', false]);\n * // => 2\n *\n * // The `_.property` iteratee shorthand.\n * _.findLastIndex(users, 'active');\n * // => 0\n */\n function findLastIndex(array, predicate, fromIndex) {\n var length = array == null ? 0 : array.length;\n if (!length) {\n return -1;\n }\n var index = length - 1;\n if (fromIndex !== undefined) {\n index = toInteger(fromIndex);\n index = fromIndex < 0\n ? nativeMax(length + index, 0)\n : nativeMin(index, length - 1);\n }\n return baseFindIndex(array, getIteratee(predicate, 3), index, true);\n }\n\n /**\n * Flattens `array` a single level deep.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to flatten.\n * @returns {Array} Returns the new flattened array.\n * @example\n *\n * _.flatten([1, [2, [3, [4]], 5]]);\n * // => [1, 2, [3, [4]], 5]\n */\n function flatten(array) {\n var length = array == null ? 0 : array.length;\n return length ? baseFlatten(array, 1) : [];\n }\n\n /**\n * Recursively flattens `array`.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to flatten.\n * @returns {Array} Returns the new flattened array.\n * @example\n *\n * _.flattenDeep([1, [2, [3, [4]], 5]]);\n * // => [1, 2, 3, 4, 5]\n */\n function flattenDeep(array) {\n var length = array == null ? 0 : array.length;\n return length ? baseFlatten(array, INFINITY) : [];\n }\n\n /**\n * Recursively flatten `array` up to `depth` times.\n *\n * @static\n * @memberOf _\n * @since 4.4.0\n * @category Array\n * @param {Array} array The array to flatten.\n * @param {number} [depth=1] The maximum recursion depth.\n * @returns {Array} Returns the new flattened array.\n * @example\n *\n * var array = [1, [2, [3, [4]], 5]];\n *\n * _.flattenDepth(array, 1);\n * // => [1, 2, [3, [4]], 5]\n *\n * _.flattenDepth(array, 2);\n * // => [1, 2, 3, [4], 5]\n */\n function flattenDepth(array, depth) {\n var length = array == null ? 0 : array.length;\n if (!length) {\n return [];\n }\n depth = depth === undefined ? 1 : toInteger(depth);\n return baseFlatten(array, depth);\n }\n\n /**\n * The inverse of `_.toPairs`; this method returns an object composed\n * from key-value `pairs`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} pairs The key-value pairs.\n * @returns {Object} Returns the new object.\n * @example\n *\n * _.fromPairs([['a', 1], ['b', 2]]);\n * // => { 'a': 1, 'b': 2 }\n */\n function fromPairs(pairs) {\n var index = -1,\n length = pairs == null ? 0 : pairs.length,\n result = {};\n\n while (++index < length) {\n var pair = pairs[index];\n result[pair[0]] = pair[1];\n }\n return result;\n }\n\n /**\n * Gets the first element of `array`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @alias first\n * @category Array\n * @param {Array} array The array to query.\n * @returns {*} Returns the first element of `array`.\n * @example\n *\n * _.head([1, 2, 3]);\n * // => 1\n *\n * _.head([]);\n * // => undefined\n */\n function head(array) {\n return (array && array.length) ? array[0] : undefined;\n }\n\n /**\n * Gets the index at which the first occurrence of `value` is found in `array`\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons. If `fromIndex` is negative, it's used as the\n * offset from the end of `array`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} [fromIndex=0] The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n * @example\n *\n * _.indexOf([1, 2, 1, 2], 2);\n * // => 1\n *\n * // Search from the `fromIndex`.\n * _.indexOf([1, 2, 1, 2], 2, 2);\n * // => 3\n */\n function indexOf(array, value, fromIndex) {\n var length = array == null ? 0 : array.length;\n if (!length) {\n return -1;\n }\n var index = fromIndex == null ? 0 : toInteger(fromIndex);\n if (index < 0) {\n index = nativeMax(length + index, 0);\n }\n return baseIndexOf(array, value, index);\n }\n\n /**\n * Gets all but the last element of `array`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to query.\n * @returns {Array} Returns the slice of `array`.\n * @example\n *\n * _.initial([1, 2, 3]);\n * // => [1, 2]\n */\n function initial(array) {\n var length = array == null ? 0 : array.length;\n return length ? baseSlice(array, 0, -1) : [];\n }\n\n /**\n * Creates an array of unique values that are included in all given arrays\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons. The order and references of result values are\n * determined by the first array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @returns {Array} Returns the new array of intersecting values.\n * @example\n *\n * _.intersection([2, 1], [2, 3]);\n * // => [2]\n */\n var intersection = baseRest(function(arrays) {\n var mapped = arrayMap(arrays, castArrayLikeObject);\n return (mapped.length && mapped[0] === arrays[0])\n ? baseIntersection(mapped)\n : [];\n });\n\n /**\n * This method is like `_.intersection` except that it accepts `iteratee`\n * which is invoked for each element of each `arrays` to generate the criterion\n * by which they're compared. The order and references of result values are\n * determined by the first array. The iteratee is invoked with one argument:\n * (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {Array} Returns the new array of intersecting values.\n * @example\n *\n * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor);\n * // => [2.1]\n *\n * // The `_.property` iteratee shorthand.\n * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');\n * // => [{ 'x': 1 }]\n */\n var intersectionBy = baseRest(function(arrays) {\n var iteratee = last(arrays),\n mapped = arrayMap(arrays, castArrayLikeObject);\n\n if (iteratee === last(mapped)) {\n iteratee = undefined;\n } else {\n mapped.pop();\n }\n return (mapped.length && mapped[0] === arrays[0])\n ? baseIntersection(mapped, getIteratee(iteratee, 2))\n : [];\n });\n\n /**\n * This method is like `_.intersection` except that it accepts `comparator`\n * which is invoked to compare elements of `arrays`. The order and references\n * of result values are determined by the first array. The comparator is\n * invoked with two arguments: (arrVal, othVal).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of intersecting values.\n * @example\n *\n * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];\n * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];\n *\n * _.intersectionWith(objects, others, _.isEqual);\n * // => [{ 'x': 1, 'y': 2 }]\n */\n var intersectionWith = baseRest(function(arrays) {\n var comparator = last(arrays),\n mapped = arrayMap(arrays, castArrayLikeObject);\n\n comparator = typeof comparator == 'function' ? comparator : undefined;\n if (comparator) {\n mapped.pop();\n }\n return (mapped.length && mapped[0] === arrays[0])\n ? baseIntersection(mapped, undefined, comparator)\n : [];\n });\n\n /**\n * Converts all elements in `array` into a string separated by `separator`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to convert.\n * @param {string} [separator=','] The element separator.\n * @returns {string} Returns the joined string.\n * @example\n *\n * _.join(['a', 'b', 'c'], '~');\n * // => 'a~b~c'\n */\n function join(array, separator) {\n return array == null ? '' : nativeJoin.call(array, separator);\n }\n\n /**\n * Gets the last element of `array`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to query.\n * @returns {*} Returns the last element of `array`.\n * @example\n *\n * _.last([1, 2, 3]);\n * // => 3\n */\n function last(array) {\n var length = array == null ? 0 : array.length;\n return length ? array[length - 1] : undefined;\n }\n\n /**\n * This method is like `_.indexOf` except that it iterates over elements of\n * `array` from right to left.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @param {number} [fromIndex=array.length-1] The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n * @example\n *\n * _.lastIndexOf([1, 2, 1, 2], 2);\n * // => 3\n *\n * // Search from the `fromIndex`.\n * _.lastIndexOf([1, 2, 1, 2], 2, 2);\n * // => 1\n */\n function lastIndexOf(array, value, fromIndex) {\n var length = array == null ? 0 : array.length;\n if (!length) {\n return -1;\n }\n var index = length;\n if (fromIndex !== undefined) {\n index = toInteger(fromIndex);\n index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);\n }\n return value === value\n ? strictLastIndexOf(array, value, index)\n : baseFindIndex(array, baseIsNaN, index, true);\n }\n\n /**\n * Gets the element at index `n` of `array`. If `n` is negative, the nth\n * element from the end is returned.\n *\n * @static\n * @memberOf _\n * @since 4.11.0\n * @category Array\n * @param {Array} array The array to query.\n * @param {number} [n=0] The index of the element to return.\n * @returns {*} Returns the nth element of `array`.\n * @example\n *\n * var array = ['a', 'b', 'c', 'd'];\n *\n * _.nth(array, 1);\n * // => 'b'\n *\n * _.nth(array, -2);\n * // => 'c';\n */\n function nth(array, n) {\n return (array && array.length) ? baseNth(array, toInteger(n)) : undefined;\n }\n\n /**\n * Removes all given values from `array` using\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`\n * to remove elements from an array by predicate.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Array\n * @param {Array} array The array to modify.\n * @param {...*} [values] The values to remove.\n * @returns {Array} Returns `array`.\n * @example\n *\n * var array = ['a', 'b', 'c', 'a', 'b', 'c'];\n *\n * _.pull(array, 'a', 'c');\n * console.log(array);\n * // => ['b', 'b']\n */\n var pull = baseRest(pullAll);\n\n /**\n * This method is like `_.pull` except that it accepts an array of values to remove.\n *\n * **Note:** Unlike `_.difference`, this method mutates `array`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to modify.\n * @param {Array} values The values to remove.\n * @returns {Array} Returns `array`.\n * @example\n *\n * var array = ['a', 'b', 'c', 'a', 'b', 'c'];\n *\n * _.pullAll(array, ['a', 'c']);\n * console.log(array);\n * // => ['b', 'b']\n */\n function pullAll(array, values) {\n return (array && array.length && values && values.length)\n ? basePullAll(array, values)\n : array;\n }\n\n /**\n * This method is like `_.pullAll` except that it accepts `iteratee` which is\n * invoked for each element of `array` and `values` to generate the criterion\n * by which they're compared. The iteratee is invoked with one argument: (value).\n *\n * **Note:** Unlike `_.differenceBy`, this method mutates `array`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to modify.\n * @param {Array} values The values to remove.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {Array} Returns `array`.\n * @example\n *\n * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];\n *\n * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');\n * console.log(array);\n * // => [{ 'x': 2 }]\n */\n function pullAllBy(array, values, iteratee) {\n return (array && array.length && values && values.length)\n ? basePullAll(array, values, getIteratee(iteratee, 2))\n : array;\n }\n\n /**\n * This method is like `_.pullAll` except that it accepts `comparator` which\n * is invoked to compare elements of `array` to `values`. The comparator is\n * invoked with two arguments: (arrVal, othVal).\n *\n * **Note:** Unlike `_.differenceWith`, this method mutates `array`.\n *\n * @static\n * @memberOf _\n * @since 4.6.0\n * @category Array\n * @param {Array} array The array to modify.\n * @param {Array} values The values to remove.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns `array`.\n * @example\n *\n * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];\n *\n * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual);\n * console.log(array);\n * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]\n */\n function pullAllWith(array, values, comparator) {\n return (array && array.length && values && values.length)\n ? basePullAll(array, values, undefined, comparator)\n : array;\n }\n\n /**\n * Removes elements from `array` corresponding to `indexes` and returns an\n * array of removed elements.\n *\n * **Note:** Unlike `_.at`, this method mutates `array`.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to modify.\n * @param {...(number|number[])} [indexes] The indexes of elements to remove.\n * @returns {Array} Returns the new array of removed elements.\n * @example\n *\n * var array = ['a', 'b', 'c', 'd'];\n * var pulled = _.pullAt(array, [1, 3]);\n *\n * console.log(array);\n * // => ['a', 'c']\n *\n * console.log(pulled);\n * // => ['b', 'd']\n */\n var pullAt = flatRest(function(array, indexes) {\n var length = array == null ? 0 : array.length,\n result = baseAt(array, indexes);\n\n basePullAt(array, arrayMap(indexes, function(index) {\n return isIndex(index, length) ? +index : index;\n }).sort(compareAscending));\n\n return result;\n });\n\n /**\n * Removes all elements from `array` that `predicate` returns truthy for\n * and returns an array of the removed elements. The predicate is invoked\n * with three arguments: (value, index, array).\n *\n * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`\n * to pull elements from an array by value.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Array\n * @param {Array} array The array to modify.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the new array of removed elements.\n * @example\n *\n * var array = [1, 2, 3, 4];\n * var evens = _.remove(array, function(n) {\n * return n % 2 == 0;\n * });\n *\n * console.log(array);\n * // => [1, 3]\n *\n * console.log(evens);\n * // => [2, 4]\n */\n function remove(array, predicate) {\n var result = [];\n if (!(array && array.length)) {\n return result;\n }\n var index = -1,\n indexes = [],\n length = array.length;\n\n predicate = getIteratee(predicate, 3);\n while (++index < length) {\n var value = array[index];\n if (predicate(value, index, array)) {\n result.push(value);\n indexes.push(index);\n }\n }\n basePullAt(array, indexes);\n return result;\n }\n\n /**\n * Reverses `array` so that the first element becomes the last, the second\n * element becomes the second to last, and so on.\n *\n * **Note:** This method mutates `array` and is based on\n * [`Array#reverse`](https://mdn.io/Array/reverse).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to modify.\n * @returns {Array} Returns `array`.\n * @example\n *\n * var array = [1, 2, 3];\n *\n * _.reverse(array);\n * // => [3, 2, 1]\n *\n * console.log(array);\n * // => [3, 2, 1]\n */\n function reverse(array) {\n return array == null ? array : nativeReverse.call(array);\n }\n\n /**\n * Creates a slice of `array` from `start` up to, but not including, `end`.\n *\n * **Note:** This method is used instead of\n * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are\n * returned.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to slice.\n * @param {number} [start=0] The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns the slice of `array`.\n */\n function slice(array, start, end) {\n var length = array == null ? 0 : array.length;\n if (!length) {\n return [];\n }\n if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {\n start = 0;\n end = length;\n }\n else {\n start = start == null ? 0 : toInteger(start);\n end = end === undefined ? length : toInteger(end);\n }\n return baseSlice(array, start, end);\n }\n\n /**\n * Uses a binary search to determine the lowest index at which `value`\n * should be inserted into `array` in order to maintain its sort order.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The sorted array to inspect.\n * @param {*} value The value to evaluate.\n * @returns {number} Returns the index at which `value` should be inserted\n * into `array`.\n * @example\n *\n * _.sortedIndex([30, 50], 40);\n * // => 1\n */\n function sortedIndex(array, value) {\n return baseSortedIndex(array, value);\n }\n\n /**\n * This method is like `_.sortedIndex` except that it accepts `iteratee`\n * which is invoked for `value` and each element of `array` to compute their\n * sort ranking. The iteratee is invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The sorted array to inspect.\n * @param {*} value The value to evaluate.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {number} Returns the index at which `value` should be inserted\n * into `array`.\n * @example\n *\n * var objects = [{ 'x': 4 }, { 'x': 5 }];\n *\n * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });\n * // => 0\n *\n * // The `_.property` iteratee shorthand.\n * _.sortedIndexBy(objects, { 'x': 4 }, 'x');\n * // => 0\n */\n function sortedIndexBy(array, value, iteratee) {\n return baseSortedIndexBy(array, value, getIteratee(iteratee, 2));\n }\n\n /**\n * This method is like `_.indexOf` except that it performs a binary\n * search on a sorted `array`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @returns {number} Returns the index of the matched value, else `-1`.\n * @example\n *\n * _.sortedIndexOf([4, 5, 5, 5, 6], 5);\n * // => 1\n */\n function sortedIndexOf(array, value) {\n var length = array == null ? 0 : array.length;\n if (length) {\n var index = baseSortedIndex(array, value);\n if (index < length && eq(array[index], value)) {\n return index;\n }\n }\n return -1;\n }\n\n /**\n * This method is like `_.sortedIndex` except that it returns the highest\n * index at which `value` should be inserted into `array` in order to\n * maintain its sort order.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The sorted array to inspect.\n * @param {*} value The value to evaluate.\n * @returns {number} Returns the index at which `value` should be inserted\n * into `array`.\n * @example\n *\n * _.sortedLastIndex([4, 5, 5, 5, 6], 5);\n * // => 4\n */\n function sortedLastIndex(array, value) {\n return baseSortedIndex(array, value, true);\n }\n\n /**\n * This method is like `_.sortedLastIndex` except that it accepts `iteratee`\n * which is invoked for `value` and each element of `array` to compute their\n * sort ranking. The iteratee is invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The sorted array to inspect.\n * @param {*} value The value to evaluate.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {number} Returns the index at which `value` should be inserted\n * into `array`.\n * @example\n *\n * var objects = [{ 'x': 4 }, { 'x': 5 }];\n *\n * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });\n * // => 1\n *\n * // The `_.property` iteratee shorthand.\n * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x');\n * // => 1\n */\n function sortedLastIndexBy(array, value, iteratee) {\n return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true);\n }\n\n /**\n * This method is like `_.lastIndexOf` except that it performs a binary\n * search on a sorted `array`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {*} value The value to search for.\n * @returns {number} Returns the index of the matched value, else `-1`.\n * @example\n *\n * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5);\n * // => 3\n */\n function sortedLastIndexOf(array, value) {\n var length = array == null ? 0 : array.length;\n if (length) {\n var index = baseSortedIndex(array, value, true) - 1;\n if (eq(array[index], value)) {\n return index;\n }\n }\n return -1;\n }\n\n /**\n * This method is like `_.uniq` except that it's designed and optimized\n * for sorted arrays.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @returns {Array} Returns the new duplicate free array.\n * @example\n *\n * _.sortedUniq([1, 1, 2]);\n * // => [1, 2]\n */\n function sortedUniq(array) {\n return (array && array.length)\n ? baseSortedUniq(array)\n : [];\n }\n\n /**\n * This method is like `_.uniqBy` except that it's designed and optimized\n * for sorted arrays.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {Function} [iteratee] The iteratee invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n * @example\n *\n * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);\n * // => [1.1, 2.3]\n */\n function sortedUniqBy(array, iteratee) {\n return (array && array.length)\n ? baseSortedUniq(array, getIteratee(iteratee, 2))\n : [];\n }\n\n /**\n * Gets all but the first element of `array`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to query.\n * @returns {Array} Returns the slice of `array`.\n * @example\n *\n * _.tail([1, 2, 3]);\n * // => [2, 3]\n */\n function tail(array) {\n var length = array == null ? 0 : array.length;\n return length ? baseSlice(array, 1, length) : [];\n }\n\n /**\n * Creates a slice of `array` with `n` elements taken from the beginning.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to query.\n * @param {number} [n=1] The number of elements to take.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Array} Returns the slice of `array`.\n * @example\n *\n * _.take([1, 2, 3]);\n * // => [1]\n *\n * _.take([1, 2, 3], 2);\n * // => [1, 2]\n *\n * _.take([1, 2, 3], 5);\n * // => [1, 2, 3]\n *\n * _.take([1, 2, 3], 0);\n * // => []\n */\n function take(array, n, guard) {\n if (!(array && array.length)) {\n return [];\n }\n n = (guard || n === undefined) ? 1 : toInteger(n);\n return baseSlice(array, 0, n < 0 ? 0 : n);\n }\n\n /**\n * Creates a slice of `array` with `n` elements taken from the end.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to query.\n * @param {number} [n=1] The number of elements to take.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Array} Returns the slice of `array`.\n * @example\n *\n * _.takeRight([1, 2, 3]);\n * // => [3]\n *\n * _.takeRight([1, 2, 3], 2);\n * // => [2, 3]\n *\n * _.takeRight([1, 2, 3], 5);\n * // => [1, 2, 3]\n *\n * _.takeRight([1, 2, 3], 0);\n * // => []\n */\n function takeRight(array, n, guard) {\n var length = array == null ? 0 : array.length;\n if (!length) {\n return [];\n }\n n = (guard || n === undefined) ? 1 : toInteger(n);\n n = length - n;\n return baseSlice(array, n < 0 ? 0 : n, length);\n }\n\n /**\n * Creates a slice of `array` with elements taken from the end. Elements are\n * taken until `predicate` returns falsey. The predicate is invoked with\n * three arguments: (value, index, array).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to query.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the slice of `array`.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'active': true },\n * { 'user': 'fred', 'active': false },\n * { 'user': 'pebbles', 'active': false }\n * ];\n *\n * _.takeRightWhile(users, function(o) { return !o.active; });\n * // => objects for ['fred', 'pebbles']\n *\n * // The `_.matches` iteratee shorthand.\n * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });\n * // => objects for ['pebbles']\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.takeRightWhile(users, ['active', false]);\n * // => objects for ['fred', 'pebbles']\n *\n * // The `_.property` iteratee shorthand.\n * _.takeRightWhile(users, 'active');\n * // => []\n */\n function takeRightWhile(array, predicate) {\n return (array && array.length)\n ? baseWhile(array, getIteratee(predicate, 3), false, true)\n : [];\n }\n\n /**\n * Creates a slice of `array` with elements taken from the beginning. Elements\n * are taken until `predicate` returns falsey. The predicate is invoked with\n * three arguments: (value, index, array).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Array\n * @param {Array} array The array to query.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the slice of `array`.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'active': false },\n * { 'user': 'fred', 'active': false },\n * { 'user': 'pebbles', 'active': true }\n * ];\n *\n * _.takeWhile(users, function(o) { return !o.active; });\n * // => objects for ['barney', 'fred']\n *\n * // The `_.matches` iteratee shorthand.\n * _.takeWhile(users, { 'user': 'barney', 'active': false });\n * // => objects for ['barney']\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.takeWhile(users, ['active', false]);\n * // => objects for ['barney', 'fred']\n *\n * // The `_.property` iteratee shorthand.\n * _.takeWhile(users, 'active');\n * // => []\n */\n function takeWhile(array, predicate) {\n return (array && array.length)\n ? baseWhile(array, getIteratee(predicate, 3))\n : [];\n }\n\n /**\n * Creates an array of unique values, in order, from all given arrays using\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @returns {Array} Returns the new array of combined values.\n * @example\n *\n * _.union([2], [1, 2]);\n * // => [2, 1]\n */\n var union = baseRest(function(arrays) {\n return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));\n });\n\n /**\n * This method is like `_.union` except that it accepts `iteratee` which is\n * invoked for each element of each `arrays` to generate the criterion by\n * which uniqueness is computed. Result values are chosen from the first\n * array in which the value occurs. The iteratee is invoked with one argument:\n * (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {Array} Returns the new array of combined values.\n * @example\n *\n * _.unionBy([2.1], [1.2, 2.3], Math.floor);\n * // => [2.1, 1.2]\n *\n * // The `_.property` iteratee shorthand.\n * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');\n * // => [{ 'x': 1 }, { 'x': 2 }]\n */\n var unionBy = baseRest(function(arrays) {\n var iteratee = last(arrays);\n if (isArrayLikeObject(iteratee)) {\n iteratee = undefined;\n }\n return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2));\n });\n\n /**\n * This method is like `_.union` except that it accepts `comparator` which\n * is invoked to compare elements of `arrays`. Result values are chosen from\n * the first array in which the value occurs. The comparator is invoked\n * with two arguments: (arrVal, othVal).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of combined values.\n * @example\n *\n * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];\n * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];\n *\n * _.unionWith(objects, others, _.isEqual);\n * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]\n */\n var unionWith = baseRest(function(arrays) {\n var comparator = last(arrays);\n comparator = typeof comparator == 'function' ? comparator : undefined;\n return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator);\n });\n\n /**\n * Creates a duplicate-free version of an array, using\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons, in which only the first occurrence of each element\n * is kept. The order of result values is determined by the order they occur\n * in the array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @returns {Array} Returns the new duplicate free array.\n * @example\n *\n * _.uniq([2, 1, 2]);\n * // => [2, 1]\n */\n function uniq(array) {\n return (array && array.length) ? baseUniq(array) : [];\n }\n\n /**\n * This method is like `_.uniq` except that it accepts `iteratee` which is\n * invoked for each element in `array` to generate the criterion by which\n * uniqueness is computed. The order of result values is determined by the\n * order they occur in the array. The iteratee is invoked with one argument:\n * (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n * @example\n *\n * _.uniqBy([2.1, 1.2, 2.3], Math.floor);\n * // => [2.1, 1.2]\n *\n * // The `_.property` iteratee shorthand.\n * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');\n * // => [{ 'x': 1 }, { 'x': 2 }]\n */\n function uniqBy(array, iteratee) {\n return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : [];\n }\n\n /**\n * This method is like `_.uniq` except that it accepts `comparator` which\n * is invoked to compare elements of `array`. The order of result values is\n * determined by the order they occur in the array.The comparator is invoked\n * with two arguments: (arrVal, othVal).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new duplicate free array.\n * @example\n *\n * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];\n *\n * _.uniqWith(objects, _.isEqual);\n * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]\n */\n function uniqWith(array, comparator) {\n comparator = typeof comparator == 'function' ? comparator : undefined;\n return (array && array.length) ? baseUniq(array, undefined, comparator) : [];\n }\n\n /**\n * This method is like `_.zip` except that it accepts an array of grouped\n * elements and creates an array regrouping the elements to their pre-zip\n * configuration.\n *\n * @static\n * @memberOf _\n * @since 1.2.0\n * @category Array\n * @param {Array} array The array of grouped elements to process.\n * @returns {Array} Returns the new array of regrouped elements.\n * @example\n *\n * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]);\n * // => [['a', 1, true], ['b', 2, false]]\n *\n * _.unzip(zipped);\n * // => [['a', 'b'], [1, 2], [true, false]]\n */\n function unzip(array) {\n if (!(array && array.length)) {\n return [];\n }\n var length = 0;\n array = arrayFilter(array, function(group) {\n if (isArrayLikeObject(group)) {\n length = nativeMax(group.length, length);\n return true;\n }\n });\n return baseTimes(length, function(index) {\n return arrayMap(array, baseProperty(index));\n });\n }\n\n /**\n * This method is like `_.unzip` except that it accepts `iteratee` to specify\n * how regrouped values should be combined. The iteratee is invoked with the\n * elements of each group: (...group).\n *\n * @static\n * @memberOf _\n * @since 3.8.0\n * @category Array\n * @param {Array} array The array of grouped elements to process.\n * @param {Function} [iteratee=_.identity] The function to combine\n * regrouped values.\n * @returns {Array} Returns the new array of regrouped elements.\n * @example\n *\n * var zipped = _.zip([1, 2], [10, 20], [100, 200]);\n * // => [[1, 10, 100], [2, 20, 200]]\n *\n * _.unzipWith(zipped, _.add);\n * // => [3, 30, 300]\n */\n function unzipWith(array, iteratee) {\n if (!(array && array.length)) {\n return [];\n }\n var result = unzip(array);\n if (iteratee == null) {\n return result;\n }\n return arrayMap(result, function(group) {\n return apply(iteratee, undefined, group);\n });\n }\n\n /**\n * Creates an array excluding all given values using\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * **Note:** Unlike `_.pull`, this method returns a new array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {Array} array The array to inspect.\n * @param {...*} [values] The values to exclude.\n * @returns {Array} Returns the new array of filtered values.\n * @see _.difference, _.xor\n * @example\n *\n * _.without([2, 1, 2, 3], 1, 2);\n * // => [3]\n */\n var without = baseRest(function(array, values) {\n return isArrayLikeObject(array)\n ? baseDifference(array, values)\n : [];\n });\n\n /**\n * Creates an array of unique values that is the\n * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)\n * of the given arrays. The order of result values is determined by the order\n * they occur in the arrays.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @returns {Array} Returns the new array of filtered values.\n * @see _.difference, _.without\n * @example\n *\n * _.xor([2, 1], [2, 3]);\n * // => [1, 3]\n */\n var xor = baseRest(function(arrays) {\n return baseXor(arrayFilter(arrays, isArrayLikeObject));\n });\n\n /**\n * This method is like `_.xor` except that it accepts `iteratee` which is\n * invoked for each element of each `arrays` to generate the criterion by\n * which by which they're compared. The order of result values is determined\n * by the order they occur in the arrays. The iteratee is invoked with one\n * argument: (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {Array} Returns the new array of filtered values.\n * @example\n *\n * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);\n * // => [1.2, 3.4]\n *\n * // The `_.property` iteratee shorthand.\n * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');\n * // => [{ 'x': 2 }]\n */\n var xorBy = baseRest(function(arrays) {\n var iteratee = last(arrays);\n if (isArrayLikeObject(iteratee)) {\n iteratee = undefined;\n }\n return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2));\n });\n\n /**\n * This method is like `_.xor` except that it accepts `comparator` which is\n * invoked to compare elements of `arrays`. The order of result values is\n * determined by the order they occur in the arrays. The comparator is invoked\n * with two arguments: (arrVal, othVal).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Array\n * @param {...Array} [arrays] The arrays to inspect.\n * @param {Function} [comparator] The comparator invoked per element.\n * @returns {Array} Returns the new array of filtered values.\n * @example\n *\n * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];\n * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];\n *\n * _.xorWith(objects, others, _.isEqual);\n * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]\n */\n var xorWith = baseRest(function(arrays) {\n var comparator = last(arrays);\n comparator = typeof comparator == 'function' ? comparator : undefined;\n return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator);\n });\n\n /**\n * Creates an array of grouped elements, the first of which contains the\n * first elements of the given arrays, the second of which contains the\n * second elements of the given arrays, and so on.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Array\n * @param {...Array} [arrays] The arrays to process.\n * @returns {Array} Returns the new array of grouped elements.\n * @example\n *\n * _.zip(['a', 'b'], [1, 2], [true, false]);\n * // => [['a', 1, true], ['b', 2, false]]\n */\n var zip = baseRest(unzip);\n\n /**\n * This method is like `_.fromPairs` except that it accepts two arrays,\n * one of property identifiers and one of corresponding values.\n *\n * @static\n * @memberOf _\n * @since 0.4.0\n * @category Array\n * @param {Array} [props=[]] The property identifiers.\n * @param {Array} [values=[]] The property values.\n * @returns {Object} Returns the new object.\n * @example\n *\n * _.zipObject(['a', 'b'], [1, 2]);\n * // => { 'a': 1, 'b': 2 }\n */\n function zipObject(props, values) {\n return baseZipObject(props || [], values || [], assignValue);\n }\n\n /**\n * This method is like `_.zipObject` except that it supports property paths.\n *\n * @static\n * @memberOf _\n * @since 4.1.0\n * @category Array\n * @param {Array} [props=[]] The property identifiers.\n * @param {Array} [values=[]] The property values.\n * @returns {Object} Returns the new object.\n * @example\n *\n * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);\n * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }\n */\n function zipObjectDeep(props, values) {\n return baseZipObject(props || [], values || [], baseSet);\n }\n\n /**\n * This method is like `_.zip` except that it accepts `iteratee` to specify\n * how grouped values should be combined. The iteratee is invoked with the\n * elements of each group: (...group).\n *\n * @static\n * @memberOf _\n * @since 3.8.0\n * @category Array\n * @param {...Array} [arrays] The arrays to process.\n * @param {Function} [iteratee=_.identity] The function to combine\n * grouped values.\n * @returns {Array} Returns the new array of grouped elements.\n * @example\n *\n * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {\n * return a + b + c;\n * });\n * // => [111, 222]\n */\n var zipWith = baseRest(function(arrays) {\n var length = arrays.length,\n iteratee = length > 1 ? arrays[length - 1] : undefined;\n\n iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined;\n return unzipWith(arrays, iteratee);\n });\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Creates a `lodash` wrapper instance that wraps `value` with explicit method\n * chain sequences enabled. The result of such sequences must be unwrapped\n * with `_#value`.\n *\n * @static\n * @memberOf _\n * @since 1.3.0\n * @category Seq\n * @param {*} value The value to wrap.\n * @returns {Object} Returns the new `lodash` wrapper instance.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'age': 36 },\n * { 'user': 'fred', 'age': 40 },\n * { 'user': 'pebbles', 'age': 1 }\n * ];\n *\n * var youngest = _\n * .chain(users)\n * .sortBy('age')\n * .map(function(o) {\n * return o.user + ' is ' + o.age;\n * })\n * .head()\n * .value();\n * // => 'pebbles is 1'\n */\n function chain(value) {\n var result = lodash(value);\n result.__chain__ = true;\n return result;\n }\n\n /**\n * This method invokes `interceptor` and returns `value`. The interceptor\n * is invoked with one argument; (value). The purpose of this method is to\n * \"tap into\" a method chain sequence in order to modify intermediate results.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Seq\n * @param {*} value The value to provide to `interceptor`.\n * @param {Function} interceptor The function to invoke.\n * @returns {*} Returns `value`.\n * @example\n *\n * _([1, 2, 3])\n * .tap(function(array) {\n * // Mutate input array.\n * array.pop();\n * })\n * .reverse()\n * .value();\n * // => [2, 1]\n */\n function tap(value, interceptor) {\n interceptor(value);\n return value;\n }\n\n /**\n * This method is like `_.tap` except that it returns the result of `interceptor`.\n * The purpose of this method is to \"pass thru\" values replacing intermediate\n * results in a method chain sequence.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Seq\n * @param {*} value The value to provide to `interceptor`.\n * @param {Function} interceptor The function to invoke.\n * @returns {*} Returns the result of `interceptor`.\n * @example\n *\n * _(' abc ')\n * .chain()\n * .trim()\n * .thru(function(value) {\n * return [value];\n * })\n * .value();\n * // => ['abc']\n */\n function thru(value, interceptor) {\n return interceptor(value);\n }\n\n /**\n * This method is the wrapper version of `_.at`.\n *\n * @name at\n * @memberOf _\n * @since 1.0.0\n * @category Seq\n * @param {...(string|string[])} [paths] The property paths to pick.\n * @returns {Object} Returns the new `lodash` wrapper instance.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };\n *\n * _(object).at(['a[0].b.c', 'a[1]']).value();\n * // => [3, 4]\n */\n var wrapperAt = flatRest(function(paths) {\n var length = paths.length,\n start = length ? paths[0] : 0,\n value = this.__wrapped__,\n interceptor = function(object) { return baseAt(object, paths); };\n\n if (length > 1 || this.__actions__.length ||\n !(value instanceof LazyWrapper) || !isIndex(start)) {\n return this.thru(interceptor);\n }\n value = value.slice(start, +start + (length ? 1 : 0));\n value.__actions__.push({\n 'func': thru,\n 'args': [interceptor],\n 'thisArg': undefined\n });\n return new LodashWrapper(value, this.__chain__).thru(function(array) {\n if (length && !array.length) {\n array.push(undefined);\n }\n return array;\n });\n });\n\n /**\n * Creates a `lodash` wrapper instance with explicit method chain sequences enabled.\n *\n * @name chain\n * @memberOf _\n * @since 0.1.0\n * @category Seq\n * @returns {Object} Returns the new `lodash` wrapper instance.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'age': 36 },\n * { 'user': 'fred', 'age': 40 }\n * ];\n *\n * // A sequence without explicit chaining.\n * _(users).head();\n * // => { 'user': 'barney', 'age': 36 }\n *\n * // A sequence with explicit chaining.\n * _(users)\n * .chain()\n * .head()\n * .pick('user')\n * .value();\n * // => { 'user': 'barney' }\n */\n function wrapperChain() {\n return chain(this);\n }\n\n /**\n * Executes the chain sequence and returns the wrapped result.\n *\n * @name commit\n * @memberOf _\n * @since 3.2.0\n * @category Seq\n * @returns {Object} Returns the new `lodash` wrapper instance.\n * @example\n *\n * var array = [1, 2];\n * var wrapped = _(array).push(3);\n *\n * console.log(array);\n * // => [1, 2]\n *\n * wrapped = wrapped.commit();\n * console.log(array);\n * // => [1, 2, 3]\n *\n * wrapped.last();\n * // => 3\n *\n * console.log(array);\n * // => [1, 2, 3]\n */\n function wrapperCommit() {\n return new LodashWrapper(this.value(), this.__chain__);\n }\n\n /**\n * Gets the next value on a wrapped object following the\n * [iterator protocol](https://mdn.io/iteration_protocols#iterator).\n *\n * @name next\n * @memberOf _\n * @since 4.0.0\n * @category Seq\n * @returns {Object} Returns the next iterator value.\n * @example\n *\n * var wrapped = _([1, 2]);\n *\n * wrapped.next();\n * // => { 'done': false, 'value': 1 }\n *\n * wrapped.next();\n * // => { 'done': false, 'value': 2 }\n *\n * wrapped.next();\n * // => { 'done': true, 'value': undefined }\n */\n function wrapperNext() {\n if (this.__values__ === undefined) {\n this.__values__ = toArray(this.value());\n }\n var done = this.__index__ >= this.__values__.length,\n value = done ? undefined : this.__values__[this.__index__++];\n\n return { 'done': done, 'value': value };\n }\n\n /**\n * Enables the wrapper to be iterable.\n *\n * @name Symbol.iterator\n * @memberOf _\n * @since 4.0.0\n * @category Seq\n * @returns {Object} Returns the wrapper object.\n * @example\n *\n * var wrapped = _([1, 2]);\n *\n * wrapped[Symbol.iterator]() === wrapped;\n * // => true\n *\n * Array.from(wrapped);\n * // => [1, 2]\n */\n function wrapperToIterator() {\n return this;\n }\n\n /**\n * Creates a clone of the chain sequence planting `value` as the wrapped value.\n *\n * @name plant\n * @memberOf _\n * @since 3.2.0\n * @category Seq\n * @param {*} value The value to plant.\n * @returns {Object} Returns the new `lodash` wrapper instance.\n * @example\n *\n * function square(n) {\n * return n * n;\n * }\n *\n * var wrapped = _([1, 2]).map(square);\n * var other = wrapped.plant([3, 4]);\n *\n * other.value();\n * // => [9, 16]\n *\n * wrapped.value();\n * // => [1, 4]\n */\n function wrapperPlant(value) {\n var result,\n parent = this;\n\n while (parent instanceof baseLodash) {\n var clone = wrapperClone(parent);\n clone.__index__ = 0;\n clone.__values__ = undefined;\n if (result) {\n previous.__wrapped__ = clone;\n } else {\n result = clone;\n }\n var previous = clone;\n parent = parent.__wrapped__;\n }\n previous.__wrapped__ = value;\n return result;\n }\n\n /**\n * This method is the wrapper version of `_.reverse`.\n *\n * **Note:** This method mutates the wrapped array.\n *\n * @name reverse\n * @memberOf _\n * @since 0.1.0\n * @category Seq\n * @returns {Object} Returns the new `lodash` wrapper instance.\n * @example\n *\n * var array = [1, 2, 3];\n *\n * _(array).reverse().value()\n * // => [3, 2, 1]\n *\n * console.log(array);\n * // => [3, 2, 1]\n */\n function wrapperReverse() {\n var value = this.__wrapped__;\n if (value instanceof LazyWrapper) {\n var wrapped = value;\n if (this.__actions__.length) {\n wrapped = new LazyWrapper(this);\n }\n wrapped = wrapped.reverse();\n wrapped.__actions__.push({\n 'func': thru,\n 'args': [reverse],\n 'thisArg': undefined\n });\n return new LodashWrapper(wrapped, this.__chain__);\n }\n return this.thru(reverse);\n }\n\n /**\n * Executes the chain sequence to resolve the unwrapped value.\n *\n * @name value\n * @memberOf _\n * @since 0.1.0\n * @alias toJSON, valueOf\n * @category Seq\n * @returns {*} Returns the resolved unwrapped value.\n * @example\n *\n * _([1, 2, 3]).value();\n * // => [1, 2, 3]\n */\n function wrapperValue() {\n return baseWrapperValue(this.__wrapped__, this.__actions__);\n }\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Creates an object composed of keys generated from the results of running\n * each element of `collection` thru `iteratee`. The corresponding value of\n * each key is the number of times the key was returned by `iteratee`. The\n * iteratee is invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 0.5.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The iteratee to transform keys.\n * @returns {Object} Returns the composed aggregate object.\n * @example\n *\n * _.countBy([6.1, 4.2, 6.3], Math.floor);\n * // => { '4': 1, '6': 2 }\n *\n * // The `_.property` iteratee shorthand.\n * _.countBy(['one', 'two', 'three'], 'length');\n * // => { '3': 2, '5': 1 }\n */\n var countBy = createAggregator(function(result, value, key) {\n if (hasOwnProperty.call(result, key)) {\n ++result[key];\n } else {\n baseAssignValue(result, key, 1);\n }\n });\n\n /**\n * Checks if `predicate` returns truthy for **all** elements of `collection`.\n * Iteration is stopped once `predicate` returns falsey. The predicate is\n * invoked with three arguments: (value, index|key, collection).\n *\n * **Note:** This method returns `true` for\n * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because\n * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of\n * elements of empty collections.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {boolean} Returns `true` if all elements pass the predicate check,\n * else `false`.\n * @example\n *\n * _.every([true, 1, null, 'yes'], Boolean);\n * // => false\n *\n * var users = [\n * { 'user': 'barney', 'age': 36, 'active': false },\n * { 'user': 'fred', 'age': 40, 'active': false }\n * ];\n *\n * // The `_.matches` iteratee shorthand.\n * _.every(users, { 'user': 'barney', 'active': false });\n * // => false\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.every(users, ['active', false]);\n * // => true\n *\n * // The `_.property` iteratee shorthand.\n * _.every(users, 'active');\n * // => false\n */\n function every(collection, predicate, guard) {\n var func = isArray(collection) ? arrayEvery : baseEvery;\n if (guard && isIterateeCall(collection, predicate, guard)) {\n predicate = undefined;\n }\n return func(collection, getIteratee(predicate, 3));\n }\n\n /**\n * Iterates over elements of `collection`, returning an array of all elements\n * `predicate` returns truthy for. The predicate is invoked with three\n * arguments: (value, index|key, collection).\n *\n * **Note:** Unlike `_.remove`, this method returns a new array.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the new filtered array.\n * @see _.reject\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'age': 36, 'active': true },\n * { 'user': 'fred', 'age': 40, 'active': false }\n * ];\n *\n * _.filter(users, function(o) { return !o.active; });\n * // => objects for ['fred']\n *\n * // The `_.matches` iteratee shorthand.\n * _.filter(users, { 'age': 36, 'active': true });\n * // => objects for ['barney']\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.filter(users, ['active', false]);\n * // => objects for ['fred']\n *\n * // The `_.property` iteratee shorthand.\n * _.filter(users, 'active');\n * // => objects for ['barney']\n */\n function filter(collection, predicate) {\n var func = isArray(collection) ? arrayFilter : baseFilter;\n return func(collection, getIteratee(predicate, 3));\n }\n\n /**\n * Iterates over elements of `collection`, returning the first element\n * `predicate` returns truthy for. The predicate is invoked with three\n * arguments: (value, index|key, collection).\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to inspect.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @param {number} [fromIndex=0] The index to search from.\n * @returns {*} Returns the matched element, else `undefined`.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'age': 36, 'active': true },\n * { 'user': 'fred', 'age': 40, 'active': false },\n * { 'user': 'pebbles', 'age': 1, 'active': true }\n * ];\n *\n * _.find(users, function(o) { return o.age < 40; });\n * // => object for 'barney'\n *\n * // The `_.matches` iteratee shorthand.\n * _.find(users, { 'age': 1, 'active': true });\n * // => object for 'pebbles'\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.find(users, ['active', false]);\n * // => object for 'fred'\n *\n * // The `_.property` iteratee shorthand.\n * _.find(users, 'active');\n * // => object for 'barney'\n */\n var find = createFind(findIndex);\n\n /**\n * This method is like `_.find` except that it iterates over elements of\n * `collection` from right to left.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Collection\n * @param {Array|Object} collection The collection to inspect.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @param {number} [fromIndex=collection.length-1] The index to search from.\n * @returns {*} Returns the matched element, else `undefined`.\n * @example\n *\n * _.findLast([1, 2, 3, 4], function(n) {\n * return n % 2 == 1;\n * });\n * // => 3\n */\n var findLast = createFind(findLastIndex);\n\n /**\n * Creates a flattened array of values by running each element in `collection`\n * thru `iteratee` and flattening the mapped results. The iteratee is invoked\n * with three arguments: (value, index|key, collection).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the new flattened array.\n * @example\n *\n * function duplicate(n) {\n * return [n, n];\n * }\n *\n * _.flatMap([1, 2], duplicate);\n * // => [1, 1, 2, 2]\n */\n function flatMap(collection, iteratee) {\n return baseFlatten(map(collection, iteratee), 1);\n }\n\n /**\n * This method is like `_.flatMap` except that it recursively flattens the\n * mapped results.\n *\n * @static\n * @memberOf _\n * @since 4.7.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the new flattened array.\n * @example\n *\n * function duplicate(n) {\n * return [[[n, n]]];\n * }\n *\n * _.flatMapDeep([1, 2], duplicate);\n * // => [1, 1, 2, 2]\n */\n function flatMapDeep(collection, iteratee) {\n return baseFlatten(map(collection, iteratee), INFINITY);\n }\n\n /**\n * This method is like `_.flatMap` except that it recursively flattens the\n * mapped results up to `depth` times.\n *\n * @static\n * @memberOf _\n * @since 4.7.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @param {number} [depth=1] The maximum recursion depth.\n * @returns {Array} Returns the new flattened array.\n * @example\n *\n * function duplicate(n) {\n * return [[[n, n]]];\n * }\n *\n * _.flatMapDepth([1, 2], duplicate, 2);\n * // => [[1, 1], [2, 2]]\n */\n function flatMapDepth(collection, iteratee, depth) {\n depth = depth === undefined ? 1 : toInteger(depth);\n return baseFlatten(map(collection, iteratee), depth);\n }\n\n /**\n * Iterates over elements of `collection` and invokes `iteratee` for each element.\n * The iteratee is invoked with three arguments: (value, index|key, collection).\n * Iteratee functions may exit iteration early by explicitly returning `false`.\n *\n * **Note:** As with other \"Collections\" methods, objects with a \"length\"\n * property are iterated like arrays. To avoid this behavior use `_.forIn`\n * or `_.forOwn` for object iteration.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @alias each\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Array|Object} Returns `collection`.\n * @see _.forEachRight\n * @example\n *\n * _.forEach([1, 2], function(value) {\n * console.log(value);\n * });\n * // => Logs `1` then `2`.\n *\n * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {\n * console.log(key);\n * });\n * // => Logs 'a' then 'b' (iteration order is not guaranteed).\n */\n function forEach(collection, iteratee) {\n var func = isArray(collection) ? arrayEach : baseEach;\n return func(collection, getIteratee(iteratee, 3));\n }\n\n /**\n * This method is like `_.forEach` except that it iterates over elements of\n * `collection` from right to left.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @alias eachRight\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Array|Object} Returns `collection`.\n * @see _.forEach\n * @example\n *\n * _.forEachRight([1, 2], function(value) {\n * console.log(value);\n * });\n * // => Logs `2` then `1`.\n */\n function forEachRight(collection, iteratee) {\n var func = isArray(collection) ? arrayEachRight : baseEachRight;\n return func(collection, getIteratee(iteratee, 3));\n }\n\n /**\n * Creates an object composed of keys generated from the results of running\n * each element of `collection` thru `iteratee`. The order of grouped values\n * is determined by the order they occur in `collection`. The corresponding\n * value of each key is an array of elements responsible for generating the\n * key. The iteratee is invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The iteratee to transform keys.\n * @returns {Object} Returns the composed aggregate object.\n * @example\n *\n * _.groupBy([6.1, 4.2, 6.3], Math.floor);\n * // => { '4': [4.2], '6': [6.1, 6.3] }\n *\n * // The `_.property` iteratee shorthand.\n * _.groupBy(['one', 'two', 'three'], 'length');\n * // => { '3': ['one', 'two'], '5': ['three'] }\n */\n var groupBy = createAggregator(function(result, value, key) {\n if (hasOwnProperty.call(result, key)) {\n result[key].push(value);\n } else {\n baseAssignValue(result, key, [value]);\n }\n });\n\n /**\n * Checks if `value` is in `collection`. If `collection` is a string, it's\n * checked for a substring of `value`, otherwise\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * is used for equality comparisons. If `fromIndex` is negative, it's used as\n * the offset from the end of `collection`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object|string} collection The collection to inspect.\n * @param {*} value The value to search for.\n * @param {number} [fromIndex=0] The index to search from.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.\n * @returns {boolean} Returns `true` if `value` is found, else `false`.\n * @example\n *\n * _.includes([1, 2, 3], 1);\n * // => true\n *\n * _.includes([1, 2, 3], 1, 2);\n * // => false\n *\n * _.includes({ 'a': 1, 'b': 2 }, 1);\n * // => true\n *\n * _.includes('abcd', 'bc');\n * // => true\n */\n function includes(collection, value, fromIndex, guard) {\n collection = isArrayLike(collection) ? collection : values(collection);\n fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;\n\n var length = collection.length;\n if (fromIndex < 0) {\n fromIndex = nativeMax(length + fromIndex, 0);\n }\n return isString(collection)\n ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)\n : (!!length && baseIndexOf(collection, value, fromIndex) > -1);\n }\n\n /**\n * Invokes the method at `path` of each element in `collection`, returning\n * an array of the results of each invoked method. Any additional arguments\n * are provided to each invoked method. If `path` is a function, it's invoked\n * for, and `this` bound to, each element in `collection`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Array|Function|string} path The path of the method to invoke or\n * the function invoked per iteration.\n * @param {...*} [args] The arguments to invoke each method with.\n * @returns {Array} Returns the array of results.\n * @example\n *\n * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');\n * // => [[1, 5, 7], [1, 2, 3]]\n *\n * _.invokeMap([123, 456], String.prototype.split, '');\n * // => [['1', '2', '3'], ['4', '5', '6']]\n */\n var invokeMap = baseRest(function(collection, path, args) {\n var index = -1,\n isFunc = typeof path == 'function',\n result = isArrayLike(collection) ? Array(collection.length) : [];\n\n baseEach(collection, function(value) {\n result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);\n });\n return result;\n });\n\n /**\n * Creates an object composed of keys generated from the results of running\n * each element of `collection` thru `iteratee`. The corresponding value of\n * each key is the last element responsible for generating the key. The\n * iteratee is invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The iteratee to transform keys.\n * @returns {Object} Returns the composed aggregate object.\n * @example\n *\n * var array = [\n * { 'dir': 'left', 'code': 97 },\n * { 'dir': 'right', 'code': 100 }\n * ];\n *\n * _.keyBy(array, function(o) {\n * return String.fromCharCode(o.code);\n * });\n * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }\n *\n * _.keyBy(array, 'dir');\n * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }\n */\n var keyBy = createAggregator(function(result, value, key) {\n baseAssignValue(result, key, value);\n });\n\n /**\n * Creates an array of values by running each element in `collection` thru\n * `iteratee`. The iteratee is invoked with three arguments:\n * (value, index|key, collection).\n *\n * Many lodash methods are guarded to work as iteratees for methods like\n * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.\n *\n * The guarded methods are:\n * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,\n * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,\n * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,\n * `template`, `trim`, `trimEnd`, `trimStart`, and `words`\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n * @example\n *\n * function square(n) {\n * return n * n;\n * }\n *\n * _.map([4, 8], square);\n * // => [16, 64]\n *\n * _.map({ 'a': 4, 'b': 8 }, square);\n * // => [16, 64] (iteration order is not guaranteed)\n *\n * var users = [\n * { 'user': 'barney' },\n * { 'user': 'fred' }\n * ];\n *\n * // The `_.property` iteratee shorthand.\n * _.map(users, 'user');\n * // => ['barney', 'fred']\n */\n function map(collection, iteratee) {\n var func = isArray(collection) ? arrayMap : baseMap;\n return func(collection, getIteratee(iteratee, 3));\n }\n\n /**\n * This method is like `_.sortBy` except that it allows specifying the sort\n * orders of the iteratees to sort by. If `orders` is unspecified, all values\n * are sorted in ascending order. Otherwise, specify an order of \"desc\" for\n * descending or \"asc\" for ascending sort order of corresponding values.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]\n * The iteratees to sort by.\n * @param {string[]} [orders] The sort orders of `iteratees`.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.\n * @returns {Array} Returns the new sorted array.\n * @example\n *\n * var users = [\n * { 'user': 'fred', 'age': 48 },\n * { 'user': 'barney', 'age': 34 },\n * { 'user': 'fred', 'age': 40 },\n * { 'user': 'barney', 'age': 36 }\n * ];\n *\n * // Sort by `user` in ascending order and by `age` in descending order.\n * _.orderBy(users, ['user', 'age'], ['asc', 'desc']);\n * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]\n */\n function orderBy(collection, iteratees, orders, guard) {\n if (collection == null) {\n return [];\n }\n if (!isArray(iteratees)) {\n iteratees = iteratees == null ? [] : [iteratees];\n }\n orders = guard ? undefined : orders;\n if (!isArray(orders)) {\n orders = orders == null ? [] : [orders];\n }\n return baseOrderBy(collection, iteratees, orders);\n }\n\n /**\n * Creates an array of elements split into two groups, the first of which\n * contains elements `predicate` returns truthy for, the second of which\n * contains elements `predicate` returns falsey for. The predicate is\n * invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the array of grouped elements.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'age': 36, 'active': false },\n * { 'user': 'fred', 'age': 40, 'active': true },\n * { 'user': 'pebbles', 'age': 1, 'active': false }\n * ];\n *\n * _.partition(users, function(o) { return o.active; });\n * // => objects for [['fred'], ['barney', 'pebbles']]\n *\n * // The `_.matches` iteratee shorthand.\n * _.partition(users, { 'age': 1, 'active': false });\n * // => objects for [['pebbles'], ['barney', 'fred']]\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.partition(users, ['active', false]);\n * // => objects for [['barney', 'pebbles'], ['fred']]\n *\n * // The `_.property` iteratee shorthand.\n * _.partition(users, 'active');\n * // => objects for [['fred'], ['barney', 'pebbles']]\n */\n var partition = createAggregator(function(result, value, key) {\n result[key ? 0 : 1].push(value);\n }, function() { return [[], []]; });\n\n /**\n * Reduces `collection` to a value which is the accumulated result of running\n * each element in `collection` thru `iteratee`, where each successive\n * invocation is supplied the return value of the previous. If `accumulator`\n * is not given, the first element of `collection` is used as the initial\n * value. The iteratee is invoked with four arguments:\n * (accumulator, value, index|key, collection).\n *\n * Many lodash methods are guarded to work as iteratees for methods like\n * `_.reduce`, `_.reduceRight`, and `_.transform`.\n *\n * The guarded methods are:\n * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,\n * and `sortBy`\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @param {*} [accumulator] The initial value.\n * @returns {*} Returns the accumulated value.\n * @see _.reduceRight\n * @example\n *\n * _.reduce([1, 2], function(sum, n) {\n * return sum + n;\n * }, 0);\n * // => 3\n *\n * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {\n * (result[value] || (result[value] = [])).push(key);\n * return result;\n * }, {});\n * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)\n */\n function reduce(collection, iteratee, accumulator) {\n var func = isArray(collection) ? arrayReduce : baseReduce,\n initAccum = arguments.length < 3;\n\n return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);\n }\n\n /**\n * This method is like `_.reduce` except that it iterates over elements of\n * `collection` from right to left.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @param {*} [accumulator] The initial value.\n * @returns {*} Returns the accumulated value.\n * @see _.reduce\n * @example\n *\n * var array = [[0, 1], [2, 3], [4, 5]];\n *\n * _.reduceRight(array, function(flattened, other) {\n * return flattened.concat(other);\n * }, []);\n * // => [4, 5, 2, 3, 0, 1]\n */\n function reduceRight(collection, iteratee, accumulator) {\n var func = isArray(collection) ? arrayReduceRight : baseReduce,\n initAccum = arguments.length < 3;\n\n return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);\n }\n\n /**\n * The opposite of `_.filter`; this method returns the elements of `collection`\n * that `predicate` does **not** return truthy for.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the new filtered array.\n * @see _.filter\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'age': 36, 'active': false },\n * { 'user': 'fred', 'age': 40, 'active': true }\n * ];\n *\n * _.reject(users, function(o) { return !o.active; });\n * // => objects for ['fred']\n *\n * // The `_.matches` iteratee shorthand.\n * _.reject(users, { 'age': 40, 'active': true });\n * // => objects for ['barney']\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.reject(users, ['active', false]);\n * // => objects for ['fred']\n *\n * // The `_.property` iteratee shorthand.\n * _.reject(users, 'active');\n * // => objects for ['barney']\n */\n function reject(collection, predicate) {\n var func = isArray(collection) ? arrayFilter : baseFilter;\n return func(collection, negate(getIteratee(predicate, 3)));\n }\n\n /**\n * Gets a random element from `collection`.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Collection\n * @param {Array|Object} collection The collection to sample.\n * @returns {*} Returns the random element.\n * @example\n *\n * _.sample([1, 2, 3, 4]);\n * // => 2\n */\n function sample(collection) {\n var func = isArray(collection) ? arraySample : baseSample;\n return func(collection);\n }\n\n /**\n * Gets `n` random elements at unique keys from `collection` up to the\n * size of `collection`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Collection\n * @param {Array|Object} collection The collection to sample.\n * @param {number} [n=1] The number of elements to sample.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Array} Returns the random elements.\n * @example\n *\n * _.sampleSize([1, 2, 3], 2);\n * // => [3, 1]\n *\n * _.sampleSize([1, 2, 3], 4);\n * // => [2, 3, 1]\n */\n function sampleSize(collection, n, guard) {\n if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) {\n n = 1;\n } else {\n n = toInteger(n);\n }\n var func = isArray(collection) ? arraySampleSize : baseSampleSize;\n return func(collection, n);\n }\n\n /**\n * Creates an array of shuffled values, using a version of the\n * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to shuffle.\n * @returns {Array} Returns the new shuffled array.\n * @example\n *\n * _.shuffle([1, 2, 3, 4]);\n * // => [4, 1, 3, 2]\n */\n function shuffle(collection) {\n var func = isArray(collection) ? arrayShuffle : baseShuffle;\n return func(collection);\n }\n\n /**\n * Gets the size of `collection` by returning its length for array-like\n * values or the number of own enumerable string keyed properties for objects.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object|string} collection The collection to inspect.\n * @returns {number} Returns the collection size.\n * @example\n *\n * _.size([1, 2, 3]);\n * // => 3\n *\n * _.size({ 'a': 1, 'b': 2 });\n * // => 2\n *\n * _.size('pebbles');\n * // => 7\n */\n function size(collection) {\n if (collection == null) {\n return 0;\n }\n if (isArrayLike(collection)) {\n return isString(collection) ? stringSize(collection) : collection.length;\n }\n var tag = getTag(collection);\n if (tag == mapTag || tag == setTag) {\n return collection.size;\n }\n return baseKeys(collection).length;\n }\n\n /**\n * Checks if `predicate` returns truthy for **any** element of `collection`.\n * Iteration is stopped once `predicate` returns truthy. The predicate is\n * invoked with three arguments: (value, index|key, collection).\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {boolean} Returns `true` if any element passes the predicate check,\n * else `false`.\n * @example\n *\n * _.some([null, 0, 'yes', false], Boolean);\n * // => true\n *\n * var users = [\n * { 'user': 'barney', 'active': true },\n * { 'user': 'fred', 'active': false }\n * ];\n *\n * // The `_.matches` iteratee shorthand.\n * _.some(users, { 'user': 'barney', 'active': false });\n * // => false\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.some(users, ['active', false]);\n * // => true\n *\n * // The `_.property` iteratee shorthand.\n * _.some(users, 'active');\n * // => true\n */\n function some(collection, predicate, guard) {\n var func = isArray(collection) ? arraySome : baseSome;\n if (guard && isIterateeCall(collection, predicate, guard)) {\n predicate = undefined;\n }\n return func(collection, getIteratee(predicate, 3));\n }\n\n /**\n * Creates an array of elements, sorted in ascending order by the results of\n * running each element in a collection thru each iteratee. This method\n * performs a stable sort, that is, it preserves the original sort order of\n * equal elements. The iteratees are invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Collection\n * @param {Array|Object} collection The collection to iterate over.\n * @param {...(Function|Function[])} [iteratees=[_.identity]]\n * The iteratees to sort by.\n * @returns {Array} Returns the new sorted array.\n * @example\n *\n * var users = [\n * { 'user': 'fred', 'age': 48 },\n * { 'user': 'barney', 'age': 36 },\n * { 'user': 'fred', 'age': 40 },\n * { 'user': 'barney', 'age': 34 }\n * ];\n *\n * _.sortBy(users, [function(o) { return o.user; }]);\n * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]\n *\n * _.sortBy(users, ['user', 'age']);\n * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]]\n */\n var sortBy = baseRest(function(collection, iteratees) {\n if (collection == null) {\n return [];\n }\n var length = iteratees.length;\n if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {\n iteratees = [];\n } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {\n iteratees = [iteratees[0]];\n }\n return baseOrderBy(collection, baseFlatten(iteratees, 1), []);\n });\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Gets the timestamp of the number of milliseconds that have elapsed since\n * the Unix epoch (1 January 1970 00:00:00 UTC).\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Date\n * @returns {number} Returns the timestamp.\n * @example\n *\n * _.defer(function(stamp) {\n * console.log(_.now() - stamp);\n * }, _.now());\n * // => Logs the number of milliseconds it took for the deferred invocation.\n */\n var now = ctxNow || function() {\n return root.Date.now();\n };\n\n /*------------------------------------------------------------------------*/\n\n /**\n * The opposite of `_.before`; this method creates a function that invokes\n * `func` once it's called `n` or more times.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {number} n The number of calls before `func` is invoked.\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new restricted function.\n * @example\n *\n * var saves = ['profile', 'settings'];\n *\n * var done = _.after(saves.length, function() {\n * console.log('done saving!');\n * });\n *\n * _.forEach(saves, function(type) {\n * asyncSave({ 'type': type, 'complete': done });\n * });\n * // => Logs 'done saving!' after the two async saves have completed.\n */\n function after(n, func) {\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n n = toInteger(n);\n return function() {\n if (--n < 1) {\n return func.apply(this, arguments);\n }\n };\n }\n\n /**\n * Creates a function that invokes `func`, with up to `n` arguments,\n * ignoring any additional arguments.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Function\n * @param {Function} func The function to cap arguments for.\n * @param {number} [n=func.length] The arity cap.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Function} Returns the new capped function.\n * @example\n *\n * _.map(['6', '8', '10'], _.ary(parseInt, 1));\n * // => [6, 8, 10]\n */\n function ary(func, n, guard) {\n n = guard ? undefined : n;\n n = (func && n == null) ? func.length : n;\n return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n);\n }\n\n /**\n * Creates a function that invokes `func`, with the `this` binding and arguments\n * of the created function, while it's called less than `n` times. Subsequent\n * calls to the created function return the result of the last `func` invocation.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Function\n * @param {number} n The number of calls at which `func` is no longer invoked.\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new restricted function.\n * @example\n *\n * jQuery(element).on('click', _.before(5, addContactToList));\n * // => Allows adding up to 4 contacts to the list.\n */\n function before(n, func) {\n var result;\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n n = toInteger(n);\n return function() {\n if (--n > 0) {\n result = func.apply(this, arguments);\n }\n if (n <= 1) {\n func = undefined;\n }\n return result;\n };\n }\n\n /**\n * Creates a function that invokes `func` with the `this` binding of `thisArg`\n * and `partials` prepended to the arguments it receives.\n *\n * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,\n * may be used as a placeholder for partially applied arguments.\n *\n * **Note:** Unlike native `Function#bind`, this method doesn't set the \"length\"\n * property of bound functions.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to bind.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {...*} [partials] The arguments to be partially applied.\n * @returns {Function} Returns the new bound function.\n * @example\n *\n * function greet(greeting, punctuation) {\n * return greeting + ' ' + this.user + punctuation;\n * }\n *\n * var object = { 'user': 'fred' };\n *\n * var bound = _.bind(greet, object, 'hi');\n * bound('!');\n * // => 'hi fred!'\n *\n * // Bound with placeholders.\n * var bound = _.bind(greet, object, _, '!');\n * bound('hi');\n * // => 'hi fred!'\n */\n var bind = baseRest(function(func, thisArg, partials) {\n var bitmask = WRAP_BIND_FLAG;\n if (partials.length) {\n var holders = replaceHolders(partials, getHolder(bind));\n bitmask |= WRAP_PARTIAL_FLAG;\n }\n return createWrap(func, bitmask, thisArg, partials, holders);\n });\n\n /**\n * Creates a function that invokes the method at `object[key]` with `partials`\n * prepended to the arguments it receives.\n *\n * This method differs from `_.bind` by allowing bound functions to reference\n * methods that may be redefined or don't yet exist. See\n * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)\n * for more details.\n *\n * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic\n * builds, may be used as a placeholder for partially applied arguments.\n *\n * @static\n * @memberOf _\n * @since 0.10.0\n * @category Function\n * @param {Object} object The object to invoke the method on.\n * @param {string} key The key of the method.\n * @param {...*} [partials] The arguments to be partially applied.\n * @returns {Function} Returns the new bound function.\n * @example\n *\n * var object = {\n * 'user': 'fred',\n * 'greet': function(greeting, punctuation) {\n * return greeting + ' ' + this.user + punctuation;\n * }\n * };\n *\n * var bound = _.bindKey(object, 'greet', 'hi');\n * bound('!');\n * // => 'hi fred!'\n *\n * object.greet = function(greeting, punctuation) {\n * return greeting + 'ya ' + this.user + punctuation;\n * };\n *\n * bound('!');\n * // => 'hiya fred!'\n *\n * // Bound with placeholders.\n * var bound = _.bindKey(object, 'greet', _, '!');\n * bound('hi');\n * // => 'hiya fred!'\n */\n var bindKey = baseRest(function(object, key, partials) {\n var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;\n if (partials.length) {\n var holders = replaceHolders(partials, getHolder(bindKey));\n bitmask |= WRAP_PARTIAL_FLAG;\n }\n return createWrap(key, bitmask, object, partials, holders);\n });\n\n /**\n * Creates a function that accepts arguments of `func` and either invokes\n * `func` returning its result, if at least `arity` number of arguments have\n * been provided, or returns a function that accepts the remaining `func`\n * arguments, and so on. The arity of `func` may be specified if `func.length`\n * is not sufficient.\n *\n * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,\n * may be used as a placeholder for provided arguments.\n *\n * **Note:** This method doesn't set the \"length\" property of curried functions.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Function\n * @param {Function} func The function to curry.\n * @param {number} [arity=func.length] The arity of `func`.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Function} Returns the new curried function.\n * @example\n *\n * var abc = function(a, b, c) {\n * return [a, b, c];\n * };\n *\n * var curried = _.curry(abc);\n *\n * curried(1)(2)(3);\n * // => [1, 2, 3]\n *\n * curried(1, 2)(3);\n * // => [1, 2, 3]\n *\n * curried(1, 2, 3);\n * // => [1, 2, 3]\n *\n * // Curried with placeholders.\n * curried(1)(_, 3)(2);\n * // => [1, 2, 3]\n */\n function curry(func, arity, guard) {\n arity = guard ? undefined : arity;\n var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity);\n result.placeholder = curry.placeholder;\n return result;\n }\n\n /**\n * This method is like `_.curry` except that arguments are applied to `func`\n * in the manner of `_.partialRight` instead of `_.partial`.\n *\n * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic\n * builds, may be used as a placeholder for provided arguments.\n *\n * **Note:** This method doesn't set the \"length\" property of curried functions.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Function\n * @param {Function} func The function to curry.\n * @param {number} [arity=func.length] The arity of `func`.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Function} Returns the new curried function.\n * @example\n *\n * var abc = function(a, b, c) {\n * return [a, b, c];\n * };\n *\n * var curried = _.curryRight(abc);\n *\n * curried(3)(2)(1);\n * // => [1, 2, 3]\n *\n * curried(2, 3)(1);\n * // => [1, 2, 3]\n *\n * curried(1, 2, 3);\n * // => [1, 2, 3]\n *\n * // Curried with placeholders.\n * curried(3)(1, _)(2);\n * // => [1, 2, 3]\n */\n function curryRight(func, arity, guard) {\n arity = guard ? undefined : arity;\n var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity);\n result.placeholder = curryRight.placeholder;\n return result;\n }\n\n /**\n * Creates a debounced function that delays invoking `func` until after `wait`\n * milliseconds have elapsed since the last time the debounced function was\n * invoked. The debounced function comes with a `cancel` method to cancel\n * delayed `func` invocations and a `flush` method to immediately invoke them.\n * Provide `options` to indicate whether `func` should be invoked on the\n * leading and/or trailing edge of the `wait` timeout. The `func` is invoked\n * with the last arguments provided to the debounced function. Subsequent\n * calls to the debounced function return the result of the last `func`\n * invocation.\n *\n * **Note:** If `leading` and `trailing` options are `true`, `func` is\n * invoked on the trailing edge of the timeout only if the debounced function\n * is invoked more than once during the `wait` timeout.\n *\n * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred\n * until to the next tick, similar to `setTimeout` with a timeout of `0`.\n *\n * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)\n * for details over the differences between `_.debounce` and `_.throttle`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to debounce.\n * @param {number} [wait=0] The number of milliseconds to delay.\n * @param {Object} [options={}] The options object.\n * @param {boolean} [options.leading=false]\n * Specify invoking on the leading edge of the timeout.\n * @param {number} [options.maxWait]\n * The maximum time `func` is allowed to be delayed before it's invoked.\n * @param {boolean} [options.trailing=true]\n * Specify invoking on the trailing edge of the timeout.\n * @returns {Function} Returns the new debounced function.\n * @example\n *\n * // Avoid costly calculations while the window size is in flux.\n * jQuery(window).on('resize', _.debounce(calculateLayout, 150));\n *\n * // Invoke `sendMail` when clicked, debouncing subsequent calls.\n * jQuery(element).on('click', _.debounce(sendMail, 300, {\n * 'leading': true,\n * 'trailing': false\n * }));\n *\n * // Ensure `batchLog` is invoked once after 1 second of debounced calls.\n * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });\n * var source = new EventSource('/stream');\n * jQuery(source).on('message', debounced);\n *\n * // Cancel the trailing debounced invocation.\n * jQuery(window).on('popstate', debounced.cancel);\n */\n function debounce(func, wait, options) {\n var lastArgs,\n lastThis,\n maxWait,\n result,\n timerId,\n lastCallTime,\n lastInvokeTime = 0,\n leading = false,\n maxing = false,\n trailing = true;\n\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n wait = toNumber(wait) || 0;\n if (isObject(options)) {\n leading = !!options.leading;\n maxing = 'maxWait' in options;\n maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;\n trailing = 'trailing' in options ? !!options.trailing : trailing;\n }\n\n function invokeFunc(time) {\n var args = lastArgs,\n thisArg = lastThis;\n\n lastArgs = lastThis = undefined;\n lastInvokeTime = time;\n result = func.apply(thisArg, args);\n return result;\n }\n\n function leadingEdge(time) {\n // Reset any `maxWait` timer.\n lastInvokeTime = time;\n // Start the timer for the trailing edge.\n timerId = setTimeout(timerExpired, wait);\n // Invoke the leading edge.\n return leading ? invokeFunc(time) : result;\n }\n\n function remainingWait(time) {\n var timeSinceLastCall = time - lastCallTime,\n timeSinceLastInvoke = time - lastInvokeTime,\n result = wait - timeSinceLastCall;\n\n return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;\n }\n\n function shouldInvoke(time) {\n var timeSinceLastCall = time - lastCallTime,\n timeSinceLastInvoke = time - lastInvokeTime;\n\n // Either this is the first call, activity has stopped and we're at the\n // trailing edge, the system time has gone backwards and we're treating\n // it as the trailing edge, or we've hit the `maxWait` limit.\n return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||\n (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));\n }\n\n function timerExpired() {\n var time = now();\n if (shouldInvoke(time)) {\n return trailingEdge(time);\n }\n // Restart the timer.\n timerId = setTimeout(timerExpired, remainingWait(time));\n }\n\n function trailingEdge(time) {\n timerId = undefined;\n\n // Only invoke if we have `lastArgs` which means `func` has been\n // debounced at least once.\n if (trailing && lastArgs) {\n return invokeFunc(time);\n }\n lastArgs = lastThis = undefined;\n return result;\n }\n\n function cancel() {\n if (timerId !== undefined) {\n clearTimeout(timerId);\n }\n lastInvokeTime = 0;\n lastArgs = lastCallTime = lastThis = timerId = undefined;\n }\n\n function flush() {\n return timerId === undefined ? result : trailingEdge(now());\n }\n\n function debounced() {\n var time = now(),\n isInvoking = shouldInvoke(time);\n\n lastArgs = arguments;\n lastThis = this;\n lastCallTime = time;\n\n if (isInvoking) {\n if (timerId === undefined) {\n return leadingEdge(lastCallTime);\n }\n if (maxing) {\n // Handle invocations in a tight loop.\n timerId = setTimeout(timerExpired, wait);\n return invokeFunc(lastCallTime);\n }\n }\n if (timerId === undefined) {\n timerId = setTimeout(timerExpired, wait);\n }\n return result;\n }\n debounced.cancel = cancel;\n debounced.flush = flush;\n return debounced;\n }\n\n /**\n * Defers invoking the `func` until the current call stack has cleared. Any\n * additional arguments are provided to `func` when it's invoked.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to defer.\n * @param {...*} [args] The arguments to invoke `func` with.\n * @returns {number} Returns the timer id.\n * @example\n *\n * _.defer(function(text) {\n * console.log(text);\n * }, 'deferred');\n * // => Logs 'deferred' after one millisecond.\n */\n var defer = baseRest(function(func, args) {\n return baseDelay(func, 1, args);\n });\n\n /**\n * Invokes `func` after `wait` milliseconds. Any additional arguments are\n * provided to `func` when it's invoked.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to delay.\n * @param {number} wait The number of milliseconds to delay invocation.\n * @param {...*} [args] The arguments to invoke `func` with.\n * @returns {number} Returns the timer id.\n * @example\n *\n * _.delay(function(text) {\n * console.log(text);\n * }, 1000, 'later');\n * // => Logs 'later' after one second.\n */\n var delay = baseRest(function(func, wait, args) {\n return baseDelay(func, toNumber(wait) || 0, args);\n });\n\n /**\n * Creates a function that invokes `func` with arguments reversed.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Function\n * @param {Function} func The function to flip arguments for.\n * @returns {Function} Returns the new flipped function.\n * @example\n *\n * var flipped = _.flip(function() {\n * return _.toArray(arguments);\n * });\n *\n * flipped('a', 'b', 'c', 'd');\n * // => ['d', 'c', 'b', 'a']\n */\n function flip(func) {\n return createWrap(func, WRAP_FLIP_FLAG);\n }\n\n /**\n * Creates a function that memoizes the result of `func`. If `resolver` is\n * provided, it determines the cache key for storing the result based on the\n * arguments provided to the memoized function. By default, the first argument\n * provided to the memoized function is used as the map cache key. The `func`\n * is invoked with the `this` binding of the memoized function.\n *\n * **Note:** The cache is exposed as the `cache` property on the memoized\n * function. Its creation may be customized by replacing the `_.memoize.Cache`\n * constructor with one whose instances implement the\n * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)\n * method interface of `clear`, `delete`, `get`, `has`, and `set`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to have its output memoized.\n * @param {Function} [resolver] The function to resolve the cache key.\n * @returns {Function} Returns the new memoized function.\n * @example\n *\n * var object = { 'a': 1, 'b': 2 };\n * var other = { 'c': 3, 'd': 4 };\n *\n * var values = _.memoize(_.values);\n * values(object);\n * // => [1, 2]\n *\n * values(other);\n * // => [3, 4]\n *\n * object.a = 2;\n * values(object);\n * // => [1, 2]\n *\n * // Modify the result cache.\n * values.cache.set(object, ['a', 'b']);\n * values(object);\n * // => ['a', 'b']\n *\n * // Replace `_.memoize.Cache`.\n * _.memoize.Cache = WeakMap;\n */\n function memoize(func, resolver) {\n if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n var memoized = function() {\n var args = arguments,\n key = resolver ? resolver.apply(this, args) : args[0],\n cache = memoized.cache;\n\n if (cache.has(key)) {\n return cache.get(key);\n }\n var result = func.apply(this, args);\n memoized.cache = cache.set(key, result) || cache;\n return result;\n };\n memoized.cache = new (memoize.Cache || MapCache);\n return memoized;\n }\n\n // Expose `MapCache`.\n memoize.Cache = MapCache;\n\n /**\n * Creates a function that negates the result of the predicate `func`. The\n * `func` predicate is invoked with the `this` binding and arguments of the\n * created function.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Function\n * @param {Function} predicate The predicate to negate.\n * @returns {Function} Returns the new negated function.\n * @example\n *\n * function isEven(n) {\n * return n % 2 == 0;\n * }\n *\n * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));\n * // => [1, 3, 5]\n */\n function negate(predicate) {\n if (typeof predicate != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n return function() {\n var args = arguments;\n switch (args.length) {\n case 0: return !predicate.call(this);\n case 1: return !predicate.call(this, args[0]);\n case 2: return !predicate.call(this, args[0], args[1]);\n case 3: return !predicate.call(this, args[0], args[1], args[2]);\n }\n return !predicate.apply(this, args);\n };\n }\n\n /**\n * Creates a function that is restricted to invoking `func` once. Repeat calls\n * to the function return the value of the first invocation. The `func` is\n * invoked with the `this` binding and arguments of the created function.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new restricted function.\n * @example\n *\n * var initialize = _.once(createApplication);\n * initialize();\n * initialize();\n * // => `createApplication` is invoked once\n */\n function once(func) {\n return before(2, func);\n }\n\n /**\n * Creates a function that invokes `func` with its arguments transformed.\n *\n * @static\n * @since 4.0.0\n * @memberOf _\n * @category Function\n * @param {Function} func The function to wrap.\n * @param {...(Function|Function[])} [transforms=[_.identity]]\n * The argument transforms.\n * @returns {Function} Returns the new function.\n * @example\n *\n * function doubled(n) {\n * return n * 2;\n * }\n *\n * function square(n) {\n * return n * n;\n * }\n *\n * var func = _.overArgs(function(x, y) {\n * return [x, y];\n * }, [square, doubled]);\n *\n * func(9, 3);\n * // => [81, 6]\n *\n * func(10, 5);\n * // => [100, 10]\n */\n var overArgs = castRest(function(func, transforms) {\n transforms = (transforms.length == 1 && isArray(transforms[0]))\n ? arrayMap(transforms[0], baseUnary(getIteratee()))\n : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));\n\n var funcsLength = transforms.length;\n return baseRest(function(args) {\n var index = -1,\n length = nativeMin(args.length, funcsLength);\n\n while (++index < length) {\n args[index] = transforms[index].call(this, args[index]);\n }\n return apply(func, this, args);\n });\n });\n\n /**\n * Creates a function that invokes `func` with `partials` prepended to the\n * arguments it receives. This method is like `_.bind` except it does **not**\n * alter the `this` binding.\n *\n * The `_.partial.placeholder` value, which defaults to `_` in monolithic\n * builds, may be used as a placeholder for partially applied arguments.\n *\n * **Note:** This method doesn't set the \"length\" property of partially\n * applied functions.\n *\n * @static\n * @memberOf _\n * @since 0.2.0\n * @category Function\n * @param {Function} func The function to partially apply arguments to.\n * @param {...*} [partials] The arguments to be partially applied.\n * @returns {Function} Returns the new partially applied function.\n * @example\n *\n * function greet(greeting, name) {\n * return greeting + ' ' + name;\n * }\n *\n * var sayHelloTo = _.partial(greet, 'hello');\n * sayHelloTo('fred');\n * // => 'hello fred'\n *\n * // Partially applied with placeholders.\n * var greetFred = _.partial(greet, _, 'fred');\n * greetFred('hi');\n * // => 'hi fred'\n */\n var partial = baseRest(function(func, partials) {\n var holders = replaceHolders(partials, getHolder(partial));\n return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders);\n });\n\n /**\n * This method is like `_.partial` except that partially applied arguments\n * are appended to the arguments it receives.\n *\n * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic\n * builds, may be used as a placeholder for partially applied arguments.\n *\n * **Note:** This method doesn't set the \"length\" property of partially\n * applied functions.\n *\n * @static\n * @memberOf _\n * @since 1.0.0\n * @category Function\n * @param {Function} func The function to partially apply arguments to.\n * @param {...*} [partials] The arguments to be partially applied.\n * @returns {Function} Returns the new partially applied function.\n * @example\n *\n * function greet(greeting, name) {\n * return greeting + ' ' + name;\n * }\n *\n * var greetFred = _.partialRight(greet, 'fred');\n * greetFred('hi');\n * // => 'hi fred'\n *\n * // Partially applied with placeholders.\n * var sayHelloTo = _.partialRight(greet, 'hello', _);\n * sayHelloTo('fred');\n * // => 'hello fred'\n */\n var partialRight = baseRest(function(func, partials) {\n var holders = replaceHolders(partials, getHolder(partialRight));\n return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders);\n });\n\n /**\n * Creates a function that invokes `func` with arguments arranged according\n * to the specified `indexes` where the argument value at the first index is\n * provided as the first argument, the argument value at the second index is\n * provided as the second argument, and so on.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Function\n * @param {Function} func The function to rearrange arguments for.\n * @param {...(number|number[])} indexes The arranged argument indexes.\n * @returns {Function} Returns the new function.\n * @example\n *\n * var rearged = _.rearg(function(a, b, c) {\n * return [a, b, c];\n * }, [2, 0, 1]);\n *\n * rearged('b', 'c', 'a')\n * // => ['a', 'b', 'c']\n */\n var rearg = flatRest(function(func, indexes) {\n return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes);\n });\n\n /**\n * Creates a function that invokes `func` with the `this` binding of the\n * created function and arguments from `start` and beyond provided as\n * an array.\n *\n * **Note:** This method is based on the\n * [rest parameter](https://mdn.io/rest_parameters).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Function\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @returns {Function} Returns the new function.\n * @example\n *\n * var say = _.rest(function(what, names) {\n * return what + ' ' + _.initial(names).join(', ') +\n * (_.size(names) > 1 ? ', & ' : '') + _.last(names);\n * });\n *\n * say('hello', 'fred', 'barney', 'pebbles');\n * // => 'hello fred, barney, & pebbles'\n */\n function rest(func, start) {\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n start = start === undefined ? start : toInteger(start);\n return baseRest(func, start);\n }\n\n /**\n * Creates a function that invokes `func` with the `this` binding of the\n * create function and an array of arguments much like\n * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply).\n *\n * **Note:** This method is based on the\n * [spread operator](https://mdn.io/spread_operator).\n *\n * @static\n * @memberOf _\n * @since 3.2.0\n * @category Function\n * @param {Function} func The function to spread arguments over.\n * @param {number} [start=0] The start position of the spread.\n * @returns {Function} Returns the new function.\n * @example\n *\n * var say = _.spread(function(who, what) {\n * return who + ' says ' + what;\n * });\n *\n * say(['fred', 'hello']);\n * // => 'fred says hello'\n *\n * var numbers = Promise.all([\n * Promise.resolve(40),\n * Promise.resolve(36)\n * ]);\n *\n * numbers.then(_.spread(function(x, y) {\n * return x + y;\n * }));\n * // => a Promise of 76\n */\n function spread(func, start) {\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n start = start == null ? 0 : nativeMax(toInteger(start), 0);\n return baseRest(function(args) {\n var array = args[start],\n otherArgs = castSlice(args, 0, start);\n\n if (array) {\n arrayPush(otherArgs, array);\n }\n return apply(func, this, otherArgs);\n });\n }\n\n /**\n * Creates a throttled function that only invokes `func` at most once per\n * every `wait` milliseconds. The throttled function comes with a `cancel`\n * method to cancel delayed `func` invocations and a `flush` method to\n * immediately invoke them. Provide `options` to indicate whether `func`\n * should be invoked on the leading and/or trailing edge of the `wait`\n * timeout. The `func` is invoked with the last arguments provided to the\n * throttled function. Subsequent calls to the throttled function return the\n * result of the last `func` invocation.\n *\n * **Note:** If `leading` and `trailing` options are `true`, `func` is\n * invoked on the trailing edge of the timeout only if the throttled function\n * is invoked more than once during the `wait` timeout.\n *\n * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred\n * until to the next tick, similar to `setTimeout` with a timeout of `0`.\n *\n * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)\n * for details over the differences between `_.throttle` and `_.debounce`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to throttle.\n * @param {number} [wait=0] The number of milliseconds to throttle invocations to.\n * @param {Object} [options={}] The options object.\n * @param {boolean} [options.leading=true]\n * Specify invoking on the leading edge of the timeout.\n * @param {boolean} [options.trailing=true]\n * Specify invoking on the trailing edge of the timeout.\n * @returns {Function} Returns the new throttled function.\n * @example\n *\n * // Avoid excessively updating the position while scrolling.\n * jQuery(window).on('scroll', _.throttle(updatePosition, 100));\n *\n * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.\n * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });\n * jQuery(element).on('click', throttled);\n *\n * // Cancel the trailing throttled invocation.\n * jQuery(window).on('popstate', throttled.cancel);\n */\n function throttle(func, wait, options) {\n var leading = true,\n trailing = true;\n\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n if (isObject(options)) {\n leading = 'leading' in options ? !!options.leading : leading;\n trailing = 'trailing' in options ? !!options.trailing : trailing;\n }\n return debounce(func, wait, {\n 'leading': leading,\n 'maxWait': wait,\n 'trailing': trailing\n });\n }\n\n /**\n * Creates a function that accepts up to one argument, ignoring any\n * additional arguments.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Function\n * @param {Function} func The function to cap arguments for.\n * @returns {Function} Returns the new capped function.\n * @example\n *\n * _.map(['6', '8', '10'], _.unary(parseInt));\n * // => [6, 8, 10]\n */\n function unary(func) {\n return ary(func, 1);\n }\n\n /**\n * Creates a function that provides `value` to `wrapper` as its first\n * argument. Any additional arguments provided to the function are appended\n * to those provided to the `wrapper`. The wrapper is invoked with the `this`\n * binding of the created function.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {*} value The value to wrap.\n * @param {Function} [wrapper=identity] The wrapper function.\n * @returns {Function} Returns the new function.\n * @example\n *\n * var p = _.wrap(_.escape, function(func, text) {\n * return '<p>' + func(text) + '</p>';\n * });\n *\n * p('fred, barney, & pebbles');\n * // => '<p>fred, barney, & pebbles</p>'\n */\n function wrap(value, wrapper) {\n return partial(castFunction(wrapper), value);\n }\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Casts `value` as an array if it's not one.\n *\n * @static\n * @memberOf _\n * @since 4.4.0\n * @category Lang\n * @param {*} value The value to inspect.\n * @returns {Array} Returns the cast array.\n * @example\n *\n * _.castArray(1);\n * // => [1]\n *\n * _.castArray({ 'a': 1 });\n * // => [{ 'a': 1 }]\n *\n * _.castArray('abc');\n * // => ['abc']\n *\n * _.castArray(null);\n * // => [null]\n *\n * _.castArray(undefined);\n * // => [undefined]\n *\n * _.castArray();\n * // => []\n *\n * var array = [1, 2, 3];\n * console.log(_.castArray(array) === array);\n * // => true\n */\n function castArray() {\n if (!arguments.length) {\n return [];\n }\n var value = arguments[0];\n return isArray(value) ? value : [value];\n }\n\n /**\n * Creates a shallow clone of `value`.\n *\n * **Note:** This method is loosely based on the\n * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)\n * and supports cloning arrays, array buffers, booleans, date objects, maps,\n * numbers, `Object` objects, regexes, sets, strings, symbols, and typed\n * arrays. The own enumerable properties of `arguments` objects are cloned\n * as plain objects. An empty object is returned for uncloneable values such\n * as error objects, functions, DOM nodes, and WeakMaps.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to clone.\n * @returns {*} Returns the cloned value.\n * @see _.cloneDeep\n * @example\n *\n * var objects = [{ 'a': 1 }, { 'b': 2 }];\n *\n * var shallow = _.clone(objects);\n * console.log(shallow[0] === objects[0]);\n * // => true\n */\n function clone(value) {\n return baseClone(value, CLONE_SYMBOLS_FLAG);\n }\n\n /**\n * This method is like `_.clone` except that it accepts `customizer` which\n * is invoked to produce the cloned value. If `customizer` returns `undefined`,\n * cloning is handled by the method instead. The `customizer` is invoked with\n * up to four arguments; (value [, index|key, object, stack]).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to clone.\n * @param {Function} [customizer] The function to customize cloning.\n * @returns {*} Returns the cloned value.\n * @see _.cloneDeepWith\n * @example\n *\n * function customizer(value) {\n * if (_.isElement(value)) {\n * return value.cloneNode(false);\n * }\n * }\n *\n * var el = _.cloneWith(document.body, customizer);\n *\n * console.log(el === document.body);\n * // => false\n * console.log(el.nodeName);\n * // => 'BODY'\n * console.log(el.childNodes.length);\n * // => 0\n */\n function cloneWith(value, customizer) {\n customizer = typeof customizer == 'function' ? customizer : undefined;\n return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);\n }\n\n /**\n * This method is like `_.clone` except that it recursively clones `value`.\n *\n * @static\n * @memberOf _\n * @since 1.0.0\n * @category Lang\n * @param {*} value The value to recursively clone.\n * @returns {*} Returns the deep cloned value.\n * @see _.clone\n * @example\n *\n * var objects = [{ 'a': 1 }, { 'b': 2 }];\n *\n * var deep = _.cloneDeep(objects);\n * console.log(deep[0] === objects[0]);\n * // => false\n */\n function cloneDeep(value) {\n return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);\n }\n\n /**\n * This method is like `_.cloneWith` except that it recursively clones `value`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to recursively clone.\n * @param {Function} [customizer] The function to customize cloning.\n * @returns {*} Returns the deep cloned value.\n * @see _.cloneWith\n * @example\n *\n * function customizer(value) {\n * if (_.isElement(value)) {\n * return value.cloneNode(true);\n * }\n * }\n *\n * var el = _.cloneDeepWith(document.body, customizer);\n *\n * console.log(el === document.body);\n * // => false\n * console.log(el.nodeName);\n * // => 'BODY'\n * console.log(el.childNodes.length);\n * // => 20\n */\n function cloneDeepWith(value, customizer) {\n customizer = typeof customizer == 'function' ? customizer : undefined;\n return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);\n }\n\n /**\n * Checks if `object` conforms to `source` by invoking the predicate\n * properties of `source` with the corresponding property values of `object`.\n *\n * **Note:** This method is equivalent to `_.conforms` when `source` is\n * partially applied.\n *\n * @static\n * @memberOf _\n * @since 4.14.0\n * @category Lang\n * @param {Object} object The object to inspect.\n * @param {Object} source The object of property predicates to conform to.\n * @returns {boolean} Returns `true` if `object` conforms, else `false`.\n * @example\n *\n * var object = { 'a': 1, 'b': 2 };\n *\n * _.conformsTo(object, { 'b': function(n) { return n > 1; } });\n * // => true\n *\n * _.conformsTo(object, { 'b': function(n) { return n > 2; } });\n * // => false\n */\n function conformsTo(object, source) {\n return source == null || baseConformsTo(object, source, keys(source));\n }\n\n /**\n * Performs a\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * comparison between two values to determine if they are equivalent.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.eq(object, object);\n * // => true\n *\n * _.eq(object, other);\n * // => false\n *\n * _.eq('a', 'a');\n * // => true\n *\n * _.eq('a', Object('a'));\n * // => false\n *\n * _.eq(NaN, NaN);\n * // => true\n */\n function eq(value, other) {\n return value === other || (value !== value && other !== other);\n }\n\n /**\n * Checks if `value` is greater than `other`.\n *\n * @static\n * @memberOf _\n * @since 3.9.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if `value` is greater than `other`,\n * else `false`.\n * @see _.lt\n * @example\n *\n * _.gt(3, 1);\n * // => true\n *\n * _.gt(3, 3);\n * // => false\n *\n * _.gt(1, 3);\n * // => false\n */\n var gt = createRelationalOperation(baseGt);\n\n /**\n * Checks if `value` is greater than or equal to `other`.\n *\n * @static\n * @memberOf _\n * @since 3.9.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if `value` is greater than or equal to\n * `other`, else `false`.\n * @see _.lte\n * @example\n *\n * _.gte(3, 1);\n * // => true\n *\n * _.gte(3, 3);\n * // => true\n *\n * _.gte(1, 3);\n * // => false\n */\n var gte = createRelationalOperation(function(value, other) {\n return value >= other;\n });\n\n /**\n * Checks if `value` is likely an `arguments` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n * else `false`.\n * @example\n *\n * _.isArguments(function() { return arguments; }());\n * // => true\n *\n * _.isArguments([1, 2, 3]);\n * // => false\n */\n var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {\n return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&\n !propertyIsEnumerable.call(value, 'callee');\n };\n\n /**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\n var isArray = Array.isArray;\n\n /**\n * Checks if `value` is classified as an `ArrayBuffer` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.\n * @example\n *\n * _.isArrayBuffer(new ArrayBuffer(2));\n * // => true\n *\n * _.isArrayBuffer(new Array(2));\n * // => false\n */\n var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;\n\n /**\n * Checks if `value` is array-like. A value is considered array-like if it's\n * not a function and has a `value.length` that's an integer greater than or\n * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n * @example\n *\n * _.isArrayLike([1, 2, 3]);\n * // => true\n *\n * _.isArrayLike(document.body.children);\n * // => true\n *\n * _.isArrayLike('abc');\n * // => true\n *\n * _.isArrayLike(_.noop);\n * // => false\n */\n function isArrayLike(value) {\n return value != null && isLength(value.length) && !isFunction(value);\n }\n\n /**\n * This method is like `_.isArrayLike` except that it also checks if `value`\n * is an object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array-like object,\n * else `false`.\n * @example\n *\n * _.isArrayLikeObject([1, 2, 3]);\n * // => true\n *\n * _.isArrayLikeObject(document.body.children);\n * // => true\n *\n * _.isArrayLikeObject('abc');\n * // => false\n *\n * _.isArrayLikeObject(_.noop);\n * // => false\n */\n function isArrayLikeObject(value) {\n return isObjectLike(value) && isArrayLike(value);\n }\n\n /**\n * Checks if `value` is classified as a boolean primitive or object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a boolean, else `false`.\n * @example\n *\n * _.isBoolean(false);\n * // => true\n *\n * _.isBoolean(null);\n * // => false\n */\n function isBoolean(value) {\n return value === true || value === false ||\n (isObjectLike(value) && baseGetTag(value) == boolTag);\n }\n\n /**\n * Checks if `value` is a buffer.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.\n * @example\n *\n * _.isBuffer(new Buffer(2));\n * // => true\n *\n * _.isBuffer(new Uint8Array(2));\n * // => false\n */\n var isBuffer = nativeIsBuffer || stubFalse;\n\n /**\n * Checks if `value` is classified as a `Date` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a date object, else `false`.\n * @example\n *\n * _.isDate(new Date);\n * // => true\n *\n * _.isDate('Mon April 23 2012');\n * // => false\n */\n var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;\n\n /**\n * Checks if `value` is likely a DOM element.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.\n * @example\n *\n * _.isElement(document.body);\n * // => true\n *\n * _.isElement('<body>');\n * // => false\n */\n function isElement(value) {\n return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);\n }\n\n /**\n * Checks if `value` is an empty object, collection, map, or set.\n *\n * Objects are considered empty if they have no own enumerable string keyed\n * properties.\n *\n * Array-like values such as `arguments` objects, arrays, buffers, strings, or\n * jQuery-like collections are considered empty if they have a `length` of `0`.\n * Similarly, maps and sets are considered empty if they have a `size` of `0`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is empty, else `false`.\n * @example\n *\n * _.isEmpty(null);\n * // => true\n *\n * _.isEmpty(true);\n * // => true\n *\n * _.isEmpty(1);\n * // => true\n *\n * _.isEmpty([1, 2, 3]);\n * // => false\n *\n * _.isEmpty({ 'a': 1 });\n * // => false\n */\n function isEmpty(value) {\n if (value == null) {\n return true;\n }\n if (isArrayLike(value) &&\n (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||\n isBuffer(value) || isTypedArray(value) || isArguments(value))) {\n return !value.length;\n }\n var tag = getTag(value);\n if (tag == mapTag || tag == setTag) {\n return !value.size;\n }\n if (isPrototype(value)) {\n return !baseKeys(value).length;\n }\n for (var key in value) {\n if (hasOwnProperty.call(value, key)) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Performs a deep comparison between two values to determine if they are\n * equivalent.\n *\n * **Note:** This method supports comparing arrays, array buffers, booleans,\n * date objects, error objects, maps, numbers, `Object` objects, regexes,\n * sets, strings, symbols, and typed arrays. `Object` objects are compared\n * by their own, not inherited, enumerable properties. Functions and DOM\n * nodes are compared by strict equality, i.e. `===`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.isEqual(object, other);\n * // => true\n *\n * object === other;\n * // => false\n */\n function isEqual(value, other) {\n return baseIsEqual(value, other);\n }\n\n /**\n * This method is like `_.isEqual` except that it accepts `customizer` which\n * is invoked to compare values. If `customizer` returns `undefined`, comparisons\n * are handled by the method instead. The `customizer` is invoked with up to\n * six arguments: (objValue, othValue [, index|key, object, other, stack]).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @param {Function} [customizer] The function to customize comparisons.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * function isGreeting(value) {\n * return /^h(?:i|ello)$/.test(value);\n * }\n *\n * function customizer(objValue, othValue) {\n * if (isGreeting(objValue) && isGreeting(othValue)) {\n * return true;\n * }\n * }\n *\n * var array = ['hello', 'goodbye'];\n * var other = ['hi', 'goodbye'];\n *\n * _.isEqualWith(array, other, customizer);\n * // => true\n */\n function isEqualWith(value, other, customizer) {\n customizer = typeof customizer == 'function' ? customizer : undefined;\n var result = customizer ? customizer(value, other) : undefined;\n return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result;\n }\n\n /**\n * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,\n * `SyntaxError`, `TypeError`, or `URIError` object.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an error object, else `false`.\n * @example\n *\n * _.isError(new Error);\n * // => true\n *\n * _.isError(Error);\n * // => false\n */\n function isError(value) {\n if (!isObjectLike(value)) {\n return false;\n }\n var tag = baseGetTag(value);\n return tag == errorTag || tag == domExcTag ||\n (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value));\n }\n\n /**\n * Checks if `value` is a finite primitive number.\n *\n * **Note:** This method is based on\n * [`Number.isFinite`](https://mdn.io/Number/isFinite).\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.\n * @example\n *\n * _.isFinite(3);\n * // => true\n *\n * _.isFinite(Number.MIN_VALUE);\n * // => true\n *\n * _.isFinite(Infinity);\n * // => false\n *\n * _.isFinite('3');\n * // => false\n */\n function isFinite(value) {\n return typeof value == 'number' && nativeIsFinite(value);\n }\n\n /**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\n function isFunction(value) {\n if (!isObject(value)) {\n return false;\n }\n // The use of `Object#toString` avoids issues with the `typeof` operator\n // in Safari 9 which returns 'object' for typed arrays and other constructors.\n var tag = baseGetTag(value);\n return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;\n }\n\n /**\n * Checks if `value` is an integer.\n *\n * **Note:** This method is based on\n * [`Number.isInteger`](https://mdn.io/Number/isInteger).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an integer, else `false`.\n * @example\n *\n * _.isInteger(3);\n * // => true\n *\n * _.isInteger(Number.MIN_VALUE);\n * // => false\n *\n * _.isInteger(Infinity);\n * // => false\n *\n * _.isInteger('3');\n * // => false\n */\n function isInteger(value) {\n return typeof value == 'number' && value == toInteger(value);\n }\n\n /**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This method is loosely based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n * @example\n *\n * _.isLength(3);\n * // => true\n *\n * _.isLength(Number.MIN_VALUE);\n * // => false\n *\n * _.isLength(Infinity);\n * // => false\n *\n * _.isLength('3');\n * // => false\n */\n function isLength(value) {\n return typeof value == 'number' &&\n value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n }\n\n /**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\n function isObject(value) {\n var type = typeof value;\n return value != null && (type == 'object' || type == 'function');\n }\n\n /**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\n function isObjectLike(value) {\n return value != null && typeof value == 'object';\n }\n\n /**\n * Checks if `value` is classified as a `Map` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a map, else `false`.\n * @example\n *\n * _.isMap(new Map);\n * // => true\n *\n * _.isMap(new WeakMap);\n * // => false\n */\n var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;\n\n /**\n * Performs a partial deep comparison between `object` and `source` to\n * determine if `object` contains equivalent property values.\n *\n * **Note:** This method is equivalent to `_.matches` when `source` is\n * partially applied.\n *\n * Partial comparisons will match empty array and empty object `source`\n * values against any array or object value, respectively. See `_.isEqual`\n * for a list of supported value comparisons.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {Object} object The object to inspect.\n * @param {Object} source The object of property values to match.\n * @returns {boolean} Returns `true` if `object` is a match, else `false`.\n * @example\n *\n * var object = { 'a': 1, 'b': 2 };\n *\n * _.isMatch(object, { 'b': 2 });\n * // => true\n *\n * _.isMatch(object, { 'b': 1 });\n * // => false\n */\n function isMatch(object, source) {\n return object === source || baseIsMatch(object, source, getMatchData(source));\n }\n\n /**\n * This method is like `_.isMatch` except that it accepts `customizer` which\n * is invoked to compare values. If `customizer` returns `undefined`, comparisons\n * are handled by the method instead. The `customizer` is invoked with five\n * arguments: (objValue, srcValue, index|key, object, source).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {Object} object The object to inspect.\n * @param {Object} source The object of property values to match.\n * @param {Function} [customizer] The function to customize comparisons.\n * @returns {boolean} Returns `true` if `object` is a match, else `false`.\n * @example\n *\n * function isGreeting(value) {\n * return /^h(?:i|ello)$/.test(value);\n * }\n *\n * function customizer(objValue, srcValue) {\n * if (isGreeting(objValue) && isGreeting(srcValue)) {\n * return true;\n * }\n * }\n *\n * var object = { 'greeting': 'hello' };\n * var source = { 'greeting': 'hi' };\n *\n * _.isMatchWith(object, source, customizer);\n * // => true\n */\n function isMatchWith(object, source, customizer) {\n customizer = typeof customizer == 'function' ? customizer : undefined;\n return baseIsMatch(object, source, getMatchData(source), customizer);\n }\n\n /**\n * Checks if `value` is `NaN`.\n *\n * **Note:** This method is based on\n * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as\n * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for\n * `undefined` and other non-number values.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.\n * @example\n *\n * _.isNaN(NaN);\n * // => true\n *\n * _.isNaN(new Number(NaN));\n * // => true\n *\n * isNaN(undefined);\n * // => true\n *\n * _.isNaN(undefined);\n * // => false\n */\n function isNaN(value) {\n // An `NaN` primitive is the only value that is not equal to itself.\n // Perform the `toStringTag` check first to avoid errors with some\n // ActiveX objects in IE.\n return isNumber(value) && value != +value;\n }\n\n /**\n * Checks if `value` is a pristine native function.\n *\n * **Note:** This method can't reliably detect native functions in the presence\n * of the core-js package because core-js circumvents this kind of detection.\n * Despite multiple requests, the core-js maintainer has made it clear: any\n * attempt to fix the detection will be obstructed. As a result, we're left\n * with little choice but to throw an error. Unfortunately, this also affects\n * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill),\n * which rely on core-js.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function,\n * else `false`.\n * @example\n *\n * _.isNative(Array.prototype.push);\n * // => true\n *\n * _.isNative(_);\n * // => false\n */\n function isNative(value) {\n if (isMaskable(value)) {\n throw new Error(CORE_ERROR_TEXT);\n }\n return baseIsNative(value);\n }\n\n /**\n * Checks if `value` is `null`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `null`, else `false`.\n * @example\n *\n * _.isNull(null);\n * // => true\n *\n * _.isNull(void 0);\n * // => false\n */\n function isNull(value) {\n return value === null;\n }\n\n /**\n * Checks if `value` is `null` or `undefined`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is nullish, else `false`.\n * @example\n *\n * _.isNil(null);\n * // => true\n *\n * _.isNil(void 0);\n * // => true\n *\n * _.isNil(NaN);\n * // => false\n */\n function isNil(value) {\n return value == null;\n }\n\n /**\n * Checks if `value` is classified as a `Number` primitive or object.\n *\n * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are\n * classified as numbers, use the `_.isFinite` method.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a number, else `false`.\n * @example\n *\n * _.isNumber(3);\n * // => true\n *\n * _.isNumber(Number.MIN_VALUE);\n * // => true\n *\n * _.isNumber(Infinity);\n * // => true\n *\n * _.isNumber('3');\n * // => false\n */\n function isNumber(value) {\n return typeof value == 'number' ||\n (isObjectLike(value) && baseGetTag(value) == numberTag);\n }\n\n /**\n * Checks if `value` is a plain object, that is, an object created by the\n * `Object` constructor or one with a `[[Prototype]]` of `null`.\n *\n * @static\n * @memberOf _\n * @since 0.8.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * }\n *\n * _.isPlainObject(new Foo);\n * // => false\n *\n * _.isPlainObject([1, 2, 3]);\n * // => false\n *\n * _.isPlainObject({ 'x': 0, 'y': 0 });\n * // => true\n *\n * _.isPlainObject(Object.create(null));\n * // => true\n */\n function isPlainObject(value) {\n if (!isObjectLike(value) || baseGetTag(value) != objectTag) {\n return false;\n }\n var proto = getPrototype(value);\n if (proto === null) {\n return true;\n }\n var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;\n return typeof Ctor == 'function' && Ctor instanceof Ctor &&\n funcToString.call(Ctor) == objectCtorString;\n }\n\n /**\n * Checks if `value` is classified as a `RegExp` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.\n * @example\n *\n * _.isRegExp(/abc/);\n * // => true\n *\n * _.isRegExp('/abc/');\n * // => false\n */\n var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;\n\n /**\n * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754\n * double precision number which isn't the result of a rounded unsafe integer.\n *\n * **Note:** This method is based on\n * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.\n * @example\n *\n * _.isSafeInteger(3);\n * // => true\n *\n * _.isSafeInteger(Number.MIN_VALUE);\n * // => false\n *\n * _.isSafeInteger(Infinity);\n * // => false\n *\n * _.isSafeInteger('3');\n * // => false\n */\n function isSafeInteger(value) {\n return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;\n }\n\n /**\n * Checks if `value` is classified as a `Set` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a set, else `false`.\n * @example\n *\n * _.isSet(new Set);\n * // => true\n *\n * _.isSet(new WeakSet);\n * // => false\n */\n var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;\n\n /**\n * Checks if `value` is classified as a `String` primitive or object.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a string, else `false`.\n * @example\n *\n * _.isString('abc');\n * // => true\n *\n * _.isString(1);\n * // => false\n */\n function isString(value) {\n return typeof value == 'string' ||\n (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);\n }\n\n /**\n * Checks if `value` is classified as a `Symbol` primitive or object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.\n * @example\n *\n * _.isSymbol(Symbol.iterator);\n * // => true\n *\n * _.isSymbol('abc');\n * // => false\n */\n function isSymbol(value) {\n return typeof value == 'symbol' ||\n (isObjectLike(value) && baseGetTag(value) == symbolTag);\n }\n\n /**\n * Checks if `value` is classified as a typed array.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n * @example\n *\n * _.isTypedArray(new Uint8Array);\n * // => true\n *\n * _.isTypedArray([]);\n * // => false\n */\n var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;\n\n /**\n * Checks if `value` is `undefined`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.\n * @example\n *\n * _.isUndefined(void 0);\n * // => true\n *\n * _.isUndefined(null);\n * // => false\n */\n function isUndefined(value) {\n return value === undefined;\n }\n\n /**\n * Checks if `value` is classified as a `WeakMap` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a weak map, else `false`.\n * @example\n *\n * _.isWeakMap(new WeakMap);\n * // => true\n *\n * _.isWeakMap(new Map);\n * // => false\n */\n function isWeakMap(value) {\n return isObjectLike(value) && getTag(value) == weakMapTag;\n }\n\n /**\n * Checks if `value` is classified as a `WeakSet` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a weak set, else `false`.\n * @example\n *\n * _.isWeakSet(new WeakSet);\n * // => true\n *\n * _.isWeakSet(new Set);\n * // => false\n */\n function isWeakSet(value) {\n return isObjectLike(value) && baseGetTag(value) == weakSetTag;\n }\n\n /**\n * Checks if `value` is less than `other`.\n *\n * @static\n * @memberOf _\n * @since 3.9.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if `value` is less than `other`,\n * else `false`.\n * @see _.gt\n * @example\n *\n * _.lt(1, 3);\n * // => true\n *\n * _.lt(3, 3);\n * // => false\n *\n * _.lt(3, 1);\n * // => false\n */\n var lt = createRelationalOperation(baseLt);\n\n /**\n * Checks if `value` is less than or equal to `other`.\n *\n * @static\n * @memberOf _\n * @since 3.9.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if `value` is less than or equal to\n * `other`, else `false`.\n * @see _.gte\n * @example\n *\n * _.lte(1, 3);\n * // => true\n *\n * _.lte(3, 3);\n * // => true\n *\n * _.lte(3, 1);\n * // => false\n */\n var lte = createRelationalOperation(function(value, other) {\n return value <= other;\n });\n\n /**\n * Converts `value` to an array.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {Array} Returns the converted array.\n * @example\n *\n * _.toArray({ 'a': 1, 'b': 2 });\n * // => [1, 2]\n *\n * _.toArray('abc');\n * // => ['a', 'b', 'c']\n *\n * _.toArray(1);\n * // => []\n *\n * _.toArray(null);\n * // => []\n */\n function toArray(value) {\n if (!value) {\n return [];\n }\n if (isArrayLike(value)) {\n return isString(value) ? stringToArray(value) : copyArray(value);\n }\n if (symIterator && value[symIterator]) {\n return iteratorToArray(value[symIterator]());\n }\n var tag = getTag(value),\n func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);\n\n return func(value);\n }\n\n /**\n * Converts `value` to a finite number.\n *\n * @static\n * @memberOf _\n * @since 4.12.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {number} Returns the converted number.\n * @example\n *\n * _.toFinite(3.2);\n * // => 3.2\n *\n * _.toFinite(Number.MIN_VALUE);\n * // => 5e-324\n *\n * _.toFinite(Infinity);\n * // => 1.7976931348623157e+308\n *\n * _.toFinite('3.2');\n * // => 3.2\n */\n function toFinite(value) {\n if (!value) {\n return value === 0 ? value : 0;\n }\n value = toNumber(value);\n if (value === INFINITY || value === -INFINITY) {\n var sign = (value < 0 ? -1 : 1);\n return sign * MAX_INTEGER;\n }\n return value === value ? value : 0;\n }\n\n /**\n * Converts `value` to an integer.\n *\n * **Note:** This method is loosely based on\n * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {number} Returns the converted integer.\n * @example\n *\n * _.toInteger(3.2);\n * // => 3\n *\n * _.toInteger(Number.MIN_VALUE);\n * // => 0\n *\n * _.toInteger(Infinity);\n * // => 1.7976931348623157e+308\n *\n * _.toInteger('3.2');\n * // => 3\n */\n function toInteger(value) {\n var result = toFinite(value),\n remainder = result % 1;\n\n return result === result ? (remainder ? result - remainder : result) : 0;\n }\n\n /**\n * Converts `value` to an integer suitable for use as the length of an\n * array-like object.\n *\n * **Note:** This method is based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {number} Returns the converted integer.\n * @example\n *\n * _.toLength(3.2);\n * // => 3\n *\n * _.toLength(Number.MIN_VALUE);\n * // => 0\n *\n * _.toLength(Infinity);\n * // => 4294967295\n *\n * _.toLength('3.2');\n * // => 3\n */\n function toLength(value) {\n return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;\n }\n\n /**\n * Converts `value` to a number.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to process.\n * @returns {number} Returns the number.\n * @example\n *\n * _.toNumber(3.2);\n * // => 3.2\n *\n * _.toNumber(Number.MIN_VALUE);\n * // => 5e-324\n *\n * _.toNumber(Infinity);\n * // => Infinity\n *\n * _.toNumber('3.2');\n * // => 3.2\n */\n function toNumber(value) {\n if (typeof value == 'number') {\n return value;\n }\n if (isSymbol(value)) {\n return NAN;\n }\n if (isObject(value)) {\n var other = typeof value.valueOf == 'function' ? value.valueOf() : value;\n value = isObject(other) ? (other + '') : other;\n }\n if (typeof value != 'string') {\n return value === 0 ? value : +value;\n }\n value = value.replace(reTrim, '');\n var isBinary = reIsBinary.test(value);\n return (isBinary || reIsOctal.test(value))\n ? freeParseInt(value.slice(2), isBinary ? 2 : 8)\n : (reIsBadHex.test(value) ? NAN : +value);\n }\n\n /**\n * Converts `value` to a plain object flattening inherited enumerable string\n * keyed properties of `value` to own properties of the plain object.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {Object} Returns the converted plain object.\n * @example\n *\n * function Foo() {\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.assign({ 'a': 1 }, new Foo);\n * // => { 'a': 1, 'b': 2 }\n *\n * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));\n * // => { 'a': 1, 'b': 2, 'c': 3 }\n */\n function toPlainObject(value) {\n return copyObject(value, keysIn(value));\n }\n\n /**\n * Converts `value` to a safe integer. A safe integer can be compared and\n * represented correctly.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {number} Returns the converted integer.\n * @example\n *\n * _.toSafeInteger(3.2);\n * // => 3\n *\n * _.toSafeInteger(Number.MIN_VALUE);\n * // => 0\n *\n * _.toSafeInteger(Infinity);\n * // => 9007199254740991\n *\n * _.toSafeInteger('3.2');\n * // => 3\n */\n function toSafeInteger(value) {\n return value\n ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER)\n : (value === 0 ? value : 0);\n }\n\n /**\n * Converts `value` to a string. An empty string is returned for `null`\n * and `undefined` values. The sign of `-0` is preserved.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n * @example\n *\n * _.toString(null);\n * // => ''\n *\n * _.toString(-0);\n * // => '-0'\n *\n * _.toString([1, 2, 3]);\n * // => '1,2,3'\n */\n function toString(value) {\n return value == null ? '' : baseToString(value);\n }\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Assigns own enumerable string keyed properties of source objects to the\n * destination object. Source objects are applied from left to right.\n * Subsequent sources overwrite property assignments of previous sources.\n *\n * **Note:** This method mutates `object` and is loosely based on\n * [`Object.assign`](https://mdn.io/Object/assign).\n *\n * @static\n * @memberOf _\n * @since 0.10.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.assignIn\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * }\n *\n * function Bar() {\n * this.c = 3;\n * }\n *\n * Foo.prototype.b = 2;\n * Bar.prototype.d = 4;\n *\n * _.assign({ 'a': 0 }, new Foo, new Bar);\n * // => { 'a': 1, 'c': 3 }\n */\n var assign = createAssigner(function(object, source) {\n if (isPrototype(source) || isArrayLike(source)) {\n copyObject(source, keys(source), object);\n return;\n }\n for (var key in source) {\n if (hasOwnProperty.call(source, key)) {\n assignValue(object, key, source[key]);\n }\n }\n });\n\n /**\n * This method is like `_.assign` except that it iterates over own and\n * inherited source properties.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @alias extend\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.assign\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * }\n *\n * function Bar() {\n * this.c = 3;\n * }\n *\n * Foo.prototype.b = 2;\n * Bar.prototype.d = 4;\n *\n * _.assignIn({ 'a': 0 }, new Foo, new Bar);\n * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }\n */\n var assignIn = createAssigner(function(object, source) {\n copyObject(source, keysIn(source), object);\n });\n\n /**\n * This method is like `_.assignIn` except that it accepts `customizer`\n * which is invoked to produce the assigned values. If `customizer` returns\n * `undefined`, assignment is handled by the method instead. The `customizer`\n * is invoked with five arguments: (objValue, srcValue, key, object, source).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @alias extendWith\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} sources The source objects.\n * @param {Function} [customizer] The function to customize assigned values.\n * @returns {Object} Returns `object`.\n * @see _.assignWith\n * @example\n *\n * function customizer(objValue, srcValue) {\n * return _.isUndefined(objValue) ? srcValue : objValue;\n * }\n *\n * var defaults = _.partialRight(_.assignInWith, customizer);\n *\n * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });\n * // => { 'a': 1, 'b': 2 }\n */\n var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {\n copyObject(source, keysIn(source), object, customizer);\n });\n\n /**\n * This method is like `_.assign` except that it accepts `customizer`\n * which is invoked to produce the assigned values. If `customizer` returns\n * `undefined`, assignment is handled by the method instead. The `customizer`\n * is invoked with five arguments: (objValue, srcValue, key, object, source).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} sources The source objects.\n * @param {Function} [customizer] The function to customize assigned values.\n * @returns {Object} Returns `object`.\n * @see _.assignInWith\n * @example\n *\n * function customizer(objValue, srcValue) {\n * return _.isUndefined(objValue) ? srcValue : objValue;\n * }\n *\n * var defaults = _.partialRight(_.assignWith, customizer);\n *\n * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });\n * // => { 'a': 1, 'b': 2 }\n */\n var assignWith = createAssigner(function(object, source, srcIndex, customizer) {\n copyObject(source, keys(source), object, customizer);\n });\n\n /**\n * Creates an array of values corresponding to `paths` of `object`.\n *\n * @static\n * @memberOf _\n * @since 1.0.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {...(string|string[])} [paths] The property paths to pick.\n * @returns {Array} Returns the picked values.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };\n *\n * _.at(object, ['a[0].b.c', 'a[1]']);\n * // => [3, 4]\n */\n var at = flatRest(baseAt);\n\n /**\n * Creates an object that inherits from the `prototype` object. If a\n * `properties` object is given, its own enumerable string keyed properties\n * are assigned to the created object.\n *\n * @static\n * @memberOf _\n * @since 2.3.0\n * @category Object\n * @param {Object} prototype The object to inherit from.\n * @param {Object} [properties] The properties to assign to the object.\n * @returns {Object} Returns the new object.\n * @example\n *\n * function Shape() {\n * this.x = 0;\n * this.y = 0;\n * }\n *\n * function Circle() {\n * Shape.call(this);\n * }\n *\n * Circle.prototype = _.create(Shape.prototype, {\n * 'constructor': Circle\n * });\n *\n * var circle = new Circle;\n * circle instanceof Circle;\n * // => true\n *\n * circle instanceof Shape;\n * // => true\n */\n function create(prototype, properties) {\n var result = baseCreate(prototype);\n return properties == null ? result : baseAssign(result, properties);\n }\n\n /**\n * Assigns own and inherited enumerable string keyed properties of source\n * objects to the destination object for all destination properties that\n * resolve to `undefined`. Source objects are applied from left to right.\n * Once a property is set, additional values of the same property are ignored.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.defaultsDeep\n * @example\n *\n * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });\n * // => { 'a': 1, 'b': 2 }\n */\n var defaults = baseRest(function(args) {\n args.push(undefined, customDefaultsAssignIn);\n return apply(assignInWith, undefined, args);\n });\n\n /**\n * This method is like `_.defaults` except that it recursively assigns\n * default properties.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 3.10.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.defaults\n * @example\n *\n * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });\n * // => { 'a': { 'b': 2, 'c': 3 } }\n */\n var defaultsDeep = baseRest(function(args) {\n args.push(undefined, customDefaultsMerge);\n return apply(mergeWith, undefined, args);\n });\n\n /**\n * This method is like `_.find` except that it returns the key of the first\n * element `predicate` returns truthy for instead of the element itself.\n *\n * @static\n * @memberOf _\n * @since 1.1.0\n * @category Object\n * @param {Object} object The object to inspect.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {string|undefined} Returns the key of the matched element,\n * else `undefined`.\n * @example\n *\n * var users = {\n * 'barney': { 'age': 36, 'active': true },\n * 'fred': { 'age': 40, 'active': false },\n * 'pebbles': { 'age': 1, 'active': true }\n * };\n *\n * _.findKey(users, function(o) { return o.age < 40; });\n * // => 'barney' (iteration order is not guaranteed)\n *\n * // The `_.matches` iteratee shorthand.\n * _.findKey(users, { 'age': 1, 'active': true });\n * // => 'pebbles'\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.findKey(users, ['active', false]);\n * // => 'fred'\n *\n * // The `_.property` iteratee shorthand.\n * _.findKey(users, 'active');\n * // => 'barney'\n */\n function findKey(object, predicate) {\n return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);\n }\n\n /**\n * This method is like `_.findKey` except that it iterates over elements of\n * a collection in the opposite order.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Object\n * @param {Object} object The object to inspect.\n * @param {Function} [predicate=_.identity] The function invoked per iteration.\n * @returns {string|undefined} Returns the key of the matched element,\n * else `undefined`.\n * @example\n *\n * var users = {\n * 'barney': { 'age': 36, 'active': true },\n * 'fred': { 'age': 40, 'active': false },\n * 'pebbles': { 'age': 1, 'active': true }\n * };\n *\n * _.findLastKey(users, function(o) { return o.age < 40; });\n * // => returns 'pebbles' assuming `_.findKey` returns 'barney'\n *\n * // The `_.matches` iteratee shorthand.\n * _.findLastKey(users, { 'age': 36, 'active': true });\n * // => 'barney'\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.findLastKey(users, ['active', false]);\n * // => 'fred'\n *\n * // The `_.property` iteratee shorthand.\n * _.findLastKey(users, 'active');\n * // => 'pebbles'\n */\n function findLastKey(object, predicate) {\n return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);\n }\n\n /**\n * Iterates over own and inherited enumerable string keyed properties of an\n * object and invokes `iteratee` for each property. The iteratee is invoked\n * with three arguments: (value, key, object). Iteratee functions may exit\n * iteration early by explicitly returning `false`.\n *\n * @static\n * @memberOf _\n * @since 0.3.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Object} Returns `object`.\n * @see _.forInRight\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.forIn(new Foo, function(value, key) {\n * console.log(key);\n * });\n * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).\n */\n function forIn(object, iteratee) {\n return object == null\n ? object\n : baseFor(object, getIteratee(iteratee, 3), keysIn);\n }\n\n /**\n * This method is like `_.forIn` except that it iterates over properties of\n * `object` in the opposite order.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Object} Returns `object`.\n * @see _.forIn\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.forInRight(new Foo, function(value, key) {\n * console.log(key);\n * });\n * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'.\n */\n function forInRight(object, iteratee) {\n return object == null\n ? object\n : baseForRight(object, getIteratee(iteratee, 3), keysIn);\n }\n\n /**\n * Iterates over own enumerable string keyed properties of an object and\n * invokes `iteratee` for each property. The iteratee is invoked with three\n * arguments: (value, key, object). Iteratee functions may exit iteration\n * early by explicitly returning `false`.\n *\n * @static\n * @memberOf _\n * @since 0.3.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Object} Returns `object`.\n * @see _.forOwnRight\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.forOwn(new Foo, function(value, key) {\n * console.log(key);\n * });\n * // => Logs 'a' then 'b' (iteration order is not guaranteed).\n */\n function forOwn(object, iteratee) {\n return object && baseForOwn(object, getIteratee(iteratee, 3));\n }\n\n /**\n * This method is like `_.forOwn` except that it iterates over properties of\n * `object` in the opposite order.\n *\n * @static\n * @memberOf _\n * @since 2.0.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Object} Returns `object`.\n * @see _.forOwn\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.forOwnRight(new Foo, function(value, key) {\n * console.log(key);\n * });\n * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'.\n */\n function forOwnRight(object, iteratee) {\n return object && baseForOwnRight(object, getIteratee(iteratee, 3));\n }\n\n /**\n * Creates an array of function property names from own enumerable properties\n * of `object`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to inspect.\n * @returns {Array} Returns the function names.\n * @see _.functionsIn\n * @example\n *\n * function Foo() {\n * this.a = _.constant('a');\n * this.b = _.constant('b');\n * }\n *\n * Foo.prototype.c = _.constant('c');\n *\n * _.functions(new Foo);\n * // => ['a', 'b']\n */\n function functions(object) {\n return object == null ? [] : baseFunctions(object, keys(object));\n }\n\n /**\n * Creates an array of function property names from own and inherited\n * enumerable properties of `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The object to inspect.\n * @returns {Array} Returns the function names.\n * @see _.functions\n * @example\n *\n * function Foo() {\n * this.a = _.constant('a');\n * this.b = _.constant('b');\n * }\n *\n * Foo.prototype.c = _.constant('c');\n *\n * _.functionsIn(new Foo);\n * // => ['a', 'b', 'c']\n */\n function functionsIn(object) {\n return object == null ? [] : baseFunctions(object, keysIn(object));\n }\n\n /**\n * Gets the value at `path` of `object`. If the resolved value is\n * `undefined`, the `defaultValue` is returned in its place.\n *\n * @static\n * @memberOf _\n * @since 3.7.0\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the property to get.\n * @param {*} [defaultValue] The value returned for `undefined` resolved values.\n * @returns {*} Returns the resolved value.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 3 } }] };\n *\n * _.get(object, 'a[0].b.c');\n * // => 3\n *\n * _.get(object, ['a', '0', 'b', 'c']);\n * // => 3\n *\n * _.get(object, 'a.b.c', 'default');\n * // => 'default'\n */\n function get(object, path, defaultValue) {\n var result = object == null ? undefined : baseGet(object, path);\n return result === undefined ? defaultValue : result;\n }\n\n /**\n * Checks if `path` is a direct property of `object`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path to check.\n * @returns {boolean} Returns `true` if `path` exists, else `false`.\n * @example\n *\n * var object = { 'a': { 'b': 2 } };\n * var other = _.create({ 'a': _.create({ 'b': 2 }) });\n *\n * _.has(object, 'a');\n * // => true\n *\n * _.has(object, 'a.b');\n * // => true\n *\n * _.has(object, ['a', 'b']);\n * // => true\n *\n * _.has(other, 'a');\n * // => false\n */\n function has(object, path) {\n return object != null && hasPath(object, path, baseHas);\n }\n\n /**\n * Checks if `path` is a direct or inherited property of `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path to check.\n * @returns {boolean} Returns `true` if `path` exists, else `false`.\n * @example\n *\n * var object = _.create({ 'a': _.create({ 'b': 2 }) });\n *\n * _.hasIn(object, 'a');\n * // => true\n *\n * _.hasIn(object, 'a.b');\n * // => true\n *\n * _.hasIn(object, ['a', 'b']);\n * // => true\n *\n * _.hasIn(object, 'b');\n * // => false\n */\n function hasIn(object, path) {\n return object != null && hasPath(object, path, baseHasIn);\n }\n\n /**\n * Creates an object composed of the inverted keys and values of `object`.\n * If `object` contains duplicate values, subsequent values overwrite\n * property assignments of previous values.\n *\n * @static\n * @memberOf _\n * @since 0.7.0\n * @category Object\n * @param {Object} object The object to invert.\n * @returns {Object} Returns the new inverted object.\n * @example\n *\n * var object = { 'a': 1, 'b': 2, 'c': 1 };\n *\n * _.invert(object);\n * // => { '1': 'c', '2': 'b' }\n */\n var invert = createInverter(function(result, value, key) {\n result[value] = key;\n }, constant(identity));\n\n /**\n * This method is like `_.invert` except that the inverted object is generated\n * from the results of running each element of `object` thru `iteratee`. The\n * corresponding inverted value of each inverted key is an array of keys\n * responsible for generating the inverted value. The iteratee is invoked\n * with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 4.1.0\n * @category Object\n * @param {Object} object The object to invert.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {Object} Returns the new inverted object.\n * @example\n *\n * var object = { 'a': 1, 'b': 2, 'c': 1 };\n *\n * _.invertBy(object);\n * // => { '1': ['a', 'c'], '2': ['b'] }\n *\n * _.invertBy(object, function(value) {\n * return 'group' + value;\n * });\n * // => { 'group1': ['a', 'c'], 'group2': ['b'] }\n */\n var invertBy = createInverter(function(result, value, key) {\n if (hasOwnProperty.call(result, value)) {\n result[value].push(key);\n } else {\n result[value] = [key];\n }\n }, getIteratee);\n\n /**\n * Invokes the method at `path` of `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the method to invoke.\n * @param {...*} [args] The arguments to invoke the method with.\n * @returns {*} Returns the result of the invoked method.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };\n *\n * _.invoke(object, 'a[0].b.c.slice', 1, 3);\n * // => [2, 3]\n */\n var invoke = baseRest(baseInvoke);\n\n /**\n * Creates an array of the own enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects. See the\n * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * for more details.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keys(new Foo);\n * // => ['a', 'b'] (iteration order is not guaranteed)\n *\n * _.keys('hi');\n * // => ['0', '1']\n */\n function keys(object) {\n return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);\n }\n\n /**\n * Creates an array of the own and inherited enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keysIn(new Foo);\n * // => ['a', 'b', 'c'] (iteration order is not guaranteed)\n */\n function keysIn(object) {\n return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);\n }\n\n /**\n * The opposite of `_.mapValues`; this method creates an object with the\n * same values as `object` and keys generated by running each own enumerable\n * string keyed property of `object` thru `iteratee`. The iteratee is invoked\n * with three arguments: (value, key, object).\n *\n * @static\n * @memberOf _\n * @since 3.8.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Object} Returns the new mapped object.\n * @see _.mapValues\n * @example\n *\n * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {\n * return key + value;\n * });\n * // => { 'a1': 1, 'b2': 2 }\n */\n function mapKeys(object, iteratee) {\n var result = {};\n iteratee = getIteratee(iteratee, 3);\n\n baseForOwn(object, function(value, key, object) {\n baseAssignValue(result, iteratee(value, key, object), value);\n });\n return result;\n }\n\n /**\n * Creates an object with the same keys as `object` and values generated\n * by running each own enumerable string keyed property of `object` thru\n * `iteratee`. The iteratee is invoked with three arguments:\n * (value, key, object).\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Object} Returns the new mapped object.\n * @see _.mapKeys\n * @example\n *\n * var users = {\n * 'fred': { 'user': 'fred', 'age': 40 },\n * 'pebbles': { 'user': 'pebbles', 'age': 1 }\n * };\n *\n * _.mapValues(users, function(o) { return o.age; });\n * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)\n *\n * // The `_.property` iteratee shorthand.\n * _.mapValues(users, 'age');\n * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)\n */\n function mapValues(object, iteratee) {\n var result = {};\n iteratee = getIteratee(iteratee, 3);\n\n baseForOwn(object, function(value, key, object) {\n baseAssignValue(result, key, iteratee(value, key, object));\n });\n return result;\n }\n\n /**\n * This method is like `_.assign` except that it recursively merges own and\n * inherited enumerable string keyed properties of source objects into the\n * destination object. Source properties that resolve to `undefined` are\n * skipped if a destination value exists. Array and plain object properties\n * are merged recursively. Other objects and value types are overridden by\n * assignment. Source objects are applied from left to right. Subsequent\n * sources overwrite property assignments of previous sources.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 0.5.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @example\n *\n * var object = {\n * 'a': [{ 'b': 2 }, { 'd': 4 }]\n * };\n *\n * var other = {\n * 'a': [{ 'c': 3 }, { 'e': 5 }]\n * };\n *\n * _.merge(object, other);\n * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }\n */\n var merge = createAssigner(function(object, source, srcIndex) {\n baseMerge(object, source, srcIndex);\n });\n\n /**\n * This method is like `_.merge` except that it accepts `customizer` which\n * is invoked to produce the merged values of the destination and source\n * properties. If `customizer` returns `undefined`, merging is handled by the\n * method instead. The `customizer` is invoked with six arguments:\n * (objValue, srcValue, key, object, source, stack).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} sources The source objects.\n * @param {Function} customizer The function to customize assigned values.\n * @returns {Object} Returns `object`.\n * @example\n *\n * function customizer(objValue, srcValue) {\n * if (_.isArray(objValue)) {\n * return objValue.concat(srcValue);\n * }\n * }\n *\n * var object = { 'a': [1], 'b': [2] };\n * var other = { 'a': [3], 'b': [4] };\n *\n * _.mergeWith(object, other, customizer);\n * // => { 'a': [1, 3], 'b': [2, 4] }\n */\n var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {\n baseMerge(object, source, srcIndex, customizer);\n });\n\n /**\n * The opposite of `_.pick`; this method creates an object composed of the\n * own and inherited enumerable property paths of `object` that are not omitted.\n *\n * **Note:** This method is considerably slower than `_.pick`.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The source object.\n * @param {...(string|string[])} [paths] The property paths to omit.\n * @returns {Object} Returns the new object.\n * @example\n *\n * var object = { 'a': 1, 'b': '2', 'c': 3 };\n *\n * _.omit(object, ['a', 'c']);\n * // => { 'b': '2' }\n */\n var omit = flatRest(function(object, paths) {\n var result = {};\n if (object == null) {\n return result;\n }\n var isDeep = false;\n paths = arrayMap(paths, function(path) {\n path = castPath(path, object);\n isDeep || (isDeep = path.length > 1);\n return path;\n });\n copyObject(object, getAllKeysIn(object), result);\n if (isDeep) {\n result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);\n }\n var length = paths.length;\n while (length--) {\n baseUnset(result, paths[length]);\n }\n return result;\n });\n\n /**\n * The opposite of `_.pickBy`; this method creates an object composed of\n * the own and inherited enumerable string keyed properties of `object` that\n * `predicate` doesn't return truthy for. The predicate is invoked with two\n * arguments: (value, key).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The source object.\n * @param {Function} [predicate=_.identity] The function invoked per property.\n * @returns {Object} Returns the new object.\n * @example\n *\n * var object = { 'a': 1, 'b': '2', 'c': 3 };\n *\n * _.omitBy(object, _.isNumber);\n * // => { 'b': '2' }\n */\n function omitBy(object, predicate) {\n return pickBy(object, negate(getIteratee(predicate)));\n }\n\n /**\n * Creates an object composed of the picked `object` properties.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The source object.\n * @param {...(string|string[])} [paths] The property paths to pick.\n * @returns {Object} Returns the new object.\n * @example\n *\n * var object = { 'a': 1, 'b': '2', 'c': 3 };\n *\n * _.pick(object, ['a', 'c']);\n * // => { 'a': 1, 'c': 3 }\n */\n var pick = flatRest(function(object, paths) {\n return object == null ? {} : basePick(object, paths);\n });\n\n /**\n * Creates an object composed of the `object` properties `predicate` returns\n * truthy for. The predicate is invoked with two arguments: (value, key).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The source object.\n * @param {Function} [predicate=_.identity] The function invoked per property.\n * @returns {Object} Returns the new object.\n * @example\n *\n * var object = { 'a': 1, 'b': '2', 'c': 3 };\n *\n * _.pickBy(object, _.isNumber);\n * // => { 'a': 1, 'c': 3 }\n */\n function pickBy(object, predicate) {\n if (object == null) {\n return {};\n }\n var props = arrayMap(getAllKeysIn(object), function(prop) {\n return [prop];\n });\n predicate = getIteratee(predicate);\n return basePickBy(object, props, function(value, path) {\n return predicate(value, path[0]);\n });\n }\n\n /**\n * This method is like `_.get` except that if the resolved value is a\n * function it's invoked with the `this` binding of its parent object and\n * its result is returned.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the property to resolve.\n * @param {*} [defaultValue] The value returned for `undefined` resolved values.\n * @returns {*} Returns the resolved value.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };\n *\n * _.result(object, 'a[0].b.c1');\n * // => 3\n *\n * _.result(object, 'a[0].b.c2');\n * // => 4\n *\n * _.result(object, 'a[0].b.c3', 'default');\n * // => 'default'\n *\n * _.result(object, 'a[0].b.c3', _.constant('default'));\n * // => 'default'\n */\n function result(object, path, defaultValue) {\n path = castPath(path, object);\n\n var index = -1,\n length = path.length;\n\n // Ensure the loop is entered when path is empty.\n if (!length) {\n length = 1;\n object = undefined;\n }\n while (++index < length) {\n var value = object == null ? undefined : object[toKey(path[index])];\n if (value === undefined) {\n index = length;\n value = defaultValue;\n }\n object = isFunction(value) ? value.call(object) : value;\n }\n return object;\n }\n\n /**\n * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,\n * it's created. Arrays are created for missing index properties while objects\n * are created for all other missing properties. Use `_.setWith` to customize\n * `path` creation.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 3.7.0\n * @category Object\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns `object`.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 3 } }] };\n *\n * _.set(object, 'a[0].b.c', 4);\n * console.log(object.a[0].b.c);\n * // => 4\n *\n * _.set(object, ['x', '0', 'y', 'z'], 5);\n * console.log(object.x[0].y.z);\n * // => 5\n */\n function set(object, path, value) {\n return object == null ? object : baseSet(object, path, value);\n }\n\n /**\n * This method is like `_.set` except that it accepts `customizer` which is\n * invoked to produce the objects of `path`. If `customizer` returns `undefined`\n * path creation is handled by the method instead. The `customizer` is invoked\n * with three arguments: (nsValue, key, nsObject).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to set.\n * @param {*} value The value to set.\n * @param {Function} [customizer] The function to customize assigned values.\n * @returns {Object} Returns `object`.\n * @example\n *\n * var object = {};\n *\n * _.setWith(object, '[0][1]', 'a', Object);\n * // => { '0': { '1': 'a' } }\n */\n function setWith(object, path, value, customizer) {\n customizer = typeof customizer == 'function' ? customizer : undefined;\n return object == null ? object : baseSet(object, path, value, customizer);\n }\n\n /**\n * Creates an array of own enumerable string keyed-value pairs for `object`\n * which can be consumed by `_.fromPairs`. If `object` is a map or set, its\n * entries are returned.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @alias entries\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the key-value pairs.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.toPairs(new Foo);\n * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)\n */\n var toPairs = createToPairs(keys);\n\n /**\n * Creates an array of own and inherited enumerable string keyed-value pairs\n * for `object` which can be consumed by `_.fromPairs`. If `object` is a map\n * or set, its entries are returned.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @alias entriesIn\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the key-value pairs.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.toPairsIn(new Foo);\n * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed)\n */\n var toPairsIn = createToPairs(keysIn);\n\n /**\n * An alternative to `_.reduce`; this method transforms `object` to a new\n * `accumulator` object which is the result of running each of its own\n * enumerable string keyed properties thru `iteratee`, with each invocation\n * potentially mutating the `accumulator` object. If `accumulator` is not\n * provided, a new object with the same `[[Prototype]]` will be used. The\n * iteratee is invoked with four arguments: (accumulator, value, key, object).\n * Iteratee functions may exit iteration early by explicitly returning `false`.\n *\n * @static\n * @memberOf _\n * @since 1.3.0\n * @category Object\n * @param {Object} object The object to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @param {*} [accumulator] The custom accumulator value.\n * @returns {*} Returns the accumulated value.\n * @example\n *\n * _.transform([2, 3, 4], function(result, n) {\n * result.push(n *= n);\n * return n % 2 == 0;\n * }, []);\n * // => [4, 9]\n *\n * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {\n * (result[value] || (result[value] = [])).push(key);\n * }, {});\n * // => { '1': ['a', 'c'], '2': ['b'] }\n */\n function transform(object, iteratee, accumulator) {\n var isArr = isArray(object),\n isArrLike = isArr || isBuffer(object) || isTypedArray(object);\n\n iteratee = getIteratee(iteratee, 4);\n if (accumulator == null) {\n var Ctor = object && object.constructor;\n if (isArrLike) {\n accumulator = isArr ? new Ctor : [];\n }\n else if (isObject(object)) {\n accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};\n }\n else {\n accumulator = {};\n }\n }\n (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) {\n return iteratee(accumulator, value, index, object);\n });\n return accumulator;\n }\n\n /**\n * Removes the property at `path` of `object`.\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Object\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to unset.\n * @returns {boolean} Returns `true` if the property is deleted, else `false`.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 7 } }] };\n * _.unset(object, 'a[0].b.c');\n * // => true\n *\n * console.log(object);\n * // => { 'a': [{ 'b': {} }] };\n *\n * _.unset(object, ['a', '0', 'b', 'c']);\n * // => true\n *\n * console.log(object);\n * // => { 'a': [{ 'b': {} }] };\n */\n function unset(object, path) {\n return object == null ? true : baseUnset(object, path);\n }\n\n /**\n * This method is like `_.set` except that accepts `updater` to produce the\n * value to set. Use `_.updateWith` to customize `path` creation. The `updater`\n * is invoked with one argument: (value).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.6.0\n * @category Object\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to set.\n * @param {Function} updater The function to produce the updated value.\n * @returns {Object} Returns `object`.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 3 } }] };\n *\n * _.update(object, 'a[0].b.c', function(n) { return n * n; });\n * console.log(object.a[0].b.c);\n * // => 9\n *\n * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; });\n * console.log(object.x[0].y.z);\n * // => 0\n */\n function update(object, path, updater) {\n return object == null ? object : baseUpdate(object, path, castFunction(updater));\n }\n\n /**\n * This method is like `_.update` except that it accepts `customizer` which is\n * invoked to produce the objects of `path`. If `customizer` returns `undefined`\n * path creation is handled by the method instead. The `customizer` is invoked\n * with three arguments: (nsValue, key, nsObject).\n *\n * **Note:** This method mutates `object`.\n *\n * @static\n * @memberOf _\n * @since 4.6.0\n * @category Object\n * @param {Object} object The object to modify.\n * @param {Array|string} path The path of the property to set.\n * @param {Function} updater The function to produce the updated value.\n * @param {Function} [customizer] The function to customize assigned values.\n * @returns {Object} Returns `object`.\n * @example\n *\n * var object = {};\n *\n * _.updateWith(object, '[0][1]', _.constant('a'), Object);\n * // => { '0': { '1': 'a' } }\n */\n function updateWith(object, path, updater, customizer) {\n customizer = typeof customizer == 'function' ? customizer : undefined;\n return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);\n }\n\n /**\n * Creates an array of the own enumerable string keyed property values of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property values.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.values(new Foo);\n * // => [1, 2] (iteration order is not guaranteed)\n *\n * _.values('hi');\n * // => ['h', 'i']\n */\n function values(object) {\n return object == null ? [] : baseValues(object, keys(object));\n }\n\n /**\n * Creates an array of the own and inherited enumerable string keyed property\n * values of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property values.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.valuesIn(new Foo);\n * // => [1, 2, 3] (iteration order is not guaranteed)\n */\n function valuesIn(object) {\n return object == null ? [] : baseValues(object, keysIn(object));\n }\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Clamps `number` within the inclusive `lower` and `upper` bounds.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Number\n * @param {number} number The number to clamp.\n * @param {number} [lower] The lower bound.\n * @param {number} upper The upper bound.\n * @returns {number} Returns the clamped number.\n * @example\n *\n * _.clamp(-10, -5, 5);\n * // => -5\n *\n * _.clamp(10, -5, 5);\n * // => 5\n */\n function clamp(number, lower, upper) {\n if (upper === undefined) {\n upper = lower;\n lower = undefined;\n }\n if (upper !== undefined) {\n upper = toNumber(upper);\n upper = upper === upper ? upper : 0;\n }\n if (lower !== undefined) {\n lower = toNumber(lower);\n lower = lower === lower ? lower : 0;\n }\n return baseClamp(toNumber(number), lower, upper);\n }\n\n /**\n * Checks if `n` is between `start` and up to, but not including, `end`. If\n * `end` is not specified, it's set to `start` with `start` then set to `0`.\n * If `start` is greater than `end` the params are swapped to support\n * negative ranges.\n *\n * @static\n * @memberOf _\n * @since 3.3.0\n * @category Number\n * @param {number} number The number to check.\n * @param {number} [start=0] The start of the range.\n * @param {number} end The end of the range.\n * @returns {boolean} Returns `true` if `number` is in the range, else `false`.\n * @see _.range, _.rangeRight\n * @example\n *\n * _.inRange(3, 2, 4);\n * // => true\n *\n * _.inRange(4, 8);\n * // => true\n *\n * _.inRange(4, 2);\n * // => false\n *\n * _.inRange(2, 2);\n * // => false\n *\n * _.inRange(1.2, 2);\n * // => true\n *\n * _.inRange(5.2, 4);\n * // => false\n *\n * _.inRange(-3, -2, -6);\n * // => true\n */\n function inRange(number, start, end) {\n start = toFinite(start);\n if (end === undefined) {\n end = start;\n start = 0;\n } else {\n end = toFinite(end);\n }\n number = toNumber(number);\n return baseInRange(number, start, end);\n }\n\n /**\n * Produces a random number between the inclusive `lower` and `upper` bounds.\n * If only one argument is provided a number between `0` and the given number\n * is returned. If `floating` is `true`, or either `lower` or `upper` are\n * floats, a floating-point number is returned instead of an integer.\n *\n * **Note:** JavaScript follows the IEEE-754 standard for resolving\n * floating-point values which can produce unexpected results.\n *\n * @static\n * @memberOf _\n * @since 0.7.0\n * @category Number\n * @param {number} [lower=0] The lower bound.\n * @param {number} [upper=1] The upper bound.\n * @param {boolean} [floating] Specify returning a floating-point number.\n * @returns {number} Returns the random number.\n * @example\n *\n * _.random(0, 5);\n * // => an integer between 0 and 5\n *\n * _.random(5);\n * // => also an integer between 0 and 5\n *\n * _.random(5, true);\n * // => a floating-point number between 0 and 5\n *\n * _.random(1.2, 5.2);\n * // => a floating-point number between 1.2 and 5.2\n */\n function random(lower, upper, floating) {\n if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {\n upper = floating = undefined;\n }\n if (floating === undefined) {\n if (typeof upper == 'boolean') {\n floating = upper;\n upper = undefined;\n }\n else if (typeof lower == 'boolean') {\n floating = lower;\n lower = undefined;\n }\n }\n if (lower === undefined && upper === undefined) {\n lower = 0;\n upper = 1;\n }\n else {\n lower = toFinite(lower);\n if (upper === undefined) {\n upper = lower;\n lower = 0;\n } else {\n upper = toFinite(upper);\n }\n }\n if (lower > upper) {\n var temp = lower;\n lower = upper;\n upper = temp;\n }\n if (floating || lower % 1 || upper % 1) {\n var rand = nativeRandom();\n return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper);\n }\n return baseRandom(lower, upper);\n }\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the camel cased string.\n * @example\n *\n * _.camelCase('Foo Bar');\n * // => 'fooBar'\n *\n * _.camelCase('--foo-bar--');\n * // => 'fooBar'\n *\n * _.camelCase('__FOO_BAR__');\n * // => 'fooBar'\n */\n var camelCase = createCompounder(function(result, word, index) {\n word = word.toLowerCase();\n return result + (index ? capitalize(word) : word);\n });\n\n /**\n * Converts the first character of `string` to upper case and the remaining\n * to lower case.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to capitalize.\n * @returns {string} Returns the capitalized string.\n * @example\n *\n * _.capitalize('FRED');\n * // => 'Fred'\n */\n function capitalize(string) {\n return upperFirst(toString(string).toLowerCase());\n }\n\n /**\n * Deburrs `string` by converting\n * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)\n * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)\n * letters to basic Latin letters and removing\n * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to deburr.\n * @returns {string} Returns the deburred string.\n * @example\n *\n * _.deburr('déjà vu');\n * // => 'deja vu'\n */\n function deburr(string) {\n string = toString(string);\n return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');\n }\n\n /**\n * Checks if `string` ends with the given target string.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to inspect.\n * @param {string} [target] The string to search for.\n * @param {number} [position=string.length] The position to search up to.\n * @returns {boolean} Returns `true` if `string` ends with `target`,\n * else `false`.\n * @example\n *\n * _.endsWith('abc', 'c');\n * // => true\n *\n * _.endsWith('abc', 'b');\n * // => false\n *\n * _.endsWith('abc', 'b', 2);\n * // => true\n */\n function endsWith(string, target, position) {\n string = toString(string);\n target = baseToString(target);\n\n var length = string.length;\n position = position === undefined\n ? length\n : baseClamp(toInteger(position), 0, length);\n\n var end = position;\n position -= target.length;\n return position >= 0 && string.slice(position, end) == target;\n }\n\n /**\n * Converts the characters \"&\", \"<\", \">\", '\"', and \"'\" in `string` to their\n * corresponding HTML entities.\n *\n * **Note:** No other characters are escaped. To escape additional\n * characters use a third-party library like [_he_](https://mths.be/he).\n *\n * Though the \">\" character is escaped for symmetry, characters like\n * \">\" and \"/\" don't need escaping in HTML and have no special meaning\n * unless they're part of a tag or unquoted attribute value. See\n * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)\n * (under \"semi-related fun fact\") for more details.\n *\n * When working with HTML you should always\n * [quote attribute values](http://wonko.com/post/html-escaping) to reduce\n * XSS vectors.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category String\n * @param {string} [string=''] The string to escape.\n * @returns {string} Returns the escaped string.\n * @example\n *\n * _.escape('fred, barney, & pebbles');\n * // => 'fred, barney, & pebbles'\n */\n function escape(string) {\n string = toString(string);\n return (string && reHasUnescapedHtml.test(string))\n ? string.replace(reUnescapedHtml, escapeHtmlChar)\n : string;\n }\n\n /**\n * Escapes the `RegExp` special characters \"^\", \"$\", \"\\\", \".\", \"*\", \"+\",\n * \"?\", \"(\", \")\", \"[\", \"]\", \"{\", \"}\", and \"|\" in `string`.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to escape.\n * @returns {string} Returns the escaped string.\n * @example\n *\n * _.escapeRegExp('[lodash](https://lodash.com/)');\n * // => '\\[lodash\\]\\(https://lodash\\.com/\\)'\n */\n function escapeRegExp(string) {\n string = toString(string);\n return (string && reHasRegExpChar.test(string))\n ? string.replace(reRegExpChar, '\\\\$&')\n : string;\n }\n\n /**\n * Converts `string` to\n * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the kebab cased string.\n * @example\n *\n * _.kebabCase('Foo Bar');\n * // => 'foo-bar'\n *\n * _.kebabCase('fooBar');\n * // => 'foo-bar'\n *\n * _.kebabCase('__FOO_BAR__');\n * // => 'foo-bar'\n */\n var kebabCase = createCompounder(function(result, word, index) {\n return result + (index ? '-' : '') + word.toLowerCase();\n });\n\n /**\n * Converts `string`, as space separated words, to lower case.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the lower cased string.\n * @example\n *\n * _.lowerCase('--Foo-Bar--');\n * // => 'foo bar'\n *\n * _.lowerCase('fooBar');\n * // => 'foo bar'\n *\n * _.lowerCase('__FOO_BAR__');\n * // => 'foo bar'\n */\n var lowerCase = createCompounder(function(result, word, index) {\n return result + (index ? ' ' : '') + word.toLowerCase();\n });\n\n /**\n * Converts the first character of `string` to lower case.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the converted string.\n * @example\n *\n * _.lowerFirst('Fred');\n * // => 'fred'\n *\n * _.lowerFirst('FRED');\n * // => 'fRED'\n */\n var lowerFirst = createCaseFirst('toLowerCase');\n\n /**\n * Pads `string` on the left and right sides if it's shorter than `length`.\n * Padding characters are truncated if they can't be evenly divided by `length`.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to pad.\n * @param {number} [length=0] The padding length.\n * @param {string} [chars=' '] The string used as padding.\n * @returns {string} Returns the padded string.\n * @example\n *\n * _.pad('abc', 8);\n * // => ' abc '\n *\n * _.pad('abc', 8, '_-');\n * // => '_-abc_-_'\n *\n * _.pad('abc', 3);\n * // => 'abc'\n */\n function pad(string, length, chars) {\n string = toString(string);\n length = toInteger(length);\n\n var strLength = length ? stringSize(string) : 0;\n if (!length || strLength >= length) {\n return string;\n }\n var mid = (length - strLength) / 2;\n return (\n createPadding(nativeFloor(mid), chars) +\n string +\n createPadding(nativeCeil(mid), chars)\n );\n }\n\n /**\n * Pads `string` on the right side if it's shorter than `length`. Padding\n * characters are truncated if they exceed `length`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to pad.\n * @param {number} [length=0] The padding length.\n * @param {string} [chars=' '] The string used as padding.\n * @returns {string} Returns the padded string.\n * @example\n *\n * _.padEnd('abc', 6);\n * // => 'abc '\n *\n * _.padEnd('abc', 6, '_-');\n * // => 'abc_-_'\n *\n * _.padEnd('abc', 3);\n * // => 'abc'\n */\n function padEnd(string, length, chars) {\n string = toString(string);\n length = toInteger(length);\n\n var strLength = length ? stringSize(string) : 0;\n return (length && strLength < length)\n ? (string + createPadding(length - strLength, chars))\n : string;\n }\n\n /**\n * Pads `string` on the left side if it's shorter than `length`. Padding\n * characters are truncated if they exceed `length`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to pad.\n * @param {number} [length=0] The padding length.\n * @param {string} [chars=' '] The string used as padding.\n * @returns {string} Returns the padded string.\n * @example\n *\n * _.padStart('abc', 6);\n * // => ' abc'\n *\n * _.padStart('abc', 6, '_-');\n * // => '_-_abc'\n *\n * _.padStart('abc', 3);\n * // => 'abc'\n */\n function padStart(string, length, chars) {\n string = toString(string);\n length = toInteger(length);\n\n var strLength = length ? stringSize(string) : 0;\n return (length && strLength < length)\n ? (createPadding(length - strLength, chars) + string)\n : string;\n }\n\n /**\n * Converts `string` to an integer of the specified radix. If `radix` is\n * `undefined` or `0`, a `radix` of `10` is used unless `value` is a\n * hexadecimal, in which case a `radix` of `16` is used.\n *\n * **Note:** This method aligns with the\n * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.\n *\n * @static\n * @memberOf _\n * @since 1.1.0\n * @category String\n * @param {string} string The string to convert.\n * @param {number} [radix=10] The radix to interpret `value` by.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {number} Returns the converted integer.\n * @example\n *\n * _.parseInt('08');\n * // => 8\n *\n * _.map(['6', '08', '10'], _.parseInt);\n * // => [6, 8, 10]\n */\n function parseInt(string, radix, guard) {\n if (guard || radix == null) {\n radix = 0;\n } else if (radix) {\n radix = +radix;\n }\n return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0);\n }\n\n /**\n * Repeats the given string `n` times.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to repeat.\n * @param {number} [n=1] The number of times to repeat the string.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {string} Returns the repeated string.\n * @example\n *\n * _.repeat('*', 3);\n * // => '***'\n *\n * _.repeat('abc', 2);\n * // => 'abcabc'\n *\n * _.repeat('abc', 0);\n * // => ''\n */\n function repeat(string, n, guard) {\n if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) {\n n = 1;\n } else {\n n = toInteger(n);\n }\n return baseRepeat(toString(string), n);\n }\n\n /**\n * Replaces matches for `pattern` in `string` with `replacement`.\n *\n * **Note:** This method is based on\n * [`String#replace`](https://mdn.io/String/replace).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to modify.\n * @param {RegExp|string} pattern The pattern to replace.\n * @param {Function|string} replacement The match replacement.\n * @returns {string} Returns the modified string.\n * @example\n *\n * _.replace('Hi Fred', 'Fred', 'Barney');\n * // => 'Hi Barney'\n */\n function replace() {\n var args = arguments,\n string = toString(args[0]);\n\n return args.length < 3 ? string : string.replace(args[1], args[2]);\n }\n\n /**\n * Converts `string` to\n * [snake case](https://en.wikipedia.org/wiki/Snake_case).\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the snake cased string.\n * @example\n *\n * _.snakeCase('Foo Bar');\n * // => 'foo_bar'\n *\n * _.snakeCase('fooBar');\n * // => 'foo_bar'\n *\n * _.snakeCase('--FOO-BAR--');\n * // => 'foo_bar'\n */\n var snakeCase = createCompounder(function(result, word, index) {\n return result + (index ? '_' : '') + word.toLowerCase();\n });\n\n /**\n * Splits `string` by `separator`.\n *\n * **Note:** This method is based on\n * [`String#split`](https://mdn.io/String/split).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to split.\n * @param {RegExp|string} separator The separator pattern to split by.\n * @param {number} [limit] The length to truncate results to.\n * @returns {Array} Returns the string segments.\n * @example\n *\n * _.split('a-b-c', '-', 2);\n * // => ['a', 'b']\n */\n function split(string, separator, limit) {\n if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) {\n separator = limit = undefined;\n }\n limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0;\n if (!limit) {\n return [];\n }\n string = toString(string);\n if (string && (\n typeof separator == 'string' ||\n (separator != null && !isRegExp(separator))\n )) {\n separator = baseToString(separator);\n if (!separator && hasUnicode(string)) {\n return castSlice(stringToArray(string), 0, limit);\n }\n }\n return string.split(separator, limit);\n }\n\n /**\n * Converts `string` to\n * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).\n *\n * @static\n * @memberOf _\n * @since 3.1.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the start cased string.\n * @example\n *\n * _.startCase('--foo-bar--');\n * // => 'Foo Bar'\n *\n * _.startCase('fooBar');\n * // => 'Foo Bar'\n *\n * _.startCase('__FOO_BAR__');\n * // => 'FOO BAR'\n */\n var startCase = createCompounder(function(result, word, index) {\n return result + (index ? ' ' : '') + upperFirst(word);\n });\n\n /**\n * Checks if `string` starts with the given target string.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to inspect.\n * @param {string} [target] The string to search for.\n * @param {number} [position=0] The position to search from.\n * @returns {boolean} Returns `true` if `string` starts with `target`,\n * else `false`.\n * @example\n *\n * _.startsWith('abc', 'a');\n * // => true\n *\n * _.startsWith('abc', 'b');\n * // => false\n *\n * _.startsWith('abc', 'b', 1);\n * // => true\n */\n function startsWith(string, target, position) {\n string = toString(string);\n position = position == null\n ? 0\n : baseClamp(toInteger(position), 0, string.length);\n\n target = baseToString(target);\n return string.slice(position, position + target.length) == target;\n }\n\n /**\n * Creates a compiled template function that can interpolate data properties\n * in \"interpolate\" delimiters, HTML-escape interpolated data properties in\n * \"escape\" delimiters, and execute JavaScript in \"evaluate\" delimiters. Data\n * properties may be accessed as free variables in the template. If a setting\n * object is given, it takes precedence over `_.templateSettings` values.\n *\n * **Note:** In the development build `_.template` utilizes\n * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)\n * for easier debugging.\n *\n * For more information on precompiling templates see\n * [lodash's custom builds documentation](https://lodash.com/custom-builds).\n *\n * For more information on Chrome extension sandboxes see\n * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category String\n * @param {string} [string=''] The template string.\n * @param {Object} [options={}] The options object.\n * @param {RegExp} [options.escape=_.templateSettings.escape]\n * The HTML \"escape\" delimiter.\n * @param {RegExp} [options.evaluate=_.templateSettings.evaluate]\n * The \"evaluate\" delimiter.\n * @param {Object} [options.imports=_.templateSettings.imports]\n * An object to import into the template as free variables.\n * @param {RegExp} [options.interpolate=_.templateSettings.interpolate]\n * The \"interpolate\" delimiter.\n * @param {string} [options.sourceURL='lodash.templateSources[n]']\n * The sourceURL of the compiled template.\n * @param {string} [options.variable='obj']\n * The data object variable name.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Function} Returns the compiled template function.\n * @example\n *\n * // Use the \"interpolate\" delimiter to create a compiled template.\n * var compiled = _.template('hello <%= user %>!');\n * compiled({ 'user': 'fred' });\n * // => 'hello fred!'\n *\n * // Use the HTML \"escape\" delimiter to escape data property values.\n * var compiled = _.template('<b><%- value %></b>');\n * compiled({ 'value': '<script>' });\n * // => '<b><script></b>'\n *\n * // Use the \"evaluate\" delimiter to execute JavaScript and generate HTML.\n * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');\n * compiled({ 'users': ['fred', 'barney'] });\n * // => '<li>fred</li><li>barney</li>'\n *\n * // Use the internal `print` function in \"evaluate\" delimiters.\n * var compiled = _.template('<% print(\"hello \" + user); %>!');\n * compiled({ 'user': 'barney' });\n * // => 'hello barney!'\n *\n * // Use the ES template literal delimiter as an \"interpolate\" delimiter.\n * // Disable support by replacing the \"interpolate\" delimiter.\n * var compiled = _.template('hello ${ user }!');\n * compiled({ 'user': 'pebbles' });\n * // => 'hello pebbles!'\n *\n * // Use backslashes to treat delimiters as plain text.\n * var compiled = _.template('<%= \"\\\\<%- value %\\\\>\" %>');\n * compiled({ 'value': 'ignored' });\n * // => '<%- value %>'\n *\n * // Use the `imports` option to import `jQuery` as `jq`.\n * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';\n * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });\n * compiled({ 'users': ['fred', 'barney'] });\n * // => '<li>fred</li><li>barney</li>'\n *\n * // Use the `sourceURL` option to specify a custom sourceURL for the template.\n * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });\n * compiled(data);\n * // => Find the source of \"greeting.jst\" under the Sources tab or Resources panel of the web inspector.\n *\n * // Use the `variable` option to ensure a with-statement isn't used in the compiled template.\n * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });\n * compiled.source;\n * // => function(data) {\n * // var __t, __p = '';\n * // __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';\n * // return __p;\n * // }\n *\n * // Use custom template delimiters.\n * _.templateSettings.interpolate = /{{([\\s\\S]+?)}}/g;\n * var compiled = _.template('hello {{ user }}!');\n * compiled({ 'user': 'mustache' });\n * // => 'hello mustache!'\n *\n * // Use the `source` property to inline compiled templates for meaningful\n * // line numbers in error messages and stack traces.\n * fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\\\n * var JST = {\\\n * \"main\": ' + _.template(mainText).source + '\\\n * };\\\n * ');\n */\n function template(string, options, guard) {\n // Based on John Resig's `tmpl` implementation\n // (http://ejohn.org/blog/javascript-micro-templating/)\n // and Laura Doktorova's doT.js (https://github.com/olado/doT).\n var settings = lodash.templateSettings;\n\n if (guard && isIterateeCall(string, options, guard)) {\n options = undefined;\n }\n string = toString(string);\n options = assignInWith({}, options, settings, customDefaultsAssignIn);\n\n var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn),\n importsKeys = keys(imports),\n importsValues = baseValues(imports, importsKeys);\n\n var isEscaping,\n isEvaluating,\n index = 0,\n interpolate = options.interpolate || reNoMatch,\n source = \"__p += '\";\n\n // Compile the regexp to match each delimiter.\n var reDelimiters = RegExp(\n (options.escape || reNoMatch).source + '|' +\n interpolate.source + '|' +\n (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +\n (options.evaluate || reNoMatch).source + '|$'\n , 'g');\n\n // Use a sourceURL for easier debugging.\n var sourceURL = '//# sourceURL=' +\n ('sourceURL' in options\n ? options.sourceURL\n : ('lodash.templateSources[' + (++templateCounter) + ']')\n ) + '\\n';\n\n string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {\n interpolateValue || (interpolateValue = esTemplateValue);\n\n // Escape characters that can't be included in string literals.\n source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);\n\n // Replace delimiters with snippets.\n if (escapeValue) {\n isEscaping = true;\n source += \"' +\\n__e(\" + escapeValue + \") +\\n'\";\n }\n if (evaluateValue) {\n isEvaluating = true;\n source += \"';\\n\" + evaluateValue + \";\\n__p += '\";\n }\n if (interpolateValue) {\n source += \"' +\\n((__t = (\" + interpolateValue + \")) == null ? '' : __t) +\\n'\";\n }\n index = offset + match.length;\n\n // The JS engine embedded in Adobe products needs `match` returned in\n // order to produce the correct `offset` value.\n return match;\n });\n\n source += \"';\\n\";\n\n // If `variable` is not specified wrap a with-statement around the generated\n // code to add the data object to the top of the scope chain.\n var variable = options.variable;\n if (!variable) {\n source = 'with (obj) {\\n' + source + '\\n}\\n';\n }\n // Cleanup code by stripping empty strings.\n source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)\n .replace(reEmptyStringMiddle, '$1')\n .replace(reEmptyStringTrailing, '$1;');\n\n // Frame code as the function body.\n source = 'function(' + (variable || 'obj') + ') {\\n' +\n (variable\n ? ''\n : 'obj || (obj = {});\\n'\n ) +\n \"var __t, __p = ''\" +\n (isEscaping\n ? ', __e = _.escape'\n : ''\n ) +\n (isEvaluating\n ? ', __j = Array.prototype.join;\\n' +\n \"function print() { __p += __j.call(arguments, '') }\\n\"\n : ';\\n'\n ) +\n source +\n 'return __p\\n}';\n\n var result = attempt(function() {\n return Function(importsKeys, sourceURL + 'return ' + source)\n .apply(undefined, importsValues);\n });\n\n // Provide the compiled function's source by its `toString` method or\n // the `source` property as a convenience for inlining compiled templates.\n result.source = source;\n if (isError(result)) {\n throw result;\n }\n return result;\n }\n\n /**\n * Converts `string`, as a whole, to lower case just like\n * [String#toLowerCase](https://mdn.io/toLowerCase).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the lower cased string.\n * @example\n *\n * _.toLower('--Foo-Bar--');\n * // => '--foo-bar--'\n *\n * _.toLower('fooBar');\n * // => 'foobar'\n *\n * _.toLower('__FOO_BAR__');\n * // => '__foo_bar__'\n */\n function toLower(value) {\n return toString(value).toLowerCase();\n }\n\n /**\n * Converts `string`, as a whole, to upper case just like\n * [String#toUpperCase](https://mdn.io/toUpperCase).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the upper cased string.\n * @example\n *\n * _.toUpper('--foo-bar--');\n * // => '--FOO-BAR--'\n *\n * _.toUpper('fooBar');\n * // => 'FOOBAR'\n *\n * _.toUpper('__foo_bar__');\n * // => '__FOO_BAR__'\n */\n function toUpper(value) {\n return toString(value).toUpperCase();\n }\n\n /**\n * Removes leading and trailing whitespace or specified characters from `string`.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to trim.\n * @param {string} [chars=whitespace] The characters to trim.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {string} Returns the trimmed string.\n * @example\n *\n * _.trim(' abc ');\n * // => 'abc'\n *\n * _.trim('-_-abc-_-', '_-');\n * // => 'abc'\n *\n * _.map([' foo ', ' bar '], _.trim);\n * // => ['foo', 'bar']\n */\n function trim(string, chars, guard) {\n string = toString(string);\n if (string && (guard || chars === undefined)) {\n return string.replace(reTrim, '');\n }\n if (!string || !(chars = baseToString(chars))) {\n return string;\n }\n var strSymbols = stringToArray(string),\n chrSymbols = stringToArray(chars),\n start = charsStartIndex(strSymbols, chrSymbols),\n end = charsEndIndex(strSymbols, chrSymbols) + 1;\n\n return castSlice(strSymbols, start, end).join('');\n }\n\n /**\n * Removes trailing whitespace or specified characters from `string`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to trim.\n * @param {string} [chars=whitespace] The characters to trim.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {string} Returns the trimmed string.\n * @example\n *\n * _.trimEnd(' abc ');\n * // => ' abc'\n *\n * _.trimEnd('-_-abc-_-', '_-');\n * // => '-_-abc'\n */\n function trimEnd(string, chars, guard) {\n string = toString(string);\n if (string && (guard || chars === undefined)) {\n return string.replace(reTrimEnd, '');\n }\n if (!string || !(chars = baseToString(chars))) {\n return string;\n }\n var strSymbols = stringToArray(string),\n end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;\n\n return castSlice(strSymbols, 0, end).join('');\n }\n\n /**\n * Removes leading whitespace or specified characters from `string`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to trim.\n * @param {string} [chars=whitespace] The characters to trim.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {string} Returns the trimmed string.\n * @example\n *\n * _.trimStart(' abc ');\n * // => 'abc '\n *\n * _.trimStart('-_-abc-_-', '_-');\n * // => 'abc-_-'\n */\n function trimStart(string, chars, guard) {\n string = toString(string);\n if (string && (guard || chars === undefined)) {\n return string.replace(reTrimStart, '');\n }\n if (!string || !(chars = baseToString(chars))) {\n return string;\n }\n var strSymbols = stringToArray(string),\n start = charsStartIndex(strSymbols, stringToArray(chars));\n\n return castSlice(strSymbols, start).join('');\n }\n\n /**\n * Truncates `string` if it's longer than the given maximum string length.\n * The last characters of the truncated string are replaced with the omission\n * string which defaults to \"...\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to truncate.\n * @param {Object} [options={}] The options object.\n * @param {number} [options.length=30] The maximum string length.\n * @param {string} [options.omission='...'] The string to indicate text is omitted.\n * @param {RegExp|string} [options.separator] The separator pattern to truncate to.\n * @returns {string} Returns the truncated string.\n * @example\n *\n * _.truncate('hi-diddly-ho there, neighborino');\n * // => 'hi-diddly-ho there, neighbo...'\n *\n * _.truncate('hi-diddly-ho there, neighborino', {\n * 'length': 24,\n * 'separator': ' '\n * });\n * // => 'hi-diddly-ho there,...'\n *\n * _.truncate('hi-diddly-ho there, neighborino', {\n * 'length': 24,\n * 'separator': /,? +/\n * });\n * // => 'hi-diddly-ho there...'\n *\n * _.truncate('hi-diddly-ho there, neighborino', {\n * 'omission': ' [...]'\n * });\n * // => 'hi-diddly-ho there, neig [...]'\n */\n function truncate(string, options) {\n var length = DEFAULT_TRUNC_LENGTH,\n omission = DEFAULT_TRUNC_OMISSION;\n\n if (isObject(options)) {\n var separator = 'separator' in options ? options.separator : separator;\n length = 'length' in options ? toInteger(options.length) : length;\n omission = 'omission' in options ? baseToString(options.omission) : omission;\n }\n string = toString(string);\n\n var strLength = string.length;\n if (hasUnicode(string)) {\n var strSymbols = stringToArray(string);\n strLength = strSymbols.length;\n }\n if (length >= strLength) {\n return string;\n }\n var end = length - stringSize(omission);\n if (end < 1) {\n return omission;\n }\n var result = strSymbols\n ? castSlice(strSymbols, 0, end).join('')\n : string.slice(0, end);\n\n if (separator === undefined) {\n return result + omission;\n }\n if (strSymbols) {\n end += (result.length - end);\n }\n if (isRegExp(separator)) {\n if (string.slice(end).search(separator)) {\n var match,\n substring = result;\n\n if (!separator.global) {\n separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');\n }\n separator.lastIndex = 0;\n while ((match = separator.exec(substring))) {\n var newEnd = match.index;\n }\n result = result.slice(0, newEnd === undefined ? end : newEnd);\n }\n } else if (string.indexOf(baseToString(separator), end) != end) {\n var index = result.lastIndexOf(separator);\n if (index > -1) {\n result = result.slice(0, index);\n }\n }\n return result + omission;\n }\n\n /**\n * The inverse of `_.escape`; this method converts the HTML entities\n * `&`, `<`, `>`, `"`, and `'` in `string` to\n * their corresponding characters.\n *\n * **Note:** No other HTML entities are unescaped. To unescape additional\n * HTML entities use a third-party library like [_he_](https://mths.be/he).\n *\n * @static\n * @memberOf _\n * @since 0.6.0\n * @category String\n * @param {string} [string=''] The string to unescape.\n * @returns {string} Returns the unescaped string.\n * @example\n *\n * _.unescape('fred, barney, & pebbles');\n * // => 'fred, barney, & pebbles'\n */\n function unescape(string) {\n string = toString(string);\n return (string && reHasEscapedHtml.test(string))\n ? string.replace(reEscapedHtml, unescapeHtmlChar)\n : string;\n }\n\n /**\n * Converts `string`, as space separated words, to upper case.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the upper cased string.\n * @example\n *\n * _.upperCase('--foo-bar');\n * // => 'FOO BAR'\n *\n * _.upperCase('fooBar');\n * // => 'FOO BAR'\n *\n * _.upperCase('__foo_bar__');\n * // => 'FOO BAR'\n */\n var upperCase = createCompounder(function(result, word, index) {\n return result + (index ? ' ' : '') + word.toUpperCase();\n });\n\n /**\n * Converts the first character of `string` to upper case.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category String\n * @param {string} [string=''] The string to convert.\n * @returns {string} Returns the converted string.\n * @example\n *\n * _.upperFirst('fred');\n * // => 'Fred'\n *\n * _.upperFirst('FRED');\n * // => 'FRED'\n */\n var upperFirst = createCaseFirst('toUpperCase');\n\n /**\n * Splits `string` into an array of its words.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category String\n * @param {string} [string=''] The string to inspect.\n * @param {RegExp|string} [pattern] The pattern to match words.\n * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.\n * @returns {Array} Returns the words of `string`.\n * @example\n *\n * _.words('fred, barney, & pebbles');\n * // => ['fred', 'barney', 'pebbles']\n *\n * _.words('fred, barney, & pebbles', /[^, ]+/g);\n * // => ['fred', 'barney', '&', 'pebbles']\n */\n function words(string, pattern, guard) {\n string = toString(string);\n pattern = guard ? undefined : pattern;\n\n if (pattern === undefined) {\n return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);\n }\n return string.match(pattern) || [];\n }\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Attempts to invoke `func`, returning either the result or the caught error\n * object. Any additional arguments are provided to `func` when it's invoked.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Util\n * @param {Function} func The function to attempt.\n * @param {...*} [args] The arguments to invoke `func` with.\n * @returns {*} Returns the `func` result or error object.\n * @example\n *\n * // Avoid throwing errors for invalid selectors.\n * var elements = _.attempt(function(selector) {\n * return document.querySelectorAll(selector);\n * }, '>_>');\n *\n * if (_.isError(elements)) {\n * elements = [];\n * }\n */\n var attempt = baseRest(function(func, args) {\n try {\n return apply(func, undefined, args);\n } catch (e) {\n return isError(e) ? e : new Error(e);\n }\n });\n\n /**\n * Binds methods of an object to the object itself, overwriting the existing\n * method.\n *\n * **Note:** This method doesn't set the \"length\" property of bound functions.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {Object} object The object to bind and assign the bound methods to.\n * @param {...(string|string[])} methodNames The object method names to bind.\n * @returns {Object} Returns `object`.\n * @example\n *\n * var view = {\n * 'label': 'docs',\n * 'click': function() {\n * console.log('clicked ' + this.label);\n * }\n * };\n *\n * _.bindAll(view, ['click']);\n * jQuery(element).on('click', view.click);\n * // => Logs 'clicked docs' when clicked.\n */\n var bindAll = flatRest(function(object, methodNames) {\n arrayEach(methodNames, function(key) {\n key = toKey(key);\n baseAssignValue(object, key, bind(object[key], object));\n });\n return object;\n });\n\n /**\n * Creates a function that iterates over `pairs` and invokes the corresponding\n * function of the first predicate to return truthy. The predicate-function\n * pairs are invoked with the `this` binding and arguments of the created\n * function.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Util\n * @param {Array} pairs The predicate-function pairs.\n * @returns {Function} Returns the new composite function.\n * @example\n *\n * var func = _.cond([\n * [_.matches({ 'a': 1 }), _.constant('matches A')],\n * [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],\n * [_.stubTrue, _.constant('no match')]\n * ]);\n *\n * func({ 'a': 1, 'b': 2 });\n * // => 'matches A'\n *\n * func({ 'a': 0, 'b': 1 });\n * // => 'matches B'\n *\n * func({ 'a': '1', 'b': '2' });\n * // => 'no match'\n */\n function cond(pairs) {\n var length = pairs == null ? 0 : pairs.length,\n toIteratee = getIteratee();\n\n pairs = !length ? [] : arrayMap(pairs, function(pair) {\n if (typeof pair[1] != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n return [toIteratee(pair[0]), pair[1]];\n });\n\n return baseRest(function(args) {\n var index = -1;\n while (++index < length) {\n var pair = pairs[index];\n if (apply(pair[0], this, args)) {\n return apply(pair[1], this, args);\n }\n }\n });\n }\n\n /**\n * Creates a function that invokes the predicate properties of `source` with\n * the corresponding property values of a given object, returning `true` if\n * all predicates return truthy, else `false`.\n *\n * **Note:** The created function is equivalent to `_.conformsTo` with\n * `source` partially applied.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Util\n * @param {Object} source The object of property predicates to conform to.\n * @returns {Function} Returns the new spec function.\n * @example\n *\n * var objects = [\n * { 'a': 2, 'b': 1 },\n * { 'a': 1, 'b': 2 }\n * ];\n *\n * _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } }));\n * // => [{ 'a': 1, 'b': 2 }]\n */\n function conforms(source) {\n return baseConforms(baseClone(source, CLONE_DEEP_FLAG));\n }\n\n /**\n * Creates a function that returns `value`.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Util\n * @param {*} value The value to return from the new function.\n * @returns {Function} Returns the new constant function.\n * @example\n *\n * var objects = _.times(2, _.constant({ 'a': 1 }));\n *\n * console.log(objects);\n * // => [{ 'a': 1 }, { 'a': 1 }]\n *\n * console.log(objects[0] === objects[1]);\n * // => true\n */\n function constant(value) {\n return function() {\n return value;\n };\n }\n\n /**\n * Checks `value` to determine whether a default value should be returned in\n * its place. The `defaultValue` is returned if `value` is `NaN`, `null`,\n * or `undefined`.\n *\n * @static\n * @memberOf _\n * @since 4.14.0\n * @category Util\n * @param {*} value The value to check.\n * @param {*} defaultValue The default value.\n * @returns {*} Returns the resolved value.\n * @example\n *\n * _.defaultTo(1, 10);\n * // => 1\n *\n * _.defaultTo(undefined, 10);\n * // => 10\n */\n function defaultTo(value, defaultValue) {\n return (value == null || value !== value) ? defaultValue : value;\n }\n\n /**\n * Creates a function that returns the result of invoking the given functions\n * with the `this` binding of the created function, where each successive\n * invocation is supplied the return value of the previous.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Util\n * @param {...(Function|Function[])} [funcs] The functions to invoke.\n * @returns {Function} Returns the new composite function.\n * @see _.flowRight\n * @example\n *\n * function square(n) {\n * return n * n;\n * }\n *\n * var addSquare = _.flow([_.add, square]);\n * addSquare(1, 2);\n * // => 9\n */\n var flow = createFlow();\n\n /**\n * This method is like `_.flow` except that it creates a function that\n * invokes the given functions from right to left.\n *\n * @static\n * @since 3.0.0\n * @memberOf _\n * @category Util\n * @param {...(Function|Function[])} [funcs] The functions to invoke.\n * @returns {Function} Returns the new composite function.\n * @see _.flow\n * @example\n *\n * function square(n) {\n * return n * n;\n * }\n *\n * var addSquare = _.flowRight([square, _.add]);\n * addSquare(1, 2);\n * // => 9\n */\n var flowRight = createFlow(true);\n\n /**\n * This method returns the first argument it receives.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {*} value Any value.\n * @returns {*} Returns `value`.\n * @example\n *\n * var object = { 'a': 1 };\n *\n * console.log(_.identity(object) === object);\n * // => true\n */\n function identity(value) {\n return value;\n }\n\n /**\n * Creates a function that invokes `func` with the arguments of the created\n * function. If `func` is a property name, the created function returns the\n * property value for a given element. If `func` is an array or object, the\n * created function returns `true` for elements that contain the equivalent\n * source properties, otherwise it returns `false`.\n *\n * @static\n * @since 4.0.0\n * @memberOf _\n * @category Util\n * @param {*} [func=_.identity] The value to convert to a callback.\n * @returns {Function} Returns the callback.\n * @example\n *\n * var users = [\n * { 'user': 'barney', 'age': 36, 'active': true },\n * { 'user': 'fred', 'age': 40, 'active': false }\n * ];\n *\n * // The `_.matches` iteratee shorthand.\n * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));\n * // => [{ 'user': 'barney', 'age': 36, 'active': true }]\n *\n * // The `_.matchesProperty` iteratee shorthand.\n * _.filter(users, _.iteratee(['user', 'fred']));\n * // => [{ 'user': 'fred', 'age': 40 }]\n *\n * // The `_.property` iteratee shorthand.\n * _.map(users, _.iteratee('user'));\n * // => ['barney', 'fred']\n *\n * // Create custom iteratee shorthands.\n * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {\n * return !_.isRegExp(func) ? iteratee(func) : function(string) {\n * return func.test(string);\n * };\n * });\n *\n * _.filter(['abc', 'def'], /ef/);\n * // => ['def']\n */\n function iteratee(func) {\n return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG));\n }\n\n /**\n * Creates a function that performs a partial deep comparison between a given\n * object and `source`, returning `true` if the given object has equivalent\n * property values, else `false`.\n *\n * **Note:** The created function is equivalent to `_.isMatch` with `source`\n * partially applied.\n *\n * Partial comparisons will match empty array and empty object `source`\n * values against any array or object value, respectively. See `_.isEqual`\n * for a list of supported value comparisons.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Util\n * @param {Object} source The object of property values to match.\n * @returns {Function} Returns the new spec function.\n * @example\n *\n * var objects = [\n * { 'a': 1, 'b': 2, 'c': 3 },\n * { 'a': 4, 'b': 5, 'c': 6 }\n * ];\n *\n * _.filter(objects, _.matches({ 'a': 4, 'c': 6 }));\n * // => [{ 'a': 4, 'b': 5, 'c': 6 }]\n */\n function matches(source) {\n return baseMatches(baseClone(source, CLONE_DEEP_FLAG));\n }\n\n /**\n * Creates a function that performs a partial deep comparison between the\n * value at `path` of a given object to `srcValue`, returning `true` if the\n * object value is equivalent, else `false`.\n *\n * **Note:** Partial comparisons will match empty array and empty object\n * `srcValue` values against any array or object value, respectively. See\n * `_.isEqual` for a list of supported value comparisons.\n *\n * @static\n * @memberOf _\n * @since 3.2.0\n * @category Util\n * @param {Array|string} path The path of the property to get.\n * @param {*} srcValue The value to match.\n * @returns {Function} Returns the new spec function.\n * @example\n *\n * var objects = [\n * { 'a': 1, 'b': 2, 'c': 3 },\n * { 'a': 4, 'b': 5, 'c': 6 }\n * ];\n *\n * _.find(objects, _.matchesProperty('a', 4));\n * // => { 'a': 4, 'b': 5, 'c': 6 }\n */\n function matchesProperty(path, srcValue) {\n return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));\n }\n\n /**\n * Creates a function that invokes the method at `path` of a given object.\n * Any additional arguments are provided to the invoked method.\n *\n * @static\n * @memberOf _\n * @since 3.7.0\n * @category Util\n * @param {Array|string} path The path of the method to invoke.\n * @param {...*} [args] The arguments to invoke the method with.\n * @returns {Function} Returns the new invoker function.\n * @example\n *\n * var objects = [\n * { 'a': { 'b': _.constant(2) } },\n * { 'a': { 'b': _.constant(1) } }\n * ];\n *\n * _.map(objects, _.method('a.b'));\n * // => [2, 1]\n *\n * _.map(objects, _.method(['a', 'b']));\n * // => [2, 1]\n */\n var method = baseRest(function(path, args) {\n return function(object) {\n return baseInvoke(object, path, args);\n };\n });\n\n /**\n * The opposite of `_.method`; this method creates a function that invokes\n * the method at a given path of `object`. Any additional arguments are\n * provided to the invoked method.\n *\n * @static\n * @memberOf _\n * @since 3.7.0\n * @category Util\n * @param {Object} object The object to query.\n * @param {...*} [args] The arguments to invoke the method with.\n * @returns {Function} Returns the new invoker function.\n * @example\n *\n * var array = _.times(3, _.constant),\n * object = { 'a': array, 'b': array, 'c': array };\n *\n * _.map(['a[2]', 'c[0]'], _.methodOf(object));\n * // => [2, 0]\n *\n * _.map([['a', '2'], ['c', '0']], _.methodOf(object));\n * // => [2, 0]\n */\n var methodOf = baseRest(function(object, args) {\n return function(path) {\n return baseInvoke(object, path, args);\n };\n });\n\n /**\n * Adds all own enumerable string keyed function properties of a source\n * object to the destination object. If `object` is a function, then methods\n * are added to its prototype as well.\n *\n * **Note:** Use `_.runInContext` to create a pristine `lodash` function to\n * avoid conflicts caused by modifying the original.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {Function|Object} [object=lodash] The destination object.\n * @param {Object} source The object of functions to add.\n * @param {Object} [options={}] The options object.\n * @param {boolean} [options.chain=true] Specify whether mixins are chainable.\n * @returns {Function|Object} Returns `object`.\n * @example\n *\n * function vowels(string) {\n * return _.filter(string, function(v) {\n * return /[aeiou]/i.test(v);\n * });\n * }\n *\n * _.mixin({ 'vowels': vowels });\n * _.vowels('fred');\n * // => ['e']\n *\n * _('fred').vowels().value();\n * // => ['e']\n *\n * _.mixin({ 'vowels': vowels }, { 'chain': false });\n * _('fred').vowels();\n * // => ['e']\n */\n function mixin(object, source, options) {\n var props = keys(source),\n methodNames = baseFunctions(source, props);\n\n if (options == null &&\n !(isObject(source) && (methodNames.length || !props.length))) {\n options = source;\n source = object;\n object = this;\n methodNames = baseFunctions(source, keys(source));\n }\n var chain = !(isObject(options) && 'chain' in options) || !!options.chain,\n isFunc = isFunction(object);\n\n arrayEach(methodNames, function(methodName) {\n var func = source[methodName];\n object[methodName] = func;\n if (isFunc) {\n object.prototype[methodName] = function() {\n var chainAll = this.__chain__;\n if (chain || chainAll) {\n var result = object(this.__wrapped__),\n actions = result.__actions__ = copyArray(this.__actions__);\n\n actions.push({ 'func': func, 'args': arguments, 'thisArg': object });\n result.__chain__ = chainAll;\n return result;\n }\n return func.apply(object, arrayPush([this.value()], arguments));\n };\n }\n });\n\n return object;\n }\n\n /**\n * Reverts the `_` variable to its previous value and returns a reference to\n * the `lodash` function.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @returns {Function} Returns the `lodash` function.\n * @example\n *\n * var lodash = _.noConflict();\n */\n function noConflict() {\n if (root._ === this) {\n root._ = oldDash;\n }\n return this;\n }\n\n /**\n * This method returns `undefined`.\n *\n * @static\n * @memberOf _\n * @since 2.3.0\n * @category Util\n * @example\n *\n * _.times(2, _.noop);\n * // => [undefined, undefined]\n */\n function noop() {\n // No operation performed.\n }\n\n /**\n * Creates a function that gets the argument at index `n`. If `n` is negative,\n * the nth argument from the end is returned.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Util\n * @param {number} [n=0] The index of the argument to return.\n * @returns {Function} Returns the new pass-thru function.\n * @example\n *\n * var func = _.nthArg(1);\n * func('a', 'b', 'c', 'd');\n * // => 'b'\n *\n * var func = _.nthArg(-2);\n * func('a', 'b', 'c', 'd');\n * // => 'c'\n */\n function nthArg(n) {\n n = toInteger(n);\n return baseRest(function(args) {\n return baseNth(args, n);\n });\n }\n\n /**\n * Creates a function that invokes `iteratees` with the arguments it receives\n * and returns their results.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Util\n * @param {...(Function|Function[])} [iteratees=[_.identity]]\n * The iteratees to invoke.\n * @returns {Function} Returns the new function.\n * @example\n *\n * var func = _.over([Math.max, Math.min]);\n *\n * func(1, 2, 3, 4);\n * // => [4, 1]\n */\n var over = createOver(arrayMap);\n\n /**\n * Creates a function that checks if **all** of the `predicates` return\n * truthy when invoked with the arguments it receives.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Util\n * @param {...(Function|Function[])} [predicates=[_.identity]]\n * The predicates to check.\n * @returns {Function} Returns the new function.\n * @example\n *\n * var func = _.overEvery([Boolean, isFinite]);\n *\n * func('1');\n * // => true\n *\n * func(null);\n * // => false\n *\n * func(NaN);\n * // => false\n */\n var overEvery = createOver(arrayEvery);\n\n /**\n * Creates a function that checks if **any** of the `predicates` return\n * truthy when invoked with the arguments it receives.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Util\n * @param {...(Function|Function[])} [predicates=[_.identity]]\n * The predicates to check.\n * @returns {Function} Returns the new function.\n * @example\n *\n * var func = _.overSome([Boolean, isFinite]);\n *\n * func('1');\n * // => true\n *\n * func(null);\n * // => true\n *\n * func(NaN);\n * // => false\n */\n var overSome = createOver(arraySome);\n\n /**\n * Creates a function that returns the value at `path` of a given object.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Util\n * @param {Array|string} path The path of the property to get.\n * @returns {Function} Returns the new accessor function.\n * @example\n *\n * var objects = [\n * { 'a': { 'b': 2 } },\n * { 'a': { 'b': 1 } }\n * ];\n *\n * _.map(objects, _.property('a.b'));\n * // => [2, 1]\n *\n * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');\n * // => [1, 2]\n */\n function property(path) {\n return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);\n }\n\n /**\n * The opposite of `_.property`; this method creates a function that returns\n * the value at a given path of `object`.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Util\n * @param {Object} object The object to query.\n * @returns {Function} Returns the new accessor function.\n * @example\n *\n * var array = [0, 1, 2],\n * object = { 'a': array, 'b': array, 'c': array };\n *\n * _.map(['a[2]', 'c[0]'], _.propertyOf(object));\n * // => [2, 0]\n *\n * _.map([['a', '2'], ['c', '0']], _.propertyOf(object));\n * // => [2, 0]\n */\n function propertyOf(object) {\n return function(path) {\n return object == null ? undefined : baseGet(object, path);\n };\n }\n\n /**\n * Creates an array of numbers (positive and/or negative) progressing from\n * `start` up to, but not including, `end`. A step of `-1` is used if a negative\n * `start` is specified without an `end` or `step`. If `end` is not specified,\n * it's set to `start` with `start` then set to `0`.\n *\n * **Note:** JavaScript follows the IEEE-754 standard for resolving\n * floating-point values which can produce unexpected results.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {number} [start=0] The start of the range.\n * @param {number} end The end of the range.\n * @param {number} [step=1] The value to increment or decrement by.\n * @returns {Array} Returns the range of numbers.\n * @see _.inRange, _.rangeRight\n * @example\n *\n * _.range(4);\n * // => [0, 1, 2, 3]\n *\n * _.range(-4);\n * // => [0, -1, -2, -3]\n *\n * _.range(1, 5);\n * // => [1, 2, 3, 4]\n *\n * _.range(0, 20, 5);\n * // => [0, 5, 10, 15]\n *\n * _.range(0, -4, -1);\n * // => [0, -1, -2, -3]\n *\n * _.range(1, 4, 0);\n * // => [1, 1, 1]\n *\n * _.range(0);\n * // => []\n */\n var range = createRange();\n\n /**\n * This method is like `_.range` except that it populates values in\n * descending order.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Util\n * @param {number} [start=0] The start of the range.\n * @param {number} end The end of the range.\n * @param {number} [step=1] The value to increment or decrement by.\n * @returns {Array} Returns the range of numbers.\n * @see _.inRange, _.range\n * @example\n *\n * _.rangeRight(4);\n * // => [3, 2, 1, 0]\n *\n * _.rangeRight(-4);\n * // => [-3, -2, -1, 0]\n *\n * _.rangeRight(1, 5);\n * // => [4, 3, 2, 1]\n *\n * _.rangeRight(0, 20, 5);\n * // => [15, 10, 5, 0]\n *\n * _.rangeRight(0, -4, -1);\n * // => [-3, -2, -1, 0]\n *\n * _.rangeRight(1, 4, 0);\n * // => [1, 1, 1]\n *\n * _.rangeRight(0);\n * // => []\n */\n var rangeRight = createRange(true);\n\n /**\n * This method returns a new empty array.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {Array} Returns the new empty array.\n * @example\n *\n * var arrays = _.times(2, _.stubArray);\n *\n * console.log(arrays);\n * // => [[], []]\n *\n * console.log(arrays[0] === arrays[1]);\n * // => false\n */\n function stubArray() {\n return [];\n }\n\n /**\n * This method returns `false`.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {boolean} Returns `false`.\n * @example\n *\n * _.times(2, _.stubFalse);\n * // => [false, false]\n */\n function stubFalse() {\n return false;\n }\n\n /**\n * This method returns a new empty object.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {Object} Returns the new empty object.\n * @example\n *\n * var objects = _.times(2, _.stubObject);\n *\n * console.log(objects);\n * // => [{}, {}]\n *\n * console.log(objects[0] === objects[1]);\n * // => false\n */\n function stubObject() {\n return {};\n }\n\n /**\n * This method returns an empty string.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {string} Returns the empty string.\n * @example\n *\n * _.times(2, _.stubString);\n * // => ['', '']\n */\n function stubString() {\n return '';\n }\n\n /**\n * This method returns `true`.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {boolean} Returns `true`.\n * @example\n *\n * _.times(2, _.stubTrue);\n * // => [true, true]\n */\n function stubTrue() {\n return true;\n }\n\n /**\n * Invokes the iteratee `n` times, returning an array of the results of\n * each invocation. The iteratee is invoked with one argument; (index).\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n * @example\n *\n * _.times(3, String);\n * // => ['0', '1', '2']\n *\n * _.times(4, _.constant(0));\n * // => [0, 0, 0, 0]\n */\n function times(n, iteratee) {\n n = toInteger(n);\n if (n < 1 || n > MAX_SAFE_INTEGER) {\n return [];\n }\n var index = MAX_ARRAY_LENGTH,\n length = nativeMin(n, MAX_ARRAY_LENGTH);\n\n iteratee = getIteratee(iteratee);\n n -= MAX_ARRAY_LENGTH;\n\n var result = baseTimes(length, iteratee);\n while (++index < n) {\n iteratee(index);\n }\n return result;\n }\n\n /**\n * Converts `value` to a property path array.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Util\n * @param {*} value The value to convert.\n * @returns {Array} Returns the new property path array.\n * @example\n *\n * _.toPath('a.b.c');\n * // => ['a', 'b', 'c']\n *\n * _.toPath('a[0].b.c');\n * // => ['a', '0', 'b', 'c']\n */\n function toPath(value) {\n if (isArray(value)) {\n return arrayMap(value, toKey);\n }\n return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));\n }\n\n /**\n * Generates a unique ID. If `prefix` is given, the ID is appended to it.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {string} [prefix=''] The value to prefix the ID with.\n * @returns {string} Returns the unique ID.\n * @example\n *\n * _.uniqueId('contact_');\n * // => 'contact_104'\n *\n * _.uniqueId();\n * // => '105'\n */\n function uniqueId(prefix) {\n var id = ++idCounter;\n return toString(prefix) + id;\n }\n\n /*------------------------------------------------------------------------*/\n\n /**\n * Adds two numbers.\n *\n * @static\n * @memberOf _\n * @since 3.4.0\n * @category Math\n * @param {number} augend The first number in an addition.\n * @param {number} addend The second number in an addition.\n * @returns {number} Returns the total.\n * @example\n *\n * _.add(6, 4);\n * // => 10\n */\n var add = createMathOperation(function(augend, addend) {\n return augend + addend;\n }, 0);\n\n /**\n * Computes `number` rounded up to `precision`.\n *\n * @static\n * @memberOf _\n * @since 3.10.0\n * @category Math\n * @param {number} number The number to round up.\n * @param {number} [precision=0] The precision to round up to.\n * @returns {number} Returns the rounded up number.\n * @example\n *\n * _.ceil(4.006);\n * // => 5\n *\n * _.ceil(6.004, 2);\n * // => 6.01\n *\n * _.ceil(6040, -2);\n * // => 6100\n */\n var ceil = createRound('ceil');\n\n /**\n * Divide two numbers.\n *\n * @static\n * @memberOf _\n * @since 4.7.0\n * @category Math\n * @param {number} dividend The first number in a division.\n * @param {number} divisor The second number in a division.\n * @returns {number} Returns the quotient.\n * @example\n *\n * _.divide(6, 4);\n * // => 1.5\n */\n var divide = createMathOperation(function(dividend, divisor) {\n return dividend / divisor;\n }, 1);\n\n /**\n * Computes `number` rounded down to `precision`.\n *\n * @static\n * @memberOf _\n * @since 3.10.0\n * @category Math\n * @param {number} number The number to round down.\n * @param {number} [precision=0] The precision to round down to.\n * @returns {number} Returns the rounded down number.\n * @example\n *\n * _.floor(4.006);\n * // => 4\n *\n * _.floor(0.046, 2);\n * // => 0.04\n *\n * _.floor(4060, -2);\n * // => 4000\n */\n var floor = createRound('floor');\n\n /**\n * Computes the maximum value of `array`. If `array` is empty or falsey,\n * `undefined` is returned.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Math\n * @param {Array} array The array to iterate over.\n * @returns {*} Returns the maximum value.\n * @example\n *\n * _.max([4, 2, 8, 6]);\n * // => 8\n *\n * _.max([]);\n * // => undefined\n */\n function max(array) {\n return (array && array.length)\n ? baseExtremum(array, identity, baseGt)\n : undefined;\n }\n\n /**\n * This method is like `_.max` except that it accepts `iteratee` which is\n * invoked for each element in `array` to generate the criterion by which\n * the value is ranked. The iteratee is invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Math\n * @param {Array} array The array to iterate over.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {*} Returns the maximum value.\n * @example\n *\n * var objects = [{ 'n': 1 }, { 'n': 2 }];\n *\n * _.maxBy(objects, function(o) { return o.n; });\n * // => { 'n': 2 }\n *\n * // The `_.property` iteratee shorthand.\n * _.maxBy(objects, 'n');\n * // => { 'n': 2 }\n */\n function maxBy(array, iteratee) {\n return (array && array.length)\n ? baseExtremum(array, getIteratee(iteratee, 2), baseGt)\n : undefined;\n }\n\n /**\n * Computes the mean of the values in `array`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Math\n * @param {Array} array The array to iterate over.\n * @returns {number} Returns the mean.\n * @example\n *\n * _.mean([4, 2, 8, 6]);\n * // => 5\n */\n function mean(array) {\n return baseMean(array, identity);\n }\n\n /**\n * This method is like `_.mean` except that it accepts `iteratee` which is\n * invoked for each element in `array` to generate the value to be averaged.\n * The iteratee is invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 4.7.0\n * @category Math\n * @param {Array} array The array to iterate over.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {number} Returns the mean.\n * @example\n *\n * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];\n *\n * _.meanBy(objects, function(o) { return o.n; });\n * // => 5\n *\n * // The `_.property` iteratee shorthand.\n * _.meanBy(objects, 'n');\n * // => 5\n */\n function meanBy(array, iteratee) {\n return baseMean(array, getIteratee(iteratee, 2));\n }\n\n /**\n * Computes the minimum value of `array`. If `array` is empty or falsey,\n * `undefined` is returned.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Math\n * @param {Array} array The array to iterate over.\n * @returns {*} Returns the minimum value.\n * @example\n *\n * _.min([4, 2, 8, 6]);\n * // => 2\n *\n * _.min([]);\n * // => undefined\n */\n function min(array) {\n return (array && array.length)\n ? baseExtremum(array, identity, baseLt)\n : undefined;\n }\n\n /**\n * This method is like `_.min` except that it accepts `iteratee` which is\n * invoked for each element in `array` to generate the criterion by which\n * the value is ranked. The iteratee is invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Math\n * @param {Array} array The array to iterate over.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {*} Returns the minimum value.\n * @example\n *\n * var objects = [{ 'n': 1 }, { 'n': 2 }];\n *\n * _.minBy(objects, function(o) { return o.n; });\n * // => { 'n': 1 }\n *\n * // The `_.property` iteratee shorthand.\n * _.minBy(objects, 'n');\n * // => { 'n': 1 }\n */\n function minBy(array, iteratee) {\n return (array && array.length)\n ? baseExtremum(array, getIteratee(iteratee, 2), baseLt)\n : undefined;\n }\n\n /**\n * Multiply two numbers.\n *\n * @static\n * @memberOf _\n * @since 4.7.0\n * @category Math\n * @param {number} multiplier The first number in a multiplication.\n * @param {number} multiplicand The second number in a multiplication.\n * @returns {number} Returns the product.\n * @example\n *\n * _.multiply(6, 4);\n * // => 24\n */\n var multiply = createMathOperation(function(multiplier, multiplicand) {\n return multiplier * multiplicand;\n }, 1);\n\n /**\n * Computes `number` rounded to `precision`.\n *\n * @static\n * @memberOf _\n * @since 3.10.0\n * @category Math\n * @param {number} number The number to round.\n * @param {number} [precision=0] The precision to round to.\n * @returns {number} Returns the rounded number.\n * @example\n *\n * _.round(4.006);\n * // => 4\n *\n * _.round(4.006, 2);\n * // => 4.01\n *\n * _.round(4060, -2);\n * // => 4100\n */\n var round = createRound('round');\n\n /**\n * Subtract two numbers.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Math\n * @param {number} minuend The first number in a subtraction.\n * @param {number} subtrahend The second number in a subtraction.\n * @returns {number} Returns the difference.\n * @example\n *\n * _.subtract(6, 4);\n * // => 2\n */\n var subtract = createMathOperation(function(minuend, subtrahend) {\n return minuend - subtrahend;\n }, 0);\n\n /**\n * Computes the sum of the values in `array`.\n *\n * @static\n * @memberOf _\n * @since 3.4.0\n * @category Math\n * @param {Array} array The array to iterate over.\n * @returns {number} Returns the sum.\n * @example\n *\n * _.sum([4, 2, 8, 6]);\n * // => 20\n */\n function sum(array) {\n return (array && array.length)\n ? baseSum(array, identity)\n : 0;\n }\n\n /**\n * This method is like `_.sum` except that it accepts `iteratee` which is\n * invoked for each element in `array` to generate the value to be summed.\n * The iteratee is invoked with one argument: (value).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Math\n * @param {Array} array The array to iterate over.\n * @param {Function} [iteratee=_.identity] The iteratee invoked per element.\n * @returns {number} Returns the sum.\n * @example\n *\n * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];\n *\n * _.sumBy(objects, function(o) { return o.n; });\n * // => 20\n *\n * // The `_.property` iteratee shorthand.\n * _.sumBy(objects, 'n');\n * // => 20\n */\n function sumBy(array, iteratee) {\n return (array && array.length)\n ? baseSum(array, getIteratee(iteratee, 2))\n : 0;\n }\n\n /*------------------------------------------------------------------------*/\n\n // Add methods that return wrapped values in chain sequences.\n lodash.after = after;\n lodash.ary = ary;\n lodash.assign = assign;\n lodash.assignIn = assignIn;\n lodash.assignInWith = assignInWith;\n lodash.assignWith = assignWith;\n lodash.at = at;\n lodash.before = before;\n lodash.bind = bind;\n lodash.bindAll = bindAll;\n lodash.bindKey = bindKey;\n lodash.castArray = castArray;\n lodash.chain = chain;\n lodash.chunk = chunk;\n lodash.compact = compact;\n lodash.concat = concat;\n lodash.cond = cond;\n lodash.conforms = conforms;\n lodash.constant = constant;\n lodash.countBy = countBy;\n lodash.create = create;\n lodash.curry = curry;\n lodash.curryRight = curryRight;\n lodash.debounce = debounce;\n lodash.defaults = defaults;\n lodash.defaultsDeep = defaultsDeep;\n lodash.defer = defer;\n lodash.delay = delay;\n lodash.difference = difference;\n lodash.differenceBy = differenceBy;\n lodash.differenceWith = differenceWith;\n lodash.drop = drop;\n lodash.dropRight = dropRight;\n lodash.dropRightWhile = dropRightWhile;\n lodash.dropWhile = dropWhile;\n lodash.fill = fill;\n lodash.filter = filter;\n lodash.flatMap = flatMap;\n lodash.flatMapDeep = flatMapDeep;\n lodash.flatMapDepth = flatMapDepth;\n lodash.flatten = flatten;\n lodash.flattenDeep = flattenDeep;\n lodash.flattenDepth = flattenDepth;\n lodash.flip = flip;\n lodash.flow = flow;\n lodash.flowRight = flowRight;\n lodash.fromPairs = fromPairs;\n lodash.functions = functions;\n lodash.functionsIn = functionsIn;\n lodash.groupBy = groupBy;\n lodash.initial = initial;\n lodash.intersection = intersection;\n lodash.intersectionBy = intersectionBy;\n lodash.intersectionWith = intersectionWith;\n lodash.invert = invert;\n lodash.invertBy = invertBy;\n lodash.invokeMap = invokeMap;\n lodash.iteratee = iteratee;\n lodash.keyBy = keyBy;\n lodash.keys = keys;\n lodash.keysIn = keysIn;\n lodash.map = map;\n lodash.mapKeys = mapKeys;\n lodash.mapValues = mapValues;\n lodash.matches = matches;\n lodash.matchesProperty = matchesProperty;\n lodash.memoize = memoize;\n lodash.merge = merge;\n lodash.mergeWith = mergeWith;\n lodash.method = method;\n lodash.methodOf = methodOf;\n lodash.mixin = mixin;\n lodash.negate = negate;\n lodash.nthArg = nthArg;\n lodash.omit = omit;\n lodash.omitBy = omitBy;\n lodash.once = once;\n lodash.orderBy = orderBy;\n lodash.over = over;\n lodash.overArgs = overArgs;\n lodash.overEvery = overEvery;\n lodash.overSome = overSome;\n lodash.partial = partial;\n lodash.partialRight = partialRight;\n lodash.partition = partition;\n lodash.pick = pick;\n lodash.pickBy = pickBy;\n lodash.property = property;\n lodash.propertyOf = propertyOf;\n lodash.pull = pull;\n lodash.pullAll = pullAll;\n lodash.pullAllBy = pullAllBy;\n lodash.pullAllWith = pullAllWith;\n lodash.pullAt = pullAt;\n lodash.range = range;\n lodash.rangeRight = rangeRight;\n lodash.rearg = rearg;\n lodash.reject = reject;\n lodash.remove = remove;\n lodash.rest = rest;\n lodash.reverse = reverse;\n lodash.sampleSize = sampleSize;\n lodash.set = set;\n lodash.setWith = setWith;\n lodash.shuffle = shuffle;\n lodash.slice = slice;\n lodash.sortBy = sortBy;\n lodash.sortedUniq = sortedUniq;\n lodash.sortedUniqBy = sortedUniqBy;\n lodash.split = split;\n lodash.spread = spread;\n lodash.tail = tail;\n lodash.take = take;\n lodash.takeRight = takeRight;\n lodash.takeRightWhile = takeRightWhile;\n lodash.takeWhile = takeWhile;\n lodash.tap = tap;\n lodash.throttle = throttle;\n lodash.thru = thru;\n lodash.toArray = toArray;\n lodash.toPairs = toPairs;\n lodash.toPairsIn = toPairsIn;\n lodash.toPath = toPath;\n lodash.toPlainObject = toPlainObject;\n lodash.transform = transform;\n lodash.unary = unary;\n lodash.union = union;\n lodash.unionBy = unionBy;\n lodash.unionWith = unionWith;\n lodash.uniq = uniq;\n lodash.uniqBy = uniqBy;\n lodash.uniqWith = uniqWith;\n lodash.unset = unset;\n lodash.unzip = unzip;\n lodash.unzipWith = unzipWith;\n lodash.update = update;\n lodash.updateWith = updateWith;\n lodash.values = values;\n lodash.valuesIn = valuesIn;\n lodash.without = without;\n lodash.words = words;\n lodash.wrap = wrap;\n lodash.xor = xor;\n lodash.xorBy = xorBy;\n lodash.xorWith = xorWith;\n lodash.zip = zip;\n lodash.zipObject = zipObject;\n lodash.zipObjectDeep = zipObjectDeep;\n lodash.zipWith = zipWith;\n\n // Add aliases.\n lodash.entries = toPairs;\n lodash.entriesIn = toPairsIn;\n lodash.extend = assignIn;\n lodash.extendWith = assignInWith;\n\n // Add methods to `lodash.prototype`.\n mixin(lodash, lodash);\n\n /*------------------------------------------------------------------------*/\n\n // Add methods that return unwrapped values in chain sequences.\n lodash.add = add;\n lodash.attempt = attempt;\n lodash.camelCase = camelCase;\n lodash.capitalize = capitalize;\n lodash.ceil = ceil;\n lodash.clamp = clamp;\n lodash.clone = clone;\n lodash.cloneDeep = cloneDeep;\n lodash.cloneDeepWith = cloneDeepWith;\n lodash.cloneWith = cloneWith;\n lodash.conformsTo = conformsTo;\n lodash.deburr = deburr;\n lodash.defaultTo = defaultTo;\n lodash.divide = divide;\n lodash.endsWith = endsWith;\n lodash.eq = eq;\n lodash.escape = escape;\n lodash.escapeRegExp = escapeRegExp;\n lodash.every = every;\n lodash.find = find;\n lodash.findIndex = findIndex;\n lodash.findKey = findKey;\n lodash.findLast = findLast;\n lodash.findLastIndex = findLastIndex;\n lodash.findLastKey = findLastKey;\n lodash.floor = floor;\n lodash.forEach = forEach;\n lodash.forEachRight = forEachRight;\n lodash.forIn = forIn;\n lodash.forInRight = forInRight;\n lodash.forOwn = forOwn;\n lodash.forOwnRight = forOwnRight;\n lodash.get = get;\n lodash.gt = gt;\n lodash.gte = gte;\n lodash.has = has;\n lodash.hasIn = hasIn;\n lodash.head = head;\n lodash.identity = identity;\n lodash.includes = includes;\n lodash.indexOf = indexOf;\n lodash.inRange = inRange;\n lodash.invoke = invoke;\n lodash.isArguments = isArguments;\n lodash.isArray = isArray;\n lodash.isArrayBuffer = isArrayBuffer;\n lodash.isArrayLike = isArrayLike;\n lodash.isArrayLikeObject = isArrayLikeObject;\n lodash.isBoolean = isBoolean;\n lodash.isBuffer = isBuffer;\n lodash.isDate = isDate;\n lodash.isElement = isElement;\n lodash.isEmpty = isEmpty;\n lodash.isEqual = isEqual;\n lodash.isEqualWith = isEqualWith;\n lodash.isError = isError;\n lodash.isFinite = isFinite;\n lodash.isFunction = isFunction;\n lodash.isInteger = isInteger;\n lodash.isLength = isLength;\n lodash.isMap = isMap;\n lodash.isMatch = isMatch;\n lodash.isMatchWith = isMatchWith;\n lodash.isNaN = isNaN;\n lodash.isNative = isNative;\n lodash.isNil = isNil;\n lodash.isNull = isNull;\n lodash.isNumber = isNumber;\n lodash.isObject = isObject;\n lodash.isObjectLike = isObjectLike;\n lodash.isPlainObject = isPlainObject;\n lodash.isRegExp = isRegExp;\n lodash.isSafeInteger = isSafeInteger;\n lodash.isSet = isSet;\n lodash.isString = isString;\n lodash.isSymbol = isSymbol;\n lodash.isTypedArray = isTypedArray;\n lodash.isUndefined = isUndefined;\n lodash.isWeakMap = isWeakMap;\n lodash.isWeakSet = isWeakSet;\n lodash.join = join;\n lodash.kebabCase = kebabCase;\n lodash.last = last;\n lodash.lastIndexOf = lastIndexOf;\n lodash.lowerCase = lowerCase;\n lodash.lowerFirst = lowerFirst;\n lodash.lt = lt;\n lodash.lte = lte;\n lodash.max = max;\n lodash.maxBy = maxBy;\n lodash.mean = mean;\n lodash.meanBy = meanBy;\n lodash.min = min;\n lodash.minBy = minBy;\n lodash.stubArray = stubArray;\n lodash.stubFalse = stubFalse;\n lodash.stubObject = stubObject;\n lodash.stubString = stubString;\n lodash.stubTrue = stubTrue;\n lodash.multiply = multiply;\n lodash.nth = nth;\n lodash.noConflict = noConflict;\n lodash.noop = noop;\n lodash.now = now;\n lodash.pad = pad;\n lodash.padEnd = padEnd;\n lodash.padStart = padStart;\n lodash.parseInt = parseInt;\n lodash.random = random;\n lodash.reduce = reduce;\n lodash.reduceRight = reduceRight;\n lodash.repeat = repeat;\n lodash.replace = replace;\n lodash.result = result;\n lodash.round = round;\n lodash.runInContext = runInContext;\n lodash.sample = sample;\n lodash.size = size;\n lodash.snakeCase = snakeCase;\n lodash.some = some;\n lodash.sortedIndex = sortedIndex;\n lodash.sortedIndexBy = sortedIndexBy;\n lodash.sortedIndexOf = sortedIndexOf;\n lodash.sortedLastIndex = sortedLastIndex;\n lodash.sortedLastIndexBy = sortedLastIndexBy;\n lodash.sortedLastIndexOf = sortedLastIndexOf;\n lodash.startCase = startCase;\n lodash.startsWith = startsWith;\n lodash.subtract = subtract;\n lodash.sum = sum;\n lodash.sumBy = sumBy;\n lodash.template = template;\n lodash.times = times;\n lodash.toFinite = toFinite;\n lodash.toInteger = toInteger;\n lodash.toLength = toLength;\n lodash.toLower = toLower;\n lodash.toNumber = toNumber;\n lodash.toSafeInteger = toSafeInteger;\n lodash.toString = toString;\n lodash.toUpper = toUpper;\n lodash.trim = trim;\n lodash.trimEnd = trimEnd;\n lodash.trimStart = trimStart;\n lodash.truncate = truncate;\n lodash.unescape = unescape;\n lodash.uniqueId = uniqueId;\n lodash.upperCase = upperCase;\n lodash.upperFirst = upperFirst;\n\n // Add aliases.\n lodash.each = forEach;\n lodash.eachRight = forEachRight;\n lodash.first = head;\n\n mixin(lodash, (function() {\n var source = {};\n baseForOwn(lodash, function(func, methodName) {\n if (!hasOwnProperty.call(lodash.prototype, methodName)) {\n source[methodName] = func;\n }\n });\n return source;\n }()), { 'chain': false });\n\n /*------------------------------------------------------------------------*/\n\n /**\n * The semantic version number.\n *\n * @static\n * @memberOf _\n * @type {string}\n */\n lodash.VERSION = VERSION;\n\n // Assign default placeholders.\n arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {\n lodash[methodName].placeholder = lodash;\n });\n\n // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.\n arrayEach(['drop', 'take'], function(methodName, index) {\n LazyWrapper.prototype[methodName] = function(n) {\n n = n === undefined ? 1 : nativeMax(toInteger(n), 0);\n\n var result = (this.__filtered__ && !index)\n ? new LazyWrapper(this)\n : this.clone();\n\n if (result.__filtered__) {\n result.__takeCount__ = nativeMin(n, result.__takeCount__);\n } else {\n result.__views__.push({\n 'size': nativeMin(n, MAX_ARRAY_LENGTH),\n 'type': methodName + (result.__dir__ < 0 ? 'Right' : '')\n });\n }\n return result;\n };\n\n LazyWrapper.prototype[methodName + 'Right'] = function(n) {\n return this.reverse()[methodName](n).reverse();\n };\n });\n\n // Add `LazyWrapper` methods that accept an `iteratee` value.\n arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {\n var type = index + 1,\n isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;\n\n LazyWrapper.prototype[methodName] = function(iteratee) {\n var result = this.clone();\n result.__iteratees__.push({\n 'iteratee': getIteratee(iteratee, 3),\n 'type': type\n });\n result.__filtered__ = result.__filtered__ || isFilter;\n return result;\n };\n });\n\n // Add `LazyWrapper` methods for `_.head` and `_.last`.\n arrayEach(['head', 'last'], function(methodName, index) {\n var takeName = 'take' + (index ? 'Right' : '');\n\n LazyWrapper.prototype[methodName] = function() {\n return this[takeName](1).value()[0];\n };\n });\n\n // Add `LazyWrapper` methods for `_.initial` and `_.tail`.\n arrayEach(['initial', 'tail'], function(methodName, index) {\n var dropName = 'drop' + (index ? '' : 'Right');\n\n LazyWrapper.prototype[methodName] = function() {\n return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);\n };\n });\n\n LazyWrapper.prototype.compact = function() {\n return this.filter(identity);\n };\n\n LazyWrapper.prototype.find = function(predicate) {\n return this.filter(predicate).head();\n };\n\n LazyWrapper.prototype.findLast = function(predicate) {\n return this.reverse().find(predicate);\n };\n\n LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {\n if (typeof path == 'function') {\n return new LazyWrapper(this);\n }\n return this.map(function(value) {\n return baseInvoke(value, path, args);\n });\n });\n\n LazyWrapper.prototype.reject = function(predicate) {\n return this.filter(negate(getIteratee(predicate)));\n };\n\n LazyWrapper.prototype.slice = function(start, end) {\n start = toInteger(start);\n\n var result = this;\n if (result.__filtered__ && (start > 0 || end < 0)) {\n return new LazyWrapper(result);\n }\n if (start < 0) {\n result = result.takeRight(-start);\n } else if (start) {\n result = result.drop(start);\n }\n if (end !== undefined) {\n end = toInteger(end);\n result = end < 0 ? result.dropRight(-end) : result.take(end - start);\n }\n return result;\n };\n\n LazyWrapper.prototype.takeRightWhile = function(predicate) {\n return this.reverse().takeWhile(predicate).reverse();\n };\n\n LazyWrapper.prototype.toArray = function() {\n return this.take(MAX_ARRAY_LENGTH);\n };\n\n // Add `LazyWrapper` methods to `lodash.prototype`.\n baseForOwn(LazyWrapper.prototype, function(func, methodName) {\n var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),\n isTaker = /^(?:head|last)$/.test(methodName),\n lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName],\n retUnwrapped = isTaker || /^find/.test(methodName);\n\n if (!lodashFunc) {\n return;\n }\n lodash.prototype[methodName] = function() {\n var value = this.__wrapped__,\n args = isTaker ? [1] : arguments,\n isLazy = value instanceof LazyWrapper,\n iteratee = args[0],\n useLazy = isLazy || isArray(value);\n\n var interceptor = function(value) {\n var result = lodashFunc.apply(lodash, arrayPush([value], args));\n return (isTaker && chainAll) ? result[0] : result;\n };\n\n if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {\n // Avoid lazy use if the iteratee has a \"length\" value other than `1`.\n isLazy = useLazy = false;\n }\n var chainAll = this.__chain__,\n isHybrid = !!this.__actions__.length,\n isUnwrapped = retUnwrapped && !chainAll,\n onlyLazy = isLazy && !isHybrid;\n\n if (!retUnwrapped && useLazy) {\n value = onlyLazy ? value : new LazyWrapper(this);\n var result = func.apply(value, args);\n result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });\n return new LodashWrapper(result, chainAll);\n }\n if (isUnwrapped && onlyLazy) {\n return func.apply(this, args);\n }\n result = this.thru(interceptor);\n return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result;\n };\n });\n\n // Add `Array` methods to `lodash.prototype`.\n arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {\n var func = arrayProto[methodName],\n chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',\n retUnwrapped = /^(?:pop|shift)$/.test(methodName);\n\n lodash.prototype[methodName] = function() {\n var args = arguments;\n if (retUnwrapped && !this.__chain__) {\n var value = this.value();\n return func.apply(isArray(value) ? value : [], args);\n }\n return this[chainName](function(value) {\n return func.apply(isArray(value) ? value : [], args);\n });\n };\n });\n\n // Map minified method names to their real names.\n baseForOwn(LazyWrapper.prototype, function(func, methodName) {\n var lodashFunc = lodash[methodName];\n if (lodashFunc) {\n var key = (lodashFunc.name + ''),\n names = realNames[key] || (realNames[key] = []);\n\n names.push({ 'name': methodName, 'func': lodashFunc });\n }\n });\n\n realNames[createHybrid(undefined, WRAP_BIND_KEY_FLAG).name] = [{\n 'name': 'wrapper',\n 'func': undefined\n }];\n\n // Add methods to `LazyWrapper`.\n LazyWrapper.prototype.clone = lazyClone;\n LazyWrapper.prototype.reverse = lazyReverse;\n LazyWrapper.prototype.value = lazyValue;\n\n // Add chain sequence methods to the `lodash` wrapper.\n lodash.prototype.at = wrapperAt;\n lodash.prototype.chain = wrapperChain;\n lodash.prototype.commit = wrapperCommit;\n lodash.prototype.next = wrapperNext;\n lodash.prototype.plant = wrapperPlant;\n lodash.prototype.reverse = wrapperReverse;\n lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;\n\n // Add lazy aliases.\n lodash.prototype.first = lodash.prototype.head;\n\n if (symIterator) {\n lodash.prototype[symIterator] = wrapperToIterator;\n }\n return lodash;\n });\n\n /*--------------------------------------------------------------------------*/\n\n // Export lodash.\n var _ = runInContext();\n\n // Some AMD build optimizers, like r.js, check for condition patterns like:\n if (true) {\n // Expose Lodash on the global object to prevent errors when Lodash is\n // loaded by a script tag in the presence of an AMD loader.\n // See http://requirejs.org/docs/errors.html#mismatch for more details.\n // Use `_.noConflict` to remove Lodash from the global object.\n root._ = _;\n\n // Define as an anonymous module so, through path mapping, it can be\n // referenced as the \"underscore\" module.\n !(__WEBPACK_AMD_DEFINE_RESULT__ = function() {\n return _;\n }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n }\n // Check for `exports` after `define` in case a build optimizer adds it.\n else if (freeModule) {\n // Export for Node.js.\n (freeModule.exports = _)._ = _;\n // Export for CommonJS support.\n freeExports._ = _;\n }\n else {\n // Export to the global object.\n root._ = _;\n }\n}.call(this));\n\n/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(75)(module)))//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNzQuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2xvZGFzaC9sb2Rhc2guanM/MDNjYyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBMb2Rhc2ggPGh0dHBzOi8vbG9kYXNoLmNvbS8+XG4gKiBDb3B5cmlnaHQgSlMgRm91bmRhdGlvbiBhbmQgb3RoZXIgY29udHJpYnV0b3JzIDxodHRwczovL2pzLmZvdW5kYXRpb24vPlxuICogUmVsZWFzZWQgdW5kZXIgTUlUIGxpY2Vuc2UgPGh0dHBzOi8vbG9kYXNoLmNvbS9saWNlbnNlPlxuICogQmFzZWQgb24gVW5kZXJzY29yZS5qcyAxLjguMyA8aHR0cDovL3VuZGVyc2NvcmVqcy5vcmcvTElDRU5TRT5cbiAqIENvcHlyaWdodCBKZXJlbXkgQXNoa2VuYXMsIERvY3VtZW50Q2xvdWQgYW5kIEludmVzdGlnYXRpdmUgUmVwb3J0ZXJzICYgRWRpdG9yc1xuICovXG47KGZ1bmN0aW9uKCkge1xuXG4gIC8qKiBVc2VkIGFzIGEgc2FmZSByZWZlcmVuY2UgZm9yIGB1bmRlZmluZWRgIGluIHByZS1FUzUgZW52aXJvbm1lbnRzLiAqL1xuICB2YXIgdW5kZWZpbmVkO1xuXG4gIC8qKiBVc2VkIGFzIHRoZSBzZW1hbnRpYyB2ZXJzaW9uIG51bWJlci4gKi9cbiAgdmFyIFZFUlNJT04gPSAnNC4xNy4zJztcblxuICAvKiogVXNlZCBhcyB0aGUgc2l6ZSB0byBlbmFibGUgbGFyZ2UgYXJyYXkgb3B0aW1pemF0aW9ucy4gKi9cbiAgdmFyIExBUkdFX0FSUkFZX1NJWkUgPSAyMDA7XG5cbiAgLyoqIEVycm9yIG1lc3NhZ2UgY29uc3RhbnRzLiAqL1xuICB2YXIgQ09SRV9FUlJPUl9URVhUID0gJ1Vuc3VwcG9ydGVkIGNvcmUtanMgdXNlLiBUcnkgaHR0cHM6Ly9ucG1zLmlvL3NlYXJjaD9xPXBvbnlmaWxsLicsXG4gICAgICBGVU5DX0VSUk9SX1RFWFQgPSAnRXhwZWN0ZWQgYSBmdW5jdGlvbic7XG5cbiAgLyoqIFVzZWQgdG8gc3RhbmQtaW4gZm9yIGB1bmRlZmluZWRgIGhhc2ggdmFsdWVzLiAqL1xuICB2YXIgSEFTSF9VTkRFRklORUQgPSAnX19sb2Rhc2hfaGFzaF91bmRlZmluZWRfXyc7XG5cbiAgLyoqIFVzZWQgYXMgdGhlIG1heGltdW0gbWVtb2l6ZSBjYWNoZSBzaXplLiAqL1xuICB2YXIgTUFYX01FTU9JWkVfU0laRSA9IDUwMDtcblxuICAvKiogVXNlZCBhcyB0aGUgaW50ZXJuYWwgYXJndW1lbnQgcGxhY2Vob2xkZXIuICovXG4gIHZhciBQTEFDRUhPTERFUiA9ICdfX2xvZGFzaF9wbGFjZWhvbGRlcl9fJztcblxuICAvKiogVXNlZCB0byBjb21wb3NlIGJpdG1hc2tzIGZvciBjbG9uaW5nLiAqL1xuICB2YXIgQ0xPTkVfREVFUF9GTEFHID0gMSxcbiAgICAgIENMT05FX0ZMQVRfRkxBRyA9IDIsXG4gICAgICBDTE9ORV9TWU1CT0xTX0ZMQUcgPSA0O1xuXG4gIC8qKiBVc2VkIHRvIGNvbXBvc2UgYml0bWFza3MgZm9yIHZhbHVlIGNvbXBhcmlzb25zLiAqL1xuICB2YXIgQ09NUEFSRV9QQVJUSUFMX0ZMQUcgPSAxLFxuICAgICAgQ09NUEFSRV9VTk9SREVSRURfRkxBRyA9IDI7XG5cbiAgLyoqIFVzZWQgdG8gY29tcG9zZSBiaXRtYXNrcyBmb3IgZnVuY3Rpb24gbWV0YWRhdGEuICovXG4gIHZhciBXUkFQX0JJTkRfRkxBRyA9IDEsXG4gICAgICBXUkFQX0JJTkRfS0VZX0ZMQUcgPSAyLFxuICAgICAgV1JBUF9DVVJSWV9CT1VORF9GTEFHID0gNCxcbiAgICAgIFdSQVBfQ1VSUllfRkxBRyA9IDgsXG4gICAgICBXUkFQX0NVUlJZX1JJR0hUX0ZMQUcgPSAxNixcbiAgICAgIFdSQVBfUEFSVElBTF9GTEFHID0gMzIsXG4gICAgICBXUkFQX1BBUlRJQUxfUklHSFRfRkxBRyA9IDY0LFxuICAgICAgV1JBUF9BUllfRkxBRyA9IDEyOCxcbiAgICAgIFdSQVBfUkVBUkdfRkxBRyA9IDI1NixcbiAgICAgIFdSQVBfRkxJUF9GTEFHID0gNTEyO1xuXG4gIC8qKiBVc2VkIGFzIGRlZmF1bHQgb3B0aW9ucyBmb3IgYF8udHJ1bmNhdGVgLiAqL1xuICB2YXIgREVGQVVMVF9UUlVOQ19MRU5HVEggPSAzMCxcbiAgICAgIERFRkFVTFRfVFJVTkNfT01JU1NJT04gPSAnLi4uJztcblxuICAvKiogVXNlZCB0byBkZXRlY3QgaG90IGZ1bmN0aW9ucyBieSBudW1iZXIgb2YgY2FsbHMgd2l0aGluIGEgc3BhbiBvZiBtaWxsaXNlY29uZHMuICovXG4gIHZhciBIT1RfQ09VTlQgPSA4MDAsXG4gICAgICBIT1RfU1BBTiA9IDE2O1xuXG4gIC8qKiBVc2VkIHRvIGluZGljYXRlIHRoZSB0eXBlIG9mIGxhenkgaXRlcmF0ZWVzLiAqL1xuICB2YXIgTEFaWV9GSUxURVJfRkxBRyA9IDEsXG4gICAgICBMQVpZX01BUF9GTEFHID0gMixcbiAgICAgIExBWllfV0hJTEVfRkxBRyA9IDM7XG5cbiAgLyoqIFVzZWQgYXMgcmVmZXJlbmNlcyBmb3IgdmFyaW91cyBgTnVtYmVyYCBjb25zdGFudHMuICovXG4gIHZhciBJTkZJTklUWSA9IDEgLyAwLFxuICAgICAgTUFYX1NBRkVfSU5URUdFUiA9IDkwMDcxOTkyNTQ3NDA5OTEsXG4gICAgICBNQVhfSU5URUdFUiA9IDEuNzk3NjkzMTM0ODYyMzE1N2UrMzA4LFxuICAgICAgTkFOID0gMCAvIDA7XG5cbiAgLyoqIFVzZWQgYXMgcmVmZXJlbmNlcyBmb3IgdGhlIG1heGltdW0gbGVuZ3RoIGFuZCBpbmRleCBvZiBhbiBhcnJheS4gKi9cbiAgdmFyIE1BWF9BUlJBWV9MRU5HVEggPSA0Mjk0OTY3Mjk1LFxuICAgICAgTUFYX0FSUkFZX0lOREVYID0gTUFYX0FSUkFZX0xFTkdUSCAtIDEsXG4gICAgICBIQUxGX01BWF9BUlJBWV9MRU5HVEggPSBNQVhfQVJSQVlfTEVOR1RIID4+PiAxO1xuXG4gIC8qKiBVc2VkIHRvIGFzc29jaWF0ZSB3cmFwIG1ldGhvZHMgd2l0aCB0aGVpciBiaXQgZmxhZ3MuICovXG4gIHZhciB3cmFwRmxhZ3MgPSBbXG4gICAgWydhcnknLCBXUkFQX0FSWV9GTEFHXSxcbiAgICBbJ2JpbmQnLCBXUkFQX0JJTkRfRkxBR10sXG4gICAgWydiaW5kS2V5JywgV1JBUF9CSU5EX0tFWV9GTEFHXSxcbiAgICBbJ2N1cnJ5JywgV1JBUF9DVVJSWV9GTEFHXSxcbiAgICBbJ2N1cnJ5UmlnaHQnLCBXUkFQX0NVUlJZX1JJR0hUX0ZMQUddLFxuICAgIFsnZmxpcCcsIFdSQVBfRkxJUF9GTEFHXSxcbiAgICBbJ3BhcnRpYWwnLCBXUkFQX1BBUlRJQUxfRkxBR10sXG4gICAgWydwYXJ0aWFsUmlnaHQnLCBXUkFQX1BBUlRJQUxfUklHSFRfRkxBR10sXG4gICAgWydyZWFyZycsIFdSQVBfUkVBUkdfRkxBR11cbiAgXTtcblxuICAvKiogYE9iamVjdCN0b1N0cmluZ2AgcmVzdWx0IHJlZmVyZW5jZXMuICovXG4gIHZhciBhcmdzVGFnID0gJ1tvYmplY3QgQXJndW1lbnRzXScsXG4gICAgICBhcnJheVRhZyA9ICdbb2JqZWN0IEFycmF5XScsXG4gICAgICBhc3luY1RhZyA9ICdbb2JqZWN0IEFzeW5jRnVuY3Rpb25dJyxcbiAgICAgIGJvb2xUYWcgPSAnW29iamVjdCBCb29sZWFuXScsXG4gICAgICBkYXRlVGFnID0gJ1tvYmplY3QgRGF0ZV0nLFxuICAgICAgZG9tRXhjVGFnID0gJ1tvYmplY3QgRE9NRXhjZXB0aW9uXScsXG4gICAgICBlcnJvclRhZyA9ICdbb2JqZWN0IEVycm9yXScsXG4gICAgICBmdW5jVGFnID0gJ1tvYmplY3QgRnVuY3Rpb25dJyxcbiAgICAgIGdlblRhZyA9ICdbb2JqZWN0IEdlbmVyYXRvckZ1bmN0aW9uXScsXG4gICAgICBtYXBUYWcgPSAnW29iamVjdCBNYXBdJyxcbiAgICAgIG51bWJlclRhZyA9ICdbb2JqZWN0IE51bWJlcl0nLFxuICAgICAgbnVsbFRhZyA9ICdbb2JqZWN0IE51bGxdJyxcbiAgICAgIG9iamVjdFRhZyA9ICdbb2JqZWN0IE9iamVjdF0nLFxuICAgICAgcHJvbWlzZVRhZyA9ICdbb2JqZWN0IFByb21pc2VdJyxcbiAgICAgIHByb3h5VGFnID0gJ1tvYmplY3QgUHJveHldJyxcbiAgICAgIHJlZ2V4cFRhZyA9ICdbb2JqZWN0IFJlZ0V4cF0nLFxuICAgICAgc2V0VGFnID0gJ1tvYmplY3QgU2V0XScsXG4gICAgICBzdHJpbmdUYWcgPSAnW29iamVjdCBTdHJpbmddJyxcbiAgICAgIHN5bWJvbFRhZyA9ICdbb2JqZWN0IFN5bWJvbF0nLFxuICAgICAgdW5kZWZpbmVkVGFnID0gJ1tvYmplY3QgVW5kZWZpbmVkXScsXG4gICAgICB3ZWFrTWFwVGFnID0gJ1tvYmplY3QgV2Vha01hcF0nLFxuICAgICAgd2Vha1NldFRhZyA9ICdbb2JqZWN0IFdlYWtTZXRdJztcblxuICB2YXIgYXJyYXlCdWZmZXJUYWcgPSAnW29iamVjdCBBcnJheUJ1ZmZlcl0nLFxuICAgICAgZGF0YVZpZXdUYWcgPSAnW29iamVjdCBEYXRhVmlld10nLFxuICAgICAgZmxvYXQzMlRhZyA9ICdbb2JqZWN0IEZsb2F0MzJBcnJheV0nLFxuICAgICAgZmxvYXQ2NFRhZyA9ICdbb2JqZWN0IEZsb2F0NjRBcnJheV0nLFxuICAgICAgaW50OFRhZyA9ICdbb2JqZWN0IEludDhBcnJheV0nLFxuICAgICAgaW50MTZUYWcgPSAnW29iamVjdCBJbnQxNkFycmF5XScsXG4gICAgICBpbnQzMlRhZyA9ICdbb2JqZWN0IEludDMyQXJyYXldJyxcbiAgICAgIHVpbnQ4VGFnID0gJ1tvYmplY3QgVWludDhBcnJheV0nLFxuICAgICAgdWludDhDbGFtcGVkVGFnID0gJ1tvYmplY3QgVWludDhDbGFtcGVkQXJyYXldJyxcbiAgICAgIHVpbnQxNlRhZyA9ICdbb2JqZWN0IFVpbnQxNkFycmF5XScsXG4gICAgICB1aW50MzJUYWcgPSAnW29iamVjdCBVaW50MzJBcnJheV0nO1xuXG4gIC8qKiBVc2VkIHRvIG1hdGNoIGVtcHR5IHN0cmluZyBsaXRlcmFscyBpbiBjb21waWxlZCB0ZW1wbGF0ZSBzb3VyY2UuICovXG4gIHZhciByZUVtcHR5U3RyaW5nTGVhZGluZyA9IC9cXGJfX3AgXFwrPSAnJzsvZyxcbiAgICAgIHJlRW1wdHlTdHJpbmdNaWRkbGUgPSAvXFxiKF9fcCBcXCs9KSAnJyBcXCsvZyxcbiAgICAgIHJlRW1wdHlTdHJpbmdUcmFpbGluZyA9IC8oX19lXFwoLio/XFwpfFxcYl9fdFxcKSkgXFwrXFxuJyc7L2c7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggSFRNTCBlbnRpdGllcyBhbmQgSFRNTCBjaGFyYWN0ZXJzLiAqL1xuICB2YXIgcmVFc2NhcGVkSHRtbCA9IC8mKD86YW1wfGx0fGd0fHF1b3R8IzM5KTsvZyxcbiAgICAgIHJlVW5lc2NhcGVkSHRtbCA9IC9bJjw+XCInXS9nLFxuICAgICAgcmVIYXNFc2NhcGVkSHRtbCA9IFJlZ0V4cChyZUVzY2FwZWRIdG1sLnNvdXJjZSksXG4gICAgICByZUhhc1VuZXNjYXBlZEh0bWwgPSBSZWdFeHAocmVVbmVzY2FwZWRIdG1sLnNvdXJjZSk7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggdGVtcGxhdGUgZGVsaW1pdGVycy4gKi9cbiAgdmFyIHJlRXNjYXBlID0gLzwlLShbXFxzXFxTXSs/KSU+L2csXG4gICAgICByZUV2YWx1YXRlID0gLzwlKFtcXHNcXFNdKz8pJT4vZyxcbiAgICAgIHJlSW50ZXJwb2xhdGUgPSAvPCU9KFtcXHNcXFNdKz8pJT4vZztcblxuICAvKiogVXNlZCB0byBtYXRjaCBwcm9wZXJ0eSBuYW1lcyB3aXRoaW4gcHJvcGVydHkgcGF0aHMuICovXG4gIHZhciByZUlzRGVlcFByb3AgPSAvXFwufFxcWyg/OlteW1xcXV0qfChbXCInXSkoPzooPyFcXDEpW15cXFxcXXxcXFxcLikqP1xcMSlcXF0vLFxuICAgICAgcmVJc1BsYWluUHJvcCA9IC9eXFx3KiQvLFxuICAgICAgcmVMZWFkaW5nRG90ID0gL15cXC4vLFxuICAgICAgcmVQcm9wTmFtZSA9IC9bXi5bXFxdXSt8XFxbKD86KC0/XFxkKyg/OlxcLlxcZCspPyl8KFtcIiddKSgoPzooPyFcXDIpW15cXFxcXXxcXFxcLikqPylcXDIpXFxdfCg/PSg/OlxcLnxcXFtcXF0pKD86XFwufFxcW1xcXXwkKSkvZztcblxuICAvKipcbiAgICogVXNlZCB0byBtYXRjaCBgUmVnRXhwYFxuICAgKiBbc3ludGF4IGNoYXJhY3RlcnNdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLXBhdHRlcm5zKS5cbiAgICovXG4gIHZhciByZVJlZ0V4cENoYXIgPSAvW1xcXFxeJC4qKz8oKVtcXF17fXxdL2csXG4gICAgICByZUhhc1JlZ0V4cENoYXIgPSBSZWdFeHAocmVSZWdFeHBDaGFyLnNvdXJjZSk7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggbGVhZGluZyBhbmQgdHJhaWxpbmcgd2hpdGVzcGFjZS4gKi9cbiAgdmFyIHJlVHJpbSA9IC9eXFxzK3xcXHMrJC9nLFxuICAgICAgcmVUcmltU3RhcnQgPSAvXlxccysvLFxuICAgICAgcmVUcmltRW5kID0gL1xccyskLztcblxuICAvKiogVXNlZCB0byBtYXRjaCB3cmFwIGRldGFpbCBjb21tZW50cy4gKi9cbiAgdmFyIHJlV3JhcENvbW1lbnQgPSAvXFx7KD86XFxuXFwvXFwqIFxcW3dyYXBwZWQgd2l0aCAuK1xcXSBcXCpcXC8pP1xcbj8vLFxuICAgICAgcmVXcmFwRGV0YWlscyA9IC9cXHtcXG5cXC9cXCogXFxbd3JhcHBlZCB3aXRoICguKylcXF0gXFwqLyxcbiAgICAgIHJlU3BsaXREZXRhaWxzID0gLyw/ICYgLztcblxuICAvKiogVXNlZCB0byBtYXRjaCB3b3JkcyBjb21wb3NlZCBvZiBhbHBoYW51bWVyaWMgY2hhcmFjdGVycy4gKi9cbiAgdmFyIHJlQXNjaWlXb3JkID0gL1teXFx4MDAtXFx4MmZcXHgzYS1cXHg0MFxceDViLVxceDYwXFx4N2ItXFx4N2ZdKy9nO1xuXG4gIC8qKiBVc2VkIHRvIG1hdGNoIGJhY2tzbGFzaGVzIGluIHByb3BlcnR5IHBhdGhzLiAqL1xuICB2YXIgcmVFc2NhcGVDaGFyID0gL1xcXFwoXFxcXCk/L2c7XG5cbiAgLyoqXG4gICAqIFVzZWQgdG8gbWF0Y2hcbiAgICogW0VTIHRlbXBsYXRlIGRlbGltaXRlcnNdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLXRlbXBsYXRlLWxpdGVyYWwtbGV4aWNhbC1jb21wb25lbnRzKS5cbiAgICovXG4gIHZhciByZUVzVGVtcGxhdGUgPSAvXFwkXFx7KFteXFxcXH1dKig/OlxcXFwuW15cXFxcfV0qKSopXFx9L2c7XG5cbiAgLyoqIFVzZWQgdG8gbWF0Y2ggYFJlZ0V4cGAgZmxhZ3MgZnJvbSB0aGVpciBjb2VyY2VkIHN0cmluZyB2YWx1ZXMuICovXG4gIHZhciByZUZsYWdzID0gL1xcdyokLztcblxuICAvKiogVXNlZCB0byBkZXRlY3QgYmFkIHNpZ25lZCBoZXhhZGVjaW1hbCBzdHJpbmcgdmFsdWVzLiAqL1xuICB2YXIgcmVJc0JhZEhleCA9IC9eWy0rXTB4WzAtOWEtZl0rJC9pO1xuXG4gIC8qKiBVc2VkIHRvIGRldGVjdCBiaW5hcnkgc3RyaW5nIHZhbHVlcy4gKi9cbiAgdmFyIHJlSXNCaW5hcnkgPSAvXjBiWzAxXSskL2k7XG5cbiAgLyoqIFVzZWQgdG8gZGV0ZWN0IGhvc3QgY29uc3RydWN0b3JzIChTYWZhcmkpLiAqL1xuICB2YXIgcmVJc0hvc3RDdG9yID0gL15cXFtvYmplY3QgLis/Q29uc3RydWN0b3JcXF0kLztcblxuICAvKiogVXNlZCB0byBkZXRlY3Qgb2N0YWwgc3RyaW5nIHZhbHVlcy4gKi9cbiAgdmFyIHJlSXNPY3RhbCA9IC9eMG9bMC03XSskL2k7XG5cbiAgLyoqIFVzZWQgdG8gZGV0ZWN0IHVuc2lnbmVkIGludGVnZXIgdmFsdWVzLiAqL1xuICB2YXIgcmVJc1VpbnQgPSAvXig/OjB8WzEtOV1cXGQqKSQvO1xuXG4gIC8qKiBVc2VkIHRvIG1hdGNoIExhdGluIFVuaWNvZGUgbGV0dGVycyAoZXhjbHVkaW5nIG1hdGhlbWF0aWNhbCBvcGVyYXRvcnMpLiAqL1xuICB2YXIgcmVMYXRpbiA9IC9bXFx4YzAtXFx4ZDZcXHhkOC1cXHhmNlxceGY4LVxceGZmXFx1MDEwMC1cXHUwMTdmXS9nO1xuXG4gIC8qKiBVc2VkIHRvIGVuc3VyZSBjYXB0dXJpbmcgb3JkZXIgb2YgdGVtcGxhdGUgZGVsaW1pdGVycy4gKi9cbiAgdmFyIHJlTm9NYXRjaCA9IC8oJF4pLztcblxuICAvKiogVXNlZCB0byBtYXRjaCB1bmVzY2FwZWQgY2hhcmFjdGVycyBpbiBjb21waWxlZCBzdHJpbmcgbGl0ZXJhbHMuICovXG4gIHZhciByZVVuZXNjYXBlZFN0cmluZyA9IC9bJ1xcblxcclxcdTIwMjhcXHUyMDI5XFxcXF0vZztcblxuICAvKiogVXNlZCB0byBjb21wb3NlIHVuaWNvZGUgY2hhcmFjdGVyIGNsYXNzZXMuICovXG4gIHZhciByc0FzdHJhbFJhbmdlID0gJ1xcXFx1ZDgwMC1cXFxcdWRmZmYnLFxuICAgICAgcnNDb21ib01hcmtzUmFuZ2UgPSAnXFxcXHUwMzAwLVxcXFx1MDM2ZicsXG4gICAgICByZUNvbWJvSGFsZk1hcmtzUmFuZ2UgPSAnXFxcXHVmZTIwLVxcXFx1ZmUyZicsXG4gICAgICByc0NvbWJvU3ltYm9sc1JhbmdlID0gJ1xcXFx1MjBkMC1cXFxcdTIwZmYnLFxuICAgICAgcnNDb21ib1JhbmdlID0gcnNDb21ib01hcmtzUmFuZ2UgKyByZUNvbWJvSGFsZk1hcmtzUmFuZ2UgKyByc0NvbWJvU3ltYm9sc1JhbmdlLFxuICAgICAgcnNEaW5nYmF0UmFuZ2UgPSAnXFxcXHUyNzAwLVxcXFx1MjdiZicsXG4gICAgICByc0xvd2VyUmFuZ2UgPSAnYS16XFxcXHhkZi1cXFxceGY2XFxcXHhmOC1cXFxceGZmJyxcbiAgICAgIHJzTWF0aE9wUmFuZ2UgPSAnXFxcXHhhY1xcXFx4YjFcXFxceGQ3XFxcXHhmNycsXG4gICAgICByc05vbkNoYXJSYW5nZSA9ICdcXFxceDAwLVxcXFx4MmZcXFxceDNhLVxcXFx4NDBcXFxceDViLVxcXFx4NjBcXFxceDdiLVxcXFx4YmYnLFxuICAgICAgcnNQdW5jdHVhdGlvblJhbmdlID0gJ1xcXFx1MjAwMC1cXFxcdTIwNmYnLFxuICAgICAgcnNTcGFjZVJhbmdlID0gJyBcXFxcdFxcXFx4MGJcXFxcZlxcXFx4YTBcXFxcdWZlZmZcXFxcblxcXFxyXFxcXHUyMDI4XFxcXHUyMDI5XFxcXHUxNjgwXFxcXHUxODBlXFxcXHUyMDAwXFxcXHUyMDAxXFxcXHUyMDAyXFxcXHUyMDAzXFxcXHUyMDA0XFxcXHUyMDA1XFxcXHUyMDA2XFxcXHUyMDA3XFxcXHUyMDA4XFxcXHUyMDA5XFxcXHUyMDBhXFxcXHUyMDJmXFxcXHUyMDVmXFxcXHUzMDAwJyxcbiAgICAgIHJzVXBwZXJSYW5nZSA9ICdBLVpcXFxceGMwLVxcXFx4ZDZcXFxceGQ4LVxcXFx4ZGUnLFxuICAgICAgcnNWYXJSYW5nZSA9ICdcXFxcdWZlMGVcXFxcdWZlMGYnLFxuICAgICAgcnNCcmVha1JhbmdlID0gcnNNYXRoT3BSYW5nZSArIHJzTm9uQ2hhclJhbmdlICsgcnNQdW5jdHVhdGlvblJhbmdlICsgcnNTcGFjZVJhbmdlO1xuXG4gIC8qKiBVc2VkIHRvIGNvbXBvc2UgdW5pY29kZSBjYXB0dXJlIGdyb3Vwcy4gKi9cbiAgdmFyIHJzQXBvcyA9IFwiWydcXHUyMDE5XVwiLFxuICAgICAgcnNBc3RyYWwgPSAnWycgKyByc0FzdHJhbFJhbmdlICsgJ10nLFxuICAgICAgcnNCcmVhayA9ICdbJyArIHJzQnJlYWtSYW5nZSArICddJyxcbiAgICAgIHJzQ29tYm8gPSAnWycgKyByc0NvbWJvUmFuZ2UgKyAnXScsXG4gICAgICByc0RpZ2l0cyA9ICdcXFxcZCsnLFxuICAgICAgcnNEaW5nYmF0ID0gJ1snICsgcnNEaW5nYmF0UmFuZ2UgKyAnXScsXG4gICAgICByc0xvd2VyID0gJ1snICsgcnNMb3dlclJhbmdlICsgJ10nLFxuICAgICAgcnNNaXNjID0gJ1teJyArIHJzQXN0cmFsUmFuZ2UgKyByc0JyZWFrUmFuZ2UgKyByc0RpZ2l0cyArIHJzRGluZ2JhdFJhbmdlICsgcnNMb3dlclJhbmdlICsgcnNVcHBlclJhbmdlICsgJ10nLFxuICAgICAgcnNGaXR6ID0gJ1xcXFx1ZDgzY1tcXFxcdWRmZmItXFxcXHVkZmZmXScsXG4gICAgICByc01vZGlmaWVyID0gJyg/OicgKyByc0NvbWJvICsgJ3wnICsgcnNGaXR6ICsgJyknLFxuICAgICAgcnNOb25Bc3RyYWwgPSAnW14nICsgcnNBc3RyYWxSYW5nZSArICddJyxcbiAgICAgIHJzUmVnaW9uYWwgPSAnKD86XFxcXHVkODNjW1xcXFx1ZGRlNi1cXFxcdWRkZmZdKXsyfScsXG4gICAgICByc1N1cnJQYWlyID0gJ1tcXFxcdWQ4MDAtXFxcXHVkYmZmXVtcXFxcdWRjMDAtXFxcXHVkZmZmXScsXG4gICAgICByc1VwcGVyID0gJ1snICsgcnNVcHBlclJhbmdlICsgJ10nLFxuICAgICAgcnNaV0ogPSAnXFxcXHUyMDBkJztcblxuICAvKiogVXNlZCB0byBjb21wb3NlIHVuaWNvZGUgcmVnZXhlcy4gKi9cbiAgdmFyIHJzTWlzY0xvd2VyID0gJyg/OicgKyByc0xvd2VyICsgJ3wnICsgcnNNaXNjICsgJyknLFxuICAgICAgcnNNaXNjVXBwZXIgPSAnKD86JyArIHJzVXBwZXIgKyAnfCcgKyByc01pc2MgKyAnKScsXG4gICAgICByc09wdENvbnRyTG93ZXIgPSAnKD86JyArIHJzQXBvcyArICcoPzpkfGxsfG18cmV8c3x0fHZlKSk/JyxcbiAgICAgIHJzT3B0Q29udHJVcHBlciA9ICcoPzonICsgcnNBcG9zICsgJyg/OkR8TEx8TXxSRXxTfFR8VkUpKT8nLFxuICAgICAgcmVPcHRNb2QgPSByc01vZGlmaWVyICsgJz8nLFxuICAgICAgcnNPcHRWYXIgPSAnWycgKyByc1ZhclJhbmdlICsgJ10/JyxcbiAgICAgIHJzT3B0Sm9pbiA9ICcoPzonICsgcnNaV0ogKyAnKD86JyArIFtyc05vbkFzdHJhbCwgcnNSZWdpb25hbCwgcnNTdXJyUGFpcl0uam9pbignfCcpICsgJyknICsgcnNPcHRWYXIgKyByZU9wdE1vZCArICcpKicsXG4gICAgICByc09yZExvd2VyID0gJ1xcXFxkKig/Oig/OjFzdHwybmR8M3JkfCg/IVsxMjNdKVxcXFxkdGgpXFxcXGIpJyxcbiAgICAgIHJzT3JkVXBwZXIgPSAnXFxcXGQqKD86KD86MVNUfDJORHwzUkR8KD8hWzEyM10pXFxcXGRUSClcXFxcYiknLFxuICAgICAgcnNTZXEgPSByc09wdFZhciArIHJlT3B0TW9kICsgcnNPcHRKb2luLFxuICAgICAgcnNFbW9qaSA9ICcoPzonICsgW3JzRGluZ2JhdCwgcnNSZWdpb25hbCwgcnNTdXJyUGFpcl0uam9pbignfCcpICsgJyknICsgcnNTZXEsXG4gICAgICByc1N5bWJvbCA9ICcoPzonICsgW3JzTm9uQXN0cmFsICsgcnNDb21ibyArICc/JywgcnNDb21ibywgcnNSZWdpb25hbCwgcnNTdXJyUGFpciwgcnNBc3RyYWxdLmpvaW4oJ3wnKSArICcpJztcblxuICAvKiogVXNlZCB0byBtYXRjaCBhcG9zdHJvcGhlcy4gKi9cbiAgdmFyIHJlQXBvcyA9IFJlZ0V4cChyc0Fwb3MsICdnJyk7XG5cbiAgLyoqXG4gICAqIFVzZWQgdG8gbWF0Y2ggW2NvbWJpbmluZyBkaWFjcml0aWNhbCBtYXJrc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ29tYmluaW5nX0RpYWNyaXRpY2FsX01hcmtzKSBhbmRcbiAgICogW2NvbWJpbmluZyBkaWFjcml0aWNhbCBtYXJrcyBmb3Igc3ltYm9sc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ29tYmluaW5nX0RpYWNyaXRpY2FsX01hcmtzX2Zvcl9TeW1ib2xzKS5cbiAgICovXG4gIHZhciByZUNvbWJvTWFyayA9IFJlZ0V4cChyc0NvbWJvLCAnZycpO1xuXG4gIC8qKiBVc2VkIHRvIG1hdGNoIFtzdHJpbmcgc3ltYm9sc10oaHR0cHM6Ly9tYXRoaWFzYnluZW5zLmJlL25vdGVzL2phdmFzY3JpcHQtdW5pY29kZSkuICovXG4gIHZhciByZVVuaWNvZGUgPSBSZWdFeHAocnNGaXR6ICsgJyg/PScgKyByc0ZpdHogKyAnKXwnICsgcnNTeW1ib2wgKyByc1NlcSwgJ2cnKTtcblxuICAvKiogVXNlZCB0byBtYXRjaCBjb21wbGV4IG9yIGNvbXBvdW5kIHdvcmRzLiAqL1xuICB2YXIgcmVVbmljb2RlV29yZCA9IFJlZ0V4cChbXG4gICAgcnNVcHBlciArICc/JyArIHJzTG93ZXIgKyAnKycgKyByc09wdENvbnRyTG93ZXIgKyAnKD89JyArIFtyc0JyZWFrLCByc1VwcGVyLCAnJCddLmpvaW4oJ3wnKSArICcpJyxcbiAgICByc01pc2NVcHBlciArICcrJyArIHJzT3B0Q29udHJVcHBlciArICcoPz0nICsgW3JzQnJlYWssIHJzVXBwZXIgKyByc01pc2NMb3dlciwgJyQnXS5qb2luKCd8JykgKyAnKScsXG4gICAgcnNVcHBlciArICc/JyArIHJzTWlzY0xvd2VyICsgJysnICsgcnNPcHRDb250ckxvd2VyLFxuICAgIHJzVXBwZXIgKyAnKycgKyByc09wdENvbnRyVXBwZXIsXG4gICAgcnNPcmRVcHBlcixcbiAgICByc09yZExvd2VyLFxuICAgIHJzRGlnaXRzLFxuICAgIHJzRW1vamlcbiAgXS5qb2luKCd8JyksICdnJyk7XG5cbiAgLyoqIFVzZWQgdG8gZGV0ZWN0IHN0cmluZ3Mgd2l0aCBbemVyby13aWR0aCBqb2luZXJzIG9yIGNvZGUgcG9pbnRzIGZyb20gdGhlIGFzdHJhbCBwbGFuZXNdKGh0dHA6Ly9lZXYuZWUvYmxvZy8yMDE1LzA5LzEyL2RhcmstY29ybmVycy1vZi11bmljb2RlLykuICovXG4gIHZhciByZUhhc1VuaWNvZGUgPSBSZWdFeHAoJ1snICsgcnNaV0ogKyByc0FzdHJhbFJhbmdlICArIHJzQ29tYm9SYW5nZSArIHJzVmFyUmFuZ2UgKyAnXScpO1xuXG4gIC8qKiBVc2VkIHRvIGRldGVjdCBzdHJpbmdzIHRoYXQgbmVlZCBhIG1vcmUgcm9idXN0IHJlZ2V4cCB0byBtYXRjaCB3b3Jkcy4gKi9cbiAgdmFyIHJlSGFzVW5pY29kZVdvcmQgPSAvW2Etel1bQS1aXXxbQS1aXXsyLH1bYS16XXxbMC05XVthLXpBLVpdfFthLXpBLVpdWzAtOV18W15hLXpBLVowLTkgXS87XG5cbiAgLyoqIFVzZWQgdG8gYXNzaWduIGRlZmF1bHQgYGNvbnRleHRgIG9iamVjdCBwcm9wZXJ0aWVzLiAqL1xuICB2YXIgY29udGV4dFByb3BzID0gW1xuICAgICdBcnJheScsICdCdWZmZXInLCAnRGF0YVZpZXcnLCAnRGF0ZScsICdFcnJvcicsICdGbG9hdDMyQXJyYXknLCAnRmxvYXQ2NEFycmF5JyxcbiAgICAnRnVuY3Rpb24nLCAnSW50OEFycmF5JywgJ0ludDE2QXJyYXknLCAnSW50MzJBcnJheScsICdNYXAnLCAnTWF0aCcsICdPYmplY3QnLFxuICAgICdQcm9taXNlJywgJ1JlZ0V4cCcsICdTZXQnLCAnU3RyaW5nJywgJ1N5bWJvbCcsICdUeXBlRXJyb3InLCAnVWludDhBcnJheScsXG4gICAgJ1VpbnQ4Q2xhbXBlZEFycmF5JywgJ1VpbnQxNkFycmF5JywgJ1VpbnQzMkFycmF5JywgJ1dlYWtNYXAnLFxuICAgICdfJywgJ2NsZWFyVGltZW91dCcsICdpc0Zpbml0ZScsICdwYXJzZUludCcsICdzZXRUaW1lb3V0J1xuICBdO1xuXG4gIC8qKiBVc2VkIHRvIG1ha2UgdGVtcGxhdGUgc291cmNlVVJMcyBlYXNpZXIgdG8gaWRlbnRpZnkuICovXG4gIHZhciB0ZW1wbGF0ZUNvdW50ZXIgPSAtMTtcblxuICAvKiogVXNlZCB0byBpZGVudGlmeSBgdG9TdHJpbmdUYWdgIHZhbHVlcyBvZiB0eXBlZCBhcnJheXMuICovXG4gIHZhciB0eXBlZEFycmF5VGFncyA9IHt9O1xuICB0eXBlZEFycmF5VGFnc1tmbG9hdDMyVGFnXSA9IHR5cGVkQXJyYXlUYWdzW2Zsb2F0NjRUYWddID1cbiAgdHlwZWRBcnJheVRhZ3NbaW50OFRhZ10gPSB0eXBlZEFycmF5VGFnc1tpbnQxNlRhZ10gPVxuICB0eXBlZEFycmF5VGFnc1tpbnQzMlRhZ10gPSB0eXBlZEFycmF5VGFnc1t1aW50OFRhZ10gPVxuICB0eXBlZEFycmF5VGFnc1t1aW50OENsYW1wZWRUYWddID0gdHlwZWRBcnJheVRhZ3NbdWludDE2VGFnXSA9XG4gIHR5cGVkQXJyYXlUYWdzW3VpbnQzMlRhZ10gPSB0cnVlO1xuICB0eXBlZEFycmF5VGFnc1thcmdzVGFnXSA9IHR5cGVkQXJyYXlUYWdzW2FycmF5VGFnXSA9XG4gIHR5cGVkQXJyYXlUYWdzW2FycmF5QnVmZmVyVGFnXSA9IHR5cGVkQXJyYXlUYWdzW2Jvb2xUYWddID1cbiAgdHlwZWRBcnJheVRhZ3NbZGF0YVZpZXdUYWddID0gdHlwZWRBcnJheVRhZ3NbZGF0ZVRhZ10gPVxuICB0eXBlZEFycmF5VGFnc1tlcnJvclRhZ10gPSB0eXBlZEFycmF5VGFnc1tmdW5jVGFnXSA9XG4gIHR5cGVkQXJyYXlUYWdzW21hcFRhZ10gPSB0eXBlZEFycmF5VGFnc1tudW1iZXJUYWddID1cbiAgdHlwZWRBcnJheVRhZ3Nbb2JqZWN0VGFnXSA9IHR5cGVkQXJyYXlUYWdzW3JlZ2V4cFRhZ10gPVxuICB0eXBlZEFycmF5VGFnc1tzZXRUYWddID0gdHlwZWRBcnJheVRhZ3Nbc3RyaW5nVGFnXSA9XG4gIHR5cGVkQXJyYXlUYWdzW3dlYWtNYXBUYWddID0gZmFsc2U7XG5cbiAgLyoqIFVzZWQgdG8gaWRlbnRpZnkgYHRvU3RyaW5nVGFnYCB2YWx1ZXMgc3VwcG9ydGVkIGJ5IGBfLmNsb25lYC4gKi9cbiAgdmFyIGNsb25lYWJsZVRhZ3MgPSB7fTtcbiAgY2xvbmVhYmxlVGFnc1thcmdzVGFnXSA9IGNsb25lYWJsZVRhZ3NbYXJyYXlUYWddID1cbiAgY2xvbmVhYmxlVGFnc1thcnJheUJ1ZmZlclRhZ10gPSBjbG9uZWFibGVUYWdzW2RhdGFWaWV3VGFnXSA9XG4gIGNsb25lYWJsZVRhZ3NbYm9vbFRhZ10gPSBjbG9uZWFibGVUYWdzW2RhdGVUYWddID1cbiAgY2xvbmVhYmxlVGFnc1tmbG9hdDMyVGFnXSA9IGNsb25lYWJsZVRhZ3NbZmxvYXQ2NFRhZ10gPVxuICBjbG9uZWFibGVUYWdzW2ludDhUYWddID0gY2xvbmVhYmxlVGFnc1tpbnQxNlRhZ10gPVxuICBjbG9uZWFibGVUYWdzW2ludDMyVGFnXSA9IGNsb25lYWJsZVRhZ3NbbWFwVGFnXSA9XG4gIGNsb25lYWJsZVRhZ3NbbnVtYmVyVGFnXSA9IGNsb25lYWJsZVRhZ3Nbb2JqZWN0VGFnXSA9XG4gIGNsb25lYWJsZVRhZ3NbcmVnZXhwVGFnXSA9IGNsb25lYWJsZVRhZ3Nbc2V0VGFnXSA9XG4gIGNsb25lYWJsZVRhZ3Nbc3RyaW5nVGFnXSA9IGNsb25lYWJsZVRhZ3Nbc3ltYm9sVGFnXSA9XG4gIGNsb25lYWJsZVRhZ3NbdWludDhUYWddID0gY2xvbmVhYmxlVGFnc1t1aW50OENsYW1wZWRUYWddID1cbiAgY2xvbmVhYmxlVGFnc1t1aW50MTZUYWddID0gY2xvbmVhYmxlVGFnc1t1aW50MzJUYWddID0gdHJ1ZTtcbiAgY2xvbmVhYmxlVGFnc1tlcnJvclRhZ10gPSBjbG9uZWFibGVUYWdzW2Z1bmNUYWddID1cbiAgY2xvbmVhYmxlVGFnc1t3ZWFrTWFwVGFnXSA9IGZhbHNlO1xuXG4gIC8qKiBVc2VkIHRvIG1hcCBMYXRpbiBVbmljb2RlIGxldHRlcnMgdG8gYmFzaWMgTGF0aW4gbGV0dGVycy4gKi9cbiAgdmFyIGRlYnVycmVkTGV0dGVycyA9IHtcbiAgICAvLyBMYXRpbi0xIFN1cHBsZW1lbnQgYmxvY2suXG4gICAgJ1xceGMwJzogJ0EnLCAgJ1xceGMxJzogJ0EnLCAnXFx4YzInOiAnQScsICdcXHhjMyc6ICdBJywgJ1xceGM0JzogJ0EnLCAnXFx4YzUnOiAnQScsXG4gICAgJ1xceGUwJzogJ2EnLCAgJ1xceGUxJzogJ2EnLCAnXFx4ZTInOiAnYScsICdcXHhlMyc6ICdhJywgJ1xceGU0JzogJ2EnLCAnXFx4ZTUnOiAnYScsXG4gICAgJ1xceGM3JzogJ0MnLCAgJ1xceGU3JzogJ2MnLFxuICAgICdcXHhkMCc6ICdEJywgICdcXHhmMCc6ICdkJyxcbiAgICAnXFx4YzgnOiAnRScsICAnXFx4YzknOiAnRScsICdcXHhjYSc6ICdFJywgJ1xceGNiJzogJ0UnLFxuICAgICdcXHhlOCc6ICdlJywgICdcXHhlOSc6ICdlJywgJ1xceGVhJzogJ2UnLCAnXFx4ZWInOiAnZScsXG4gICAgJ1xceGNjJzogJ0knLCAgJ1xceGNkJzogJ0knLCAnXFx4Y2UnOiAnSScsICdcXHhjZic6ICdJJyxcbiAgICAnXFx4ZWMnOiAnaScsICAnXFx4ZWQnOiAnaScsICdcXHhlZSc6ICdpJywgJ1xceGVmJzogJ2knLFxuICAgICdcXHhkMSc6ICdOJywgICdcXHhmMSc6ICduJyxcbiAgICAnXFx4ZDInOiAnTycsICAnXFx4ZDMnOiAnTycsICdcXHhkNCc6ICdPJywgJ1xceGQ1JzogJ08nLCAnXFx4ZDYnOiAnTycsICdcXHhkOCc6ICdPJyxcbiAgICAnXFx4ZjInOiAnbycsICAnXFx4ZjMnOiAnbycsICdcXHhmNCc6ICdvJywgJ1xceGY1JzogJ28nLCAnXFx4ZjYnOiAnbycsICdcXHhmOCc6ICdvJyxcbiAgICAnXFx4ZDknOiAnVScsICAnXFx4ZGEnOiAnVScsICdcXHhkYic6ICdVJywgJ1xceGRjJzogJ1UnLFxuICAgICdcXHhmOSc6ICd1JywgICdcXHhmYSc6ICd1JywgJ1xceGZiJzogJ3UnLCAnXFx4ZmMnOiAndScsXG4gICAgJ1xceGRkJzogJ1knLCAgJ1xceGZkJzogJ3knLCAnXFx4ZmYnOiAneScsXG4gICAgJ1xceGM2JzogJ0FlJywgJ1xceGU2JzogJ2FlJyxcbiAgICAnXFx4ZGUnOiAnVGgnLCAnXFx4ZmUnOiAndGgnLFxuICAgICdcXHhkZic6ICdzcycsXG4gICAgLy8gTGF0aW4gRXh0ZW5kZWQtQSBibG9jay5cbiAgICAnXFx1MDEwMCc6ICdBJywgICdcXHUwMTAyJzogJ0EnLCAnXFx1MDEwNCc6ICdBJyxcbiAgICAnXFx1MDEwMSc6ICdhJywgICdcXHUwMTAzJzogJ2EnLCAnXFx1MDEwNSc6ICdhJyxcbiAgICAnXFx1MDEwNic6ICdDJywgICdcXHUwMTA4JzogJ0MnLCAnXFx1MDEwYSc6ICdDJywgJ1xcdTAxMGMnOiAnQycsXG4gICAgJ1xcdTAxMDcnOiAnYycsICAnXFx1MDEwOSc6ICdjJywgJ1xcdTAxMGInOiAnYycsICdcXHUwMTBkJzogJ2MnLFxuICAgICdcXHUwMTBlJzogJ0QnLCAgJ1xcdTAxMTAnOiAnRCcsICdcXHUwMTBmJzogJ2QnLCAnXFx1MDExMSc6ICdkJyxcbiAgICAnXFx1MDExMic6ICdFJywgICdcXHUwMTE0JzogJ0UnLCAnXFx1MDExNic6ICdFJywgJ1xcdTAxMTgnOiAnRScsICdcXHUwMTFhJzogJ0UnLFxuICAgICdcXHUwMTEzJzogJ2UnLCAgJ1xcdTAxMTUnOiAnZScsICdcXHUwMTE3JzogJ2UnLCAnXFx1MDExOSc6ICdlJywgJ1xcdTAxMWInOiAnZScsXG4gICAgJ1xcdTAxMWMnOiAnRycsICAnXFx1MDExZSc6ICdHJywgJ1xcdTAxMjAnOiAnRycsICdcXHUwMTIyJzogJ0cnLFxuICAgICdcXHUwMTFkJzogJ2cnLCAgJ1xcdTAxMWYnOiAnZycsICdcXHUwMTIxJzogJ2cnLCAnXFx1MDEyMyc6ICdnJyxcbiAgICAnXFx1MDEyNCc6ICdIJywgICdcXHUwMTI2JzogJ0gnLCAnXFx1MDEyNSc6ICdoJywgJ1xcdTAxMjcnOiAnaCcsXG4gICAgJ1xcdTAxMjgnOiAnSScsICAnXFx1MDEyYSc6ICdJJywgJ1xcdTAxMmMnOiAnSScsICdcXHUwMTJlJzogJ0knLCAnXFx1MDEzMCc6ICdJJyxcbiAgICAnXFx1MDEyOSc6ICdpJywgICdcXHUwMTJiJzogJ2knLCAnXFx1MDEyZCc6ICdpJywgJ1xcdTAxMmYnOiAnaScsICdcXHUwMTMxJzogJ2knLFxuICAgICdcXHUwMTM0JzogJ0onLCAgJ1xcdTAxMzUnOiAnaicsXG4gICAgJ1xcdTAxMzYnOiAnSycsICAnXFx1MDEzNyc6ICdrJywgJ1xcdTAxMzgnOiAnaycsXG4gICAgJ1xcdTAxMzknOiAnTCcsICAnXFx1MDEzYic6ICdMJywgJ1xcdTAxM2QnOiAnTCcsICdcXHUwMTNmJzogJ0wnLCAnXFx1MDE0MSc6ICdMJyxcbiAgICAnXFx1MDEzYSc6ICdsJywgICdcXHUwMTNjJzogJ2wnLCAnXFx1MDEzZSc6ICdsJywgJ1xcdTAxNDAnOiAnbCcsICdcXHUwMTQyJzogJ2wnLFxuICAgICdcXHUwMTQzJzogJ04nLCAgJ1xcdTAxNDUnOiAnTicsICdcXHUwMTQ3JzogJ04nLCAnXFx1MDE0YSc6ICdOJyxcbiAgICAnXFx1MDE0NCc6ICduJywgICdcXHUwMTQ2JzogJ24nLCAnXFx1MDE0OCc6ICduJywgJ1xcdTAxNGInOiAnbicsXG4gICAgJ1xcdTAxNGMnOiAnTycsICAnXFx1MDE0ZSc6ICdPJywgJ1xcdTAxNTAnOiAnTycsXG4gICAgJ1xcdTAxNGQnOiAnbycsICAnXFx1MDE0Zic6ICdvJywgJ1xcdTAxNTEnOiAnbycsXG4gICAgJ1xcdTAxNTQnOiAnUicsICAnXFx1MDE1Nic6ICdSJywgJ1xcdTAxNTgnOiAnUicsXG4gICAgJ1xcdTAxNTUnOiAncicsICAnXFx1MDE1Nyc6ICdyJywgJ1xcdTAxNTknOiAncicsXG4gICAgJ1xcdTAxNWEnOiAnUycsICAnXFx1MDE1Yyc6ICdTJywgJ1xcdTAxNWUnOiAnUycsICdcXHUwMTYwJzogJ1MnLFxuICAgICdcXHUwMTViJzogJ3MnLCAgJ1xcdTAxNWQnOiAncycsICdcXHUwMTVmJzogJ3MnLCAnXFx1MDE2MSc6ICdzJyxcbiAgICAnXFx1MDE2Mic6ICdUJywgICdcXHUwMTY0JzogJ1QnLCAnXFx1MDE2Nic6ICdUJyxcbiAgICAnXFx1MDE2Myc6ICd0JywgICdcXHUwMTY1JzogJ3QnLCAnXFx1MDE2Nyc6ICd0JyxcbiAgICAnXFx1MDE2OCc6ICdVJywgICdcXHUwMTZhJzogJ1UnLCAnXFx1MDE2Yyc6ICdVJywgJ1xcdTAxNmUnOiAnVScsICdcXHUwMTcwJzogJ1UnLCAnXFx1MDE3Mic6ICdVJyxcbiAgICAnXFx1MDE2OSc6ICd1JywgICdcXHUwMTZiJzogJ3UnLCAnXFx1MDE2ZCc6ICd1JywgJ1xcdTAxNmYnOiAndScsICdcXHUwMTcxJzogJ3UnLCAnXFx1MDE3Myc6ICd1JyxcbiAgICAnXFx1MDE3NCc6ICdXJywgICdcXHUwMTc1JzogJ3cnLFxuICAgICdcXHUwMTc2JzogJ1knLCAgJ1xcdTAxNzcnOiAneScsICdcXHUwMTc4JzogJ1knLFxuICAgICdcXHUwMTc5JzogJ1onLCAgJ1xcdTAxN2InOiAnWicsICdcXHUwMTdkJzogJ1onLFxuICAgICdcXHUwMTdhJzogJ3onLCAgJ1xcdTAxN2MnOiAneicsICdcXHUwMTdlJzogJ3onLFxuICAgICdcXHUwMTMyJzogJ0lKJywgJ1xcdTAxMzMnOiAnaWonLFxuICAgICdcXHUwMTUyJzogJ09lJywgJ1xcdTAxNTMnOiAnb2UnLFxuICAgICdcXHUwMTQ5JzogXCInblwiLCAnXFx1MDE3Zic6ICdzJ1xuICB9O1xuXG4gIC8qKiBVc2VkIHRvIG1hcCBjaGFyYWN0ZXJzIHRvIEhUTUwgZW50aXRpZXMuICovXG4gIHZhciBodG1sRXNjYXBlcyA9IHtcbiAgICAnJic6ICcmYW1wOycsXG4gICAgJzwnOiAnJmx0OycsXG4gICAgJz4nOiAnJmd0OycsXG4gICAgJ1wiJzogJyZxdW90OycsXG4gICAgXCInXCI6ICcmIzM5OydcbiAgfTtcblxuICAvKiogVXNlZCB0byBtYXAgSFRNTCBlbnRpdGllcyB0byBjaGFyYWN0ZXJzLiAqL1xuICB2YXIgaHRtbFVuZXNjYXBlcyA9IHtcbiAgICAnJmFtcDsnOiAnJicsXG4gICAgJyZsdDsnOiAnPCcsXG4gICAgJyZndDsnOiAnPicsXG4gICAgJyZxdW90Oyc6ICdcIicsXG4gICAgJyYjMzk7JzogXCInXCJcbiAgfTtcblxuICAvKiogVXNlZCB0byBlc2NhcGUgY2hhcmFjdGVycyBmb3IgaW5jbHVzaW9uIGluIGNvbXBpbGVkIHN0cmluZyBsaXRlcmFscy4gKi9cbiAgdmFyIHN0cmluZ0VzY2FwZXMgPSB7XG4gICAgJ1xcXFwnOiAnXFxcXCcsXG4gICAgXCInXCI6IFwiJ1wiLFxuICAgICdcXG4nOiAnbicsXG4gICAgJ1xccic6ICdyJyxcbiAgICAnXFx1MjAyOCc6ICd1MjAyOCcsXG4gICAgJ1xcdTIwMjknOiAndTIwMjknXG4gIH07XG5cbiAgLyoqIEJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzIHdpdGhvdXQgYSBkZXBlbmRlbmN5IG9uIGByb290YC4gKi9cbiAgdmFyIGZyZWVQYXJzZUZsb2F0ID0gcGFyc2VGbG9hdCxcbiAgICAgIGZyZWVQYXJzZUludCA9IHBhcnNlSW50O1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZ2xvYmFsYCBmcm9tIE5vZGUuanMuICovXG4gIHZhciBmcmVlR2xvYmFsID0gdHlwZW9mIGdsb2JhbCA9PSAnb2JqZWN0JyAmJiBnbG9iYWwgJiYgZ2xvYmFsLk9iamVjdCA9PT0gT2JqZWN0ICYmIGdsb2JhbDtcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYHNlbGZgLiAqL1xuICB2YXIgZnJlZVNlbGYgPSB0eXBlb2Ygc2VsZiA9PSAnb2JqZWN0JyAmJiBzZWxmICYmIHNlbGYuT2JqZWN0ID09PSBPYmplY3QgJiYgc2VsZjtcblxuICAvKiogVXNlZCBhcyBhIHJlZmVyZW5jZSB0byB0aGUgZ2xvYmFsIG9iamVjdC4gKi9cbiAgdmFyIHJvb3QgPSBmcmVlR2xvYmFsIHx8IGZyZWVTZWxmIHx8IEZ1bmN0aW9uKCdyZXR1cm4gdGhpcycpKCk7XG5cbiAgLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBleHBvcnRzYC4gKi9cbiAgdmFyIGZyZWVFeHBvcnRzID0gdHlwZW9mIGV4cG9ydHMgPT0gJ29iamVjdCcgJiYgZXhwb3J0cyAmJiAhZXhwb3J0cy5ub2RlVHlwZSAmJiBleHBvcnRzO1xuXG4gIC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgbW9kdWxlYC4gKi9cbiAgdmFyIGZyZWVNb2R1bGUgPSBmcmVlRXhwb3J0cyAmJiB0eXBlb2YgbW9kdWxlID09ICdvYmplY3QnICYmIG1vZHVsZSAmJiAhbW9kdWxlLm5vZGVUeXBlICYmIG1vZHVsZTtcblxuICAvKiogRGV0ZWN0IHRoZSBwb3B1bGFyIENvbW1vbkpTIGV4dGVuc2lvbiBgbW9kdWxlLmV4cG9ydHNgLiAqL1xuICB2YXIgbW9kdWxlRXhwb3J0cyA9IGZyZWVNb2R1bGUgJiYgZnJlZU1vZHVsZS5leHBvcnRzID09PSBmcmVlRXhwb3J0cztcblxuICAvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYHByb2Nlc3NgIGZyb20gTm9kZS5qcy4gKi9cbiAgdmFyIGZyZWVQcm9jZXNzID0gbW9kdWxlRXhwb3J0cyAmJiBmcmVlR2xvYmFsLnByb2Nlc3M7XG5cbiAgLyoqIFVzZWQgdG8gYWNjZXNzIGZhc3RlciBOb2RlLmpzIGhlbHBlcnMuICovXG4gIHZhciBub2RlVXRpbCA9IChmdW5jdGlvbigpIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGZyZWVQcm9jZXNzICYmIGZyZWVQcm9jZXNzLmJpbmRpbmcgJiYgZnJlZVByb2Nlc3MuYmluZGluZygndXRpbCcpO1xuICAgIH0gY2F0Y2ggKGUpIHt9XG4gIH0oKSk7XG5cbiAgLyogTm9kZS5qcyBoZWxwZXIgcmVmZXJlbmNlcy4gKi9cbiAgdmFyIG5vZGVJc0FycmF5QnVmZmVyID0gbm9kZVV0aWwgJiYgbm9kZVV0aWwuaXNBcnJheUJ1ZmZlcixcbiAgICAgIG5vZGVJc0RhdGUgPSBub2RlVXRpbCAmJiBub2RlVXRpbC5pc0RhdGUsXG4gICAgICBub2RlSXNNYXAgPSBub2RlVXRpbCAmJiBub2RlVXRpbC5pc01hcCxcbiAgICAgIG5vZGVJc1JlZ0V4cCA9IG5vZGVVdGlsICYmIG5vZGVVdGlsLmlzUmVnRXhwLFxuICAgICAgbm9kZUlzU2V0ID0gbm9kZVV0aWwgJiYgbm9kZVV0aWwuaXNTZXQsXG4gICAgICBub2RlSXNUeXBlZEFycmF5ID0gbm9kZVV0aWwgJiYgbm9kZVV0aWwuaXNUeXBlZEFycmF5O1xuXG4gIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gIC8qKlxuICAgKiBBZGRzIHRoZSBrZXktdmFsdWUgYHBhaXJgIHRvIGBtYXBgLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gbWFwIFRoZSBtYXAgdG8gbW9kaWZ5LlxuICAgKiBAcGFyYW0ge0FycmF5fSBwYWlyIFRoZSBrZXktdmFsdWUgcGFpciB0byBhZGQuXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG1hcGAuXG4gICAqL1xuICBmdW5jdGlvbiBhZGRNYXBFbnRyeShtYXAsIHBhaXIpIHtcbiAgICAvLyBEb24ndCByZXR1cm4gYG1hcC5zZXRgIGJlY2F1c2UgaXQncyBub3QgY2hhaW5hYmxlIGluIElFIDExLlxuICAgIG1hcC5zZXQocGFpclswXSwgcGFpclsxXSk7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGB2YWx1ZWAgdG8gYHNldGAuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBzZXQgVGhlIHNldCB0byBtb2RpZnkuXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGFkZC5cbiAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgc2V0YC5cbiAgICovXG4gIGZ1bmN0aW9uIGFkZFNldEVudHJ5KHNldCwgdmFsdWUpIHtcbiAgICAvLyBEb24ndCByZXR1cm4gYHNldC5hZGRgIGJlY2F1c2UgaXQncyBub3QgY2hhaW5hYmxlIGluIElFIDExLlxuICAgIHNldC5hZGQodmFsdWUpO1xuICAgIHJldHVybiBzZXQ7XG4gIH1cblxuICAvKipcbiAgICogQSBmYXN0ZXIgYWx0ZXJuYXRpdmUgdG8gYEZ1bmN0aW9uI2FwcGx5YCwgdGhpcyBmdW5jdGlvbiBpbnZva2VzIGBmdW5jYFxuICAgKiB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBvZiBgdGhpc0FyZ2AgYW5kIHRoZSBhcmd1bWVudHMgb2YgYGFyZ3NgLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBpbnZva2UuXG4gICAqIEBwYXJhbSB7Kn0gdGhpc0FyZyBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGZ1bmNgLlxuICAgKiBAcGFyYW0ge0FycmF5fSBhcmdzIFRoZSBhcmd1bWVudHMgdG8gaW52b2tlIGBmdW5jYCB3aXRoLlxuICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcmVzdWx0IG9mIGBmdW5jYC5cbiAgICovXG4gIGZ1bmN0aW9uIGFwcGx5KGZ1bmMsIHRoaXNBcmcsIGFyZ3MpIHtcbiAgICBzd2l0Y2ggKGFyZ3MubGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6IHJldHVybiBmdW5jLmNhbGwodGhpc0FyZyk7XG4gICAgICBjYXNlIDE6IHJldHVybiBmdW5jLmNhbGwodGhpc0FyZywgYXJnc1swXSk7XG4gICAgICBjYXNlIDI6IHJldHVybiBmdW5jLmNhbGwodGhpc0FyZywgYXJnc1swXSwgYXJnc1sxXSk7XG4gICAgICBjYXNlIDM6IHJldHVybiBmdW5jLmNhbGwodGhpc0FyZywgYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSk7XG4gICAgfVxuICAgIHJldHVybiBmdW5jLmFwcGx5KHRoaXNBcmcsIGFyZ3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZUFnZ3JlZ2F0b3JgIGZvciBhcnJheXMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IFthcnJheV0gVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gc2V0dGVyIFRoZSBmdW5jdGlvbiB0byBzZXQgYGFjY3VtdWxhdG9yYCB2YWx1ZXMuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBpdGVyYXRlZSB0byB0cmFuc2Zvcm0ga2V5cy5cbiAgICogQHBhcmFtIHtPYmplY3R9IGFjY3VtdWxhdG9yIFRoZSBpbml0aWFsIGFnZ3JlZ2F0ZWQgb2JqZWN0LlxuICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgYGFjY3VtdWxhdG9yYC5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5QWdncmVnYXRvcihhcnJheSwgc2V0dGVyLCBpdGVyYXRlZSwgYWNjdW11bGF0b3IpIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdO1xuICAgICAgc2V0dGVyKGFjY3VtdWxhdG9yLCB2YWx1ZSwgaXRlcmF0ZWUodmFsdWUpLCBhcnJheSk7XG4gICAgfVxuICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uZm9yRWFjaGAgZm9yIGFycmF5cyB3aXRob3V0IHN1cHBvcnQgZm9yXG4gICAqIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IFthcnJheV0gVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAqL1xuICBmdW5jdGlvbiBhcnJheUVhY2goYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgIGlmIChpdGVyYXRlZShhcnJheVtpbmRleF0sIGluZGV4LCBhcnJheSkgPT09IGZhbHNlKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYXJyYXk7XG4gIH1cblxuICAvKipcbiAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLmZvckVhY2hSaWdodGAgZm9yIGFycmF5cyB3aXRob3V0IHN1cHBvcnQgZm9yXG4gICAqIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IFthcnJheV0gVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAqL1xuICBmdW5jdGlvbiBhcnJheUVhY2hSaWdodChhcnJheSwgaXRlcmF0ZWUpIHtcbiAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG5cbiAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgIGlmIChpdGVyYXRlZShhcnJheVtsZW5ndGhdLCBsZW5ndGgsIGFycmF5KSA9PT0gZmFsc2UpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBhcnJheTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uZXZlcnlgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvclxuICAgKiBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBbYXJyYXldIFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYWxsIGVsZW1lbnRzIHBhc3MgdGhlIHByZWRpY2F0ZSBjaGVjayxcbiAgICogIGVsc2UgYGZhbHNlYC5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5RXZlcnkoYXJyYXksIHByZWRpY2F0ZSkge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICBpZiAoIXByZWRpY2F0ZShhcnJheVtpbmRleF0sIGluZGV4LCBhcnJheSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uZmlsdGVyYCBmb3IgYXJyYXlzIHdpdGhvdXQgc3VwcG9ydCBmb3JcbiAgICogaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gW2FycmF5XSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZmlsdGVyZWQgYXJyYXkuXG4gICAqL1xuICBmdW5jdGlvbiBhcnJheUZpbHRlcihhcnJheSwgcHJlZGljYXRlKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoLFxuICAgICAgICByZXNJbmRleCA9IDAsXG4gICAgICAgIHJlc3VsdCA9IFtdO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XTtcbiAgICAgIGlmIChwcmVkaWNhdGUodmFsdWUsIGluZGV4LCBhcnJheSkpIHtcbiAgICAgICAgcmVzdWx0W3Jlc0luZGV4KytdID0gdmFsdWU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLmluY2x1ZGVzYCBmb3IgYXJyYXlzIHdpdGhvdXQgc3VwcG9ydCBmb3JcbiAgICogc3BlY2lmeWluZyBhbiBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gW2FycmF5XSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICogQHBhcmFtIHsqfSB0YXJnZXQgVGhlIHZhbHVlIHRvIHNlYXJjaCBmb3IuXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdGFyZ2V0YCBpcyBmb3VuZCwgZWxzZSBgZmFsc2VgLlxuICAgKi9cbiAgZnVuY3Rpb24gYXJyYXlJbmNsdWRlcyhhcnJheSwgdmFsdWUpIHtcbiAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgcmV0dXJuICEhbGVuZ3RoICYmIGJhc2VJbmRleE9mKGFycmF5LCB2YWx1ZSwgMCkgPiAtMTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIGZ1bmN0aW9uIGlzIGxpa2UgYGFycmF5SW5jbHVkZXNgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYSBjb21wYXJhdG9yLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBbYXJyYXldIFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgKiBAcGFyYW0geyp9IHRhcmdldCBUaGUgdmFsdWUgdG8gc2VhcmNoIGZvci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY29tcGFyYXRvciBUaGUgY29tcGFyYXRvciBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHRhcmdldGAgaXMgZm91bmQsIGVsc2UgYGZhbHNlYC5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5SW5jbHVkZXNXaXRoKGFycmF5LCB2YWx1ZSwgY29tcGFyYXRvcikge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICBpZiAoY29tcGFyYXRvcih2YWx1ZSwgYXJyYXlbaW5kZXhdKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5tYXBgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZVxuICAgKiBzaG9ydGhhbmRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBbYXJyYXldIFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IG1hcHBlZCBhcnJheS5cbiAgICovXG4gIGZ1bmN0aW9uIGFycmF5TWFwKGFycmF5LCBpdGVyYXRlZSkge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgcmVzdWx0ID0gQXJyYXkobGVuZ3RoKTtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICByZXN1bHRbaW5kZXhdID0gaXRlcmF0ZWUoYXJyYXlbaW5kZXhdLCBpbmRleCwgYXJyYXkpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIEFwcGVuZHMgdGhlIGVsZW1lbnRzIG9mIGB2YWx1ZXNgIHRvIGBhcnJheWAuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBtb2RpZnkuXG4gICAqIEBwYXJhbSB7QXJyYXl9IHZhbHVlcyBUaGUgdmFsdWVzIHRvIGFwcGVuZC5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAqL1xuICBmdW5jdGlvbiBhcnJheVB1c2goYXJyYXksIHZhbHVlcykge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSB2YWx1ZXMubGVuZ3RoLFxuICAgICAgICBvZmZzZXQgPSBhcnJheS5sZW5ndGg7XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgYXJyYXlbb2Zmc2V0ICsgaW5kZXhdID0gdmFsdWVzW2luZGV4XTtcbiAgICB9XG4gICAgcmV0dXJuIGFycmF5O1xuICB9XG5cbiAgLyoqXG4gICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5yZWR1Y2VgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvclxuICAgKiBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBbYXJyYXldIFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAqIEBwYXJhbSB7Kn0gW2FjY3VtdWxhdG9yXSBUaGUgaW5pdGlhbCB2YWx1ZS5cbiAgICogQHBhcmFtIHtib29sZWFufSBbaW5pdEFjY3VtXSBTcGVjaWZ5IHVzaW5nIHRoZSBmaXJzdCBlbGVtZW50IG9mIGBhcnJheWAgYXNcbiAgICogIHRoZSBpbml0aWFsIHZhbHVlLlxuICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgYWNjdW11bGF0ZWQgdmFsdWUuXG4gICAqL1xuICBmdW5jdGlvbiBhcnJheVJlZHVjZShhcnJheSwgaXRlcmF0ZWUsIGFjY3VtdWxhdG9yLCBpbml0QWNjdW0pIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG5cbiAgICBpZiAoaW5pdEFjY3VtICYmIGxlbmd0aCkge1xuICAgICAgYWNjdW11bGF0b3IgPSBhcnJheVsrK2luZGV4XTtcbiAgICB9XG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgIGFjY3VtdWxhdG9yID0gaXRlcmF0ZWUoYWNjdW11bGF0b3IsIGFycmF5W2luZGV4XSwgaW5kZXgsIGFycmF5KTtcbiAgICB9XG4gICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5yZWR1Y2VSaWdodGAgZm9yIGFycmF5cyB3aXRob3V0IHN1cHBvcnQgZm9yXG4gICAqIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IFthcnJheV0gVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHBhcmFtIHsqfSBbYWNjdW11bGF0b3JdIFRoZSBpbml0aWFsIHZhbHVlLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpbml0QWNjdW1dIFNwZWNpZnkgdXNpbmcgdGhlIGxhc3QgZWxlbWVudCBvZiBgYXJyYXlgIGFzXG4gICAqICB0aGUgaW5pdGlhbCB2YWx1ZS5cbiAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGFjY3VtdWxhdGVkIHZhbHVlLlxuICAgKi9cbiAgZnVuY3Rpb24gYXJyYXlSZWR1Y2VSaWdodChhcnJheSwgaXRlcmF0ZWUsIGFjY3VtdWxhdG9yLCBpbml0QWNjdW0pIHtcbiAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgaWYgKGluaXRBY2N1bSAmJiBsZW5ndGgpIHtcbiAgICAgIGFjY3VtdWxhdG9yID0gYXJyYXlbLS1sZW5ndGhdO1xuICAgIH1cbiAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgIGFjY3VtdWxhdG9yID0gaXRlcmF0ZWUoYWNjdW11bGF0b3IsIGFycmF5W2xlbmd0aF0sIGxlbmd0aCwgYXJyYXkpO1xuICAgIH1cbiAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gIH1cblxuICAvKipcbiAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLnNvbWVgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZVxuICAgKiBzaG9ydGhhbmRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBbYXJyYXldIFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYW55IGVsZW1lbnQgcGFzc2VzIHRoZSBwcmVkaWNhdGUgY2hlY2ssXG4gICAqICBlbHNlIGBmYWxzZWAuXG4gICAqL1xuICBmdW5jdGlvbiBhcnJheVNvbWUoYXJyYXksIHByZWRpY2F0ZSkge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICBpZiAocHJlZGljYXRlKGFycmF5W2luZGV4XSwgaW5kZXgsIGFycmF5KSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIHNpemUgb2YgYW4gQVNDSUkgYHN0cmluZ2AuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyBpbnNwZWN0LlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBzdHJpbmcgc2l6ZS5cbiAgICovXG4gIHZhciBhc2NpaVNpemUgPSBiYXNlUHJvcGVydHkoJ2xlbmd0aCcpO1xuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhbiBBU0NJSSBgc3RyaW5nYCB0byBhbiBhcnJheS5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgY29udmVydGVkIGFycmF5LlxuICAgKi9cbiAgZnVuY3Rpb24gYXNjaWlUb0FycmF5KHN0cmluZykge1xuICAgIHJldHVybiBzdHJpbmcuc3BsaXQoJycpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNwbGl0cyBhbiBBU0NJSSBgc3RyaW5nYCBpbnRvIGFuIGFycmF5IG9mIGl0cyB3b3Jkcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IFRoZSBzdHJpbmcgdG8gaW5zcGVjdC5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSB3b3JkcyBvZiBgc3RyaW5nYC5cbiAgICovXG4gIGZ1bmN0aW9uIGFzY2lpV29yZHMoc3RyaW5nKSB7XG4gICAgcmV0dXJuIHN0cmluZy5tYXRjaChyZUFzY2lpV29yZCkgfHwgW107XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgbWV0aG9kcyBsaWtlIGBfLmZpbmRLZXlgIGFuZCBgXy5maW5kTGFzdEtleWAsXG4gICAqIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcywgd2hpY2ggaXRlcmF0ZXMgb3ZlciBgY29sbGVjdGlvbmBcbiAgICogdXNpbmcgYGVhY2hGdW5jYC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaW5zcGVjdC5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZGljYXRlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGVhY2hGdW5jIFRoZSBmdW5jdGlvbiB0byBpdGVyYXRlIG92ZXIgYGNvbGxlY3Rpb25gLlxuICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZm91bmQgZWxlbWVudCBvciBpdHMga2V5LCBlbHNlIGB1bmRlZmluZWRgLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZUZpbmRLZXkoY29sbGVjdGlvbiwgcHJlZGljYXRlLCBlYWNoRnVuYykge1xuICAgIHZhciByZXN1bHQ7XG4gICAgZWFjaEZ1bmMoY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGtleSwgY29sbGVjdGlvbikge1xuICAgICAgaWYgKHByZWRpY2F0ZSh2YWx1ZSwga2V5LCBjb2xsZWN0aW9uKSkge1xuICAgICAgICByZXN1bHQgPSBrZXk7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmZpbmRJbmRleGAgYW5kIGBfLmZpbmRMYXN0SW5kZXhgIHdpdGhvdXRcbiAgICogc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcGFyYW0ge251bWJlcn0gZnJvbUluZGV4IFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICogQHBhcmFtIHtib29sZWFufSBbZnJvbVJpZ2h0XSBTcGVjaWZ5IGl0ZXJhdGluZyBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBtYXRjaGVkIHZhbHVlLCBlbHNlIGAtMWAuXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlRmluZEluZGV4KGFycmF5LCBwcmVkaWNhdGUsIGZyb21JbmRleCwgZnJvbVJpZ2h0KSB7XG4gICAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgaW5kZXggPSBmcm9tSW5kZXggKyAoZnJvbVJpZ2h0ID8gMSA6IC0xKTtcblxuICAgIHdoaWxlICgoZnJvbVJpZ2h0ID8gaW5kZXgtLSA6ICsraW5kZXggPCBsZW5ndGgpKSB7XG4gICAgICBpZiAocHJlZGljYXRlKGFycmF5W2luZGV4XSwgaW5kZXgsIGFycmF5KSkge1xuICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiAtMTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pbmRleE9mYCB3aXRob3V0IGBmcm9tSW5kZXhgIGJvdW5kcyBjaGVja3MuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgKiBAcGFyYW0ge251bWJlcn0gZnJvbUluZGV4IFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUsIGVsc2UgYC0xYC5cbiAgICovXG4gIGZ1bmN0aW9uIGJhc2VJbmRleE9mKGFycmF5LCB2YWx1ZSwgZnJvbUluZGV4KSB7XG4gICAgcmV0dXJuIHZhbHVlID09PSB2YWx1ZVxuICAgICAgPyBzdHJpY3RJbmRleE9mKGFycmF5LCB2YWx1ZSwgZnJvbUluZGV4KVxuICAgICAgOiBiYXNlRmluZEluZGV4KGFycmF5LCBiYXNlSXNOYU4sIGZyb21JbmRleCk7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBmdW5jdGlvbiBpcyBsaWtlIGBiYXNlSW5kZXhPZmAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBhIGNvbXBhcmF0b3IuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgKiBAcGFyYW0ge251bWJlcn0gZnJvbUluZGV4IFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY29tcGFyYXRvciBUaGUgY29tcGFyYXRvciBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgbWF0Y2hlZCB2YWx1ZSwgZWxzZSBgLTFgLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZUluZGV4T2ZXaXRoKGFycmF5LCB2YWx1ZSwgZnJvbUluZGV4LCBjb21wYXJhdG9yKSB7XG4gICAgdmFyIGluZGV4ID0gZnJvbUluZGV4IC0gMSxcbiAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgIGlmIChjb21wYXJhdG9yKGFycmF5W2luZGV4XSwgdmFsdWUpKSB7XG4gICAgICAgIHJldHVybiBpbmRleDtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIC0xO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmlzTmFOYCB3aXRob3V0IHN1cHBvcnQgZm9yIG51bWJlciBvYmplY3RzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYE5hTmAsIGVsc2UgYGZhbHNlYC5cbiAgICovXG4gIGZ1bmN0aW9uIGJhc2VJc05hTih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZSAhPT0gdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ubWVhbmAgYW5kIGBfLm1lYW5CeWAgd2l0aG91dCBzdXBwb3J0IGZvclxuICAgKiBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBtZWFuLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZU1lYW4oYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuICAgIHJldHVybiBsZW5ndGggPyAoYmFzZVN1bShhcnJheSwgaXRlcmF0ZWUpIC8gbGVuZ3RoKSA6IE5BTjtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5wcm9wZXJ0eWAgd2l0aG91dCBzdXBwb3J0IGZvciBkZWVwIHBhdGhzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHByb3BlcnR5IHRvIGdldC5cbiAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYWNjZXNzb3IgZnVuY3Rpb24uXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlUHJvcGVydHkoa2V5KSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsID8gdW5kZWZpbmVkIDogb2JqZWN0W2tleV07XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5wcm9wZXJ0eU9mYCB3aXRob3V0IHN1cHBvcnQgZm9yIGRlZXAgcGF0aHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYWNjZXNzb3IgZnVuY3Rpb24uXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlUHJvcGVydHlPZihvYmplY3QpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oa2V5KSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyB1bmRlZmluZWQgOiBvYmplY3Rba2V5XTtcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnJlZHVjZWAgYW5kIGBfLnJlZHVjZVJpZ2h0YCwgd2l0aG91dCBzdXBwb3J0XG4gICAqIGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLCB3aGljaCBpdGVyYXRlcyBvdmVyIGBjb2xsZWN0aW9uYCB1c2luZyBgZWFjaEZ1bmNgLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAqIEBwYXJhbSB7Kn0gYWNjdW11bGF0b3IgVGhlIGluaXRpYWwgdmFsdWUuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gaW5pdEFjY3VtIFNwZWNpZnkgdXNpbmcgdGhlIGZpcnN0IG9yIGxhc3QgZWxlbWVudCBvZlxuICAgKiAgYGNvbGxlY3Rpb25gIGFzIHRoZSBpbml0aWFsIHZhbHVlLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBlYWNoRnVuYyBUaGUgZnVuY3Rpb24gdG8gaXRlcmF0ZSBvdmVyIGBjb2xsZWN0aW9uYC5cbiAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGFjY3VtdWxhdGVkIHZhbHVlLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZVJlZHVjZShjb2xsZWN0aW9uLCBpdGVyYXRlZSwgYWNjdW11bGF0b3IsIGluaXRBY2N1bSwgZWFjaEZ1bmMpIHtcbiAgICBlYWNoRnVuYyhjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pIHtcbiAgICAgIGFjY3VtdWxhdG9yID0gaW5pdEFjY3VtXG4gICAgICAgID8gKGluaXRBY2N1bSA9IGZhbHNlLCB2YWx1ZSlcbiAgICAgICAgOiBpdGVyYXRlZShhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKTtcbiAgICB9KTtcbiAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uc29ydEJ5YCB3aGljaCB1c2VzIGBjb21wYXJlcmAgdG8gZGVmaW5lIHRoZVxuICAgKiBzb3J0IG9yZGVyIG9mIGBhcnJheWAgYW5kIHJlcGxhY2VzIGNyaXRlcmlhIG9iamVjdHMgd2l0aCB0aGVpciBjb3JyZXNwb25kaW5nXG4gICAqIHZhbHVlcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNvcnQuXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNvbXBhcmVyIFRoZSBmdW5jdGlvbiB0byBkZWZpbmUgc29ydCBvcmRlci5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlU29ydEJ5KGFycmF5LCBjb21wYXJlcikge1xuICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgICBhcnJheS5zb3J0KGNvbXBhcmVyKTtcbiAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgIGFycmF5W2xlbmd0aF0gPSBhcnJheVtsZW5ndGhdLnZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gYXJyYXk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uc3VtYCBhbmQgYF8uc3VtQnlgIHdpdGhvdXQgc3VwcG9ydCBmb3JcbiAgICogaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgc3VtLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZVN1bShhcnJheSwgaXRlcmF0ZWUpIHtcbiAgICB2YXIgcmVzdWx0LFxuICAgICAgICBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgdmFyIGN1cnJlbnQgPSBpdGVyYXRlZShhcnJheVtpbmRleF0pO1xuICAgICAgaWYgKGN1cnJlbnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXN1bHQgPSByZXN1bHQgPT09IHVuZGVmaW5lZCA/IGN1cnJlbnQgOiAocmVzdWx0ICsgY3VycmVudCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8udGltZXNgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kc1xuICAgKiBvciBtYXggYXJyYXkgbGVuZ3RoIGNoZWNrcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtudW1iZXJ9IG4gVGhlIG51bWJlciBvZiB0aW1lcyB0byBpbnZva2UgYGl0ZXJhdGVlYC5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiByZXN1bHRzLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZVRpbWVzKG4sIGl0ZXJhdGVlKSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIHJlc3VsdCA9IEFycmF5KG4pO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBuKSB7XG4gICAgICByZXN1bHRbaW5kZXhdID0gaXRlcmF0ZWUoaW5kZXgpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnRvUGFpcnNgIGFuZCBgXy50b1BhaXJzSW5gIHdoaWNoIGNyZWF0ZXMgYW4gYXJyYXlcbiAgICogb2Yga2V5LXZhbHVlIHBhaXJzIGZvciBgb2JqZWN0YCBjb3JyZXNwb25kaW5nIHRvIHRoZSBwcm9wZXJ0eSBuYW1lcyBvZiBgcHJvcHNgLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAqIEBwYXJhbSB7QXJyYXl9IHByb3BzIFRoZSBwcm9wZXJ0eSBuYW1lcyB0byBnZXQgdmFsdWVzIGZvci5cbiAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUga2V5LXZhbHVlIHBhaXJzLlxuICAgKi9cbiAgZnVuY3Rpb24gYmFzZVRvUGFpcnMob2JqZWN0LCBwcm9wcykge1xuICAgIHJldHVybiBhcnJheU1hcChwcm9wcywgZnVuY3Rpb24oa2V5KSB7XG4gICAgICByZXR1cm4gW2tleSwgb2JqZWN0W2tleV1dO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnVuYXJ5YCB3aXRob3V0IHN1cHBvcnQgZm9yIHN0b3JpbmcgbWV0YWRhdGEuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGNhcCBhcmd1bWVudHMgZm9yLlxuICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBjYXBwZWQgZnVuY3Rpb24uXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlVW5hcnkoZnVuYykge1xuICAgIHJldHVybiBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgcmV0dXJuIGZ1bmModmFsdWUpO1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8udmFsdWVzYCBhbmQgYF8udmFsdWVzSW5gIHdoaWNoIGNyZWF0ZXMgYW5cbiAgICogYXJyYXkgb2YgYG9iamVjdGAgcHJvcGVydHkgdmFsdWVzIGNvcnJlc3BvbmRpbmcgdG8gdGhlIHByb3BlcnR5IG5hbWVzXG4gICAqIG9mIGBwcm9wc2AuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICogQHBhcmFtIHtBcnJheX0gcHJvcHMgVGhlIHByb3BlcnR5IG5hbWVzIHRvIGdldCB2YWx1ZXMgZm9yLlxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSB2YWx1ZXMuXG4gICAqL1xuICBmdW5jdGlvbiBiYXNlVmFsdWVzKG9iamVjdCwgcHJvcHMpIHtcbiAgICByZXR1cm4gYXJyYXlNYXAocHJvcHMsIGZ1bmN0aW9uKGtleSkge1xuICAgICAgcmV0dXJuIG9iamVjdFtrZXldO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiBhIGBjYWNoZWAgdmFsdWUgZm9yIGBrZXlgIGV4aXN0cy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtPYmplY3R9IGNhY2hlIFRoZSBjYWNoZSB0byBxdWVyeS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBlbnRyeSB0byBjaGVjay5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFuIGVudHJ5IGZvciBga2V5YCBleGlzdHMsIGVsc2UgYGZhbHNlYC5cbiAgICovXG4gIGZ1bmN0aW9uIGNhY2hlSGFzKGNhY2hlLCBrZXkpIHtcbiAgICByZXR1cm4gY2FjaGUuaGFzKGtleSk7XG4gIH1cblxuICAvKipcbiAgICogVXNlZCBieSBgXy50cmltYCBhbmQgYF8udHJpbVN0YXJ0YCB0byBnZXQgdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBzdHJpbmcgc3ltYm9sXG4gICAqIHRoYXQgaXMgbm90IGZvdW5kIGluIHRoZSBjaGFyYWN0ZXIgc3ltYm9scy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gc3RyU3ltYm9scyBUaGUgc3RyaW5nIHN5bWJvbHMgdG8gaW5zcGVjdC5cbiAgICogQHBhcmFtIHtBcnJheX0gY2hyU3ltYm9scyBUaGUgY2hhcmFjdGVyIHN5bWJvbHMgdG8gZmluZC5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIGZpcnN0IHVubWF0Y2hlZCBzdHJpbmcgc3ltYm9sLlxuICAgKi9cbiAgZnVuY3Rpb24gY2hhcnNTdGFydEluZGV4KHN0clN5bWJvbHMsIGNoclN5bWJvbHMpIHtcbiAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgbGVuZ3RoID0gc3RyU3ltYm9scy5sZW5ndGg7XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCAmJiBiYXNlSW5kZXhPZihjaHJTeW1ib2xzLCBzdHJTeW1ib2xzW2luZGV4XSwgMCkgPiAtMSkge31cbiAgICByZXR1cm4gaW5kZXg7XG4gIH1cblxuICAvKipcbiAgICogVXNlZCBieSBgXy50cmltYCBhbmQgYF8udHJpbUVuZGAgdG8gZ2V0IHRoZSBpbmRleCBvZiB0aGUgbGFzdCBzdHJpbmcgc3ltYm9sXG4gICAqIHRoYXQgaXMgbm90IGZvdW5kIGluIHRoZSBjaGFyYWN0ZXIgc3ltYm9scy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gc3RyU3ltYm9scyBUaGUgc3RyaW5nIHN5bWJvbHMgdG8gaW5zcGVjdC5cbiAgICogQHBhcmFtIHtBcnJheX0gY2hyU3ltYm9scyBUaGUgY2hhcmFjdGVyIHN5bWJvbHMgdG8gZmluZC5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIGxhc3QgdW5tYXRjaGVkIHN0cmluZyBzeW1ib2wuXG4gICAqL1xuICBmdW5jdGlvbiBjaGFyc0VuZEluZGV4KHN0clN5bWJvbHMsIGNoclN5bWJvbHMpIHtcbiAgICB2YXIgaW5kZXggPSBzdHJTeW1ib2xzLmxlbmd0aDtcblxuICAgIHdoaWxlIChpbmRleC0tICYmIGJhc2VJbmRleE9mKGNoclN5bWJvbHMsIHN0clN5bWJvbHNbaW5kZXhdLCAwKSA+IC0xKSB7fVxuICAgIHJldHVybiBpbmRleDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBudW1iZXIgb2YgYHBsYWNlaG9sZGVyYCBvY2N1cnJlbmNlcyBpbiBgYXJyYXlgLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICogQHBhcmFtIHsqfSBwbGFjZWhvbGRlciBUaGUgcGxhY2Vob2xkZXIgdG8gc2VhcmNoIGZvci5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgcGxhY2Vob2xkZXIgY291bnQuXG4gICAqL1xuICBmdW5jdGlvbiBjb3VudEhvbGRlcnMoYXJyYXksIHBsYWNlaG9sZGVyKSB7XG4gICAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgcmVzdWx0ID0gMDtcblxuICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgaWYgKGFycmF5W2xlbmd0aF0gPT09IHBsYWNlaG9sZGVyKSB7XG4gICAgICAgICsrcmVzdWx0O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZWQgYnkgYF8uZGVidXJyYCB0byBjb252ZXJ0IExhdGluLTEgU3VwcGxlbWVudCBhbmQgTGF0aW4gRXh0ZW5kZWQtQVxuICAgKiBsZXR0ZXJzIHRvIGJhc2ljIExhdGluIGxldHRlcnMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBsZXR0ZXIgVGhlIG1hdGNoZWQgbGV0dGVyIHRvIGRlYnVyci5cbiAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgZGVidXJyZWQgbGV0dGVyLlxuICAgKi9cbiAgdmFyIGRlYnVyckxldHRlciA9IGJhc2VQcm9wZXJ0eU9mKGRlYnVycmVkTGV0dGVycyk7XG5cbiAgLyoqXG4gICAqIFVzZWQgYnkgYF8uZXNjYXBlYCB0byBjb252ZXJ0IGNoYXJhY3RlcnMgdG8gSFRNTCBlbnRpdGllcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IGNociBUaGUgbWF0Y2hlZCBjaGFyYWN0ZXIgdG8gZXNjYXBlLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBlc2NhcGVkIGNoYXJhY3Rlci5cbiAgICovXG4gIHZhciBlc2NhcGVIdG1sQ2hhciA9IGJhc2VQcm9wZXJ0eU9mKGh0bWxFc2NhcGVzKTtcblxuICAvKipcbiAgICogVXNlZCBieSBgXy50ZW1wbGF0ZWAgdG8gZXNjYXBlIGNoYXJhY3RlcnMgZm9yIGluY2x1c2lvbiBpbiBjb21waWxlZCBzdHJpbmcgbGl0ZXJhbHMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBjaHIgVGhlIG1hdGNoZWQgY2hhcmFjdGVyIHRvIGVzY2FwZS5cbiAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgZXNjYXBlZCBjaGFyYWN0ZXIuXG4gICAqL1xuICBmdW5jdGlvbiBlc2NhcGVTdHJpbmdDaGFyKGNocikge1xuICAgIHJldHVybiAnXFxcXCcgKyBzdHJpbmdFc2NhcGVzW2Nocl07XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgdmFsdWUgYXQgYGtleWAgb2YgYG9iamVjdGAuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0XSBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHByb3BlcnR5IHRvIGdldC5cbiAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHByb3BlcnR5IHZhbHVlLlxuICAgKi9cbiAgZnVuY3Rpb24gZ2V0VmFsdWUob2JqZWN0LCBrZXkpIHtcbiAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyB1bmRlZmluZWQgOiBvYmplY3Rba2V5XTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgYHN0cmluZ2AgY29udGFpbnMgVW5pY29kZSBzeW1ib2xzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gaW5zcGVjdC5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGEgc3ltYm9sIGlzIGZvdW5kLCBlbHNlIGBmYWxzZWAuXG4gICAqL1xuICBmdW5jdGlvbiBoYXNVbmljb2RlKHN0cmluZykge1xuICAgIHJldHVybiByZUhhc1VuaWNvZGUudGVzdChzdHJpbmcpO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiBgc3RyaW5nYCBjb250YWlucyBhIHdvcmQgY29tcG9zZWQgb2YgVW5pY29kZSBzeW1ib2xzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gaW5zcGVjdC5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGEgd29yZCBpcyBmb3VuZCwgZWxzZSBgZmFsc2VgLlxuICAgKi9cbiAgZnVuY3Rpb24gaGFzVW5pY29kZVdvcmQoc3RyaW5nKSB7XG4gICAgcmV0dXJuIHJlSGFzVW5pY29kZVdvcmQudGVzdChzdHJpbmcpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGBpdGVyYXRvcmAgdG8gYW4gYXJyYXkuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBpdGVyYXRvciBUaGUgaXRlcmF0b3IgdG8gY29udmVydC5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBjb252ZXJ0ZWQgYXJyYXkuXG4gICAqL1xuICBmdW5jdGlvbiBpdGVyYXRvclRvQXJyYXkoaXRlcmF0b3IpIHtcbiAgICB2YXIgZGF0YSxcbiAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICB3aGlsZSAoIShkYXRhID0gaXRlcmF0b3IubmV4dCgpKS5kb25lKSB7XG4gICAgICByZXN1bHQucHVzaChkYXRhLnZhbHVlKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBgbWFwYCB0byBpdHMga2V5LXZhbHVlIHBhaXJzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gbWFwIFRoZSBtYXAgdG8gY29udmVydC5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBrZXktdmFsdWUgcGFpcnMuXG4gICAqL1xuICBmdW5jdGlvbiBtYXBUb0FycmF5KG1hcCkge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICByZXN1bHQgPSBBcnJheShtYXAuc2l6ZSk7XG5cbiAgICBtYXAuZm9yRWFjaChmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG4gICAgICByZXN1bHRbKytpbmRleF0gPSBba2V5LCB2YWx1ZV07XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgdW5hcnkgZnVuY3Rpb24gdGhhdCBpbnZva2VzIGBmdW5jYCB3aXRoIGl0cyBhcmd1bWVudCB0cmFuc2Zvcm1lZC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gd3JhcC5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gdHJhbnNmb3JtIFRoZSBhcmd1bWVudCB0cmFuc2Zvcm0uXG4gICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgKi9cbiAgZnVuY3Rpb24gb3ZlckFyZyhmdW5jLCB0cmFuc2Zvcm0pIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oYXJnKSB7XG4gICAgICByZXR1cm4gZnVuYyh0cmFuc2Zvcm0oYXJnKSk7XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXBsYWNlcyBhbGwgYHBsYWNlaG9sZGVyYCBlbGVtZW50cyBpbiBgYXJyYXlgIHdpdGggYW4gaW50ZXJuYWwgcGxhY2Vob2xkZXJcbiAgICogYW5kIHJldHVybnMgYW4gYXJyYXkgb2YgdGhlaXIgaW5kZXhlcy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAgICogQHBhcmFtIHsqfSBwbGFjZWhvbGRlciBUaGUgcGxhY2Vob2xkZXIgdG8gcmVwbGFjZS5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgcGxhY2Vob2xkZXIgaW5kZXhlcy5cbiAgICovXG4gIGZ1bmN0aW9uIHJlcGxhY2VIb2xkZXJzKGFycmF5LCBwbGFjZWhvbGRlcikge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgIHJlc0luZGV4ID0gMCxcbiAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdO1xuICAgICAgaWYgKHZhbHVlID09PSBwbGFjZWhvbGRlciB8fCB2YWx1ZSA9PT0gUExBQ0VIT0xERVIpIHtcbiAgICAgICAgYXJyYXlbaW5kZXhdID0gUExBQ0VIT0xERVI7XG4gICAgICAgIHJlc3VsdFtyZXNJbmRleCsrXSA9IGluZGV4O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGBzZXRgIHRvIGFuIGFycmF5IG9mIGl0cyB2YWx1ZXMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBzZXQgVGhlIHNldCB0byBjb252ZXJ0LlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHZhbHVlcy5cbiAgICovXG4gIGZ1bmN0aW9uIHNldFRvQXJyYXkoc2V0KSB7XG4gICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgIHJlc3VsdCA9IEFycmF5KHNldC5zaXplKTtcblxuICAgIHNldC5mb3JFYWNoKGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICByZXN1bHRbKytpbmRleF0gPSB2YWx1ZTtcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGBzZXRgIHRvIGl0cyB2YWx1ZS12YWx1ZSBwYWlycy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtPYmplY3R9IHNldCBUaGUgc2V0IHRvIGNvbnZlcnQuXG4gICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgdmFsdWUtdmFsdWUgcGFpcnMuXG4gICAqL1xuICBmdW5jdGlvbiBzZXRUb1BhaXJzKHNldCkge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICByZXN1bHQgPSBBcnJheShzZXQuc2l6ZSk7XG5cbiAgICBzZXQuZm9yRWFjaChmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgcmVzdWx0WysraW5kZXhdID0gW3ZhbHVlLCB2YWx1ZV07XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uaW5kZXhPZmAgd2hpY2ggcGVyZm9ybXMgc3RyaWN0IGVxdWFsaXR5XG4gICAqIGNvbXBhcmlzb25zIG9mIHZhbHVlcywgaS5lLiBgPT09YC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNlYXJjaCBmb3IuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBmcm9tSW5kZXggVGhlIGluZGV4IHRvIHNlYXJjaCBmcm9tLlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgbWF0Y2hlZCB2YWx1ZSwgZWxzZSBgLTFgLlxuICAgKi9cbiAgZnVuY3Rpb24gc3RyaWN0SW5kZXhPZihhcnJheSwgdmFsdWUsIGZyb21JbmRleCkge1xuICAgIHZhciBpbmRleCA9IGZyb21JbmRleCAtIDEsXG4gICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICBpZiAoYXJyYXlbaW5kZXhdID09PSB2YWx1ZSkge1xuICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiAtMTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8ubGFzdEluZGV4T2ZgIHdoaWNoIHBlcmZvcm1zIHN0cmljdCBlcXVhbGl0eVxuICAgKiBjb21wYXJpc29ucyBvZiB2YWx1ZXMsIGkuZS4gYD09PWAuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgKiBAcGFyYW0ge251bWJlcn0gZnJvbUluZGV4IFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUsIGVsc2UgYC0xYC5cbiAgICovXG4gIGZ1bmN0aW9uIHN0cmljdExhc3RJbmRleE9mKGFycmF5LCB2YWx1ZSwgZnJvbUluZGV4KSB7XG4gICAgdmFyIGluZGV4ID0gZnJvbUluZGV4ICsgMTtcbiAgICB3aGlsZSAoaW5kZXgtLSkge1xuICAgICAgaWYgKGFycmF5W2luZGV4XSA9PT0gdmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIGluZGV4O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gaW5kZXg7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgbnVtYmVyIG9mIHN5bWJvbHMgaW4gYHN0cmluZ2AuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBpbnNwZWN0LlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBzdHJpbmcgc2l6ZS5cbiAgICovXG4gIGZ1bmN0aW9uIHN0cmluZ1NpemUoc3RyaW5nKSB7XG4gICAgcmV0dXJuIGhhc1VuaWNvZGUoc3RyaW5nKVxuICAgICAgPyB1bmljb2RlU2l6ZShzdHJpbmcpXG4gICAgICA6IGFzY2lpU2l6ZShzdHJpbmcpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGBzdHJpbmdgIHRvIGFuIGFycmF5LlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gY29udmVydC5cbiAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBjb252ZXJ0ZWQgYXJyYXkuXG4gICAqL1xuICBmdW5jdGlvbiBzdHJpbmdUb0FycmF5KHN0cmluZykge1xuICAgIHJldHVybiBoYXNVbmljb2RlKHN0cmluZylcbiAgICAgID8gdW5pY29kZVRvQXJyYXkoc3RyaW5nKVxuICAgICAgOiBhc2NpaVRvQXJyYXkoc3RyaW5nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVc2VkIGJ5IGBfLnVuZXNjYXBlYCB0byBjb252ZXJ0IEhUTUwgZW50aXRpZXMgdG8gY2hhcmFjdGVycy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IGNociBUaGUgbWF0Y2hlZCBjaGFyYWN0ZXIgdG8gdW5lc2NhcGUuXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHVuZXNjYXBlZCBjaGFyYWN0ZXIuXG4gICAqL1xuICB2YXIgdW5lc2NhcGVIdG1sQ2hhciA9IGJhc2VQcm9wZXJ0eU9mKGh0bWxVbmVzY2FwZXMpO1xuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBzaXplIG9mIGEgVW5pY29kZSBgc3RyaW5nYC5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIGluc3BlY3QuXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHN0cmluZyBzaXplLlxuICAgKi9cbiAgZnVuY3Rpb24gdW5pY29kZVNpemUoc3RyaW5nKSB7XG4gICAgdmFyIHJlc3VsdCA9IHJlVW5pY29kZS5sYXN0SW5kZXggPSAwO1xuICAgIHdoaWxlIChyZVVuaWNvZGUudGVzdChzdHJpbmcpKSB7XG4gICAgICArK3Jlc3VsdDtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhIFVuaWNvZGUgYHN0cmluZ2AgdG8gYW4gYXJyYXkuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBhcnJheS5cbiAgICovXG4gIGZ1bmN0aW9uIHVuaWNvZGVUb0FycmF5KHN0cmluZykge1xuICAgIHJldHVybiBzdHJpbmcubWF0Y2gocmVVbmljb2RlKSB8fCBbXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTcGxpdHMgYSBVbmljb2RlIGBzdHJpbmdgIGludG8gYW4gYXJyYXkgb2YgaXRzIHdvcmRzLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gVGhlIHN0cmluZyB0byBpbnNwZWN0LlxuICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHdvcmRzIG9mIGBzdHJpbmdgLlxuICAgKi9cbiAgZnVuY3Rpb24gdW5pY29kZVdvcmRzKHN0cmluZykge1xuICAgIHJldHVybiBzdHJpbmcubWF0Y2gocmVVbmljb2RlV29yZCkgfHwgW107XG4gIH1cblxuICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IHByaXN0aW5lIGBsb2Rhc2hgIGZ1bmN0aW9uIHVzaW5nIHRoZSBgY29udGV4dGAgb2JqZWN0LlxuICAgKlxuICAgKiBAc3RhdGljXG4gICAqIEBtZW1iZXJPZiBfXG4gICAqIEBzaW5jZSAxLjEuMFxuICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgKiBAcGFyYW0ge09iamVjdH0gW2NvbnRleHQ9cm9vdF0gVGhlIGNvbnRleHQgb2JqZWN0LlxuICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgYSBuZXcgYGxvZGFzaGAgZnVuY3Rpb24uXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqIF8ubWl4aW4oeyAnZm9vJzogXy5jb25zdGFudCgnZm9vJykgfSk7XG4gICAqXG4gICAqIHZhciBsb2Rhc2ggPSBfLnJ1bkluQ29udGV4dCgpO1xuICAgKiBsb2Rhc2gubWl4aW4oeyAnYmFyJzogbG9kYXNoLmNvbnN0YW50KCdiYXInKSB9KTtcbiAgICpcbiAgICogXy5pc0Z1bmN0aW9uKF8uZm9vKTtcbiAgICogLy8gPT4gdHJ1ZVxuICAgKiBfLmlzRnVuY3Rpb24oXy5iYXIpO1xuICAgKiAvLyA9PiBmYWxzZVxuICAgKlxuICAgKiBsb2Rhc2guaXNGdW5jdGlvbihsb2Rhc2guZm9vKTtcbiAgICogLy8gPT4gZmFsc2VcbiAgICogbG9kYXNoLmlzRnVuY3Rpb24obG9kYXNoLmJhcik7XG4gICAqIC8vID0+IHRydWVcbiAgICpcbiAgICogLy8gQ3JlYXRlIGEgc3VwZWQtdXAgYGRlZmVyYCBpbiBOb2RlLmpzLlxuICAgKiB2YXIgZGVmZXIgPSBfLnJ1bkluQ29udGV4dCh7ICdzZXRUaW1lb3V0Jzogc2V0SW1tZWRpYXRlIH0pLmRlZmVyO1xuICAgKi9cbiAgdmFyIHJ1bkluQ29udGV4dCA9IChmdW5jdGlvbiBydW5JbkNvbnRleHQoY29udGV4dCkge1xuICAgIGNvbnRleHQgPSBjb250ZXh0ID09IG51bGwgPyByb290IDogXy5kZWZhdWx0cyhyb290Lk9iamVjdCgpLCBjb250ZXh0LCBfLnBpY2socm9vdCwgY29udGV4dFByb3BzKSk7XG5cbiAgICAvKiogQnVpbHQtaW4gY29uc3RydWN0b3IgcmVmZXJlbmNlcy4gKi9cbiAgICB2YXIgQXJyYXkgPSBjb250ZXh0LkFycmF5LFxuICAgICAgICBEYXRlID0gY29udGV4dC5EYXRlLFxuICAgICAgICBFcnJvciA9IGNvbnRleHQuRXJyb3IsXG4gICAgICAgIEZ1bmN0aW9uID0gY29udGV4dC5GdW5jdGlvbixcbiAgICAgICAgTWF0aCA9IGNvbnRleHQuTWF0aCxcbiAgICAgICAgT2JqZWN0ID0gY29udGV4dC5PYmplY3QsXG4gICAgICAgIFJlZ0V4cCA9IGNvbnRleHQuUmVnRXhwLFxuICAgICAgICBTdHJpbmcgPSBjb250ZXh0LlN0cmluZyxcbiAgICAgICAgVHlwZUVycm9yID0gY29udGV4dC5UeXBlRXJyb3I7XG5cbiAgICAvKiogVXNlZCBmb3IgYnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMuICovXG4gICAgdmFyIGFycmF5UHJvdG8gPSBBcnJheS5wcm90b3R5cGUsXG4gICAgICAgIGZ1bmNQcm90byA9IEZ1bmN0aW9uLnByb3RvdHlwZSxcbiAgICAgICAgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4gICAgLyoqIFVzZWQgdG8gZGV0ZWN0IG92ZXJyZWFjaGluZyBjb3JlLWpzIHNoaW1zLiAqL1xuICAgIHZhciBjb3JlSnNEYXRhID0gY29udGV4dFsnX19jb3JlLWpzX3NoYXJlZF9fJ107XG5cbiAgICAvKiogVXNlZCB0byByZXNvbHZlIHRoZSBkZWNvbXBpbGVkIHNvdXJjZSBvZiBmdW5jdGlvbnMuICovXG4gICAgdmFyIGZ1bmNUb1N0cmluZyA9IGZ1bmNQcm90by50b1N0cmluZztcblxuICAgIC8qKiBVc2VkIHRvIGNoZWNrIG9iamVjdHMgZm9yIG93biBwcm9wZXJ0aWVzLiAqL1xuICAgIHZhciBoYXNPd25Qcm9wZXJ0eSA9IG9iamVjdFByb3RvLmhhc093blByb3BlcnR5O1xuXG4gICAgLyoqIFVzZWQgdG8gZ2VuZXJhdGUgdW5pcXVlIElEcy4gKi9cbiAgICB2YXIgaWRDb3VudGVyID0gMDtcblxuICAgIC8qKiBVc2VkIHRvIGRldGVjdCBtZXRob2RzIG1hc3F1ZXJhZGluZyBhcyBuYXRpdmUuICovXG4gICAgdmFyIG1hc2tTcmNLZXkgPSAoZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgdWlkID0gL1teLl0rJC8uZXhlYyhjb3JlSnNEYXRhICYmIGNvcmVKc0RhdGEua2V5cyAmJiBjb3JlSnNEYXRhLmtleXMuSUVfUFJPVE8gfHwgJycpO1xuICAgICAgcmV0dXJuIHVpZCA/ICgnU3ltYm9sKHNyYylfMS4nICsgdWlkKSA6ICcnO1xuICAgIH0oKSk7XG5cbiAgICAvKipcbiAgICAgKiBVc2VkIHRvIHJlc29sdmUgdGhlXG4gICAgICogW2B0b1N0cmluZ1RhZ2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLW9iamVjdC5wcm90b3R5cGUudG9zdHJpbmcpXG4gICAgICogb2YgdmFsdWVzLlxuICAgICAqL1xuICAgIHZhciBuYXRpdmVPYmplY3RUb1N0cmluZyA9IG9iamVjdFByb3RvLnRvU3RyaW5nO1xuXG4gICAgLyoqIFVzZWQgdG8gaW5mZXIgdGhlIGBPYmplY3RgIGNvbnN0cnVjdG9yLiAqL1xuICAgIHZhciBvYmplY3RDdG9yU3RyaW5nID0gZnVuY1RvU3RyaW5nLmNhbGwoT2JqZWN0KTtcblxuICAgIC8qKiBVc2VkIHRvIHJlc3RvcmUgdGhlIG9yaWdpbmFsIGBfYCByZWZlcmVuY2UgaW4gYF8ubm9Db25mbGljdGAuICovXG4gICAgdmFyIG9sZERhc2ggPSByb290Ll87XG5cbiAgICAvKiogVXNlZCB0byBkZXRlY3QgaWYgYSBtZXRob2QgaXMgbmF0aXZlLiAqL1xuICAgIHZhciByZUlzTmF0aXZlID0gUmVnRXhwKCdeJyArXG4gICAgICBmdW5jVG9TdHJpbmcuY2FsbChoYXNPd25Qcm9wZXJ0eSkucmVwbGFjZShyZVJlZ0V4cENoYXIsICdcXFxcJCYnKVxuICAgICAgLnJlcGxhY2UoL2hhc093blByb3BlcnR5fChmdW5jdGlvbikuKj8oPz1cXFxcXFwoKXwgZm9yIC4rPyg/PVxcXFxcXF0pL2csICckMS4qPycpICsgJyQnXG4gICAgKTtcblxuICAgIC8qKiBCdWlsdC1pbiB2YWx1ZSByZWZlcmVuY2VzLiAqL1xuICAgIHZhciBCdWZmZXIgPSBtb2R1bGVFeHBvcnRzID8gY29udGV4dC5CdWZmZXIgOiB1bmRlZmluZWQsXG4gICAgICAgIFN5bWJvbCA9IGNvbnRleHQuU3ltYm9sLFxuICAgICAgICBVaW50OEFycmF5ID0gY29udGV4dC5VaW50OEFycmF5LFxuICAgICAgICBhbGxvY1Vuc2FmZSA9IEJ1ZmZlciA/IEJ1ZmZlci5hbGxvY1Vuc2FmZSA6IHVuZGVmaW5lZCxcbiAgICAgICAgZ2V0UHJvdG90eXBlID0gb3ZlckFyZyhPYmplY3QuZ2V0UHJvdG90eXBlT2YsIE9iamVjdCksXG4gICAgICAgIG9iamVjdENyZWF0ZSA9IE9iamVjdC5jcmVhdGUsXG4gICAgICAgIHByb3BlcnR5SXNFbnVtZXJhYmxlID0gb2JqZWN0UHJvdG8ucHJvcGVydHlJc0VudW1lcmFibGUsXG4gICAgICAgIHNwbGljZSA9IGFycmF5UHJvdG8uc3BsaWNlLFxuICAgICAgICBzcHJlYWRhYmxlU3ltYm9sID0gU3ltYm9sID8gU3ltYm9sLmlzQ29uY2F0U3ByZWFkYWJsZSA6IHVuZGVmaW5lZCxcbiAgICAgICAgc3ltSXRlcmF0b3IgPSBTeW1ib2wgPyBTeW1ib2wuaXRlcmF0b3IgOiB1bmRlZmluZWQsXG4gICAgICAgIHN5bVRvU3RyaW5nVGFnID0gU3ltYm9sID8gU3ltYm9sLnRvU3RyaW5nVGFnIDogdW5kZWZpbmVkO1xuXG4gICAgdmFyIGRlZmluZVByb3BlcnR5ID0gKGZ1bmN0aW9uKCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgdmFyIGZ1bmMgPSBnZXROYXRpdmUoT2JqZWN0LCAnZGVmaW5lUHJvcGVydHknKTtcbiAgICAgICAgZnVuYyh7fSwgJycsIHt9KTtcbiAgICAgICAgcmV0dXJuIGZ1bmM7XG4gICAgICB9IGNhdGNoIChlKSB7fVxuICAgIH0oKSk7XG5cbiAgICAvKiogTW9ja2VkIGJ1aWx0LWlucy4gKi9cbiAgICB2YXIgY3R4Q2xlYXJUaW1lb3V0ID0gY29udGV4dC5jbGVhclRpbWVvdXQgIT09IHJvb3QuY2xlYXJUaW1lb3V0ICYmIGNvbnRleHQuY2xlYXJUaW1lb3V0LFxuICAgICAgICBjdHhOb3cgPSBEYXRlICYmIERhdGUubm93ICE9PSByb290LkRhdGUubm93ICYmIERhdGUubm93LFxuICAgICAgICBjdHhTZXRUaW1lb3V0ID0gY29udGV4dC5zZXRUaW1lb3V0ICE9PSByb290LnNldFRpbWVvdXQgJiYgY29udGV4dC5zZXRUaW1lb3V0O1xuXG4gICAgLyogQnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMgZm9yIHRob3NlIHdpdGggdGhlIHNhbWUgbmFtZSBhcyBvdGhlciBgbG9kYXNoYCBtZXRob2RzLiAqL1xuICAgIHZhciBuYXRpdmVDZWlsID0gTWF0aC5jZWlsLFxuICAgICAgICBuYXRpdmVGbG9vciA9IE1hdGguZmxvb3IsXG4gICAgICAgIG5hdGl2ZUdldFN5bWJvbHMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzLFxuICAgICAgICBuYXRpdmVJc0J1ZmZlciA9IEJ1ZmZlciA/IEJ1ZmZlci5pc0J1ZmZlciA6IHVuZGVmaW5lZCxcbiAgICAgICAgbmF0aXZlSXNGaW5pdGUgPSBjb250ZXh0LmlzRmluaXRlLFxuICAgICAgICBuYXRpdmVKb2luID0gYXJyYXlQcm90by5qb2luLFxuICAgICAgICBuYXRpdmVLZXlzID0gb3ZlckFyZyhPYmplY3Qua2V5cywgT2JqZWN0KSxcbiAgICAgICAgbmF0aXZlTWF4ID0gTWF0aC5tYXgsXG4gICAgICAgIG5hdGl2ZU1pbiA9IE1hdGgubWluLFxuICAgICAgICBuYXRpdmVOb3cgPSBEYXRlLm5vdyxcbiAgICAgICAgbmF0aXZlUGFyc2VJbnQgPSBjb250ZXh0LnBhcnNlSW50LFxuICAgICAgICBuYXRpdmVSYW5kb20gPSBNYXRoLnJhbmRvbSxcbiAgICAgICAgbmF0aXZlUmV2ZXJzZSA9IGFycmF5UHJvdG8ucmV2ZXJzZTtcblxuICAgIC8qIEJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzIHRoYXQgYXJlIHZlcmlmaWVkIHRvIGJlIG5hdGl2ZS4gKi9cbiAgICB2YXIgRGF0YVZpZXcgPSBnZXROYXRpdmUoY29udGV4dCwgJ0RhdGFWaWV3JyksXG4gICAgICAgIE1hcCA9IGdldE5hdGl2ZShjb250ZXh0LCAnTWFwJyksXG4gICAgICAgIFByb21pc2UgPSBnZXROYXRpdmUoY29udGV4dCwgJ1Byb21pc2UnKSxcbiAgICAgICAgU2V0ID0gZ2V0TmF0aXZlKGNvbnRleHQsICdTZXQnKSxcbiAgICAgICAgV2Vha01hcCA9IGdldE5hdGl2ZShjb250ZXh0LCAnV2Vha01hcCcpLFxuICAgICAgICBuYXRpdmVDcmVhdGUgPSBnZXROYXRpdmUoT2JqZWN0LCAnY3JlYXRlJyk7XG5cbiAgICAvKiogVXNlZCB0byBzdG9yZSBmdW5jdGlvbiBtZXRhZGF0YS4gKi9cbiAgICB2YXIgbWV0YU1hcCA9IFdlYWtNYXAgJiYgbmV3IFdlYWtNYXA7XG5cbiAgICAvKiogVXNlZCB0byBsb29rdXAgdW5taW5pZmllZCBmdW5jdGlvbiBuYW1lcy4gKi9cbiAgICB2YXIgcmVhbE5hbWVzID0ge307XG5cbiAgICAvKiogVXNlZCB0byBkZXRlY3QgbWFwcywgc2V0cywgYW5kIHdlYWttYXBzLiAqL1xuICAgIHZhciBkYXRhVmlld0N0b3JTdHJpbmcgPSB0b1NvdXJjZShEYXRhVmlldyksXG4gICAgICAgIG1hcEN0b3JTdHJpbmcgPSB0b1NvdXJjZShNYXApLFxuICAgICAgICBwcm9taXNlQ3RvclN0cmluZyA9IHRvU291cmNlKFByb21pc2UpLFxuICAgICAgICBzZXRDdG9yU3RyaW5nID0gdG9Tb3VyY2UoU2V0KSxcbiAgICAgICAgd2Vha01hcEN0b3JTdHJpbmcgPSB0b1NvdXJjZShXZWFrTWFwKTtcblxuICAgIC8qKiBVc2VkIHRvIGNvbnZlcnQgc3ltYm9scyB0byBwcmltaXRpdmVzIGFuZCBzdHJpbmdzLiAqL1xuICAgIHZhciBzeW1ib2xQcm90byA9IFN5bWJvbCA/IFN5bWJvbC5wcm90b3R5cGUgOiB1bmRlZmluZWQsXG4gICAgICAgIHN5bWJvbFZhbHVlT2YgPSBzeW1ib2xQcm90byA/IHN5bWJvbFByb3RvLnZhbHVlT2YgOiB1bmRlZmluZWQsXG4gICAgICAgIHN5bWJvbFRvU3RyaW5nID0gc3ltYm9sUHJvdG8gPyBzeW1ib2xQcm90by50b1N0cmluZyA6IHVuZGVmaW5lZDtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBgbG9kYXNoYCBvYmplY3Qgd2hpY2ggd3JhcHMgYHZhbHVlYCB0byBlbmFibGUgaW1wbGljaXQgbWV0aG9kXG4gICAgICogY2hhaW4gc2VxdWVuY2VzLiBNZXRob2RzIHRoYXQgb3BlcmF0ZSBvbiBhbmQgcmV0dXJuIGFycmF5cywgY29sbGVjdGlvbnMsXG4gICAgICogYW5kIGZ1bmN0aW9ucyBjYW4gYmUgY2hhaW5lZCB0b2dldGhlci4gTWV0aG9kcyB0aGF0IHJldHJpZXZlIGEgc2luZ2xlIHZhbHVlXG4gICAgICogb3IgbWF5IHJldHVybiBhIHByaW1pdGl2ZSB2YWx1ZSB3aWxsIGF1dG9tYXRpY2FsbHkgZW5kIHRoZSBjaGFpbiBzZXF1ZW5jZVxuICAgICAqIGFuZCByZXR1cm4gdGhlIHVud3JhcHBlZCB2YWx1ZS4gT3RoZXJ3aXNlLCB0aGUgdmFsdWUgbXVzdCBiZSB1bndyYXBwZWRcbiAgICAgKiB3aXRoIGBfI3ZhbHVlYC5cbiAgICAgKlxuICAgICAqIEV4cGxpY2l0IGNoYWluIHNlcXVlbmNlcywgd2hpY2ggbXVzdCBiZSB1bndyYXBwZWQgd2l0aCBgXyN2YWx1ZWAsIG1heSBiZVxuICAgICAqIGVuYWJsZWQgdXNpbmcgYF8uY2hhaW5gLlxuICAgICAqXG4gICAgICogVGhlIGV4ZWN1dGlvbiBvZiBjaGFpbmVkIG1ldGhvZHMgaXMgbGF6eSwgdGhhdCBpcywgaXQncyBkZWZlcnJlZCB1bnRpbFxuICAgICAqIGBfI3ZhbHVlYCBpcyBpbXBsaWNpdGx5IG9yIGV4cGxpY2l0bHkgY2FsbGVkLlxuICAgICAqXG4gICAgICogTGF6eSBldmFsdWF0aW9uIGFsbG93cyBzZXZlcmFsIG1ldGhvZHMgdG8gc3VwcG9ydCBzaG9ydGN1dCBmdXNpb24uXG4gICAgICogU2hvcnRjdXQgZnVzaW9uIGlzIGFuIG9wdGltaXphdGlvbiB0byBtZXJnZSBpdGVyYXRlZSBjYWxsczsgdGhpcyBhdm9pZHNcbiAgICAgKiB0aGUgY3JlYXRpb24gb2YgaW50ZXJtZWRpYXRlIGFycmF5cyBhbmQgY2FuIGdyZWF0bHkgcmVkdWNlIHRoZSBudW1iZXIgb2ZcbiAgICAgKiBpdGVyYXRlZSBleGVjdXRpb25zLiBTZWN0aW9ucyBvZiBhIGNoYWluIHNlcXVlbmNlIHF1YWxpZnkgZm9yIHNob3J0Y3V0XG4gICAgICogZnVzaW9uIGlmIHRoZSBzZWN0aW9uIGlzIGFwcGxpZWQgdG8gYW4gYXJyYXkgYW5kIGl0ZXJhdGVlcyBhY2NlcHQgb25seVxuICAgICAqIG9uZSBhcmd1bWVudC4gVGhlIGhldXJpc3RpYyBmb3Igd2hldGhlciBhIHNlY3Rpb24gcXVhbGlmaWVzIGZvciBzaG9ydGN1dFxuICAgICAqIGZ1c2lvbiBpcyBzdWJqZWN0IHRvIGNoYW5nZS5cbiAgICAgKlxuICAgICAqIENoYWluaW5nIGlzIHN1cHBvcnRlZCBpbiBjdXN0b20gYnVpbGRzIGFzIGxvbmcgYXMgdGhlIGBfI3ZhbHVlYCBtZXRob2QgaXNcbiAgICAgKiBkaXJlY3RseSBvciBpbmRpcmVjdGx5IGluY2x1ZGVkIGluIHRoZSBidWlsZC5cbiAgICAgKlxuICAgICAqIEluIGFkZGl0aW9uIHRvIGxvZGFzaCBtZXRob2RzLCB3cmFwcGVycyBoYXZlIGBBcnJheWAgYW5kIGBTdHJpbmdgIG1ldGhvZHMuXG4gICAgICpcbiAgICAgKiBUaGUgd3JhcHBlciBgQXJyYXlgIG1ldGhvZHMgYXJlOlxuICAgICAqIGBjb25jYXRgLCBgam9pbmAsIGBwb3BgLCBgcHVzaGAsIGBzaGlmdGAsIGBzb3J0YCwgYHNwbGljZWAsIGFuZCBgdW5zaGlmdGBcbiAgICAgKlxuICAgICAqIFRoZSB3cmFwcGVyIGBTdHJpbmdgIG1ldGhvZHMgYXJlOlxuICAgICAqIGByZXBsYWNlYCBhbmQgYHNwbGl0YFxuICAgICAqXG4gICAgICogVGhlIHdyYXBwZXIgbWV0aG9kcyB0aGF0IHN1cHBvcnQgc2hvcnRjdXQgZnVzaW9uIGFyZTpcbiAgICAgKiBgYXRgLCBgY29tcGFjdGAsIGBkcm9wYCwgYGRyb3BSaWdodGAsIGBkcm9wV2hpbGVgLCBgZmlsdGVyYCwgYGZpbmRgLFxuICAgICAqIGBmaW5kTGFzdGAsIGBoZWFkYCwgYGluaXRpYWxgLCBgbGFzdGAsIGBtYXBgLCBgcmVqZWN0YCwgYHJldmVyc2VgLCBgc2xpY2VgLFxuICAgICAqIGB0YWlsYCwgYHRha2VgLCBgdGFrZVJpZ2h0YCwgYHRha2VSaWdodFdoaWxlYCwgYHRha2VXaGlsZWAsIGFuZCBgdG9BcnJheWBcbiAgICAgKlxuICAgICAqIFRoZSBjaGFpbmFibGUgd3JhcHBlciBtZXRob2RzIGFyZTpcbiAgICAgKiBgYWZ0ZXJgLCBgYXJ5YCwgYGFzc2lnbmAsIGBhc3NpZ25JbmAsIGBhc3NpZ25JbldpdGhgLCBgYXNzaWduV2l0aGAsIGBhdGAsXG4gICAgICogYGJlZm9yZWAsIGBiaW5kYCwgYGJpbmRBbGxgLCBgYmluZEtleWAsIGBjYXN0QXJyYXlgLCBgY2hhaW5gLCBgY2h1bmtgLFxuICAgICAqIGBjb21taXRgLCBgY29tcGFjdGAsIGBjb25jYXRgLCBgY29uZm9ybXNgLCBgY29uc3RhbnRgLCBgY291bnRCeWAsIGBjcmVhdGVgLFxuICAgICAqIGBjdXJyeWAsIGBkZWJvdW5jZWAsIGBkZWZhdWx0c2AsIGBkZWZhdWx0c0RlZXBgLCBgZGVmZXJgLCBgZGVsYXlgLFxuICAgICAqIGBkaWZmZXJlbmNlYCwgYGRpZmZlcmVuY2VCeWAsIGBkaWZmZXJlbmNlV2l0aGAsIGBkcm9wYCwgYGRyb3BSaWdodGAsXG4gICAgICogYGRyb3BSaWdodFdoaWxlYCwgYGRyb3BXaGlsZWAsIGBleHRlbmRgLCBgZXh0ZW5kV2l0aGAsIGBmaWxsYCwgYGZpbHRlcmAsXG4gICAgICogYGZsYXRNYXBgLCBgZmxhdE1hcERlZXBgLCBgZmxhdE1hcERlcHRoYCwgYGZsYXR0ZW5gLCBgZmxhdHRlbkRlZXBgLFxuICAgICAqIGBmbGF0dGVuRGVwdGhgLCBgZmxpcGAsIGBmbG93YCwgYGZsb3dSaWdodGAsIGBmcm9tUGFpcnNgLCBgZnVuY3Rpb25zYCxcbiAgICAgKiBgZnVuY3Rpb25zSW5gLCBgZ3JvdXBCeWAsIGBpbml0aWFsYCwgYGludGVyc2VjdGlvbmAsIGBpbnRlcnNlY3Rpb25CeWAsXG4gICAgICogYGludGVyc2VjdGlvbldpdGhgLCBgaW52ZXJ0YCwgYGludmVydEJ5YCwgYGludm9rZU1hcGAsIGBpdGVyYXRlZWAsIGBrZXlCeWAsXG4gICAgICogYGtleXNgLCBga2V5c0luYCwgYG1hcGAsIGBtYXBLZXlzYCwgYG1hcFZhbHVlc2AsIGBtYXRjaGVzYCwgYG1hdGNoZXNQcm9wZXJ0eWAsXG4gICAgICogYG1lbW9pemVgLCBgbWVyZ2VgLCBgbWVyZ2VXaXRoYCwgYG1ldGhvZGAsIGBtZXRob2RPZmAsIGBtaXhpbmAsIGBuZWdhdGVgLFxuICAgICAqIGBudGhBcmdgLCBgb21pdGAsIGBvbWl0QnlgLCBgb25jZWAsIGBvcmRlckJ5YCwgYG92ZXJgLCBgb3ZlckFyZ3NgLFxuICAgICAqIGBvdmVyRXZlcnlgLCBgb3ZlclNvbWVgLCBgcGFydGlhbGAsIGBwYXJ0aWFsUmlnaHRgLCBgcGFydGl0aW9uYCwgYHBpY2tgLFxuICAgICAqIGBwaWNrQnlgLCBgcGxhbnRgLCBgcHJvcGVydHlgLCBgcHJvcGVydHlPZmAsIGBwdWxsYCwgYHB1bGxBbGxgLCBgcHVsbEFsbEJ5YCxcbiAgICAgKiBgcHVsbEFsbFdpdGhgLCBgcHVsbEF0YCwgYHB1c2hgLCBgcmFuZ2VgLCBgcmFuZ2VSaWdodGAsIGByZWFyZ2AsIGByZWplY3RgLFxuICAgICAqIGByZW1vdmVgLCBgcmVzdGAsIGByZXZlcnNlYCwgYHNhbXBsZVNpemVgLCBgc2V0YCwgYHNldFdpdGhgLCBgc2h1ZmZsZWAsXG4gICAgICogYHNsaWNlYCwgYHNvcnRgLCBgc29ydEJ5YCwgYHNwbGljZWAsIGBzcHJlYWRgLCBgdGFpbGAsIGB0YWtlYCwgYHRha2VSaWdodGAsXG4gICAgICogYHRha2VSaWdodFdoaWxlYCwgYHRha2VXaGlsZWAsIGB0YXBgLCBgdGhyb3R0bGVgLCBgdGhydWAsIGB0b0FycmF5YCxcbiAgICAgKiBgdG9QYWlyc2AsIGB0b1BhaXJzSW5gLCBgdG9QYXRoYCwgYHRvUGxhaW5PYmplY3RgLCBgdHJhbnNmb3JtYCwgYHVuYXJ5YCxcbiAgICAgKiBgdW5pb25gLCBgdW5pb25CeWAsIGB1bmlvbldpdGhgLCBgdW5pcWAsIGB1bmlxQnlgLCBgdW5pcVdpdGhgLCBgdW5zZXRgLFxuICAgICAqIGB1bnNoaWZ0YCwgYHVuemlwYCwgYHVuemlwV2l0aGAsIGB1cGRhdGVgLCBgdXBkYXRlV2l0aGAsIGB2YWx1ZXNgLFxuICAgICAqIGB2YWx1ZXNJbmAsIGB3aXRob3V0YCwgYHdyYXBgLCBgeG9yYCwgYHhvckJ5YCwgYHhvcldpdGhgLCBgemlwYCxcbiAgICAgKiBgemlwT2JqZWN0YCwgYHppcE9iamVjdERlZXBgLCBhbmQgYHppcFdpdGhgXG4gICAgICpcbiAgICAgKiBUaGUgd3JhcHBlciBtZXRob2RzIHRoYXQgYXJlICoqbm90KiogY2hhaW5hYmxlIGJ5IGRlZmF1bHQgYXJlOlxuICAgICAqIGBhZGRgLCBgYXR0ZW1wdGAsIGBjYW1lbENhc2VgLCBgY2FwaXRhbGl6ZWAsIGBjZWlsYCwgYGNsYW1wYCwgYGNsb25lYCxcbiAgICAgKiBgY2xvbmVEZWVwYCwgYGNsb25lRGVlcFdpdGhgLCBgY2xvbmVXaXRoYCwgYGNvbmZvcm1zVG9gLCBgZGVidXJyYCxcbiAgICAgKiBgZGVmYXVsdFRvYCwgYGRpdmlkZWAsIGBlYWNoYCwgYGVhY2hSaWdodGAsIGBlbmRzV2l0aGAsIGBlcWAsIGBlc2NhcGVgLFxuICAgICAqIGBlc2NhcGVSZWdFeHBgLCBgZXZlcnlgLCBgZmluZGAsIGBmaW5kSW5kZXhgLCBgZmluZEtleWAsIGBmaW5kTGFzdGAsXG4gICAgICogYGZpbmRMYXN0SW5kZXhgLCBgZmluZExhc3RLZXlgLCBgZmlyc3RgLCBgZmxvb3JgLCBgZm9yRWFjaGAsIGBmb3JFYWNoUmlnaHRgLFxuICAgICAqIGBmb3JJbmAsIGBmb3JJblJpZ2h0YCwgYGZvck93bmAsIGBmb3JPd25SaWdodGAsIGBnZXRgLCBgZ3RgLCBgZ3RlYCwgYGhhc2AsXG4gICAgICogYGhhc0luYCwgYGhlYWRgLCBgaWRlbnRpdHlgLCBgaW5jbHVkZXNgLCBgaW5kZXhPZmAsIGBpblJhbmdlYCwgYGludm9rZWAsXG4gICAgICogYGlzQXJndW1lbnRzYCwgYGlzQXJyYXlgLCBgaXNBcnJheUJ1ZmZlcmAsIGBpc0FycmF5TGlrZWAsIGBpc0FycmF5TGlrZU9iamVjdGAsXG4gICAgICogYGlzQm9vbGVhbmAsIGBpc0J1ZmZlcmAsIGBpc0RhdGVgLCBgaXNFbGVtZW50YCwgYGlzRW1wdHlgLCBgaXNFcXVhbGAsXG4gICAgICogYGlzRXF1YWxXaXRoYCwgYGlzRXJyb3JgLCBgaXNGaW5pdGVgLCBgaXNGdW5jdGlvbmAsIGBpc0ludGVnZXJgLCBgaXNMZW5ndGhgLFxuICAgICAqIGBpc01hcGAsIGBpc01hdGNoYCwgYGlzTWF0Y2hXaXRoYCwgYGlzTmFOYCwgYGlzTmF0aXZlYCwgYGlzTmlsYCwgYGlzTnVsbGAsXG4gICAgICogYGlzTnVtYmVyYCwgYGlzT2JqZWN0YCwgYGlzT2JqZWN0TGlrZWAsIGBpc1BsYWluT2JqZWN0YCwgYGlzUmVnRXhwYCxcbiAgICAgKiBgaXNTYWZlSW50ZWdlcmAsIGBpc1NldGAsIGBpc1N0cmluZ2AsIGBpc1VuZGVmaW5lZGAsIGBpc1R5cGVkQXJyYXlgLFxuICAgICAqIGBpc1dlYWtNYXBgLCBgaXNXZWFrU2V0YCwgYGpvaW5gLCBga2ViYWJDYXNlYCwgYGxhc3RgLCBgbGFzdEluZGV4T2ZgLFxuICAgICAqIGBsb3dlckNhc2VgLCBgbG93ZXJGaXJzdGAsIGBsdGAsIGBsdGVgLCBgbWF4YCwgYG1heEJ5YCwgYG1lYW5gLCBgbWVhbkJ5YCxcbiAgICAgKiBgbWluYCwgYG1pbkJ5YCwgYG11bHRpcGx5YCwgYG5vQ29uZmxpY3RgLCBgbm9vcGAsIGBub3dgLCBgbnRoYCwgYHBhZGAsXG4gICAgICogYHBhZEVuZGAsIGBwYWRTdGFydGAsIGBwYXJzZUludGAsIGBwb3BgLCBgcmFuZG9tYCwgYHJlZHVjZWAsIGByZWR1Y2VSaWdodGAsXG4gICAgICogYHJlcGVhdGAsIGByZXN1bHRgLCBgcm91bmRgLCBgcnVuSW5Db250ZXh0YCwgYHNhbXBsZWAsIGBzaGlmdGAsIGBzaXplYCxcbiAgICAgKiBgc25ha2VDYXNlYCwgYHNvbWVgLCBgc29ydGVkSW5kZXhgLCBgc29ydGVkSW5kZXhCeWAsIGBzb3J0ZWRMYXN0SW5kZXhgLFxuICAgICAqIGBzb3J0ZWRMYXN0SW5kZXhCeWAsIGBzdGFydENhc2VgLCBgc3RhcnRzV2l0aGAsIGBzdHViQXJyYXlgLCBgc3R1YkZhbHNlYCxcbiAgICAgKiBgc3R1Yk9iamVjdGAsIGBzdHViU3RyaW5nYCwgYHN0dWJUcnVlYCwgYHN1YnRyYWN0YCwgYHN1bWAsIGBzdW1CeWAsXG4gICAgICogYHRlbXBsYXRlYCwgYHRpbWVzYCwgYHRvRmluaXRlYCwgYHRvSW50ZWdlcmAsIGB0b0pTT05gLCBgdG9MZW5ndGhgLFxuICAgICAqIGB0b0xvd2VyYCwgYHRvTnVtYmVyYCwgYHRvU2FmZUludGVnZXJgLCBgdG9TdHJpbmdgLCBgdG9VcHBlcmAsIGB0cmltYCxcbiAgICAgKiBgdHJpbUVuZGAsIGB0cmltU3RhcnRgLCBgdHJ1bmNhdGVgLCBgdW5lc2NhcGVgLCBgdW5pcXVlSWRgLCBgdXBwZXJDYXNlYCxcbiAgICAgKiBgdXBwZXJGaXJzdGAsIGB2YWx1ZWAsIGFuZCBgd29yZHNgXG4gICAgICpcbiAgICAgKiBAbmFtZSBfXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICogQGNhdGVnb3J5IFNlcVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHdyYXAgaW4gYSBgbG9kYXNoYCBpbnN0YW5jZS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgYGxvZGFzaGAgd3JhcHBlciBpbnN0YW5jZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gc3F1YXJlKG4pIHtcbiAgICAgKiAgIHJldHVybiBuICogbjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgd3JhcHBlZCA9IF8oWzEsIDIsIDNdKTtcbiAgICAgKlxuICAgICAqIC8vIFJldHVybnMgYW4gdW53cmFwcGVkIHZhbHVlLlxuICAgICAqIHdyYXBwZWQucmVkdWNlKF8uYWRkKTtcbiAgICAgKiAvLyA9PiA2XG4gICAgICpcbiAgICAgKiAvLyBSZXR1cm5zIGEgd3JhcHBlZCB2YWx1ZS5cbiAgICAgKiB2YXIgc3F1YXJlcyA9IHdyYXBwZWQubWFwKHNxdWFyZSk7XG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXkoc3F1YXJlcyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheShzcXVhcmVzLnZhbHVlKCkpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBsb2Rhc2godmFsdWUpIHtcbiAgICAgIGlmIChpc09iamVjdExpa2UodmFsdWUpICYmICFpc0FycmF5KHZhbHVlKSAmJiAhKHZhbHVlIGluc3RhbmNlb2YgTGF6eVdyYXBwZXIpKSB7XG4gICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIExvZGFzaFdyYXBwZXIpIHtcbiAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwodmFsdWUsICdfX3dyYXBwZWRfXycpKSB7XG4gICAgICAgICAgcmV0dXJuIHdyYXBwZXJDbG9uZSh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBuZXcgTG9kYXNoV3JhcHBlcih2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uY3JlYXRlYCB3aXRob3V0IHN1cHBvcnQgZm9yIGFzc2lnbmluZ1xuICAgICAqIHByb3BlcnRpZXMgdG8gdGhlIGNyZWF0ZWQgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcHJvdG8gVGhlIG9iamVjdCB0byBpbmhlcml0IGZyb20uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG9iamVjdC5cbiAgICAgKi9cbiAgICB2YXIgYmFzZUNyZWF0ZSA9IChmdW5jdGlvbigpIHtcbiAgICAgIGZ1bmN0aW9uIG9iamVjdCgpIHt9XG4gICAgICByZXR1cm4gZnVuY3Rpb24ocHJvdG8pIHtcbiAgICAgICAgaWYgKCFpc09iamVjdChwcm90bykpIHtcbiAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9iamVjdENyZWF0ZSkge1xuICAgICAgICAgIHJldHVybiBvYmplY3RDcmVhdGUocHJvdG8pO1xuICAgICAgICB9XG4gICAgICAgIG9iamVjdC5wcm90b3R5cGUgPSBwcm90bztcbiAgICAgICAgdmFyIHJlc3VsdCA9IG5ldyBvYmplY3Q7XG4gICAgICAgIG9iamVjdC5wcm90b3R5cGUgPSB1bmRlZmluZWQ7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9O1xuICAgIH0oKSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZnVuY3Rpb24gd2hvc2UgcHJvdG90eXBlIGNoYWluIHNlcXVlbmNlIHdyYXBwZXJzIGluaGVyaXQgZnJvbS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUxvZGFzaCgpIHtcbiAgICAgIC8vIE5vIG9wZXJhdGlvbiBwZXJmb3JtZWQuXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgY29uc3RydWN0b3IgZm9yIGNyZWF0aW5nIGBsb2Rhc2hgIHdyYXBwZXIgb2JqZWN0cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gd3JhcC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtjaGFpbkFsbF0gRW5hYmxlIGV4cGxpY2l0IG1ldGhvZCBjaGFpbiBzZXF1ZW5jZXMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gTG9kYXNoV3JhcHBlcih2YWx1ZSwgY2hhaW5BbGwpIHtcbiAgICAgIHRoaXMuX193cmFwcGVkX18gPSB2YWx1ZTtcbiAgICAgIHRoaXMuX19hY3Rpb25zX18gPSBbXTtcbiAgICAgIHRoaXMuX19jaGFpbl9fID0gISFjaGFpbkFsbDtcbiAgICAgIHRoaXMuX19pbmRleF9fID0gMDtcbiAgICAgIHRoaXMuX192YWx1ZXNfXyA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBCeSBkZWZhdWx0LCB0aGUgdGVtcGxhdGUgZGVsaW1pdGVycyB1c2VkIGJ5IGxvZGFzaCBhcmUgbGlrZSB0aG9zZSBpblxuICAgICAqIGVtYmVkZGVkIFJ1YnkgKEVSQikgYXMgd2VsbCBhcyBFUzIwMTUgdGVtcGxhdGUgc3RyaW5ncy4gQ2hhbmdlIHRoZVxuICAgICAqIGZvbGxvd2luZyB0ZW1wbGF0ZSBzZXR0aW5ncyB0byB1c2UgYWx0ZXJuYXRpdmUgZGVsaW1pdGVycy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICovXG4gICAgbG9kYXNoLnRlbXBsYXRlU2V0dGluZ3MgPSB7XG5cbiAgICAgIC8qKlxuICAgICAgICogVXNlZCB0byBkZXRlY3QgYGRhdGFgIHByb3BlcnR5IHZhbHVlcyB0byBiZSBIVE1MLWVzY2FwZWQuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIF8udGVtcGxhdGVTZXR0aW5nc1xuICAgICAgICogQHR5cGUge1JlZ0V4cH1cbiAgICAgICAqL1xuICAgICAgJ2VzY2FwZSc6IHJlRXNjYXBlLFxuXG4gICAgICAvKipcbiAgICAgICAqIFVzZWQgdG8gZGV0ZWN0IGNvZGUgdG8gYmUgZXZhbHVhdGVkLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBfLnRlbXBsYXRlU2V0dGluZ3NcbiAgICAgICAqIEB0eXBlIHtSZWdFeHB9XG4gICAgICAgKi9cbiAgICAgICdldmFsdWF0ZSc6IHJlRXZhbHVhdGUsXG5cbiAgICAgIC8qKlxuICAgICAgICogVXNlZCB0byBkZXRlY3QgYGRhdGFgIHByb3BlcnR5IHZhbHVlcyB0byBpbmplY3QuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIF8udGVtcGxhdGVTZXR0aW5nc1xuICAgICAgICogQHR5cGUge1JlZ0V4cH1cbiAgICAgICAqL1xuICAgICAgJ2ludGVycG9sYXRlJzogcmVJbnRlcnBvbGF0ZSxcblxuICAgICAgLyoqXG4gICAgICAgKiBVc2VkIHRvIHJlZmVyZW5jZSB0aGUgZGF0YSBvYmplY3QgaW4gdGhlIHRlbXBsYXRlIHRleHQuXG4gICAgICAgKlxuICAgICAgICogQG1lbWJlck9mIF8udGVtcGxhdGVTZXR0aW5nc1xuICAgICAgICogQHR5cGUge3N0cmluZ31cbiAgICAgICAqL1xuICAgICAgJ3ZhcmlhYmxlJzogJycsXG5cbiAgICAgIC8qKlxuICAgICAgICogVXNlZCB0byBpbXBvcnQgdmFyaWFibGVzIGludG8gdGhlIGNvbXBpbGVkIHRlbXBsYXRlLlxuICAgICAgICpcbiAgICAgICAqIEBtZW1iZXJPZiBfLnRlbXBsYXRlU2V0dGluZ3NcbiAgICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICAgKi9cbiAgICAgICdpbXBvcnRzJzoge1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBIHJlZmVyZW5jZSB0byB0aGUgYGxvZGFzaGAgZnVuY3Rpb24uXG4gICAgICAgICAqXG4gICAgICAgICAqIEBtZW1iZXJPZiBfLnRlbXBsYXRlU2V0dGluZ3MuaW1wb3J0c1xuICAgICAgICAgKiBAdHlwZSB7RnVuY3Rpb259XG4gICAgICAgICAqL1xuICAgICAgICAnXyc6IGxvZGFzaFxuICAgICAgfVxuICAgIH07XG5cbiAgICAvLyBFbnN1cmUgd3JhcHBlcnMgYXJlIGluc3RhbmNlcyBvZiBgYmFzZUxvZGFzaGAuXG4gICAgbG9kYXNoLnByb3RvdHlwZSA9IGJhc2VMb2Rhc2gucHJvdG90eXBlO1xuICAgIGxvZGFzaC5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBsb2Rhc2g7XG5cbiAgICBMb2Rhc2hXcmFwcGVyLnByb3RvdHlwZSA9IGJhc2VDcmVhdGUoYmFzZUxvZGFzaC5wcm90b3R5cGUpO1xuICAgIExvZGFzaFdyYXBwZXIucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gTG9kYXNoV3JhcHBlcjtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBsYXp5IHdyYXBwZXIgb2JqZWN0IHdoaWNoIHdyYXBzIGB2YWx1ZWAgdG8gZW5hYmxlIGxhenkgZXZhbHVhdGlvbi5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gd3JhcC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBMYXp5V3JhcHBlcih2YWx1ZSkge1xuICAgICAgdGhpcy5fX3dyYXBwZWRfXyA9IHZhbHVlO1xuICAgICAgdGhpcy5fX2FjdGlvbnNfXyA9IFtdO1xuICAgICAgdGhpcy5fX2Rpcl9fID0gMTtcbiAgICAgIHRoaXMuX19maWx0ZXJlZF9fID0gZmFsc2U7XG4gICAgICB0aGlzLl9faXRlcmF0ZWVzX18gPSBbXTtcbiAgICAgIHRoaXMuX190YWtlQ291bnRfXyA9IE1BWF9BUlJBWV9MRU5HVEg7XG4gICAgICB0aGlzLl9fdmlld3NfXyA9IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBjbG9uZSBvZiB0aGUgbGF6eSB3cmFwcGVyIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgY2xvbmVcbiAgICAgKiBAbWVtYmVyT2YgTGF6eVdyYXBwZXJcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjbG9uZWQgYExhenlXcmFwcGVyYCBvYmplY3QuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbGF6eUNsb25lKCkge1xuICAgICAgdmFyIHJlc3VsdCA9IG5ldyBMYXp5V3JhcHBlcih0aGlzLl9fd3JhcHBlZF9fKTtcbiAgICAgIHJlc3VsdC5fX2FjdGlvbnNfXyA9IGNvcHlBcnJheSh0aGlzLl9fYWN0aW9uc19fKTtcbiAgICAgIHJlc3VsdC5fX2Rpcl9fID0gdGhpcy5fX2Rpcl9fO1xuICAgICAgcmVzdWx0Ll9fZmlsdGVyZWRfXyA9IHRoaXMuX19maWx0ZXJlZF9fO1xuICAgICAgcmVzdWx0Ll9faXRlcmF0ZWVzX18gPSBjb3B5QXJyYXkodGhpcy5fX2l0ZXJhdGVlc19fKTtcbiAgICAgIHJlc3VsdC5fX3Rha2VDb3VudF9fID0gdGhpcy5fX3Rha2VDb3VudF9fO1xuICAgICAgcmVzdWx0Ll9fdmlld3NfXyA9IGNvcHlBcnJheSh0aGlzLl9fdmlld3NfXyk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldmVyc2VzIHRoZSBkaXJlY3Rpb24gb2YgbGF6eSBpdGVyYXRpb24uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIHJldmVyc2VcbiAgICAgKiBAbWVtYmVyT2YgTGF6eVdyYXBwZXJcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgcmV2ZXJzZWQgYExhenlXcmFwcGVyYCBvYmplY3QuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbGF6eVJldmVyc2UoKSB7XG4gICAgICBpZiAodGhpcy5fX2ZpbHRlcmVkX18pIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IG5ldyBMYXp5V3JhcHBlcih0aGlzKTtcbiAgICAgICAgcmVzdWx0Ll9fZGlyX18gPSAtMTtcbiAgICAgICAgcmVzdWx0Ll9fZmlsdGVyZWRfXyA9IHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXN1bHQgPSB0aGlzLmNsb25lKCk7XG4gICAgICAgIHJlc3VsdC5fX2Rpcl9fICo9IC0xO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFeHRyYWN0cyB0aGUgdW53cmFwcGVkIHZhbHVlIGZyb20gaXRzIGxhenkgd3JhcHBlci5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgdmFsdWVcbiAgICAgKiBAbWVtYmVyT2YgTGF6eVdyYXBwZXJcbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgdW53cmFwcGVkIHZhbHVlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGxhenlWYWx1ZSgpIHtcbiAgICAgIHZhciBhcnJheSA9IHRoaXMuX193cmFwcGVkX18udmFsdWUoKSxcbiAgICAgICAgICBkaXIgPSB0aGlzLl9fZGlyX18sXG4gICAgICAgICAgaXNBcnIgPSBpc0FycmF5KGFycmF5KSxcbiAgICAgICAgICBpc1JpZ2h0ID0gZGlyIDwgMCxcbiAgICAgICAgICBhcnJMZW5ndGggPSBpc0FyciA/IGFycmF5Lmxlbmd0aCA6IDAsXG4gICAgICAgICAgdmlldyA9IGdldFZpZXcoMCwgYXJyTGVuZ3RoLCB0aGlzLl9fdmlld3NfXyksXG4gICAgICAgICAgc3RhcnQgPSB2aWV3LnN0YXJ0LFxuICAgICAgICAgIGVuZCA9IHZpZXcuZW5kLFxuICAgICAgICAgIGxlbmd0aCA9IGVuZCAtIHN0YXJ0LFxuICAgICAgICAgIGluZGV4ID0gaXNSaWdodCA/IGVuZCA6IChzdGFydCAtIDEpLFxuICAgICAgICAgIGl0ZXJhdGVlcyA9IHRoaXMuX19pdGVyYXRlZXNfXyxcbiAgICAgICAgICBpdGVyTGVuZ3RoID0gaXRlcmF0ZWVzLmxlbmd0aCxcbiAgICAgICAgICByZXNJbmRleCA9IDAsXG4gICAgICAgICAgdGFrZUNvdW50ID0gbmF0aXZlTWluKGxlbmd0aCwgdGhpcy5fX3Rha2VDb3VudF9fKTtcblxuICAgICAgaWYgKCFpc0FyciB8fCAoIWlzUmlnaHQgJiYgYXJyTGVuZ3RoID09IGxlbmd0aCAmJiB0YWtlQ291bnQgPT0gbGVuZ3RoKSkge1xuICAgICAgICByZXR1cm4gYmFzZVdyYXBwZXJWYWx1ZShhcnJheSwgdGhpcy5fX2FjdGlvbnNfXyk7XG4gICAgICB9XG4gICAgICB2YXIgcmVzdWx0ID0gW107XG5cbiAgICAgIG91dGVyOlxuICAgICAgd2hpbGUgKGxlbmd0aC0tICYmIHJlc0luZGV4IDwgdGFrZUNvdW50KSB7XG4gICAgICAgIGluZGV4ICs9IGRpcjtcblxuICAgICAgICB2YXIgaXRlckluZGV4ID0gLTEsXG4gICAgICAgICAgICB2YWx1ZSA9IGFycmF5W2luZGV4XTtcblxuICAgICAgICB3aGlsZSAoKytpdGVySW5kZXggPCBpdGVyTGVuZ3RoKSB7XG4gICAgICAgICAgdmFyIGRhdGEgPSBpdGVyYXRlZXNbaXRlckluZGV4XSxcbiAgICAgICAgICAgICAgaXRlcmF0ZWUgPSBkYXRhLml0ZXJhdGVlLFxuICAgICAgICAgICAgICB0eXBlID0gZGF0YS50eXBlLFxuICAgICAgICAgICAgICBjb21wdXRlZCA9IGl0ZXJhdGVlKHZhbHVlKTtcblxuICAgICAgICAgIGlmICh0eXBlID09IExBWllfTUFQX0ZMQUcpIHtcbiAgICAgICAgICAgIHZhbHVlID0gY29tcHV0ZWQ7XG4gICAgICAgICAgfSBlbHNlIGlmICghY29tcHV0ZWQpIHtcbiAgICAgICAgICAgIGlmICh0eXBlID09IExBWllfRklMVEVSX0ZMQUcpIHtcbiAgICAgICAgICAgICAgY29udGludWUgb3V0ZXI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBicmVhayBvdXRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmVzdWx0W3Jlc0luZGV4KytdID0gdmFsdWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8vIEVuc3VyZSBgTGF6eVdyYXBwZXJgIGlzIGFuIGluc3RhbmNlIG9mIGBiYXNlTG9kYXNoYC5cbiAgICBMYXp5V3JhcHBlci5wcm90b3R5cGUgPSBiYXNlQ3JlYXRlKGJhc2VMb2Rhc2gucHJvdG90eXBlKTtcbiAgICBMYXp5V3JhcHBlci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBMYXp5V3JhcHBlcjtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBoYXNoIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2VudHJpZXNdIFRoZSBrZXktdmFsdWUgcGFpcnMgdG8gY2FjaGUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gSGFzaChlbnRyaWVzKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBlbnRyaWVzID09IG51bGwgPyAwIDogZW50cmllcy5sZW5ndGg7XG5cbiAgICAgIHRoaXMuY2xlYXIoKTtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBlbnRyeSA9IGVudHJpZXNbaW5kZXhdO1xuICAgICAgICB0aGlzLnNldChlbnRyeVswXSwgZW50cnlbMV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGtleS12YWx1ZSBlbnRyaWVzIGZyb20gdGhlIGhhc2guXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIGNsZWFyXG4gICAgICogQG1lbWJlck9mIEhhc2hcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBoYXNoQ2xlYXIoKSB7XG4gICAgICB0aGlzLl9fZGF0YV9fID0gbmF0aXZlQ3JlYXRlID8gbmF0aXZlQ3JlYXRlKG51bGwpIDoge307XG4gICAgICB0aGlzLnNpemUgPSAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYGtleWAgYW5kIGl0cyB2YWx1ZSBmcm9tIHRoZSBoYXNoLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBkZWxldGVcbiAgICAgKiBAbWVtYmVyT2YgSGFzaFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBoYXNoIFRoZSBoYXNoIHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGVudHJ5IHdhcyByZW1vdmVkLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaGFzaERlbGV0ZShrZXkpIHtcbiAgICAgIHZhciByZXN1bHQgPSB0aGlzLmhhcyhrZXkpICYmIGRlbGV0ZSB0aGlzLl9fZGF0YV9fW2tleV07XG4gICAgICB0aGlzLnNpemUgLT0gcmVzdWx0ID8gMSA6IDA7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGhhc2ggdmFsdWUgZm9yIGBrZXlgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBnZXRcbiAgICAgKiBAbWVtYmVyT2YgSGFzaFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gZ2V0LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBlbnRyeSB2YWx1ZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBoYXNoR2V0KGtleSkge1xuICAgICAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fO1xuICAgICAgaWYgKG5hdGl2ZUNyZWF0ZSkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gZGF0YVtrZXldO1xuICAgICAgICByZXR1cm4gcmVzdWx0ID09PSBIQVNIX1VOREVGSU5FRCA/IHVuZGVmaW5lZCA6IHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBoYXNPd25Qcm9wZXJ0eS5jYWxsKGRhdGEsIGtleSkgPyBkYXRhW2tleV0gOiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGEgaGFzaCB2YWx1ZSBmb3IgYGtleWAgZXhpc3RzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBoYXNcbiAgICAgKiBAbWVtYmVyT2YgSGFzaFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgZW50cnkgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFuIGVudHJ5IGZvciBga2V5YCBleGlzdHMsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBoYXNoSGFzKGtleSkge1xuICAgICAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fO1xuICAgICAgcmV0dXJuIG5hdGl2ZUNyZWF0ZSA/IChkYXRhW2tleV0gIT09IHVuZGVmaW5lZCkgOiBoYXNPd25Qcm9wZXJ0eS5jYWxsKGRhdGEsIGtleSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgaGFzaCBga2V5YCB0byBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBzZXRcbiAgICAgKiBAbWVtYmVyT2YgSGFzaFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gc2V0LlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNldC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBoYXNoIGluc3RhbmNlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGhhc2hTZXQoa2V5LCB2YWx1ZSkge1xuICAgICAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fO1xuICAgICAgdGhpcy5zaXplICs9IHRoaXMuaGFzKGtleSkgPyAwIDogMTtcbiAgICAgIGRhdGFba2V5XSA9IChuYXRpdmVDcmVhdGUgJiYgdmFsdWUgPT09IHVuZGVmaW5lZCkgPyBIQVNIX1VOREVGSU5FRCA6IHZhbHVlO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLy8gQWRkIG1ldGhvZHMgdG8gYEhhc2hgLlxuICAgIEhhc2gucHJvdG90eXBlLmNsZWFyID0gaGFzaENsZWFyO1xuICAgIEhhc2gucHJvdG90eXBlWydkZWxldGUnXSA9IGhhc2hEZWxldGU7XG4gICAgSGFzaC5wcm90b3R5cGUuZ2V0ID0gaGFzaEdldDtcbiAgICBIYXNoLnByb3RvdHlwZS5oYXMgPSBoYXNoSGFzO1xuICAgIEhhc2gucHJvdG90eXBlLnNldCA9IGhhc2hTZXQ7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGxpc3QgY2FjaGUgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbZW50cmllc10gVGhlIGtleS12YWx1ZSBwYWlycyB0byBjYWNoZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBMaXN0Q2FjaGUoZW50cmllcykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gZW50cmllcyA9PSBudWxsID8gMCA6IGVudHJpZXMubGVuZ3RoO1xuXG4gICAgICB0aGlzLmNsZWFyKCk7XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIgZW50cnkgPSBlbnRyaWVzW2luZGV4XTtcbiAgICAgICAgdGhpcy5zZXQoZW50cnlbMF0sIGVudHJ5WzFdKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFsbCBrZXktdmFsdWUgZW50cmllcyBmcm9tIHRoZSBsaXN0IGNhY2hlLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBjbGVhclxuICAgICAqIEBtZW1iZXJPZiBMaXN0Q2FjaGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBsaXN0Q2FjaGVDbGVhcigpIHtcbiAgICAgIHRoaXMuX19kYXRhX18gPSBbXTtcbiAgICAgIHRoaXMuc2l6ZSA9IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBga2V5YCBhbmQgaXRzIHZhbHVlIGZyb20gdGhlIGxpc3QgY2FjaGUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIGRlbGV0ZVxuICAgICAqIEBtZW1iZXJPZiBMaXN0Q2FjaGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGVudHJ5IHdhcyByZW1vdmVkLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbGlzdENhY2hlRGVsZXRlKGtleSkge1xuICAgICAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fLFxuICAgICAgICAgIGluZGV4ID0gYXNzb2NJbmRleE9mKGRhdGEsIGtleSk7XG5cbiAgICAgIGlmIChpbmRleCA8IDApIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgdmFyIGxhc3RJbmRleCA9IGRhdGEubGVuZ3RoIC0gMTtcbiAgICAgIGlmIChpbmRleCA9PSBsYXN0SW5kZXgpIHtcbiAgICAgICAgZGF0YS5wb3AoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNwbGljZS5jYWxsKGRhdGEsIGluZGV4LCAxKTtcbiAgICAgIH1cbiAgICAgIC0tdGhpcy5zaXplO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbGlzdCBjYWNoZSB2YWx1ZSBmb3IgYGtleWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIGdldFxuICAgICAqIEBtZW1iZXJPZiBMaXN0Q2FjaGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIGdldC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZW50cnkgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbGlzdENhY2hlR2V0KGtleSkge1xuICAgICAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fLFxuICAgICAgICAgIGluZGV4ID0gYXNzb2NJbmRleE9mKGRhdGEsIGtleSk7XG5cbiAgICAgIHJldHVybiBpbmRleCA8IDAgPyB1bmRlZmluZWQgOiBkYXRhW2luZGV4XVsxXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYSBsaXN0IGNhY2hlIHZhbHVlIGZvciBga2V5YCBleGlzdHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIGhhc1xuICAgICAqIEBtZW1iZXJPZiBMaXN0Q2FjaGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIGVudHJ5IHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbiBlbnRyeSBmb3IgYGtleWAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbGlzdENhY2hlSGFzKGtleSkge1xuICAgICAgcmV0dXJuIGFzc29jSW5kZXhPZih0aGlzLl9fZGF0YV9fLCBrZXkpID4gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgbGlzdCBjYWNoZSBga2V5YCB0byBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBzZXRcbiAgICAgKiBAbWVtYmVyT2YgTGlzdENhY2hlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBzZXQuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGxpc3QgY2FjaGUgaW5zdGFuY2UuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbGlzdENhY2hlU2V0KGtleSwgdmFsdWUpIHtcbiAgICAgIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXyxcbiAgICAgICAgICBpbmRleCA9IGFzc29jSW5kZXhPZihkYXRhLCBrZXkpO1xuXG4gICAgICBpZiAoaW5kZXggPCAwKSB7XG4gICAgICAgICsrdGhpcy5zaXplO1xuICAgICAgICBkYXRhLnB1c2goW2tleSwgdmFsdWVdKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRhdGFbaW5kZXhdWzFdID0gdmFsdWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvLyBBZGQgbWV0aG9kcyB0byBgTGlzdENhY2hlYC5cbiAgICBMaXN0Q2FjaGUucHJvdG90eXBlLmNsZWFyID0gbGlzdENhY2hlQ2xlYXI7XG4gICAgTGlzdENhY2hlLnByb3RvdHlwZVsnZGVsZXRlJ10gPSBsaXN0Q2FjaGVEZWxldGU7XG4gICAgTGlzdENhY2hlLnByb3RvdHlwZS5nZXQgPSBsaXN0Q2FjaGVHZXQ7XG4gICAgTGlzdENhY2hlLnByb3RvdHlwZS5oYXMgPSBsaXN0Q2FjaGVIYXM7XG4gICAgTGlzdENhY2hlLnByb3RvdHlwZS5zZXQgPSBsaXN0Q2FjaGVTZXQ7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbWFwIGNhY2hlIG9iamVjdCB0byBzdG9yZSBrZXktdmFsdWUgcGFpcnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtlbnRyaWVzXSBUaGUga2V5LXZhbHVlIHBhaXJzIHRvIGNhY2hlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIE1hcENhY2hlKGVudHJpZXMpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGVudHJpZXMgPT0gbnVsbCA/IDAgOiBlbnRyaWVzLmxlbmd0aDtcblxuICAgICAgdGhpcy5jbGVhcigpO1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIGVudHJ5ID0gZW50cmllc1tpbmRleF07XG4gICAgICAgIHRoaXMuc2V0KGVudHJ5WzBdLCBlbnRyeVsxXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhbGwga2V5LXZhbHVlIGVudHJpZXMgZnJvbSB0aGUgbWFwLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBjbGVhclxuICAgICAqIEBtZW1iZXJPZiBNYXBDYWNoZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1hcENhY2hlQ2xlYXIoKSB7XG4gICAgICB0aGlzLnNpemUgPSAwO1xuICAgICAgdGhpcy5fX2RhdGFfXyA9IHtcbiAgICAgICAgJ2hhc2gnOiBuZXcgSGFzaCxcbiAgICAgICAgJ21hcCc6IG5ldyAoTWFwIHx8IExpc3RDYWNoZSksXG4gICAgICAgICdzdHJpbmcnOiBuZXcgSGFzaFxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGBrZXlgIGFuZCBpdHMgdmFsdWUgZnJvbSB0aGUgbWFwLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBkZWxldGVcbiAgICAgKiBAbWVtYmVyT2YgTWFwQ2FjaGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGVudHJ5IHdhcyByZW1vdmVkLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWFwQ2FjaGVEZWxldGUoa2V5KSB7XG4gICAgICB2YXIgcmVzdWx0ID0gZ2V0TWFwRGF0YSh0aGlzLCBrZXkpWydkZWxldGUnXShrZXkpO1xuICAgICAgdGhpcy5zaXplIC09IHJlc3VsdCA/IDEgOiAwO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBtYXAgdmFsdWUgZm9yIGBrZXlgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBnZXRcbiAgICAgKiBAbWVtYmVyT2YgTWFwQ2FjaGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIGdldC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZW50cnkgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWFwQ2FjaGVHZXQoa2V5KSB7XG4gICAgICByZXR1cm4gZ2V0TWFwRGF0YSh0aGlzLCBrZXkpLmdldChrZXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBhIG1hcCB2YWx1ZSBmb3IgYGtleWAgZXhpc3RzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBoYXNcbiAgICAgKiBAbWVtYmVyT2YgTWFwQ2FjaGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIGVudHJ5IHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbiBlbnRyeSBmb3IgYGtleWAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWFwQ2FjaGVIYXMoa2V5KSB7XG4gICAgICByZXR1cm4gZ2V0TWFwRGF0YSh0aGlzLCBrZXkpLmhhcyhrZXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIG1hcCBga2V5YCB0byBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAbmFtZSBzZXRcbiAgICAgKiBAbWVtYmVyT2YgTWFwQ2FjaGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHNldC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZXQuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbWFwIGNhY2hlIGluc3RhbmNlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1hcENhY2hlU2V0KGtleSwgdmFsdWUpIHtcbiAgICAgIHZhciBkYXRhID0gZ2V0TWFwRGF0YSh0aGlzLCBrZXkpLFxuICAgICAgICAgIHNpemUgPSBkYXRhLnNpemU7XG5cbiAgICAgIGRhdGEuc2V0KGtleSwgdmFsdWUpO1xuICAgICAgdGhpcy5zaXplICs9IGRhdGEuc2l6ZSA9PSBzaXplID8gMCA6IDE7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvLyBBZGQgbWV0aG9kcyB0byBgTWFwQ2FjaGVgLlxuICAgIE1hcENhY2hlLnByb3RvdHlwZS5jbGVhciA9IG1hcENhY2hlQ2xlYXI7XG4gICAgTWFwQ2FjaGUucHJvdG90eXBlWydkZWxldGUnXSA9IG1hcENhY2hlRGVsZXRlO1xuICAgIE1hcENhY2hlLnByb3RvdHlwZS5nZXQgPSBtYXBDYWNoZUdldDtcbiAgICBNYXBDYWNoZS5wcm90b3R5cGUuaGFzID0gbWFwQ2FjaGVIYXM7XG4gICAgTWFwQ2FjaGUucHJvdG90eXBlLnNldCA9IG1hcENhY2hlU2V0O1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IGNhY2hlIG9iamVjdCB0byBzdG9yZSB1bmlxdWUgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbdmFsdWVzXSBUaGUgdmFsdWVzIHRvIGNhY2hlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIFNldENhY2hlKHZhbHVlcykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gdmFsdWVzID09IG51bGwgPyAwIDogdmFsdWVzLmxlbmd0aDtcblxuICAgICAgdGhpcy5fX2RhdGFfXyA9IG5ldyBNYXBDYWNoZTtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHRoaXMuYWRkKHZhbHVlc1tpbmRleF0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZHMgYHZhbHVlYCB0byB0aGUgYXJyYXkgY2FjaGUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIGFkZFxuICAgICAqIEBtZW1iZXJPZiBTZXRDYWNoZVxuICAgICAqIEBhbGlhcyBwdXNoXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2FjaGUuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY2FjaGUgaW5zdGFuY2UuXG4gICAgICovXG4gICAgZnVuY3Rpb24gc2V0Q2FjaGVBZGQodmFsdWUpIHtcbiAgICAgIHRoaXMuX19kYXRhX18uc2V0KHZhbHVlLCBIQVNIX1VOREVGSU5FRCk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBpbiB0aGUgYXJyYXkgY2FjaGUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIGhhc1xuICAgICAqIEBtZW1iZXJPZiBTZXRDYWNoZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNlYXJjaCBmb3IuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBmb3VuZCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNldENhY2hlSGFzKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdGhpcy5fX2RhdGFfXy5oYXModmFsdWUpO1xuICAgIH1cblxuICAgIC8vIEFkZCBtZXRob2RzIHRvIGBTZXRDYWNoZWAuXG4gICAgU2V0Q2FjaGUucHJvdG90eXBlLmFkZCA9IFNldENhY2hlLnByb3RvdHlwZS5wdXNoID0gc2V0Q2FjaGVBZGQ7XG4gICAgU2V0Q2FjaGUucHJvdG90eXBlLmhhcyA9IHNldENhY2hlSGFzO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHN0YWNrIGNhY2hlIG9iamVjdCB0byBzdG9yZSBrZXktdmFsdWUgcGFpcnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtlbnRyaWVzXSBUaGUga2V5LXZhbHVlIHBhaXJzIHRvIGNhY2hlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIFN0YWNrKGVudHJpZXMpIHtcbiAgICAgIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXyA9IG5ldyBMaXN0Q2FjaGUoZW50cmllcyk7XG4gICAgICB0aGlzLnNpemUgPSBkYXRhLnNpemU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhbGwga2V5LXZhbHVlIGVudHJpZXMgZnJvbSB0aGUgc3RhY2suXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIGNsZWFyXG4gICAgICogQG1lbWJlck9mIFN0YWNrXG4gICAgICovXG4gICAgZnVuY3Rpb24gc3RhY2tDbGVhcigpIHtcbiAgICAgIHRoaXMuX19kYXRhX18gPSBuZXcgTGlzdENhY2hlO1xuICAgICAgdGhpcy5zaXplID0gMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGBrZXlgIGFuZCBpdHMgdmFsdWUgZnJvbSB0aGUgc3RhY2suXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBuYW1lIGRlbGV0ZVxuICAgICAqIEBtZW1iZXJPZiBTdGFja1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gcmVtb3ZlLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZW50cnkgd2FzIHJlbW92ZWQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzdGFja0RlbGV0ZShrZXkpIHtcbiAgICAgIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXyxcbiAgICAgICAgICByZXN1bHQgPSBkYXRhWydkZWxldGUnXShrZXkpO1xuXG4gICAgICB0aGlzLnNpemUgPSBkYXRhLnNpemU7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHN0YWNrIHZhbHVlIGZvciBga2V5YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgZ2V0XG4gICAgICogQG1lbWJlck9mIFN0YWNrXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBnZXQuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGVudHJ5IHZhbHVlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHN0YWNrR2V0KGtleSkge1xuICAgICAgcmV0dXJuIHRoaXMuX19kYXRhX18uZ2V0KGtleSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGEgc3RhY2sgdmFsdWUgZm9yIGBrZXlgIGV4aXN0cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgaGFzXG4gICAgICogQG1lbWJlck9mIFN0YWNrXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBlbnRyeSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYW4gZW50cnkgZm9yIGBrZXlgIGV4aXN0cywgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHN0YWNrSGFzKGtleSkge1xuICAgICAgcmV0dXJuIHRoaXMuX19kYXRhX18uaGFzKGtleSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgc3RhY2sgYGtleWAgdG8gYHZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQG5hbWUgc2V0XG4gICAgICogQG1lbWJlck9mIFN0YWNrXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBzZXQuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIHN0YWNrIGNhY2hlIGluc3RhbmNlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHN0YWNrU2V0KGtleSwgdmFsdWUpIHtcbiAgICAgIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXztcbiAgICAgIGlmIChkYXRhIGluc3RhbmNlb2YgTGlzdENhY2hlKSB7XG4gICAgICAgIHZhciBwYWlycyA9IGRhdGEuX19kYXRhX187XG4gICAgICAgIGlmICghTWFwIHx8IChwYWlycy5sZW5ndGggPCBMQVJHRV9BUlJBWV9TSVpFIC0gMSkpIHtcbiAgICAgICAgICBwYWlycy5wdXNoKFtrZXksIHZhbHVlXSk7XG4gICAgICAgICAgdGhpcy5zaXplID0gKytkYXRhLnNpemU7XG4gICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgZGF0YSA9IHRoaXMuX19kYXRhX18gPSBuZXcgTWFwQ2FjaGUocGFpcnMpO1xuICAgICAgfVxuICAgICAgZGF0YS5zZXQoa2V5LCB2YWx1ZSk7XG4gICAgICB0aGlzLnNpemUgPSBkYXRhLnNpemU7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvLyBBZGQgbWV0aG9kcyB0byBgU3RhY2tgLlxuICAgIFN0YWNrLnByb3RvdHlwZS5jbGVhciA9IHN0YWNrQ2xlYXI7XG4gICAgU3RhY2sucHJvdG90eXBlWydkZWxldGUnXSA9IHN0YWNrRGVsZXRlO1xuICAgIFN0YWNrLnByb3RvdHlwZS5nZXQgPSBzdGFja0dldDtcbiAgICBTdGFjay5wcm90b3R5cGUuaGFzID0gc3RhY2tIYXM7XG4gICAgU3RhY2sucHJvdG90eXBlLnNldCA9IHN0YWNrU2V0O1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgZW51bWVyYWJsZSBwcm9wZXJ0eSBuYW1lcyBvZiB0aGUgYXJyYXktbGlrZSBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGluaGVyaXRlZCBTcGVjaWZ5IHJldHVybmluZyBpbmhlcml0ZWQgcHJvcGVydHkgbmFtZXMuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhcnJheUxpa2VLZXlzKHZhbHVlLCBpbmhlcml0ZWQpIHtcbiAgICAgIHZhciBpc0FyciA9IGlzQXJyYXkodmFsdWUpLFxuICAgICAgICAgIGlzQXJnID0gIWlzQXJyICYmIGlzQXJndW1lbnRzKHZhbHVlKSxcbiAgICAgICAgICBpc0J1ZmYgPSAhaXNBcnIgJiYgIWlzQXJnICYmIGlzQnVmZmVyKHZhbHVlKSxcbiAgICAgICAgICBpc1R5cGUgPSAhaXNBcnIgJiYgIWlzQXJnICYmICFpc0J1ZmYgJiYgaXNUeXBlZEFycmF5KHZhbHVlKSxcbiAgICAgICAgICBza2lwSW5kZXhlcyA9IGlzQXJyIHx8IGlzQXJnIHx8IGlzQnVmZiB8fCBpc1R5cGUsXG4gICAgICAgICAgcmVzdWx0ID0gc2tpcEluZGV4ZXMgPyBiYXNlVGltZXModmFsdWUubGVuZ3RoLCBTdHJpbmcpIDogW10sXG4gICAgICAgICAgbGVuZ3RoID0gcmVzdWx0Lmxlbmd0aDtcblxuICAgICAgZm9yICh2YXIga2V5IGluIHZhbHVlKSB7XG4gICAgICAgIGlmICgoaW5oZXJpdGVkIHx8IGhhc093blByb3BlcnR5LmNhbGwodmFsdWUsIGtleSkpICYmXG4gICAgICAgICAgICAhKHNraXBJbmRleGVzICYmIChcbiAgICAgICAgICAgICAgIC8vIFNhZmFyaSA5IGhhcyBlbnVtZXJhYmxlIGBhcmd1bWVudHMubGVuZ3RoYCBpbiBzdHJpY3QgbW9kZS5cbiAgICAgICAgICAgICAgIGtleSA9PSAnbGVuZ3RoJyB8fFxuICAgICAgICAgICAgICAgLy8gTm9kZS5qcyAwLjEwIGhhcyBlbnVtZXJhYmxlIG5vbi1pbmRleCBwcm9wZXJ0aWVzIG9uIGJ1ZmZlcnMuXG4gICAgICAgICAgICAgICAoaXNCdWZmICYmIChrZXkgPT0gJ29mZnNldCcgfHwga2V5ID09ICdwYXJlbnQnKSkgfHxcbiAgICAgICAgICAgICAgIC8vIFBoYW50b21KUyAyIGhhcyBlbnVtZXJhYmxlIG5vbi1pbmRleCBwcm9wZXJ0aWVzIG9uIHR5cGVkIGFycmF5cy5cbiAgICAgICAgICAgICAgIChpc1R5cGUgJiYgKGtleSA9PSAnYnVmZmVyJyB8fCBrZXkgPT0gJ2J5dGVMZW5ndGgnIHx8IGtleSA9PSAnYnl0ZU9mZnNldCcpKSB8fFxuICAgICAgICAgICAgICAgLy8gU2tpcCBpbmRleCBwcm9wZXJ0aWVzLlxuICAgICAgICAgICAgICAgaXNJbmRleChrZXksIGxlbmd0aClcbiAgICAgICAgICAgICkpKSB7XG4gICAgICAgICAgcmVzdWx0LnB1c2goa2V5KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uc2FtcGxlYCBmb3IgYXJyYXlzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gc2FtcGxlLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSByYW5kb20gZWxlbWVudC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhcnJheVNhbXBsZShhcnJheSkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcbiAgICAgIHJldHVybiBsZW5ndGggPyBhcnJheVtiYXNlUmFuZG9tKDAsIGxlbmd0aCAtIDEpXSA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uc2FtcGxlU2l6ZWAgZm9yIGFycmF5cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNhbXBsZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbiBUaGUgbnVtYmVyIG9mIGVsZW1lbnRzIHRvIHNhbXBsZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHJhbmRvbSBlbGVtZW50cy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhcnJheVNhbXBsZVNpemUoYXJyYXksIG4pIHtcbiAgICAgIHJldHVybiBzaHVmZmxlU2VsZihjb3B5QXJyYXkoYXJyYXkpLCBiYXNlQ2xhbXAobiwgMCwgYXJyYXkubGVuZ3RoKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLnNodWZmbGVgIGZvciBhcnJheXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBzaHVmZmxlLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IHNodWZmbGVkIGFycmF5LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFycmF5U2h1ZmZsZShhcnJheSkge1xuICAgICAgcmV0dXJuIHNodWZmbGVTZWxmKGNvcHlBcnJheShhcnJheSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gaXMgbGlrZSBgYXNzaWduVmFsdWVgIGV4Y2VwdCB0aGF0IGl0IGRvZXNuJ3QgYXNzaWduXG4gICAgICogYHVuZGVmaW5lZGAgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgcHJvcGVydHkgdG8gYXNzaWduLlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGFzc2lnbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhc3NpZ25NZXJnZVZhbHVlKG9iamVjdCwga2V5LCB2YWx1ZSkge1xuICAgICAgaWYgKCh2YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFlcShvYmplY3Rba2V5XSwgdmFsdWUpKSB8fFxuICAgICAgICAgICh2YWx1ZSA9PT0gdW5kZWZpbmVkICYmICEoa2V5IGluIG9iamVjdCkpKSB7XG4gICAgICAgIGJhc2VBc3NpZ25WYWx1ZShvYmplY3QsIGtleSwgdmFsdWUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFzc2lnbnMgYHZhbHVlYCB0byBga2V5YCBvZiBgb2JqZWN0YCBpZiB0aGUgZXhpc3RpbmcgdmFsdWUgaXMgbm90IGVxdWl2YWxlbnRcbiAgICAgKiB1c2luZyBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICAgICAqIGZvciBlcXVhbGl0eSBjb21wYXJpc29ucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHByb3BlcnR5IHRvIGFzc2lnbi5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBhc3NpZ24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXNzaWduVmFsdWUob2JqZWN0LCBrZXksIHZhbHVlKSB7XG4gICAgICB2YXIgb2JqVmFsdWUgPSBvYmplY3Rba2V5XTtcbiAgICAgIGlmICghKGhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpICYmIGVxKG9ialZhbHVlLCB2YWx1ZSkpIHx8XG4gICAgICAgICAgKHZhbHVlID09PSB1bmRlZmluZWQgJiYgIShrZXkgaW4gb2JqZWN0KSkpIHtcbiAgICAgICAgYmFzZUFzc2lnblZhbHVlKG9iamVjdCwga2V5LCB2YWx1ZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgaW5kZXggYXQgd2hpY2ggdGhlIGBrZXlgIGlzIGZvdW5kIGluIGBhcnJheWAgb2Yga2V5LXZhbHVlIHBhaXJzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0geyp9IGtleSBUaGUga2V5IHRvIHNlYXJjaCBmb3IuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUsIGVsc2UgYC0xYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhc3NvY0luZGV4T2YoYXJyYXksIGtleSkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICBpZiAoZXEoYXJyYXlbbGVuZ3RoXVswXSwga2V5KSkge1xuICAgICAgICAgIHJldHVybiBsZW5ndGg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiAtMTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZ2dyZWdhdGVzIGVsZW1lbnRzIG9mIGBjb2xsZWN0aW9uYCBvbiBgYWNjdW11bGF0b3JgIHdpdGgga2V5cyB0cmFuc2Zvcm1lZFxuICAgICAqIGJ5IGBpdGVyYXRlZWAgYW5kIHZhbHVlcyBzZXQgYnkgYHNldHRlcmAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBzZXR0ZXIgVGhlIGZ1bmN0aW9uIHRvIHNldCBgYWNjdW11bGF0b3JgIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgaXRlcmF0ZWUgdG8gdHJhbnNmb3JtIGtleXMuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGFjY3VtdWxhdG9yIFRoZSBpbml0aWFsIGFnZ3JlZ2F0ZWQgb2JqZWN0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyBgYWNjdW11bGF0b3JgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VBZ2dyZWdhdG9yKGNvbGxlY3Rpb24sIHNldHRlciwgaXRlcmF0ZWUsIGFjY3VtdWxhdG9yKSB7XG4gICAgICBiYXNlRWFjaChjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwga2V5LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgIHNldHRlcihhY2N1bXVsYXRvciwgdmFsdWUsIGl0ZXJhdGVlKHZhbHVlKSwgY29sbGVjdGlvbik7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5hc3NpZ25gIHdpdGhvdXQgc3VwcG9ydCBmb3IgbXVsdGlwbGUgc291cmNlc1xuICAgICAqIG9yIGBjdXN0b21pemVyYCBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBzb3VyY2Ugb2JqZWN0LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUFzc2lnbihvYmplY3QsIHNvdXJjZSkge1xuICAgICAgcmV0dXJuIG9iamVjdCAmJiBjb3B5T2JqZWN0KHNvdXJjZSwga2V5cyhzb3VyY2UpLCBvYmplY3QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmFzc2lnbkluYCB3aXRob3V0IHN1cHBvcnQgZm9yIG11bHRpcGxlIHNvdXJjZXNcbiAgICAgKiBvciBgY3VzdG9taXplcmAgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VBc3NpZ25JbihvYmplY3QsIHNvdXJjZSkge1xuICAgICAgcmV0dXJuIG9iamVjdCAmJiBjb3B5T2JqZWN0KHNvdXJjZSwga2V5c0luKHNvdXJjZSksIG9iamVjdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYGFzc2lnblZhbHVlYCBhbmQgYGFzc2lnbk1lcmdlVmFsdWVgIHdpdGhvdXRcbiAgICAgKiB2YWx1ZSBjaGVja3MuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBwcm9wZXJ0eSB0byBhc3NpZ24uXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gYXNzaWduLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VBc3NpZ25WYWx1ZShvYmplY3QsIGtleSwgdmFsdWUpIHtcbiAgICAgIGlmIChrZXkgPT0gJ19fcHJvdG9fXycgJiYgZGVmaW5lUHJvcGVydHkpIHtcbiAgICAgICAgZGVmaW5lUHJvcGVydHkob2JqZWN0LCBrZXksIHtcbiAgICAgICAgICAnY29uZmlndXJhYmxlJzogdHJ1ZSxcbiAgICAgICAgICAnZW51bWVyYWJsZSc6IHRydWUsXG4gICAgICAgICAgJ3ZhbHVlJzogdmFsdWUsXG4gICAgICAgICAgJ3dyaXRhYmxlJzogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG9iamVjdFtrZXldID0gdmFsdWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uYXRgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaW5kaXZpZHVhbCBwYXRocy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBwYXRocyBUaGUgcHJvcGVydHkgcGF0aHMgdG8gcGljay5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHBpY2tlZCBlbGVtZW50cy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlQXQob2JqZWN0LCBwYXRocykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gcGF0aHMubGVuZ3RoLFxuICAgICAgICAgIHJlc3VsdCA9IEFycmF5KGxlbmd0aCksXG4gICAgICAgICAgc2tpcCA9IG9iamVjdCA9PSBudWxsO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICByZXN1bHRbaW5kZXhdID0gc2tpcCA/IHVuZGVmaW5lZCA6IGdldChvYmplY3QsIHBhdGhzW2luZGV4XSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmNsYW1wYCB3aGljaCBkb2Vzbid0IGNvZXJjZSBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBudW1iZXIgVGhlIG51bWJlciB0byBjbGFtcC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xvd2VyXSBUaGUgbG93ZXIgYm91bmQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHVwcGVyIFRoZSB1cHBlciBib3VuZC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBjbGFtcGVkIG51bWJlci5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlQ2xhbXAobnVtYmVyLCBsb3dlciwgdXBwZXIpIHtcbiAgICAgIGlmIChudW1iZXIgPT09IG51bWJlcikge1xuICAgICAgICBpZiAodXBwZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIG51bWJlciA9IG51bWJlciA8PSB1cHBlciA/IG51bWJlciA6IHVwcGVyO1xuICAgICAgICB9XG4gICAgICAgIGlmIChsb3dlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgbnVtYmVyID0gbnVtYmVyID49IGxvd2VyID8gbnVtYmVyIDogbG93ZXI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBudW1iZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uY2xvbmVgIGFuZCBgXy5jbG9uZURlZXBgIHdoaWNoIHRyYWNrc1xuICAgICAqIHRyYXZlcnNlZCBvYmplY3RzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjbG9uZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGJpdG1hc2sgVGhlIGJpdG1hc2sgZmxhZ3MuXG4gICAgICogIDEgLSBEZWVwIGNsb25lXG4gICAgICogIDIgLSBGbGF0dGVuIGluaGVyaXRlZCBwcm9wZXJ0aWVzXG4gICAgICogIDQgLSBDbG9uZSBzeW1ib2xzXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY2xvbmluZy5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW2tleV0gVGhlIGtleSBvZiBgdmFsdWVgLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0XSBUaGUgcGFyZW50IG9iamVjdCBvZiBgdmFsdWVgLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbc3RhY2tdIFRyYWNrcyB0cmF2ZXJzZWQgb2JqZWN0cyBhbmQgdGhlaXIgY2xvbmUgY291bnRlcnBhcnRzLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBjbG9uZWQgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUNsb25lKHZhbHVlLCBiaXRtYXNrLCBjdXN0b21pemVyLCBrZXksIG9iamVjdCwgc3RhY2spIHtcbiAgICAgIHZhciByZXN1bHQsXG4gICAgICAgICAgaXNEZWVwID0gYml0bWFzayAmIENMT05FX0RFRVBfRkxBRyxcbiAgICAgICAgICBpc0ZsYXQgPSBiaXRtYXNrICYgQ0xPTkVfRkxBVF9GTEFHLFxuICAgICAgICAgIGlzRnVsbCA9IGJpdG1hc2sgJiBDTE9ORV9TWU1CT0xTX0ZMQUc7XG5cbiAgICAgIGlmIChjdXN0b21pemVyKSB7XG4gICAgICAgIHJlc3VsdCA9IG9iamVjdCA/IGN1c3RvbWl6ZXIodmFsdWUsIGtleSwgb2JqZWN0LCBzdGFjaykgOiBjdXN0b21pemVyKHZhbHVlKTtcbiAgICAgIH1cbiAgICAgIGlmIChyZXN1bHQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgICAgaWYgKCFpc09iamVjdCh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfVxuICAgICAgdmFyIGlzQXJyID0gaXNBcnJheSh2YWx1ZSk7XG4gICAgICBpZiAoaXNBcnIpIHtcbiAgICAgICAgcmVzdWx0ID0gaW5pdENsb25lQXJyYXkodmFsdWUpO1xuICAgICAgICBpZiAoIWlzRGVlcCkge1xuICAgICAgICAgIHJldHVybiBjb3B5QXJyYXkodmFsdWUsIHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciB0YWcgPSBnZXRUYWcodmFsdWUpLFxuICAgICAgICAgICAgaXNGdW5jID0gdGFnID09IGZ1bmNUYWcgfHwgdGFnID09IGdlblRhZztcblxuICAgICAgICBpZiAoaXNCdWZmZXIodmFsdWUpKSB7XG4gICAgICAgICAgcmV0dXJuIGNsb25lQnVmZmVyKHZhbHVlLCBpc0RlZXApO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0YWcgPT0gb2JqZWN0VGFnIHx8IHRhZyA9PSBhcmdzVGFnIHx8IChpc0Z1bmMgJiYgIW9iamVjdCkpIHtcbiAgICAgICAgICByZXN1bHQgPSAoaXNGbGF0IHx8IGlzRnVuYykgPyB7fSA6IGluaXRDbG9uZU9iamVjdCh2YWx1ZSk7XG4gICAgICAgICAgaWYgKCFpc0RlZXApIHtcbiAgICAgICAgICAgIHJldHVybiBpc0ZsYXRcbiAgICAgICAgICAgICAgPyBjb3B5U3ltYm9sc0luKHZhbHVlLCBiYXNlQXNzaWduSW4ocmVzdWx0LCB2YWx1ZSkpXG4gICAgICAgICAgICAgIDogY29weVN5bWJvbHModmFsdWUsIGJhc2VBc3NpZ24ocmVzdWx0LCB2YWx1ZSkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoIWNsb25lYWJsZVRhZ3NbdGFnXSkge1xuICAgICAgICAgICAgcmV0dXJuIG9iamVjdCA/IHZhbHVlIDoge307XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc3VsdCA9IGluaXRDbG9uZUJ5VGFnKHZhbHVlLCB0YWcsIGJhc2VDbG9uZSwgaXNEZWVwKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gQ2hlY2sgZm9yIGNpcmN1bGFyIHJlZmVyZW5jZXMgYW5kIHJldHVybiBpdHMgY29ycmVzcG9uZGluZyBjbG9uZS5cbiAgICAgIHN0YWNrIHx8IChzdGFjayA9IG5ldyBTdGFjayk7XG4gICAgICB2YXIgc3RhY2tlZCA9IHN0YWNrLmdldCh2YWx1ZSk7XG4gICAgICBpZiAoc3RhY2tlZCkge1xuICAgICAgICByZXR1cm4gc3RhY2tlZDtcbiAgICAgIH1cbiAgICAgIHN0YWNrLnNldCh2YWx1ZSwgcmVzdWx0KTtcblxuICAgICAgdmFyIGtleXNGdW5jID0gaXNGdWxsXG4gICAgICAgID8gKGlzRmxhdCA/IGdldEFsbEtleXNJbiA6IGdldEFsbEtleXMpXG4gICAgICAgIDogKGlzRmxhdCA/IGtleXNJbiA6IGtleXMpO1xuXG4gICAgICB2YXIgcHJvcHMgPSBpc0FyciA/IHVuZGVmaW5lZCA6IGtleXNGdW5jKHZhbHVlKTtcbiAgICAgIGFycmF5RWFjaChwcm9wcyB8fCB2YWx1ZSwgZnVuY3Rpb24oc3ViVmFsdWUsIGtleSkge1xuICAgICAgICBpZiAocHJvcHMpIHtcbiAgICAgICAgICBrZXkgPSBzdWJWYWx1ZTtcbiAgICAgICAgICBzdWJWYWx1ZSA9IHZhbHVlW2tleV07XG4gICAgICAgIH1cbiAgICAgICAgLy8gUmVjdXJzaXZlbHkgcG9wdWxhdGUgY2xvbmUgKHN1c2NlcHRpYmxlIHRvIGNhbGwgc3RhY2sgbGltaXRzKS5cbiAgICAgICAgYXNzaWduVmFsdWUocmVzdWx0LCBrZXksIGJhc2VDbG9uZShzdWJWYWx1ZSwgYml0bWFzaywgY3VzdG9taXplciwga2V5LCB2YWx1ZSwgc3RhY2spKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5jb25mb3Jtc2Agd2hpY2ggZG9lc24ndCBjbG9uZSBgc291cmNlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IG9mIHByb3BlcnR5IHByZWRpY2F0ZXMgdG8gY29uZm9ybSB0by5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBzcGVjIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VDb25mb3Jtcyhzb3VyY2UpIHtcbiAgICAgIHZhciBwcm9wcyA9IGtleXMoc291cmNlKTtcbiAgICAgIHJldHVybiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgICAgcmV0dXJuIGJhc2VDb25mb3Jtc1RvKG9iamVjdCwgc291cmNlLCBwcm9wcyk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmNvbmZvcm1zVG9gIHdoaWNoIGFjY2VwdHMgYHByb3BzYCB0byBjaGVjay5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IG9mIHByb3BlcnR5IHByZWRpY2F0ZXMgdG8gY29uZm9ybSB0by5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYG9iamVjdGAgY29uZm9ybXMsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlQ29uZm9ybXNUbyhvYmplY3QsIHNvdXJjZSwgcHJvcHMpIHtcbiAgICAgIHZhciBsZW5ndGggPSBwcm9wcy5sZW5ndGg7XG4gICAgICBpZiAob2JqZWN0ID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuICFsZW5ndGg7XG4gICAgICB9XG4gICAgICBvYmplY3QgPSBPYmplY3Qob2JqZWN0KTtcbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICB2YXIga2V5ID0gcHJvcHNbbGVuZ3RoXSxcbiAgICAgICAgICAgIHByZWRpY2F0ZSA9IHNvdXJjZVtrZXldLFxuICAgICAgICAgICAgdmFsdWUgPSBvYmplY3Rba2V5XTtcblxuICAgICAgICBpZiAoKHZhbHVlID09PSB1bmRlZmluZWQgJiYgIShrZXkgaW4gb2JqZWN0KSkgfHwgIXByZWRpY2F0ZSh2YWx1ZSkpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmRlbGF5YCBhbmQgYF8uZGVmZXJgIHdoaWNoIGFjY2VwdHMgYGFyZ3NgXG4gICAgICogdG8gcHJvdmlkZSB0byBgZnVuY2AuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRlbGF5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB3YWl0IFRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIGRlbGF5IGludm9jYXRpb24uXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJncyBUaGUgYXJndW1lbnRzIHRvIHByb3ZpZGUgdG8gYGZ1bmNgLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ8T2JqZWN0fSBSZXR1cm5zIHRoZSB0aW1lciBpZCBvciB0aW1lb3V0IG9iamVjdC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlRGVsYXkoZnVuYywgd2FpdCwgYXJncykge1xuICAgICAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7IGZ1bmMuYXBwbHkodW5kZWZpbmVkLCBhcmdzKTsgfSwgd2FpdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgbWV0aG9kcyBsaWtlIGBfLmRpZmZlcmVuY2VgIHdpdGhvdXQgc3VwcG9ydFxuICAgICAqIGZvciBleGNsdWRpbmcgbXVsdGlwbGUgYXJyYXlzIG9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHZhbHVlcyBUaGUgdmFsdWVzIHRvIGV4Y2x1ZGUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlXSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY29tcGFyYXRvcl0gVGhlIGNvbXBhcmF0b3IgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBmaWx0ZXJlZCB2YWx1ZXMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZURpZmZlcmVuY2UoYXJyYXksIHZhbHVlcywgaXRlcmF0ZWUsIGNvbXBhcmF0b3IpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGluY2x1ZGVzID0gYXJyYXlJbmNsdWRlcyxcbiAgICAgICAgICBpc0NvbW1vbiA9IHRydWUsXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICAgIHJlc3VsdCA9IFtdLFxuICAgICAgICAgIHZhbHVlc0xlbmd0aCA9IHZhbHVlcy5sZW5ndGg7XG5cbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgICBpZiAoaXRlcmF0ZWUpIHtcbiAgICAgICAgdmFsdWVzID0gYXJyYXlNYXAodmFsdWVzLCBiYXNlVW5hcnkoaXRlcmF0ZWUpKTtcbiAgICAgIH1cbiAgICAgIGlmIChjb21wYXJhdG9yKSB7XG4gICAgICAgIGluY2x1ZGVzID0gYXJyYXlJbmNsdWRlc1dpdGg7XG4gICAgICAgIGlzQ29tbW9uID0gZmFsc2U7XG4gICAgICB9XG4gICAgICBlbHNlIGlmICh2YWx1ZXMubGVuZ3RoID49IExBUkdFX0FSUkFZX1NJWkUpIHtcbiAgICAgICAgaW5jbHVkZXMgPSBjYWNoZUhhcztcbiAgICAgICAgaXNDb21tb24gPSBmYWxzZTtcbiAgICAgICAgdmFsdWVzID0gbmV3IFNldENhY2hlKHZhbHVlcyk7XG4gICAgICB9XG4gICAgICBvdXRlcjpcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XSxcbiAgICAgICAgICAgIGNvbXB1dGVkID0gaXRlcmF0ZWUgPT0gbnVsbCA/IHZhbHVlIDogaXRlcmF0ZWUodmFsdWUpO1xuXG4gICAgICAgIHZhbHVlID0gKGNvbXBhcmF0b3IgfHwgdmFsdWUgIT09IDApID8gdmFsdWUgOiAwO1xuICAgICAgICBpZiAoaXNDb21tb24gJiYgY29tcHV0ZWQgPT09IGNvbXB1dGVkKSB7XG4gICAgICAgICAgdmFyIHZhbHVlc0luZGV4ID0gdmFsdWVzTGVuZ3RoO1xuICAgICAgICAgIHdoaWxlICh2YWx1ZXNJbmRleC0tKSB7XG4gICAgICAgICAgICBpZiAodmFsdWVzW3ZhbHVlc0luZGV4XSA9PT0gY29tcHV0ZWQpIHtcbiAgICAgICAgICAgICAgY29udGludWUgb3V0ZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc3VsdC5wdXNoKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICghaW5jbHVkZXModmFsdWVzLCBjb21wdXRlZCwgY29tcGFyYXRvcikpIHtcbiAgICAgICAgICByZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZm9yRWFjaGAgd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl8T2JqZWN0fSBSZXR1cm5zIGBjb2xsZWN0aW9uYC5cbiAgICAgKi9cbiAgICB2YXIgYmFzZUVhY2ggPSBjcmVhdGVCYXNlRWFjaChiYXNlRm9yT3duKTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmZvckVhY2hSaWdodGAgd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl8T2JqZWN0fSBSZXR1cm5zIGBjb2xsZWN0aW9uYC5cbiAgICAgKi9cbiAgICB2YXIgYmFzZUVhY2hSaWdodCA9IGNyZWF0ZUJhc2VFYWNoKGJhc2VGb3JPd25SaWdodCwgdHJ1ZSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5ldmVyeWAgd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZGljYXRlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFsbCBlbGVtZW50cyBwYXNzIHRoZSBwcmVkaWNhdGUgY2hlY2ssXG4gICAgICogIGVsc2UgYGZhbHNlYFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VFdmVyeShjb2xsZWN0aW9uLCBwcmVkaWNhdGUpIHtcbiAgICAgIHZhciByZXN1bHQgPSB0cnVlO1xuICAgICAgYmFzZUVhY2goY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgIHJlc3VsdCA9ICEhcHJlZGljYXRlKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbik7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgbWV0aG9kcyBsaWtlIGBfLm1heGAgYW5kIGBfLm1pbmAgd2hpY2ggYWNjZXB0cyBhXG4gICAgICogYGNvbXBhcmF0b3JgIHRvIGRldGVybWluZSB0aGUgZXh0cmVtdW0gdmFsdWUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjb21wYXJhdG9yIFRoZSBjb21wYXJhdG9yIHVzZWQgdG8gY29tcGFyZSB2YWx1ZXMuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGV4dHJlbXVtIHZhbHVlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VFeHRyZW11bShhcnJheSwgaXRlcmF0ZWUsIGNvbXBhcmF0b3IpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdLFxuICAgICAgICAgICAgY3VycmVudCA9IGl0ZXJhdGVlKHZhbHVlKTtcblxuICAgICAgICBpZiAoY3VycmVudCAhPSBudWxsICYmIChjb21wdXRlZCA9PT0gdW5kZWZpbmVkXG4gICAgICAgICAgICAgID8gKGN1cnJlbnQgPT09IGN1cnJlbnQgJiYgIWlzU3ltYm9sKGN1cnJlbnQpKVxuICAgICAgICAgICAgICA6IGNvbXBhcmF0b3IoY3VycmVudCwgY29tcHV0ZWQpXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgdmFyIGNvbXB1dGVkID0gY3VycmVudCxcbiAgICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZmlsbGAgd2l0aG91dCBhbiBpdGVyYXRlZSBjYWxsIGd1YXJkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gZmlsbC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBmaWxsIGBhcnJheWAgd2l0aC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0YXJ0PTBdIFRoZSBzdGFydCBwb3NpdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2VuZD1hcnJheS5sZW5ndGhdIFRoZSBlbmQgcG9zaXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUZpbGwoYXJyYXksIHZhbHVlLCBzdGFydCwgZW5kKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuXG4gICAgICBzdGFydCA9IHRvSW50ZWdlcihzdGFydCk7XG4gICAgICBpZiAoc3RhcnQgPCAwKSB7XG4gICAgICAgIHN0YXJ0ID0gLXN0YXJ0ID4gbGVuZ3RoID8gMCA6IChsZW5ndGggKyBzdGFydCk7XG4gICAgICB9XG4gICAgICBlbmQgPSAoZW5kID09PSB1bmRlZmluZWQgfHwgZW5kID4gbGVuZ3RoKSA/IGxlbmd0aCA6IHRvSW50ZWdlcihlbmQpO1xuICAgICAgaWYgKGVuZCA8IDApIHtcbiAgICAgICAgZW5kICs9IGxlbmd0aDtcbiAgICAgIH1cbiAgICAgIGVuZCA9IHN0YXJ0ID4gZW5kID8gMCA6IHRvTGVuZ3RoKGVuZCk7XG4gICAgICB3aGlsZSAoc3RhcnQgPCBlbmQpIHtcbiAgICAgICAgYXJyYXlbc3RhcnQrK10gPSB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhcnJheTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5maWx0ZXJgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGZpbHRlcmVkIGFycmF5LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VGaWx0ZXIoY29sbGVjdGlvbiwgcHJlZGljYXRlKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICBiYXNlRWFjaChjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgaWYgKHByZWRpY2F0ZSh2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pKSB7XG4gICAgICAgICAgcmVzdWx0LnB1c2godmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZmxhdHRlbmAgd2l0aCBzdXBwb3J0IGZvciByZXN0cmljdGluZyBmbGF0dGVuaW5nLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gZmxhdHRlbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gZGVwdGggVGhlIG1heGltdW0gcmVjdXJzaW9uIGRlcHRoLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW3ByZWRpY2F0ZT1pc0ZsYXR0ZW5hYmxlXSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzU3RyaWN0XSBSZXN0cmljdCB0byB2YWx1ZXMgdGhhdCBwYXNzIGBwcmVkaWNhdGVgIGNoZWNrcy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbcmVzdWx0PVtdXSBUaGUgaW5pdGlhbCByZXN1bHQgdmFsdWUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZmxhdHRlbmVkIGFycmF5LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VGbGF0dGVuKGFycmF5LCBkZXB0aCwgcHJlZGljYXRlLCBpc1N0cmljdCwgcmVzdWx0KSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgICAgIHByZWRpY2F0ZSB8fCAocHJlZGljYXRlID0gaXNGbGF0dGVuYWJsZSk7XG4gICAgICByZXN1bHQgfHwgKHJlc3VsdCA9IFtdKTtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdO1xuICAgICAgICBpZiAoZGVwdGggPiAwICYmIHByZWRpY2F0ZSh2YWx1ZSkpIHtcbiAgICAgICAgICBpZiAoZGVwdGggPiAxKSB7XG4gICAgICAgICAgICAvLyBSZWN1cnNpdmVseSBmbGF0dGVuIGFycmF5cyAoc3VzY2VwdGlibGUgdG8gY2FsbCBzdGFjayBsaW1pdHMpLlxuICAgICAgICAgICAgYmFzZUZsYXR0ZW4odmFsdWUsIGRlcHRoIC0gMSwgcHJlZGljYXRlLCBpc1N0cmljdCwgcmVzdWx0KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYXJyYXlQdXNoKHJlc3VsdCwgdmFsdWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICghaXNTdHJpY3QpIHtcbiAgICAgICAgICByZXN1bHRbcmVzdWx0Lmxlbmd0aF0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgYmFzZUZvck93bmAgd2hpY2ggaXRlcmF0ZXMgb3ZlciBgb2JqZWN0YFxuICAgICAqIHByb3BlcnRpZXMgcmV0dXJuZWQgYnkgYGtleXNGdW5jYCBhbmQgaW52b2tlcyBgaXRlcmF0ZWVgIGZvciBlYWNoIHByb3BlcnR5LlxuICAgICAqIEl0ZXJhdGVlIGZ1bmN0aW9ucyBtYXkgZXhpdCBpdGVyYXRpb24gZWFybHkgYnkgZXhwbGljaXRseSByZXR1cm5pbmcgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGtleXNGdW5jIFRoZSBmdW5jdGlvbiB0byBnZXQgdGhlIGtleXMgb2YgYG9iamVjdGAuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKi9cbiAgICB2YXIgYmFzZUZvciA9IGNyZWF0ZUJhc2VGb3IoKTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gaXMgbGlrZSBgYmFzZUZvcmAgZXhjZXB0IHRoYXQgaXQgaXRlcmF0ZXMgb3ZlciBwcm9wZXJ0aWVzXG4gICAgICogaW4gdGhlIG9wcG9zaXRlIG9yZGVyLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0ga2V5c0Z1bmMgVGhlIGZ1bmN0aW9uIHRvIGdldCB0aGUga2V5cyBvZiBgb2JqZWN0YC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqL1xuICAgIHZhciBiYXNlRm9yUmlnaHQgPSBjcmVhdGVCYXNlRm9yKHRydWUpO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZm9yT3duYCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VGb3JPd24ob2JqZWN0LCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIG9iamVjdCAmJiBiYXNlRm9yKG9iamVjdCwgaXRlcmF0ZWUsIGtleXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmZvck93blJpZ2h0YCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VGb3JPd25SaWdodChvYmplY3QsIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ICYmIGJhc2VGb3JSaWdodChvYmplY3QsIGl0ZXJhdGVlLCBrZXlzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5mdW5jdGlvbnNgIHdoaWNoIGNyZWF0ZXMgYW4gYXJyYXkgb2ZcbiAgICAgKiBgb2JqZWN0YCBmdW5jdGlvbiBwcm9wZXJ0eSBuYW1lcyBmaWx0ZXJlZCBmcm9tIGBwcm9wc2AuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHByb3BzIFRoZSBwcm9wZXJ0eSBuYW1lcyB0byBmaWx0ZXIuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBmdW5jdGlvbiBuYW1lcy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlRnVuY3Rpb25zKG9iamVjdCwgcHJvcHMpIHtcbiAgICAgIHJldHVybiBhcnJheUZpbHRlcihwcm9wcywgZnVuY3Rpb24oa2V5KSB7XG4gICAgICAgIHJldHVybiBpc0Z1bmN0aW9uKG9iamVjdFtrZXldKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmdldGAgd2l0aG91dCBzdXBwb3J0IGZvciBkZWZhdWx0IHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBnZXQuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJlc29sdmVkIHZhbHVlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VHZXQob2JqZWN0LCBwYXRoKSB7XG4gICAgICBwYXRoID0gY2FzdFBhdGgocGF0aCwgb2JqZWN0KTtcblxuICAgICAgdmFyIGluZGV4ID0gMCxcbiAgICAgICAgICBsZW5ndGggPSBwYXRoLmxlbmd0aDtcblxuICAgICAgd2hpbGUgKG9iamVjdCAhPSBudWxsICYmIGluZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIG9iamVjdCA9IG9iamVjdFt0b0tleShwYXRoW2luZGV4KytdKV07XG4gICAgICB9XG4gICAgICByZXR1cm4gKGluZGV4ICYmIGluZGV4ID09IGxlbmd0aCkgPyBvYmplY3QgOiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYGdldEFsbEtleXNgIGFuZCBgZ2V0QWxsS2V5c0luYCB3aGljaCB1c2VzXG4gICAgICogYGtleXNGdW5jYCBhbmQgYHN5bWJvbHNGdW5jYCB0byBnZXQgdGhlIGVudW1lcmFibGUgcHJvcGVydHkgbmFtZXMgYW5kXG4gICAgICogc3ltYm9scyBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGtleXNGdW5jIFRoZSBmdW5jdGlvbiB0byBnZXQgdGhlIGtleXMgb2YgYG9iamVjdGAuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gc3ltYm9sc0Z1bmMgVGhlIGZ1bmN0aW9uIHRvIGdldCB0aGUgc3ltYm9scyBvZiBgb2JqZWN0YC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzIGFuZCBzeW1ib2xzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VHZXRBbGxLZXlzKG9iamVjdCwga2V5c0Z1bmMsIHN5bWJvbHNGdW5jKSB7XG4gICAgICB2YXIgcmVzdWx0ID0ga2V5c0Z1bmMob2JqZWN0KTtcbiAgICAgIHJldHVybiBpc0FycmF5KG9iamVjdCkgPyByZXN1bHQgOiBhcnJheVB1c2gocmVzdWx0LCBzeW1ib2xzRnVuYyhvYmplY3QpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgZ2V0VGFnYCB3aXRob3V0IGZhbGxiYWNrcyBmb3IgYnVnZ3kgZW52aXJvbm1lbnRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBgdG9TdHJpbmdUYWdgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VHZXRUYWcodmFsdWUpIHtcbiAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gdW5kZWZpbmVkVGFnIDogbnVsbFRhZztcbiAgICAgIH1cbiAgICAgIHJldHVybiAoc3ltVG9TdHJpbmdUYWcgJiYgc3ltVG9TdHJpbmdUYWcgaW4gT2JqZWN0KHZhbHVlKSlcbiAgICAgICAgPyBnZXRSYXdUYWcodmFsdWUpXG4gICAgICAgIDogb2JqZWN0VG9TdHJpbmcodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmd0YCB3aGljaCBkb2Vzbid0IGNvZXJjZSBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBncmVhdGVyIHRoYW4gYG90aGVyYCxcbiAgICAgKiAgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VHdCh2YWx1ZSwgb3RoZXIpIHtcbiAgICAgIHJldHVybiB2YWx1ZSA+IG90aGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmhhc2Agd2l0aG91dCBzdXBwb3J0IGZvciBkZWVwIHBhdGhzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29iamVjdF0gVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30ga2V5IFRoZSBrZXkgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGBrZXlgIGV4aXN0cywgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VIYXMob2JqZWN0LCBrZXkpIHtcbiAgICAgIHJldHVybiBvYmplY3QgIT0gbnVsbCAmJiBoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5oYXNJbmAgd2l0aG91dCBzdXBwb3J0IGZvciBkZWVwIHBhdGhzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29iamVjdF0gVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30ga2V5IFRoZSBrZXkgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGBrZXlgIGV4aXN0cywgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VIYXNJbihvYmplY3QsIGtleSkge1xuICAgICAgcmV0dXJuIG9iamVjdCAhPSBudWxsICYmIGtleSBpbiBPYmplY3Qob2JqZWN0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pblJhbmdlYCB3aGljaCBkb2Vzbid0IGNvZXJjZSBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBudW1iZXIgVGhlIG51bWJlciB0byBjaGVjay5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gc3RhcnQgVGhlIHN0YXJ0IG9mIHRoZSByYW5nZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gZW5kIFRoZSBlbmQgb2YgdGhlIHJhbmdlLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgbnVtYmVyYCBpcyBpbiB0aGUgcmFuZ2UsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSW5SYW5nZShudW1iZXIsIHN0YXJ0LCBlbmQpIHtcbiAgICAgIHJldHVybiBudW1iZXIgPj0gbmF0aXZlTWluKHN0YXJ0LCBlbmQpICYmIG51bWJlciA8IG5hdGl2ZU1heChzdGFydCwgZW5kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBtZXRob2RzIGxpa2UgYF8uaW50ZXJzZWN0aW9uYCwgd2l0aG91dCBzdXBwb3J0XG4gICAgICogZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMsIHRoYXQgYWNjZXB0cyBhbiBhcnJheSBvZiBhcnJheXMgdG8gaW5zcGVjdC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXlzIFRoZSBhcnJheXMgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWVdIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJhdG9yXSBUaGUgY29tcGFyYXRvciBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIHNoYXJlZCB2YWx1ZXMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUludGVyc2VjdGlvbihhcnJheXMsIGl0ZXJhdGVlLCBjb21wYXJhdG9yKSB7XG4gICAgICB2YXIgaW5jbHVkZXMgPSBjb21wYXJhdG9yID8gYXJyYXlJbmNsdWRlc1dpdGggOiBhcnJheUluY2x1ZGVzLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5c1swXS5sZW5ndGgsXG4gICAgICAgICAgb3RoTGVuZ3RoID0gYXJyYXlzLmxlbmd0aCxcbiAgICAgICAgICBvdGhJbmRleCA9IG90aExlbmd0aCxcbiAgICAgICAgICBjYWNoZXMgPSBBcnJheShvdGhMZW5ndGgpLFxuICAgICAgICAgIG1heExlbmd0aCA9IEluZmluaXR5LFxuICAgICAgICAgIHJlc3VsdCA9IFtdO1xuXG4gICAgICB3aGlsZSAob3RoSW5kZXgtLSkge1xuICAgICAgICB2YXIgYXJyYXkgPSBhcnJheXNbb3RoSW5kZXhdO1xuICAgICAgICBpZiAob3RoSW5kZXggJiYgaXRlcmF0ZWUpIHtcbiAgICAgICAgICBhcnJheSA9IGFycmF5TWFwKGFycmF5LCBiYXNlVW5hcnkoaXRlcmF0ZWUpKTtcbiAgICAgICAgfVxuICAgICAgICBtYXhMZW5ndGggPSBuYXRpdmVNaW4oYXJyYXkubGVuZ3RoLCBtYXhMZW5ndGgpO1xuICAgICAgICBjYWNoZXNbb3RoSW5kZXhdID0gIWNvbXBhcmF0b3IgJiYgKGl0ZXJhdGVlIHx8IChsZW5ndGggPj0gMTIwICYmIGFycmF5Lmxlbmd0aCA+PSAxMjApKVxuICAgICAgICAgID8gbmV3IFNldENhY2hlKG90aEluZGV4ICYmIGFycmF5KVxuICAgICAgICAgIDogdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgYXJyYXkgPSBhcnJheXNbMF07XG5cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIHNlZW4gPSBjYWNoZXNbMF07XG5cbiAgICAgIG91dGVyOlxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGggJiYgcmVzdWx0Lmxlbmd0aCA8IG1heExlbmd0aCkge1xuICAgICAgICB2YXIgdmFsdWUgPSBhcnJheVtpbmRleF0sXG4gICAgICAgICAgICBjb21wdXRlZCA9IGl0ZXJhdGVlID8gaXRlcmF0ZWUodmFsdWUpIDogdmFsdWU7XG5cbiAgICAgICAgdmFsdWUgPSAoY29tcGFyYXRvciB8fCB2YWx1ZSAhPT0gMCkgPyB2YWx1ZSA6IDA7XG4gICAgICAgIGlmICghKHNlZW5cbiAgICAgICAgICAgICAgPyBjYWNoZUhhcyhzZWVuLCBjb21wdXRlZClcbiAgICAgICAgICAgICAgOiBpbmNsdWRlcyhyZXN1bHQsIGNvbXB1dGVkLCBjb21wYXJhdG9yKVxuICAgICAgICAgICAgKSkge1xuICAgICAgICAgIG90aEluZGV4ID0gb3RoTGVuZ3RoO1xuICAgICAgICAgIHdoaWxlICgtLW90aEluZGV4KSB7XG4gICAgICAgICAgICB2YXIgY2FjaGUgPSBjYWNoZXNbb3RoSW5kZXhdO1xuICAgICAgICAgICAgaWYgKCEoY2FjaGVcbiAgICAgICAgICAgICAgICAgID8gY2FjaGVIYXMoY2FjaGUsIGNvbXB1dGVkKVxuICAgICAgICAgICAgICAgICAgOiBpbmNsdWRlcyhhcnJheXNbb3RoSW5kZXhdLCBjb21wdXRlZCwgY29tcGFyYXRvcikpXG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlIG91dGVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoc2Vlbikge1xuICAgICAgICAgICAgc2Vlbi5wdXNoKGNvbXB1dGVkKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzdWx0LnB1c2godmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmludmVydGAgYW5kIGBfLmludmVydEJ5YCB3aGljaCBpbnZlcnRzXG4gICAgICogYG9iamVjdGAgd2l0aCB2YWx1ZXMgdHJhbnNmb3JtZWQgYnkgYGl0ZXJhdGVlYCBhbmQgc2V0IGJ5IGBzZXR0ZXJgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHNldHRlciBUaGUgZnVuY3Rpb24gdG8gc2V0IGBhY2N1bXVsYXRvcmAgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBpdGVyYXRlZSB0byB0cmFuc2Zvcm0gdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBhY2N1bXVsYXRvciBUaGUgaW5pdGlhbCBpbnZlcnRlZCBvYmplY3QuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIGBhY2N1bXVsYXRvcmAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUludmVydGVyKG9iamVjdCwgc2V0dGVyLCBpdGVyYXRlZSwgYWNjdW11bGF0b3IpIHtcbiAgICAgIGJhc2VGb3JPd24ob2JqZWN0LCBmdW5jdGlvbih2YWx1ZSwga2V5LCBvYmplY3QpIHtcbiAgICAgICAgc2V0dGVyKGFjY3VtdWxhdG9yLCBpdGVyYXRlZSh2YWx1ZSksIGtleSwgb2JqZWN0KTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmludm9rZWAgd2l0aG91dCBzdXBwb3J0IGZvciBpbmRpdmlkdWFsXG4gICAgICogbWV0aG9kIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBtZXRob2QgdG8gaW52b2tlLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFyZ3MgVGhlIGFyZ3VtZW50cyB0byBpbnZva2UgdGhlIG1ldGhvZCB3aXRoLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSByZXN1bHQgb2YgdGhlIGludm9rZWQgbWV0aG9kLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VJbnZva2Uob2JqZWN0LCBwYXRoLCBhcmdzKSB7XG4gICAgICBwYXRoID0gY2FzdFBhdGgocGF0aCwgb2JqZWN0KTtcbiAgICAgIG9iamVjdCA9IHBhcmVudChvYmplY3QsIHBhdGgpO1xuICAgICAgdmFyIGZ1bmMgPSBvYmplY3QgPT0gbnVsbCA/IG9iamVjdCA6IG9iamVjdFt0b0tleShsYXN0KHBhdGgpKV07XG4gICAgICByZXR1cm4gZnVuYyA9PSBudWxsID8gdW5kZWZpbmVkIDogYXBwbHkoZnVuYywgb2JqZWN0LCBhcmdzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pc0FyZ3VtZW50c2AuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFuIGBhcmd1bWVudHNgIG9iamVjdCxcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSXNBcmd1bWVudHModmFsdWUpIHtcbiAgICAgIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmIGJhc2VHZXRUYWcodmFsdWUpID09IGFyZ3NUYWc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNBcnJheUJ1ZmZlcmAgd2l0aG91dCBOb2RlLmpzIG9wdGltaXphdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFuIGFycmF5IGJ1ZmZlciwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VJc0FycmF5QnVmZmVyKHZhbHVlKSB7XG4gICAgICByZXR1cm4gaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBiYXNlR2V0VGFnKHZhbHVlKSA9PSBhcnJheUJ1ZmZlclRhZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pc0RhdGVgIHdpdGhvdXQgTm9kZS5qcyBvcHRpbWl6YXRpb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIGRhdGUgb2JqZWN0LCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUlzRGF0ZSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgYmFzZUdldFRhZyh2YWx1ZSkgPT0gZGF0ZVRhZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pc0VxdWFsYCB3aGljaCBzdXBwb3J0cyBwYXJ0aWFsIGNvbXBhcmlzb25zXG4gICAgICogYW5kIHRyYWNrcyB0cmF2ZXJzZWQgb2JqZWN0cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0geyp9IG90aGVyIFRoZSBvdGhlciB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy5cbiAgICAgKiAgMSAtIFVub3JkZXJlZCBjb21wYXJpc29uXG4gICAgICogIDIgLSBQYXJ0aWFsIGNvbXBhcmlzb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb21wYXJpc29ucy5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW3N0YWNrXSBUcmFja3MgdHJhdmVyc2VkIGB2YWx1ZWAgYW5kIGBvdGhlcmAgb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHZhbHVlcyBhcmUgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VJc0VxdWFsKHZhbHVlLCBvdGhlciwgYml0bWFzaywgY3VzdG9taXplciwgc3RhY2spIHtcbiAgICAgIGlmICh2YWx1ZSA9PT0gb3RoZXIpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgICBpZiAodmFsdWUgPT0gbnVsbCB8fCBvdGhlciA9PSBudWxsIHx8ICghaXNPYmplY3RMaWtlKHZhbHVlKSAmJiAhaXNPYmplY3RMaWtlKG90aGVyKSkpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlICE9PSB2YWx1ZSAmJiBvdGhlciAhPT0gb3RoZXI7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZUlzRXF1YWxEZWVwKHZhbHVlLCBvdGhlciwgYml0bWFzaywgY3VzdG9taXplciwgYmFzZUlzRXF1YWwsIHN0YWNrKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYGJhc2VJc0VxdWFsYCBmb3IgYXJyYXlzIGFuZCBvYmplY3RzIHdoaWNoIHBlcmZvcm1zXG4gICAgICogZGVlcCBjb21wYXJpc29ucyBhbmQgdHJhY2tzIHRyYXZlcnNlZCBvYmplY3RzIGVuYWJsaW5nIG9iamVjdHMgd2l0aCBjaXJjdWxhclxuICAgICAqIHJlZmVyZW5jZXMgdG8gYmUgY29tcGFyZWQuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvdGhlciBUaGUgb3RoZXIgb2JqZWN0IHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGJpdG1hc2sgVGhlIGJpdG1hc2sgZmxhZ3MuIFNlZSBgYmFzZUlzRXF1YWxgIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gY3VzdG9taXplciBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNvbXBhcmlzb25zLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGVxdWFsRnVuYyBUaGUgZnVuY3Rpb24gdG8gZGV0ZXJtaW5lIGVxdWl2YWxlbnRzIG9mIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW3N0YWNrXSBUcmFja3MgdHJhdmVyc2VkIGBvYmplY3RgIGFuZCBgb3RoZXJgIG9iamVjdHMuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBvYmplY3RzIGFyZSBlcXVpdmFsZW50LCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUlzRXF1YWxEZWVwKG9iamVjdCwgb3RoZXIsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIGVxdWFsRnVuYywgc3RhY2spIHtcbiAgICAgIHZhciBvYmpJc0FyciA9IGlzQXJyYXkob2JqZWN0KSxcbiAgICAgICAgICBvdGhJc0FyciA9IGlzQXJyYXkob3RoZXIpLFxuICAgICAgICAgIG9ialRhZyA9IG9iaklzQXJyID8gYXJyYXlUYWcgOiBnZXRUYWcob2JqZWN0KSxcbiAgICAgICAgICBvdGhUYWcgPSBvdGhJc0FyciA/IGFycmF5VGFnIDogZ2V0VGFnKG90aGVyKTtcblxuICAgICAgb2JqVGFnID0gb2JqVGFnID09IGFyZ3NUYWcgPyBvYmplY3RUYWcgOiBvYmpUYWc7XG4gICAgICBvdGhUYWcgPSBvdGhUYWcgPT0gYXJnc1RhZyA/IG9iamVjdFRhZyA6IG90aFRhZztcblxuICAgICAgdmFyIG9iaklzT2JqID0gb2JqVGFnID09IG9iamVjdFRhZyxcbiAgICAgICAgICBvdGhJc09iaiA9IG90aFRhZyA9PSBvYmplY3RUYWcsXG4gICAgICAgICAgaXNTYW1lVGFnID0gb2JqVGFnID09IG90aFRhZztcblxuICAgICAgaWYgKGlzU2FtZVRhZyAmJiBpc0J1ZmZlcihvYmplY3QpKSB7XG4gICAgICAgIGlmICghaXNCdWZmZXIob3RoZXIpKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIG9iaklzQXJyID0gdHJ1ZTtcbiAgICAgICAgb2JqSXNPYmogPSBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGlmIChpc1NhbWVUYWcgJiYgIW9iaklzT2JqKSB7XG4gICAgICAgIHN0YWNrIHx8IChzdGFjayA9IG5ldyBTdGFjayk7XG4gICAgICAgIHJldHVybiAob2JqSXNBcnIgfHwgaXNUeXBlZEFycmF5KG9iamVjdCkpXG4gICAgICAgICAgPyBlcXVhbEFycmF5cyhvYmplY3QsIG90aGVyLCBiaXRtYXNrLCBjdXN0b21pemVyLCBlcXVhbEZ1bmMsIHN0YWNrKVxuICAgICAgICAgIDogZXF1YWxCeVRhZyhvYmplY3QsIG90aGVyLCBvYmpUYWcsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIGVxdWFsRnVuYywgc3RhY2spO1xuICAgICAgfVxuICAgICAgaWYgKCEoYml0bWFzayAmIENPTVBBUkVfUEFSVElBTF9GTEFHKSkge1xuICAgICAgICB2YXIgb2JqSXNXcmFwcGVkID0gb2JqSXNPYmogJiYgaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsICdfX3dyYXBwZWRfXycpLFxuICAgICAgICAgICAgb3RoSXNXcmFwcGVkID0gb3RoSXNPYmogJiYgaGFzT3duUHJvcGVydHkuY2FsbChvdGhlciwgJ19fd3JhcHBlZF9fJyk7XG5cbiAgICAgICAgaWYgKG9iaklzV3JhcHBlZCB8fCBvdGhJc1dyYXBwZWQpIHtcbiAgICAgICAgICB2YXIgb2JqVW53cmFwcGVkID0gb2JqSXNXcmFwcGVkID8gb2JqZWN0LnZhbHVlKCkgOiBvYmplY3QsXG4gICAgICAgICAgICAgIG90aFVud3JhcHBlZCA9IG90aElzV3JhcHBlZCA/IG90aGVyLnZhbHVlKCkgOiBvdGhlcjtcblxuICAgICAgICAgIHN0YWNrIHx8IChzdGFjayA9IG5ldyBTdGFjayk7XG4gICAgICAgICAgcmV0dXJuIGVxdWFsRnVuYyhvYmpVbndyYXBwZWQsIG90aFVud3JhcHBlZCwgYml0bWFzaywgY3VzdG9taXplciwgc3RhY2spO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoIWlzU2FtZVRhZykge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBzdGFjayB8fCAoc3RhY2sgPSBuZXcgU3RhY2spO1xuICAgICAgcmV0dXJuIGVxdWFsT2JqZWN0cyhvYmplY3QsIG90aGVyLCBiaXRtYXNrLCBjdXN0b21pemVyLCBlcXVhbEZ1bmMsIHN0YWNrKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pc01hcGAgd2l0aG91dCBOb2RlLmpzIG9wdGltaXphdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgbWFwLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUlzTWFwKHZhbHVlKSB7XG4gICAgICByZXR1cm4gaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBnZXRUYWcodmFsdWUpID09IG1hcFRhZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pc01hdGNoYCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCBvZiBwcm9wZXJ0eSB2YWx1ZXMgdG8gbWF0Y2guXG4gICAgICogQHBhcmFtIHtBcnJheX0gbWF0Y2hEYXRhIFRoZSBwcm9wZXJ0eSBuYW1lcywgdmFsdWVzLCBhbmQgY29tcGFyZSBmbGFncyB0byBtYXRjaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb21wYXJpc29ucy5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYG9iamVjdGAgaXMgYSBtYXRjaCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VJc01hdGNoKG9iamVjdCwgc291cmNlLCBtYXRjaERhdGEsIGN1c3RvbWl6ZXIpIHtcbiAgICAgIHZhciBpbmRleCA9IG1hdGNoRGF0YS5sZW5ndGgsXG4gICAgICAgICAgbGVuZ3RoID0gaW5kZXgsXG4gICAgICAgICAgbm9DdXN0b21pemVyID0gIWN1c3RvbWl6ZXI7XG5cbiAgICAgIGlmIChvYmplY3QgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gIWxlbmd0aDtcbiAgICAgIH1cbiAgICAgIG9iamVjdCA9IE9iamVjdChvYmplY3QpO1xuICAgICAgd2hpbGUgKGluZGV4LS0pIHtcbiAgICAgICAgdmFyIGRhdGEgPSBtYXRjaERhdGFbaW5kZXhdO1xuICAgICAgICBpZiAoKG5vQ3VzdG9taXplciAmJiBkYXRhWzJdKVxuICAgICAgICAgICAgICA/IGRhdGFbMV0gIT09IG9iamVjdFtkYXRhWzBdXVxuICAgICAgICAgICAgICA6ICEoZGF0YVswXSBpbiBvYmplY3QpXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIGRhdGEgPSBtYXRjaERhdGFbaW5kZXhdO1xuICAgICAgICB2YXIga2V5ID0gZGF0YVswXSxcbiAgICAgICAgICAgIG9ialZhbHVlID0gb2JqZWN0W2tleV0sXG4gICAgICAgICAgICBzcmNWYWx1ZSA9IGRhdGFbMV07XG5cbiAgICAgICAgaWYgKG5vQ3VzdG9taXplciAmJiBkYXRhWzJdKSB7XG4gICAgICAgICAgaWYgKG9ialZhbHVlID09PSB1bmRlZmluZWQgJiYgIShrZXkgaW4gb2JqZWN0KSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2YXIgc3RhY2sgPSBuZXcgU3RhY2s7XG4gICAgICAgICAgaWYgKGN1c3RvbWl6ZXIpIHtcbiAgICAgICAgICAgIHZhciByZXN1bHQgPSBjdXN0b21pemVyKG9ialZhbHVlLCBzcmNWYWx1ZSwga2V5LCBvYmplY3QsIHNvdXJjZSwgc3RhY2spO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIShyZXN1bHQgPT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgID8gYmFzZUlzRXF1YWwoc3JjVmFsdWUsIG9ialZhbHVlLCBDT01QQVJFX1BBUlRJQUxfRkxBRyB8IENPTVBBUkVfVU5PUkRFUkVEX0ZMQUcsIGN1c3RvbWl6ZXIsIHN0YWNrKVxuICAgICAgICAgICAgICAgIDogcmVzdWx0XG4gICAgICAgICAgICAgICkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmlzTmF0aXZlYCB3aXRob3V0IGJhZCBzaGltIGNoZWNrcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBuYXRpdmUgZnVuY3Rpb24sXG4gICAgICogIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlSXNOYXRpdmUodmFsdWUpIHtcbiAgICAgIGlmICghaXNPYmplY3QodmFsdWUpIHx8IGlzTWFza2VkKHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICB2YXIgcGF0dGVybiA9IGlzRnVuY3Rpb24odmFsdWUpID8gcmVJc05hdGl2ZSA6IHJlSXNIb3N0Q3RvcjtcbiAgICAgIHJldHVybiBwYXR0ZXJuLnRlc3QodG9Tb3VyY2UodmFsdWUpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pc1JlZ0V4cGAgd2l0aG91dCBOb2RlLmpzIG9wdGltaXphdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgcmVnZXhwLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUlzUmVnRXhwKHZhbHVlKSB7XG4gICAgICByZXR1cm4gaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBiYXNlR2V0VGFnKHZhbHVlKSA9PSByZWdleHBUYWc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNTZXRgIHdpdGhvdXQgTm9kZS5qcyBvcHRpbWl6YXRpb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHNldCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VJc1NldCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgZ2V0VGFnKHZhbHVlKSA9PSBzZXRUYWc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNUeXBlZEFycmF5YCB3aXRob3V0IE5vZGUuanMgb3B0aW1pemF0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSB0eXBlZCBhcnJheSwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VJc1R5cGVkQXJyYXkodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmXG4gICAgICAgIGlzTGVuZ3RoKHZhbHVlLmxlbmd0aCkgJiYgISF0eXBlZEFycmF5VGFnc1tiYXNlR2V0VGFnKHZhbHVlKV07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXRlcmF0ZWVgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IFt2YWx1ZT1fLmlkZW50aXR5XSBUaGUgdmFsdWUgdG8gY29udmVydCB0byBhbiBpdGVyYXRlZS5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIGl0ZXJhdGVlLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VJdGVyYXRlZSh2YWx1ZSkge1xuICAgICAgLy8gRG9uJ3Qgc3RvcmUgdGhlIGB0eXBlb2ZgIHJlc3VsdCBpbiBhIHZhcmlhYmxlIHRvIGF2b2lkIGEgSklUIGJ1ZyBpbiBTYWZhcmkgOS5cbiAgICAgIC8vIFNlZSBodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTU2MDM0IGZvciBtb3JlIGRldGFpbHMuXG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfVxuICAgICAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIGlkZW50aXR5O1xuICAgICAgfVxuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PSAnb2JqZWN0Jykge1xuICAgICAgICByZXR1cm4gaXNBcnJheSh2YWx1ZSlcbiAgICAgICAgICA/IGJhc2VNYXRjaGVzUHJvcGVydHkodmFsdWVbMF0sIHZhbHVlWzFdKVxuICAgICAgICAgIDogYmFzZU1hdGNoZXModmFsdWUpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHByb3BlcnR5KHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5rZXlzYCB3aGljaCBkb2Vzbid0IHRyZWF0IHNwYXJzZSBhcnJheXMgYXMgZGVuc2UuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VLZXlzKG9iamVjdCkge1xuICAgICAgaWYgKCFpc1Byb3RvdHlwZShvYmplY3QpKSB7XG4gICAgICAgIHJldHVybiBuYXRpdmVLZXlzKG9iamVjdCk7XG4gICAgICB9XG4gICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICBmb3IgKHZhciBrZXkgaW4gT2JqZWN0KG9iamVjdCkpIHtcbiAgICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpICYmIGtleSAhPSAnY29uc3RydWN0b3InKSB7XG4gICAgICAgICAgcmVzdWx0LnB1c2goa2V5KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5rZXlzSW5gIHdoaWNoIGRvZXNuJ3QgdHJlYXQgc3BhcnNlIGFycmF5cyBhcyBkZW5zZS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZUtleXNJbihvYmplY3QpIHtcbiAgICAgIGlmICghaXNPYmplY3Qob2JqZWN0KSkge1xuICAgICAgICByZXR1cm4gbmF0aXZlS2V5c0luKG9iamVjdCk7XG4gICAgICB9XG4gICAgICB2YXIgaXNQcm90byA9IGlzUHJvdG90eXBlKG9iamVjdCksXG4gICAgICAgICAgcmVzdWx0ID0gW107XG5cbiAgICAgIGZvciAodmFyIGtleSBpbiBvYmplY3QpIHtcbiAgICAgICAgaWYgKCEoa2V5ID09ICdjb25zdHJ1Y3RvcicgJiYgKGlzUHJvdG8gfHwgIWhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpKSkpIHtcbiAgICAgICAgICByZXN1bHQucHVzaChrZXkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmx0YCB3aGljaCBkb2Vzbid0IGNvZXJjZSBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBsZXNzIHRoYW4gYG90aGVyYCxcbiAgICAgKiAgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VMdCh2YWx1ZSwgb3RoZXIpIHtcbiAgICAgIHJldHVybiB2YWx1ZSA8IG90aGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLm1hcGAgd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBtYXBwZWQgYXJyYXkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZU1hcChjb2xsZWN0aW9uLCBpdGVyYXRlZSkge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgcmVzdWx0ID0gaXNBcnJheUxpa2UoY29sbGVjdGlvbikgPyBBcnJheShjb2xsZWN0aW9uLmxlbmd0aCkgOiBbXTtcblxuICAgICAgYmFzZUVhY2goY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGtleSwgY29sbGVjdGlvbikge1xuICAgICAgICByZXN1bHRbKytpbmRleF0gPSBpdGVyYXRlZSh2YWx1ZSwga2V5LCBjb2xsZWN0aW9uKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5tYXRjaGVzYCB3aGljaCBkb2Vzbid0IGNsb25lIGBzb3VyY2VgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBvYmplY3Qgb2YgcHJvcGVydHkgdmFsdWVzIHRvIG1hdGNoLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHNwZWMgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZU1hdGNoZXMoc291cmNlKSB7XG4gICAgICB2YXIgbWF0Y2hEYXRhID0gZ2V0TWF0Y2hEYXRhKHNvdXJjZSk7XG4gICAgICBpZiAobWF0Y2hEYXRhLmxlbmd0aCA9PSAxICYmIG1hdGNoRGF0YVswXVsyXSkge1xuICAgICAgICByZXR1cm4gbWF0Y2hlc1N0cmljdENvbXBhcmFibGUobWF0Y2hEYXRhWzBdWzBdLCBtYXRjaERhdGFbMF1bMV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgICByZXR1cm4gb2JqZWN0ID09PSBzb3VyY2UgfHwgYmFzZUlzTWF0Y2gob2JqZWN0LCBzb3VyY2UsIG1hdGNoRGF0YSk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLm1hdGNoZXNQcm9wZXJ0eWAgd2hpY2ggZG9lc24ndCBjbG9uZSBgc3JjVmFsdWVgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICAgICAqIEBwYXJhbSB7Kn0gc3JjVmFsdWUgVGhlIHZhbHVlIHRvIG1hdGNoLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHNwZWMgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZU1hdGNoZXNQcm9wZXJ0eShwYXRoLCBzcmNWYWx1ZSkge1xuICAgICAgaWYgKGlzS2V5KHBhdGgpICYmIGlzU3RyaWN0Q29tcGFyYWJsZShzcmNWYWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIG1hdGNoZXNTdHJpY3RDb21wYXJhYmxlKHRvS2V5KHBhdGgpLCBzcmNWYWx1ZSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICAgIHZhciBvYmpWYWx1ZSA9IGdldChvYmplY3QsIHBhdGgpO1xuICAgICAgICByZXR1cm4gKG9ialZhbHVlID09PSB1bmRlZmluZWQgJiYgb2JqVmFsdWUgPT09IHNyY1ZhbHVlKVxuICAgICAgICAgID8gaGFzSW4ob2JqZWN0LCBwYXRoKVxuICAgICAgICAgIDogYmFzZUlzRXF1YWwoc3JjVmFsdWUsIG9ialZhbHVlLCBDT01QQVJFX1BBUlRJQUxfRkxBRyB8IENPTVBBUkVfVU5PUkRFUkVEX0ZMQUcpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5tZXJnZWAgd2l0aG91dCBzdXBwb3J0IGZvciBtdWx0aXBsZSBzb3VyY2VzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gc3JjSW5kZXggVGhlIGluZGV4IG9mIGBzb3VyY2VgLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIG1lcmdlZCB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtzdGFja10gVHJhY2tzIHRyYXZlcnNlZCBzb3VyY2UgdmFsdWVzIGFuZCB0aGVpciBtZXJnZWRcbiAgICAgKiAgY291bnRlcnBhcnRzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VNZXJnZShvYmplY3QsIHNvdXJjZSwgc3JjSW5kZXgsIGN1c3RvbWl6ZXIsIHN0YWNrKSB7XG4gICAgICBpZiAob2JqZWN0ID09PSBzb3VyY2UpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgYmFzZUZvcihzb3VyY2UsIGZ1bmN0aW9uKHNyY1ZhbHVlLCBrZXkpIHtcbiAgICAgICAgaWYgKGlzT2JqZWN0KHNyY1ZhbHVlKSkge1xuICAgICAgICAgIHN0YWNrIHx8IChzdGFjayA9IG5ldyBTdGFjayk7XG4gICAgICAgICAgYmFzZU1lcmdlRGVlcChvYmplY3QsIHNvdXJjZSwga2V5LCBzcmNJbmRleCwgYmFzZU1lcmdlLCBjdXN0b21pemVyLCBzdGFjayk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgdmFyIG5ld1ZhbHVlID0gY3VzdG9taXplclxuICAgICAgICAgICAgPyBjdXN0b21pemVyKG9iamVjdFtrZXldLCBzcmNWYWx1ZSwgKGtleSArICcnKSwgb2JqZWN0LCBzb3VyY2UsIHN0YWNrKVxuICAgICAgICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICBpZiAobmV3VmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgbmV3VmFsdWUgPSBzcmNWYWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYXNzaWduTWVyZ2VWYWx1ZShvYmplY3QsIGtleSwgbmV3VmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9LCBrZXlzSW4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZU1lcmdlYCBmb3IgYXJyYXlzIGFuZCBvYmplY3RzIHdoaWNoIHBlcmZvcm1zXG4gICAgICogZGVlcCBtZXJnZXMgYW5kIHRyYWNrcyB0cmF2ZXJzZWQgb2JqZWN0cyBlbmFibGluZyBvYmplY3RzIHdpdGggY2lyY3VsYXJcbiAgICAgKiByZWZlcmVuY2VzIHRvIGJlIG1lcmdlZC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIHNvdXJjZSBvYmplY3QuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBtZXJnZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gc3JjSW5kZXggVGhlIGluZGV4IG9mIGBzb3VyY2VgLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IG1lcmdlRnVuYyBUaGUgZnVuY3Rpb24gdG8gbWVyZ2UgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGFzc2lnbmVkIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW3N0YWNrXSBUcmFja3MgdHJhdmVyc2VkIHNvdXJjZSB2YWx1ZXMgYW5kIHRoZWlyIG1lcmdlZFxuICAgICAqICBjb3VudGVycGFydHMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZU1lcmdlRGVlcChvYmplY3QsIHNvdXJjZSwga2V5LCBzcmNJbmRleCwgbWVyZ2VGdW5jLCBjdXN0b21pemVyLCBzdGFjaykge1xuICAgICAgdmFyIG9ialZhbHVlID0gb2JqZWN0W2tleV0sXG4gICAgICAgICAgc3JjVmFsdWUgPSBzb3VyY2Vba2V5XSxcbiAgICAgICAgICBzdGFja2VkID0gc3RhY2suZ2V0KHNyY1ZhbHVlKTtcblxuICAgICAgaWYgKHN0YWNrZWQpIHtcbiAgICAgICAgYXNzaWduTWVyZ2VWYWx1ZShvYmplY3QsIGtleSwgc3RhY2tlZCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHZhciBuZXdWYWx1ZSA9IGN1c3RvbWl6ZXJcbiAgICAgICAgPyBjdXN0b21pemVyKG9ialZhbHVlLCBzcmNWYWx1ZSwgKGtleSArICcnKSwgb2JqZWN0LCBzb3VyY2UsIHN0YWNrKVxuICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgICAgdmFyIGlzQ29tbW9uID0gbmV3VmFsdWUgPT09IHVuZGVmaW5lZDtcblxuICAgICAgaWYgKGlzQ29tbW9uKSB7XG4gICAgICAgIHZhciBpc0FyciA9IGlzQXJyYXkoc3JjVmFsdWUpLFxuICAgICAgICAgICAgaXNCdWZmID0gIWlzQXJyICYmIGlzQnVmZmVyKHNyY1ZhbHVlKSxcbiAgICAgICAgICAgIGlzVHlwZWQgPSAhaXNBcnIgJiYgIWlzQnVmZiAmJiBpc1R5cGVkQXJyYXkoc3JjVmFsdWUpO1xuXG4gICAgICAgIG5ld1ZhbHVlID0gc3JjVmFsdWU7XG4gICAgICAgIGlmIChpc0FyciB8fCBpc0J1ZmYgfHwgaXNUeXBlZCkge1xuICAgICAgICAgIGlmIChpc0FycmF5KG9ialZhbHVlKSkge1xuICAgICAgICAgICAgbmV3VmFsdWUgPSBvYmpWYWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSBpZiAoaXNBcnJheUxpa2VPYmplY3Qob2JqVmFsdWUpKSB7XG4gICAgICAgICAgICBuZXdWYWx1ZSA9IGNvcHlBcnJheShvYmpWYWx1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsc2UgaWYgKGlzQnVmZikge1xuICAgICAgICAgICAgaXNDb21tb24gPSBmYWxzZTtcbiAgICAgICAgICAgIG5ld1ZhbHVlID0gY2xvbmVCdWZmZXIoc3JjVmFsdWUsIHRydWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIGlmIChpc1R5cGVkKSB7XG4gICAgICAgICAgICBpc0NvbW1vbiA9IGZhbHNlO1xuICAgICAgICAgICAgbmV3VmFsdWUgPSBjbG9uZVR5cGVkQXJyYXkoc3JjVmFsdWUsIHRydWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIG5ld1ZhbHVlID0gW107XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGlzUGxhaW5PYmplY3Qoc3JjVmFsdWUpIHx8IGlzQXJndW1lbnRzKHNyY1ZhbHVlKSkge1xuICAgICAgICAgIG5ld1ZhbHVlID0gb2JqVmFsdWU7XG4gICAgICAgICAgaWYgKGlzQXJndW1lbnRzKG9ialZhbHVlKSkge1xuICAgICAgICAgICAgbmV3VmFsdWUgPSB0b1BsYWluT2JqZWN0KG9ialZhbHVlKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSBpZiAoIWlzT2JqZWN0KG9ialZhbHVlKSB8fCAoc3JjSW5kZXggJiYgaXNGdW5jdGlvbihvYmpWYWx1ZSkpKSB7XG4gICAgICAgICAgICBuZXdWYWx1ZSA9IGluaXRDbG9uZU9iamVjdChzcmNWYWx1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGlzQ29tbW9uID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChpc0NvbW1vbikge1xuICAgICAgICAvLyBSZWN1cnNpdmVseSBtZXJnZSBvYmplY3RzIGFuZCBhcnJheXMgKHN1c2NlcHRpYmxlIHRvIGNhbGwgc3RhY2sgbGltaXRzKS5cbiAgICAgICAgc3RhY2suc2V0KHNyY1ZhbHVlLCBuZXdWYWx1ZSk7XG4gICAgICAgIG1lcmdlRnVuYyhuZXdWYWx1ZSwgc3JjVmFsdWUsIHNyY0luZGV4LCBjdXN0b21pemVyLCBzdGFjayk7XG4gICAgICAgIHN0YWNrWydkZWxldGUnXShzcmNWYWx1ZSk7XG4gICAgICB9XG4gICAgICBhc3NpZ25NZXJnZVZhbHVlKG9iamVjdCwga2V5LCBuZXdWYWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ubnRoYCB3aGljaCBkb2Vzbid0IGNvZXJjZSBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbiBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBudGggZWxlbWVudCBvZiBgYXJyYXlgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VOdGgoYXJyYXksIG4pIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBuICs9IG4gPCAwID8gbGVuZ3RoIDogMDtcbiAgICAgIHJldHVybiBpc0luZGV4KG4sIGxlbmd0aCkgPyBhcnJheVtuXSA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5vcmRlckJ5YCB3aXRob3V0IHBhcmFtIGd1YXJkcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXXxPYmplY3RbXXxzdHJpbmdbXX0gaXRlcmF0ZWVzIFRoZSBpdGVyYXRlZXMgdG8gc29ydCBieS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBvcmRlcnMgVGhlIHNvcnQgb3JkZXJzIG9mIGBpdGVyYXRlZXNgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IHNvcnRlZCBhcnJheS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlT3JkZXJCeShjb2xsZWN0aW9uLCBpdGVyYXRlZXMsIG9yZGVycykge1xuICAgICAgdmFyIGluZGV4ID0gLTE7XG4gICAgICBpdGVyYXRlZXMgPSBhcnJheU1hcChpdGVyYXRlZXMubGVuZ3RoID8gaXRlcmF0ZWVzIDogW2lkZW50aXR5XSwgYmFzZVVuYXJ5KGdldEl0ZXJhdGVlKCkpKTtcblxuICAgICAgdmFyIHJlc3VsdCA9IGJhc2VNYXAoY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGtleSwgY29sbGVjdGlvbikge1xuICAgICAgICB2YXIgY3JpdGVyaWEgPSBhcnJheU1hcChpdGVyYXRlZXMsIGZ1bmN0aW9uKGl0ZXJhdGVlKSB7XG4gICAgICAgICAgcmV0dXJuIGl0ZXJhdGVlKHZhbHVlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB7ICdjcml0ZXJpYSc6IGNyaXRlcmlhLCAnaW5kZXgnOiArK2luZGV4LCAndmFsdWUnOiB2YWx1ZSB9O1xuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiBiYXNlU29ydEJ5KHJlc3VsdCwgZnVuY3Rpb24ob2JqZWN0LCBvdGhlcikge1xuICAgICAgICByZXR1cm4gY29tcGFyZU11bHRpcGxlKG9iamVjdCwgb3RoZXIsIG9yZGVycyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5waWNrYCB3aXRob3V0IHN1cHBvcnQgZm9yIGluZGl2aWR1YWxcbiAgICAgKiBwcm9wZXJ0eSBpZGVudGlmaWVycy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBwYXRocyBUaGUgcHJvcGVydHkgcGF0aHMgdG8gcGljay5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VQaWNrKG9iamVjdCwgcGF0aHMpIHtcbiAgICAgIHJldHVybiBiYXNlUGlja0J5KG9iamVjdCwgcGF0aHMsIGZ1bmN0aW9uKHZhbHVlLCBwYXRoKSB7XG4gICAgICAgIHJldHVybiBoYXNJbihvYmplY3QsIHBhdGgpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgIGBfLnBpY2tCeWAgd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBzb3VyY2Ugb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nW119IHBhdGhzIFRoZSBwcm9wZXJ0eSBwYXRocyB0byBwaWNrLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgcHJvcGVydHkuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG9iamVjdC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlUGlja0J5KG9iamVjdCwgcGF0aHMsIHByZWRpY2F0ZSkge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gcGF0aHMubGVuZ3RoLFxuICAgICAgICAgIHJlc3VsdCA9IHt9O1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIgcGF0aCA9IHBhdGhzW2luZGV4XSxcbiAgICAgICAgICAgIHZhbHVlID0gYmFzZUdldChvYmplY3QsIHBhdGgpO1xuXG4gICAgICAgIGlmIChwcmVkaWNhdGUodmFsdWUsIHBhdGgpKSB7XG4gICAgICAgICAgYmFzZVNldChyZXN1bHQsIGNhc3RQYXRoKHBhdGgsIG9iamVjdCksIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYGJhc2VQcm9wZXJ0eWAgd2hpY2ggc3VwcG9ydHMgZGVlcCBwYXRocy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIGdldC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBhY2Nlc3NvciBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlUHJvcGVydHlEZWVwKHBhdGgpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgICAgcmV0dXJuIGJhc2VHZXQob2JqZWN0LCBwYXRoKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ucHVsbEFsbEJ5YCB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlXG4gICAgICogc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB2YWx1ZXMgVGhlIHZhbHVlcyB0byByZW1vdmUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlXSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY29tcGFyYXRvcl0gVGhlIGNvbXBhcmF0b3IgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlUHVsbEFsbChhcnJheSwgdmFsdWVzLCBpdGVyYXRlZSwgY29tcGFyYXRvcikge1xuICAgICAgdmFyIGluZGV4T2YgPSBjb21wYXJhdG9yID8gYmFzZUluZGV4T2ZXaXRoIDogYmFzZUluZGV4T2YsXG4gICAgICAgICAgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSB2YWx1ZXMubGVuZ3RoLFxuICAgICAgICAgIHNlZW4gPSBhcnJheTtcblxuICAgICAgaWYgKGFycmF5ID09PSB2YWx1ZXMpIHtcbiAgICAgICAgdmFsdWVzID0gY29weUFycmF5KHZhbHVlcyk7XG4gICAgICB9XG4gICAgICBpZiAoaXRlcmF0ZWUpIHtcbiAgICAgICAgc2VlbiA9IGFycmF5TWFwKGFycmF5LCBiYXNlVW5hcnkoaXRlcmF0ZWUpKTtcbiAgICAgIH1cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBmcm9tSW5kZXggPSAwLFxuICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZXNbaW5kZXhdLFxuICAgICAgICAgICAgY29tcHV0ZWQgPSBpdGVyYXRlZSA/IGl0ZXJhdGVlKHZhbHVlKSA6IHZhbHVlO1xuXG4gICAgICAgIHdoaWxlICgoZnJvbUluZGV4ID0gaW5kZXhPZihzZWVuLCBjb21wdXRlZCwgZnJvbUluZGV4LCBjb21wYXJhdG9yKSkgPiAtMSkge1xuICAgICAgICAgIGlmIChzZWVuICE9PSBhcnJheSkge1xuICAgICAgICAgICAgc3BsaWNlLmNhbGwoc2VlbiwgZnJvbUluZGV4LCAxKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgc3BsaWNlLmNhbGwoYXJyYXksIGZyb21JbmRleCwgMSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBhcnJheTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5wdWxsQXRgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaW5kaXZpZHVhbFxuICAgICAqIGluZGV4ZXMgb3IgY2FwdHVyaW5nIHRoZSByZW1vdmVkIGVsZW1lbnRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyW119IGluZGV4ZXMgVGhlIGluZGV4ZXMgb2YgZWxlbWVudHMgdG8gcmVtb3ZlLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgYXJyYXlgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VQdWxsQXQoYXJyYXksIGluZGV4ZXMpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA/IGluZGV4ZXMubGVuZ3RoIDogMCxcbiAgICAgICAgICBsYXN0SW5kZXggPSBsZW5ndGggLSAxO1xuXG4gICAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgICAgdmFyIGluZGV4ID0gaW5kZXhlc1tsZW5ndGhdO1xuICAgICAgICBpZiAobGVuZ3RoID09IGxhc3RJbmRleCB8fCBpbmRleCAhPT0gcHJldmlvdXMpIHtcbiAgICAgICAgICB2YXIgcHJldmlvdXMgPSBpbmRleDtcbiAgICAgICAgICBpZiAoaXNJbmRleChpbmRleCkpIHtcbiAgICAgICAgICAgIHNwbGljZS5jYWxsKGFycmF5LCBpbmRleCwgMSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGJhc2VVbnNldChhcnJheSwgaW5kZXgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGFycmF5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnJhbmRvbWAgd2l0aG91dCBzdXBwb3J0IGZvciByZXR1cm5pbmdcbiAgICAgKiBmbG9hdGluZy1wb2ludCBudW1iZXJzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbG93ZXIgVGhlIGxvd2VyIGJvdW5kLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB1cHBlciBUaGUgdXBwZXIgYm91bmQuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgcmFuZG9tIG51bWJlci5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlUmFuZG9tKGxvd2VyLCB1cHBlcikge1xuICAgICAgcmV0dXJuIGxvd2VyICsgbmF0aXZlRmxvb3IobmF0aXZlUmFuZG9tKCkgKiAodXBwZXIgLSBsb3dlciArIDEpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5yYW5nZWAgYW5kIGBfLnJhbmdlUmlnaHRgIHdoaWNoIGRvZXNuJ3RcbiAgICAgKiBjb2VyY2UgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gc3RhcnQgVGhlIHN0YXJ0IG9mIHRoZSByYW5nZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gZW5kIFRoZSBlbmQgb2YgdGhlIHJhbmdlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBzdGVwIFRoZSB2YWx1ZSB0byBpbmNyZW1lbnQgb3IgZGVjcmVtZW50IGJ5LlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2Zyb21SaWdodF0gU3BlY2lmeSBpdGVyYXRpbmcgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgcmFuZ2Ugb2YgbnVtYmVycy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlUmFuZ2Uoc3RhcnQsIGVuZCwgc3RlcCwgZnJvbVJpZ2h0KSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBuYXRpdmVNYXgobmF0aXZlQ2VpbCgoZW5kIC0gc3RhcnQpIC8gKHN0ZXAgfHwgMSkpLCAwKSxcbiAgICAgICAgICByZXN1bHQgPSBBcnJheShsZW5ndGgpO1xuXG4gICAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgICAgcmVzdWx0W2Zyb21SaWdodCA/IGxlbmd0aCA6ICsraW5kZXhdID0gc3RhcnQ7XG4gICAgICAgIHN0YXJ0ICs9IHN0ZXA7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnJlcGVhdGAgd2hpY2ggZG9lc24ndCBjb2VyY2UgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFRoZSBzdHJpbmcgdG8gcmVwZWF0LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBuIFRoZSBudW1iZXIgb2YgdGltZXMgdG8gcmVwZWF0IHRoZSBzdHJpbmcuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgcmVwZWF0ZWQgc3RyaW5nLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VSZXBlYXQoc3RyaW5nLCBuKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gJyc7XG4gICAgICBpZiAoIXN0cmluZyB8fCBuIDwgMSB8fCBuID4gTUFYX1NBRkVfSU5URUdFUikge1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgICAgLy8gTGV2ZXJhZ2UgdGhlIGV4cG9uZW50aWF0aW9uIGJ5IHNxdWFyaW5nIGFsZ29yaXRobSBmb3IgYSBmYXN0ZXIgcmVwZWF0LlxuICAgICAgLy8gU2VlIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0V4cG9uZW50aWF0aW9uX2J5X3NxdWFyaW5nIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICBkbyB7XG4gICAgICAgIGlmIChuICUgMikge1xuICAgICAgICAgIHJlc3VsdCArPSBzdHJpbmc7XG4gICAgICAgIH1cbiAgICAgICAgbiA9IG5hdGl2ZUZsb29yKG4gLyAyKTtcbiAgICAgICAgaWYgKG4pIHtcbiAgICAgICAgICBzdHJpbmcgKz0gc3RyaW5nO1xuICAgICAgICB9XG4gICAgICB9IHdoaWxlIChuKTtcblxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5yZXN0YCB3aGljaCBkb2Vzbid0IHZhbGlkYXRlIG9yIGNvZXJjZSBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGFwcGx5IGEgcmVzdCBwYXJhbWV0ZXIgdG8uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGFydD1mdW5jLmxlbmd0aC0xXSBUaGUgc3RhcnQgcG9zaXRpb24gb2YgdGhlIHJlc3QgcGFyYW1ldGVyLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VSZXN0KGZ1bmMsIHN0YXJ0KSB7XG4gICAgICByZXR1cm4gc2V0VG9TdHJpbmcob3ZlclJlc3QoZnVuYywgc3RhcnQsIGlkZW50aXR5KSwgZnVuYyArICcnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5zYW1wbGVgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBzYW1wbGUuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJhbmRvbSBlbGVtZW50LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VTYW1wbGUoY29sbGVjdGlvbikge1xuICAgICAgcmV0dXJuIGFycmF5U2FtcGxlKHZhbHVlcyhjb2xsZWN0aW9uKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uc2FtcGxlU2l6ZWAgd2l0aG91dCBwYXJhbSBndWFyZHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIHNhbXBsZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbiBUaGUgbnVtYmVyIG9mIGVsZW1lbnRzIHRvIHNhbXBsZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHJhbmRvbSBlbGVtZW50cy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlU2FtcGxlU2l6ZShjb2xsZWN0aW9uLCBuKSB7XG4gICAgICB2YXIgYXJyYXkgPSB2YWx1ZXMoY29sbGVjdGlvbik7XG4gICAgICByZXR1cm4gc2h1ZmZsZVNlbGYoYXJyYXksIGJhc2VDbGFtcChuLCAwLCBhcnJheS5sZW5ndGgpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5zZXRgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBzZXQuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIHBhdGggY3JlYXRpb24uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlU2V0KG9iamVjdCwgcGF0aCwgdmFsdWUsIGN1c3RvbWl6ZXIpIHtcbiAgICAgIGlmICghaXNPYmplY3Qob2JqZWN0KSkge1xuICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgfVxuICAgICAgcGF0aCA9IGNhc3RQYXRoKHBhdGgsIG9iamVjdCk7XG5cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IHBhdGgubGVuZ3RoLFxuICAgICAgICAgIGxhc3RJbmRleCA9IGxlbmd0aCAtIDEsXG4gICAgICAgICAgbmVzdGVkID0gb2JqZWN0O1xuXG4gICAgICB3aGlsZSAobmVzdGVkICE9IG51bGwgJiYgKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIga2V5ID0gdG9LZXkocGF0aFtpbmRleF0pLFxuICAgICAgICAgICAgbmV3VmFsdWUgPSB2YWx1ZTtcblxuICAgICAgICBpZiAoaW5kZXggIT0gbGFzdEluZGV4KSB7XG4gICAgICAgICAgdmFyIG9ialZhbHVlID0gbmVzdGVkW2tleV07XG4gICAgICAgICAgbmV3VmFsdWUgPSBjdXN0b21pemVyID8gY3VzdG9taXplcihvYmpWYWx1ZSwga2V5LCBuZXN0ZWQpIDogdW5kZWZpbmVkO1xuICAgICAgICAgIGlmIChuZXdWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBuZXdWYWx1ZSA9IGlzT2JqZWN0KG9ialZhbHVlKVxuICAgICAgICAgICAgICA/IG9ialZhbHVlXG4gICAgICAgICAgICAgIDogKGlzSW5kZXgocGF0aFtpbmRleCArIDFdKSA/IFtdIDoge30pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBhc3NpZ25WYWx1ZShuZXN0ZWQsIGtleSwgbmV3VmFsdWUpO1xuICAgICAgICBuZXN0ZWQgPSBuZXN0ZWRba2V5XTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYHNldERhdGFgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaG90IGxvb3Agc2hvcnRpbmcuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGFzc29jaWF0ZSBtZXRhZGF0YSB3aXRoLlxuICAgICAqIEBwYXJhbSB7Kn0gZGF0YSBUaGUgbWV0YWRhdGEuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIGBmdW5jYC5cbiAgICAgKi9cbiAgICB2YXIgYmFzZVNldERhdGEgPSAhbWV0YU1hcCA/IGlkZW50aXR5IDogZnVuY3Rpb24oZnVuYywgZGF0YSkge1xuICAgICAgbWV0YU1hcC5zZXQoZnVuYywgZGF0YSk7XG4gICAgICByZXR1cm4gZnVuYztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYHNldFRvU3RyaW5nYCB3aXRob3V0IHN1cHBvcnQgZm9yIGhvdCBsb29wIHNob3J0aW5nLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gc3RyaW5nIFRoZSBgdG9TdHJpbmdgIHJlc3VsdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgYGZ1bmNgLlxuICAgICAqL1xuICAgIHZhciBiYXNlU2V0VG9TdHJpbmcgPSAhZGVmaW5lUHJvcGVydHkgPyBpZGVudGl0eSA6IGZ1bmN0aW9uKGZ1bmMsIHN0cmluZykge1xuICAgICAgcmV0dXJuIGRlZmluZVByb3BlcnR5KGZ1bmMsICd0b1N0cmluZycsIHtcbiAgICAgICAgJ2NvbmZpZ3VyYWJsZSc6IHRydWUsXG4gICAgICAgICdlbnVtZXJhYmxlJzogZmFsc2UsXG4gICAgICAgICd2YWx1ZSc6IGNvbnN0YW50KHN0cmluZyksXG4gICAgICAgICd3cml0YWJsZSc6IHRydWVcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5zaHVmZmxlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gc2h1ZmZsZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBzaHVmZmxlZCBhcnJheS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlU2h1ZmZsZShjb2xsZWN0aW9uKSB7XG4gICAgICByZXR1cm4gc2h1ZmZsZVNlbGYodmFsdWVzKGNvbGxlY3Rpb24pKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5zbGljZWAgd2l0aG91dCBhbiBpdGVyYXRlZSBjYWxsIGd1YXJkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gc2xpY2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGFydD0wXSBUaGUgc3RhcnQgcG9zaXRpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtlbmQ9YXJyYXkubGVuZ3RoXSBUaGUgZW5kIHBvc2l0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlU2xpY2UoYXJyYXksIHN0YXJ0LCBlbmQpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICAgICAgaWYgKHN0YXJ0IDwgMCkge1xuICAgICAgICBzdGFydCA9IC1zdGFydCA+IGxlbmd0aCA/IDAgOiAobGVuZ3RoICsgc3RhcnQpO1xuICAgICAgfVxuICAgICAgZW5kID0gZW5kID4gbGVuZ3RoID8gbGVuZ3RoIDogZW5kO1xuICAgICAgaWYgKGVuZCA8IDApIHtcbiAgICAgICAgZW5kICs9IGxlbmd0aDtcbiAgICAgIH1cbiAgICAgIGxlbmd0aCA9IHN0YXJ0ID4gZW5kID8gMCA6ICgoZW5kIC0gc3RhcnQpID4+PiAwKTtcbiAgICAgIHN0YXJ0ID4+Pj0gMDtcblxuICAgICAgdmFyIHJlc3VsdCA9IEFycmF5KGxlbmd0aCk7XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICByZXN1bHRbaW5kZXhdID0gYXJyYXlbaW5kZXggKyBzdGFydF07XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnNvbWVgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbnkgZWxlbWVudCBwYXNzZXMgdGhlIHByZWRpY2F0ZSBjaGVjayxcbiAgICAgKiAgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VTb21lKGNvbGxlY3Rpb24sIHByZWRpY2F0ZSkge1xuICAgICAgdmFyIHJlc3VsdDtcblxuICAgICAgYmFzZUVhY2goY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgIHJlc3VsdCA9IHByZWRpY2F0ZSh2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pO1xuICAgICAgICByZXR1cm4gIXJlc3VsdDtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuICEhcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnNvcnRlZEluZGV4YCBhbmQgYF8uc29ydGVkTGFzdEluZGV4YCB3aGljaFxuICAgICAqIHBlcmZvcm1zIGEgYmluYXJ5IHNlYXJjaCBvZiBgYXJyYXlgIHRvIGRldGVybWluZSB0aGUgaW5kZXggYXQgd2hpY2ggYHZhbHVlYFxuICAgICAqIHNob3VsZCBiZSBpbnNlcnRlZCBpbnRvIGBhcnJheWAgaW4gb3JkZXIgdG8gbWFpbnRhaW4gaXRzIHNvcnQgb3JkZXIuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBzb3J0ZWQgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBldmFsdWF0ZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtyZXRIaWdoZXN0XSBTcGVjaWZ5IHJldHVybmluZyB0aGUgaGlnaGVzdCBxdWFsaWZpZWQgaW5kZXguXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggYXQgd2hpY2ggYHZhbHVlYCBzaG91bGQgYmUgaW5zZXJ0ZWRcbiAgICAgKiAgaW50byBgYXJyYXlgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VTb3J0ZWRJbmRleChhcnJheSwgdmFsdWUsIHJldEhpZ2hlc3QpIHtcbiAgICAgIHZhciBsb3cgPSAwLFxuICAgICAgICAgIGhpZ2ggPSBhcnJheSA9PSBudWxsID8gbG93IDogYXJyYXkubGVuZ3RoO1xuXG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09ICdudW1iZXInICYmIHZhbHVlID09PSB2YWx1ZSAmJiBoaWdoIDw9IEhBTEZfTUFYX0FSUkFZX0xFTkdUSCkge1xuICAgICAgICB3aGlsZSAobG93IDwgaGlnaCkge1xuICAgICAgICAgIHZhciBtaWQgPSAobG93ICsgaGlnaCkgPj4+IDEsXG4gICAgICAgICAgICAgIGNvbXB1dGVkID0gYXJyYXlbbWlkXTtcblxuICAgICAgICAgIGlmIChjb21wdXRlZCAhPT0gbnVsbCAmJiAhaXNTeW1ib2woY29tcHV0ZWQpICYmXG4gICAgICAgICAgICAgIChyZXRIaWdoZXN0ID8gKGNvbXB1dGVkIDw9IHZhbHVlKSA6IChjb21wdXRlZCA8IHZhbHVlKSkpIHtcbiAgICAgICAgICAgIGxvdyA9IG1pZCArIDE7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGhpZ2ggPSBtaWQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBoaWdoO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VTb3J0ZWRJbmRleEJ5KGFycmF5LCB2YWx1ZSwgaWRlbnRpdHksIHJldEhpZ2hlc3QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnNvcnRlZEluZGV4QnlgIGFuZCBgXy5zb3J0ZWRMYXN0SW5kZXhCeWBcbiAgICAgKiB3aGljaCBpbnZva2VzIGBpdGVyYXRlZWAgZm9yIGB2YWx1ZWAgYW5kIGVhY2ggZWxlbWVudCBvZiBgYXJyYXlgIHRvIGNvbXB1dGVcbiAgICAgKiB0aGVpciBzb3J0IHJhbmtpbmcuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OyAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgc29ydGVkIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gZXZhbHVhdGUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbcmV0SGlnaGVzdF0gU3BlY2lmeSByZXR1cm5pbmcgdGhlIGhpZ2hlc3QgcXVhbGlmaWVkIGluZGV4LlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IGF0IHdoaWNoIGB2YWx1ZWAgc2hvdWxkIGJlIGluc2VydGVkXG4gICAgICogIGludG8gYGFycmF5YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlU29ydGVkSW5kZXhCeShhcnJheSwgdmFsdWUsIGl0ZXJhdGVlLCByZXRIaWdoZXN0KSB7XG4gICAgICB2YWx1ZSA9IGl0ZXJhdGVlKHZhbHVlKTtcblxuICAgICAgdmFyIGxvdyA9IDAsXG4gICAgICAgICAgaGlnaCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoLFxuICAgICAgICAgIHZhbElzTmFOID0gdmFsdWUgIT09IHZhbHVlLFxuICAgICAgICAgIHZhbElzTnVsbCA9IHZhbHVlID09PSBudWxsLFxuICAgICAgICAgIHZhbElzU3ltYm9sID0gaXNTeW1ib2wodmFsdWUpLFxuICAgICAgICAgIHZhbElzVW5kZWZpbmVkID0gdmFsdWUgPT09IHVuZGVmaW5lZDtcblxuICAgICAgd2hpbGUgKGxvdyA8IGhpZ2gpIHtcbiAgICAgICAgdmFyIG1pZCA9IG5hdGl2ZUZsb29yKChsb3cgKyBoaWdoKSAvIDIpLFxuICAgICAgICAgICAgY29tcHV0ZWQgPSBpdGVyYXRlZShhcnJheVttaWRdKSxcbiAgICAgICAgICAgIG90aElzRGVmaW5lZCA9IGNvbXB1dGVkICE9PSB1bmRlZmluZWQsXG4gICAgICAgICAgICBvdGhJc051bGwgPSBjb21wdXRlZCA9PT0gbnVsbCxcbiAgICAgICAgICAgIG90aElzUmVmbGV4aXZlID0gY29tcHV0ZWQgPT09IGNvbXB1dGVkLFxuICAgICAgICAgICAgb3RoSXNTeW1ib2wgPSBpc1N5bWJvbChjb21wdXRlZCk7XG5cbiAgICAgICAgaWYgKHZhbElzTmFOKSB7XG4gICAgICAgICAgdmFyIHNldExvdyA9IHJldEhpZ2hlc3QgfHwgb3RoSXNSZWZsZXhpdmU7XG4gICAgICAgIH0gZWxzZSBpZiAodmFsSXNVbmRlZmluZWQpIHtcbiAgICAgICAgICBzZXRMb3cgPSBvdGhJc1JlZmxleGl2ZSAmJiAocmV0SGlnaGVzdCB8fCBvdGhJc0RlZmluZWQpO1xuICAgICAgICB9IGVsc2UgaWYgKHZhbElzTnVsbCkge1xuICAgICAgICAgIHNldExvdyA9IG90aElzUmVmbGV4aXZlICYmIG90aElzRGVmaW5lZCAmJiAocmV0SGlnaGVzdCB8fCAhb3RoSXNOdWxsKTtcbiAgICAgICAgfSBlbHNlIGlmICh2YWxJc1N5bWJvbCkge1xuICAgICAgICAgIHNldExvdyA9IG90aElzUmVmbGV4aXZlICYmIG90aElzRGVmaW5lZCAmJiAhb3RoSXNOdWxsICYmIChyZXRIaWdoZXN0IHx8ICFvdGhJc1N5bWJvbCk7XG4gICAgICAgIH0gZWxzZSBpZiAob3RoSXNOdWxsIHx8IG90aElzU3ltYm9sKSB7XG4gICAgICAgICAgc2V0TG93ID0gZmFsc2U7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc2V0TG93ID0gcmV0SGlnaGVzdCA/IChjb21wdXRlZCA8PSB2YWx1ZSkgOiAoY29tcHV0ZWQgPCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNldExvdykge1xuICAgICAgICAgIGxvdyA9IG1pZCArIDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaGlnaCA9IG1pZDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIG5hdGl2ZU1pbihoaWdoLCBNQVhfQVJSQVlfSU5ERVgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnNvcnRlZFVuaXFgIGFuZCBgXy5zb3J0ZWRVbmlxQnlgIHdpdGhvdXRcbiAgICAgKiBzdXBwb3J0IGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWVdIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGR1cGxpY2F0ZSBmcmVlIGFycmF5LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VTb3J0ZWRVbmlxKGFycmF5LCBpdGVyYXRlZSkge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICAgIHJlc0luZGV4ID0gMCxcbiAgICAgICAgICByZXN1bHQgPSBbXTtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaW5kZXhdLFxuICAgICAgICAgICAgY29tcHV0ZWQgPSBpdGVyYXRlZSA/IGl0ZXJhdGVlKHZhbHVlKSA6IHZhbHVlO1xuXG4gICAgICAgIGlmICghaW5kZXggfHwgIWVxKGNvbXB1dGVkLCBzZWVuKSkge1xuICAgICAgICAgIHZhciBzZWVuID0gY29tcHV0ZWQ7XG4gICAgICAgICAgcmVzdWx0W3Jlc0luZGV4KytdID0gdmFsdWUgPT09IDAgPyAwIDogdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8udG9OdW1iZXJgIHdoaWNoIGRvZXNuJ3QgZW5zdXJlIGNvcnJlY3RcbiAgICAgKiBjb252ZXJzaW9ucyBvZiBiaW5hcnksIGhleGFkZWNpbWFsLCBvciBvY3RhbCBzdHJpbmcgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBwcm9jZXNzLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIG51bWJlci5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlVG9OdW1iZXIodmFsdWUpIHtcbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT0gJ251bWJlcicpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfVxuICAgICAgaWYgKGlzU3ltYm9sKHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gTkFOO1xuICAgICAgfVxuICAgICAgcmV0dXJuICt2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy50b1N0cmluZ2Agd2hpY2ggZG9lc24ndCBjb252ZXJ0IG51bGxpc2hcbiAgICAgKiB2YWx1ZXMgdG8gZW1wdHkgc3RyaW5ncy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcHJvY2Vzcy5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBzdHJpbmcuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVRvU3RyaW5nKHZhbHVlKSB7XG4gICAgICAvLyBFeGl0IGVhcmx5IGZvciBzdHJpbmdzIHRvIGF2b2lkIGEgcGVyZm9ybWFuY2UgaGl0IGluIHNvbWUgZW52aXJvbm1lbnRzLlxuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICB9XG4gICAgICBpZiAoaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgLy8gUmVjdXJzaXZlbHkgY29udmVydCB2YWx1ZXMgKHN1c2NlcHRpYmxlIHRvIGNhbGwgc3RhY2sgbGltaXRzKS5cbiAgICAgICAgcmV0dXJuIGFycmF5TWFwKHZhbHVlLCBiYXNlVG9TdHJpbmcpICsgJyc7XG4gICAgICB9XG4gICAgICBpZiAoaXNTeW1ib2wodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiBzeW1ib2xUb1N0cmluZyA/IHN5bWJvbFRvU3RyaW5nLmNhbGwodmFsdWUpIDogJyc7XG4gICAgICB9XG4gICAgICB2YXIgcmVzdWx0ID0gKHZhbHVlICsgJycpO1xuICAgICAgcmV0dXJuIChyZXN1bHQgPT0gJzAnICYmICgxIC8gdmFsdWUpID09IC1JTkZJTklUWSkgPyAnLTAnIDogcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnVuaXFCeWAgd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWVdIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJhdG9yXSBUaGUgY29tcGFyYXRvciBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGR1cGxpY2F0ZSBmcmVlIGFycmF5LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJhc2VVbmlxKGFycmF5LCBpdGVyYXRlZSwgY29tcGFyYXRvcikge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgaW5jbHVkZXMgPSBhcnJheUluY2x1ZGVzLFxuICAgICAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgICBpc0NvbW1vbiA9IHRydWUsXG4gICAgICAgICAgcmVzdWx0ID0gW10sXG4gICAgICAgICAgc2VlbiA9IHJlc3VsdDtcblxuICAgICAgaWYgKGNvbXBhcmF0b3IpIHtcbiAgICAgICAgaXNDb21tb24gPSBmYWxzZTtcbiAgICAgICAgaW5jbHVkZXMgPSBhcnJheUluY2x1ZGVzV2l0aDtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKGxlbmd0aCA+PSBMQVJHRV9BUlJBWV9TSVpFKSB7XG4gICAgICAgIHZhciBzZXQgPSBpdGVyYXRlZSA/IG51bGwgOiBjcmVhdGVTZXQoYXJyYXkpO1xuICAgICAgICBpZiAoc2V0KSB7XG4gICAgICAgICAgcmV0dXJuIHNldFRvQXJyYXkoc2V0KTtcbiAgICAgICAgfVxuICAgICAgICBpc0NvbW1vbiA9IGZhbHNlO1xuICAgICAgICBpbmNsdWRlcyA9IGNhY2hlSGFzO1xuICAgICAgICBzZWVuID0gbmV3IFNldENhY2hlO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIHNlZW4gPSBpdGVyYXRlZSA/IFtdIDogcmVzdWx0O1xuICAgICAgfVxuICAgICAgb3V0ZXI6XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIgdmFsdWUgPSBhcnJheVtpbmRleF0sXG4gICAgICAgICAgICBjb21wdXRlZCA9IGl0ZXJhdGVlID8gaXRlcmF0ZWUodmFsdWUpIDogdmFsdWU7XG5cbiAgICAgICAgdmFsdWUgPSAoY29tcGFyYXRvciB8fCB2YWx1ZSAhPT0gMCkgPyB2YWx1ZSA6IDA7XG4gICAgICAgIGlmIChpc0NvbW1vbiAmJiBjb21wdXRlZCA9PT0gY29tcHV0ZWQpIHtcbiAgICAgICAgICB2YXIgc2VlbkluZGV4ID0gc2Vlbi5sZW5ndGg7XG4gICAgICAgICAgd2hpbGUgKHNlZW5JbmRleC0tKSB7XG4gICAgICAgICAgICBpZiAoc2VlbltzZWVuSW5kZXhdID09PSBjb21wdXRlZCkge1xuICAgICAgICAgICAgICBjb250aW51ZSBvdXRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGl0ZXJhdGVlKSB7XG4gICAgICAgICAgICBzZWVuLnB1c2goY29tcHV0ZWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoIWluY2x1ZGVzKHNlZW4sIGNvbXB1dGVkLCBjb21wYXJhdG9yKSkge1xuICAgICAgICAgIGlmIChzZWVuICE9PSByZXN1bHQpIHtcbiAgICAgICAgICAgIHNlZW4ucHVzaChjb21wdXRlZCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc3VsdC5wdXNoKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy51bnNldGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHByb3BlcnR5IHBhdGggdG8gdW5zZXQuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBwcm9wZXJ0eSBpcyBkZWxldGVkLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVVuc2V0KG9iamVjdCwgcGF0aCkge1xuICAgICAgcGF0aCA9IGNhc3RQYXRoKHBhdGgsIG9iamVjdCk7XG4gICAgICBvYmplY3QgPSBwYXJlbnQob2JqZWN0LCBwYXRoKTtcbiAgICAgIHJldHVybiBvYmplY3QgPT0gbnVsbCB8fCBkZWxldGUgb2JqZWN0W3RvS2V5KGxhc3QocGF0aCkpXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy51cGRhdGVgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byB1cGRhdGUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gdXBkYXRlciBUaGUgZnVuY3Rpb24gdG8gcHJvZHVjZSB0aGUgdXBkYXRlZCB2YWx1ZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBwYXRoIGNyZWF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVVwZGF0ZShvYmplY3QsIHBhdGgsIHVwZGF0ZXIsIGN1c3RvbWl6ZXIpIHtcbiAgICAgIHJldHVybiBiYXNlU2V0KG9iamVjdCwgcGF0aCwgdXBkYXRlcihiYXNlR2V0KG9iamVjdCwgcGF0aCkpLCBjdXN0b21pemVyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBtZXRob2RzIGxpa2UgYF8uZHJvcFdoaWxlYCBhbmQgYF8udGFrZVdoaWxlYFxuICAgICAqIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzRHJvcF0gU3BlY2lmeSBkcm9wcGluZyBlbGVtZW50cyBpbnN0ZWFkIG9mIHRha2luZyB0aGVtLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2Zyb21SaWdodF0gU3BlY2lmeSBpdGVyYXRpbmcgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlV2hpbGUoYXJyYXksIHByZWRpY2F0ZSwgaXNEcm9wLCBmcm9tUmlnaHQpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgICAgaW5kZXggPSBmcm9tUmlnaHQgPyBsZW5ndGggOiAtMTtcblxuICAgICAgd2hpbGUgKChmcm9tUmlnaHQgPyBpbmRleC0tIDogKytpbmRleCA8IGxlbmd0aCkgJiZcbiAgICAgICAgcHJlZGljYXRlKGFycmF5W2luZGV4XSwgaW5kZXgsIGFycmF5KSkge31cblxuICAgICAgcmV0dXJuIGlzRHJvcFxuICAgICAgICA/IGJhc2VTbGljZShhcnJheSwgKGZyb21SaWdodCA/IDAgOiBpbmRleCksIChmcm9tUmlnaHQgPyBpbmRleCArIDEgOiBsZW5ndGgpKVxuICAgICAgICA6IGJhc2VTbGljZShhcnJheSwgKGZyb21SaWdodCA/IGluZGV4ICsgMSA6IDApLCAoZnJvbVJpZ2h0ID8gbGVuZ3RoIDogaW5kZXgpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgd3JhcHBlclZhbHVlYCB3aGljaCByZXR1cm5zIHRoZSByZXN1bHQgb2ZcbiAgICAgKiBwZXJmb3JtaW5nIGEgc2VxdWVuY2Ugb2YgYWN0aW9ucyBvbiB0aGUgdW53cmFwcGVkIGB2YWx1ZWAsIHdoZXJlIGVhY2hcbiAgICAgKiBzdWNjZXNzaXZlIGFjdGlvbiBpcyBzdXBwbGllZCB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBwcmV2aW91cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdW53cmFwcGVkIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFjdGlvbnMgQWN0aW9ucyB0byBwZXJmb3JtIHRvIHJlc29sdmUgdGhlIHVud3JhcHBlZCB2YWx1ZS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcmVzb2x2ZWQgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVdyYXBwZXJWYWx1ZSh2YWx1ZSwgYWN0aW9ucykge1xuICAgICAgdmFyIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIExhenlXcmFwcGVyKSB7XG4gICAgICAgIHJlc3VsdCA9IHJlc3VsdC52YWx1ZSgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFycmF5UmVkdWNlKGFjdGlvbnMsIGZ1bmN0aW9uKHJlc3VsdCwgYWN0aW9uKSB7XG4gICAgICAgIHJldHVybiBhY3Rpb24uZnVuYy5hcHBseShhY3Rpb24udGhpc0FyZywgYXJyYXlQdXNoKFtyZXN1bHRdLCBhY3Rpb24uYXJncykpO1xuICAgICAgfSwgcmVzdWx0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBtZXRob2RzIGxpa2UgYF8ueG9yYCwgd2l0aG91dCBzdXBwb3J0IGZvclxuICAgICAqIGl0ZXJhdGVlIHNob3J0aGFuZHMsIHRoYXQgYWNjZXB0cyBhbiBhcnJheSBvZiBhcnJheXMgdG8gaW5zcGVjdC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXlzIFRoZSBhcnJheXMgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWVdIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJhdG9yXSBUaGUgY29tcGFyYXRvciBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIHZhbHVlcy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBiYXNlWG9yKGFycmF5cywgaXRlcmF0ZWUsIGNvbXBhcmF0b3IpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheXMubGVuZ3RoO1xuICAgICAgaWYgKGxlbmd0aCA8IDIpIHtcbiAgICAgICAgcmV0dXJuIGxlbmd0aCA/IGJhc2VVbmlxKGFycmF5c1swXSkgOiBbXTtcbiAgICAgIH1cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIHJlc3VsdCA9IEFycmF5KGxlbmd0aCk7XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBhcnJheSA9IGFycmF5c1tpbmRleF0sXG4gICAgICAgICAgICBvdGhJbmRleCA9IC0xO1xuXG4gICAgICAgIHdoaWxlICgrK290aEluZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgICAgaWYgKG90aEluZGV4ICE9IGluZGV4KSB7XG4gICAgICAgICAgICByZXN1bHRbaW5kZXhdID0gYmFzZURpZmZlcmVuY2UocmVzdWx0W2luZGV4XSB8fCBhcnJheSwgYXJyYXlzW290aEluZGV4XSwgaXRlcmF0ZWUsIGNvbXBhcmF0b3IpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VVbmlxKGJhc2VGbGF0dGVuKHJlc3VsdCwgMSksIGl0ZXJhdGVlLCBjb21wYXJhdG9yKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uemlwT2JqZWN0YCB3aGljaCBhc3NpZ25zIHZhbHVlcyB1c2luZyBgYXNzaWduRnVuY2AuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHByb3BzIFRoZSBwcm9wZXJ0eSBpZGVudGlmaWVycy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB2YWx1ZXMgVGhlIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBhc3NpZ25GdW5jIFRoZSBmdW5jdGlvbiB0byBhc3NpZ24gdmFsdWVzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICovXG4gICAgZnVuY3Rpb24gYmFzZVppcE9iamVjdChwcm9wcywgdmFsdWVzLCBhc3NpZ25GdW5jKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBsZW5ndGggPSBwcm9wcy5sZW5ndGgsXG4gICAgICAgICAgdmFsc0xlbmd0aCA9IHZhbHVlcy5sZW5ndGgsXG4gICAgICAgICAgcmVzdWx0ID0ge307XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGluZGV4IDwgdmFsc0xlbmd0aCA/IHZhbHVlc1tpbmRleF0gOiB1bmRlZmluZWQ7XG4gICAgICAgIGFzc2lnbkZ1bmMocmVzdWx0LCBwcm9wc1tpbmRleF0sIHZhbHVlKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2FzdHMgYHZhbHVlYCB0byBhbiBlbXB0eSBhcnJheSBpZiBpdCdzIG5vdCBhbiBhcnJheSBsaWtlIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl8T2JqZWN0fSBSZXR1cm5zIHRoZSBjYXN0IGFycmF5LWxpa2Ugb2JqZWN0LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNhc3RBcnJheUxpa2VPYmplY3QodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc0FycmF5TGlrZU9iamVjdCh2YWx1ZSkgPyB2YWx1ZSA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhc3RzIGB2YWx1ZWAgdG8gYGlkZW50aXR5YCBpZiBpdCdzIG5vdCBhIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBpbnNwZWN0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyBjYXN0IGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNhc3RGdW5jdGlvbih2YWx1ZSkge1xuICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSAnZnVuY3Rpb24nID8gdmFsdWUgOiBpZGVudGl0eTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYXN0cyBgdmFsdWVgIHRvIGEgcGF0aCBhcnJheSBpZiBpdCdzIG5vdCBvbmUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvYmplY3RdIFRoZSBvYmplY3QgdG8gcXVlcnkga2V5cyBvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGNhc3QgcHJvcGVydHkgcGF0aCBhcnJheS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjYXN0UGF0aCh2YWx1ZSwgb2JqZWN0KSB7XG4gICAgICBpZiAoaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGlzS2V5KHZhbHVlLCBvYmplY3QpID8gW3ZhbHVlXSA6IHN0cmluZ1RvUGF0aCh0b1N0cmluZyh2YWx1ZSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgYGJhc2VSZXN0YCBhbGlhcyB3aGljaCBjYW4gYmUgcmVwbGFjZWQgd2l0aCBgaWRlbnRpdHlgIGJ5IG1vZHVsZVxuICAgICAqIHJlcGxhY2VtZW50IHBsdWdpbnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtGdW5jdGlvbn1cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBhcHBseSBhIHJlc3QgcGFyYW1ldGVyIHRvLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIHZhciBjYXN0UmVzdCA9IGJhc2VSZXN0O1xuXG4gICAgLyoqXG4gICAgICogQ2FzdHMgYGFycmF5YCB0byBhIHNsaWNlIGlmIGl0J3MgbmVlZGVkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gc3RhcnQgVGhlIHN0YXJ0IHBvc2l0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZW5kPWFycmF5Lmxlbmd0aF0gVGhlIGVuZCBwb3NpdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGNhc3Qgc2xpY2UuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2FzdFNsaWNlKGFycmF5LCBzdGFydCwgZW5kKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuICAgICAgZW5kID0gZW5kID09PSB1bmRlZmluZWQgPyBsZW5ndGggOiBlbmQ7XG4gICAgICByZXR1cm4gKCFzdGFydCAmJiBlbmQgPj0gbGVuZ3RoKSA/IGFycmF5IDogYmFzZVNsaWNlKGFycmF5LCBzdGFydCwgZW5kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNpbXBsZSB3cmFwcGVyIGFyb3VuZCB0aGUgZ2xvYmFsIFtgY2xlYXJUaW1lb3V0YF0oaHR0cHM6Ly9tZG4uaW8vY2xlYXJUaW1lb3V0KS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtudW1iZXJ8T2JqZWN0fSBpZCBUaGUgdGltZXIgaWQgb3IgdGltZW91dCBvYmplY3Qgb2YgdGhlIHRpbWVyIHRvIGNsZWFyLlxuICAgICAqL1xuICAgIHZhciBjbGVhclRpbWVvdXQgPSBjdHhDbGVhclRpbWVvdXQgfHwgZnVuY3Rpb24oaWQpIHtcbiAgICAgIHJldHVybiByb290LmNsZWFyVGltZW91dChpZCk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBjbG9uZSBvZiAgYGJ1ZmZlcmAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QnVmZmVyfSBidWZmZXIgVGhlIGJ1ZmZlciB0byBjbG9uZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc0RlZXBdIFNwZWNpZnkgYSBkZWVwIGNsb25lLlxuICAgICAqIEByZXR1cm5zIHtCdWZmZXJ9IFJldHVybnMgdGhlIGNsb25lZCBidWZmZXIuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2xvbmVCdWZmZXIoYnVmZmVyLCBpc0RlZXApIHtcbiAgICAgIGlmIChpc0RlZXApIHtcbiAgICAgICAgcmV0dXJuIGJ1ZmZlci5zbGljZSgpO1xuICAgICAgfVxuICAgICAgdmFyIGxlbmd0aCA9IGJ1ZmZlci5sZW5ndGgsXG4gICAgICAgICAgcmVzdWx0ID0gYWxsb2NVbnNhZmUgPyBhbGxvY1Vuc2FmZShsZW5ndGgpIDogbmV3IGJ1ZmZlci5jb25zdHJ1Y3RvcihsZW5ndGgpO1xuXG4gICAgICBidWZmZXIuY29weShyZXN1bHQpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgY2xvbmUgb2YgYGFycmF5QnVmZmVyYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheUJ1ZmZlcn0gYXJyYXlCdWZmZXIgVGhlIGFycmF5IGJ1ZmZlciB0byBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXlCdWZmZXJ9IFJldHVybnMgdGhlIGNsb25lZCBhcnJheSBidWZmZXIuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2xvbmVBcnJheUJ1ZmZlcihhcnJheUJ1ZmZlcikge1xuICAgICAgdmFyIHJlc3VsdCA9IG5ldyBhcnJheUJ1ZmZlci5jb25zdHJ1Y3RvcihhcnJheUJ1ZmZlci5ieXRlTGVuZ3RoKTtcbiAgICAgIG5ldyBVaW50OEFycmF5KHJlc3VsdCkuc2V0KG5ldyBVaW50OEFycmF5KGFycmF5QnVmZmVyKSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBjbG9uZSBvZiBgZGF0YVZpZXdgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gZGF0YVZpZXcgVGhlIGRhdGEgdmlldyB0byBjbG9uZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc0RlZXBdIFNwZWNpZnkgYSBkZWVwIGNsb25lLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNsb25lZCBkYXRhIHZpZXcuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2xvbmVEYXRhVmlldyhkYXRhVmlldywgaXNEZWVwKSB7XG4gICAgICB2YXIgYnVmZmVyID0gaXNEZWVwID8gY2xvbmVBcnJheUJ1ZmZlcihkYXRhVmlldy5idWZmZXIpIDogZGF0YVZpZXcuYnVmZmVyO1xuICAgICAgcmV0dXJuIG5ldyBkYXRhVmlldy5jb25zdHJ1Y3RvcihidWZmZXIsIGRhdGFWaWV3LmJ5dGVPZmZzZXQsIGRhdGFWaWV3LmJ5dGVMZW5ndGgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBjbG9uZSBvZiBgbWFwYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG1hcCBUaGUgbWFwIHRvIGNsb25lLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGNsb25lRnVuYyBUaGUgZnVuY3Rpb24gdG8gY2xvbmUgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzRGVlcF0gU3BlY2lmeSBhIGRlZXAgY2xvbmUuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY2xvbmVkIG1hcC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjbG9uZU1hcChtYXAsIGlzRGVlcCwgY2xvbmVGdW5jKSB7XG4gICAgICB2YXIgYXJyYXkgPSBpc0RlZXAgPyBjbG9uZUZ1bmMobWFwVG9BcnJheShtYXApLCBDTE9ORV9ERUVQX0ZMQUcpIDogbWFwVG9BcnJheShtYXApO1xuICAgICAgcmV0dXJuIGFycmF5UmVkdWNlKGFycmF5LCBhZGRNYXBFbnRyeSwgbmV3IG1hcC5jb25zdHJ1Y3Rvcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGNsb25lIG9mIGByZWdleHBgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcmVnZXhwIFRoZSByZWdleHAgdG8gY2xvbmUuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY2xvbmVkIHJlZ2V4cC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjbG9uZVJlZ0V4cChyZWdleHApIHtcbiAgICAgIHZhciByZXN1bHQgPSBuZXcgcmVnZXhwLmNvbnN0cnVjdG9yKHJlZ2V4cC5zb3VyY2UsIHJlRmxhZ3MuZXhlYyhyZWdleHApKTtcbiAgICAgIHJlc3VsdC5sYXN0SW5kZXggPSByZWdleHAubGFzdEluZGV4O1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgY2xvbmUgb2YgYHNldGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzZXQgVGhlIHNldCB0byBjbG9uZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjbG9uZUZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGNsb25lIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtpc0RlZXBdIFNwZWNpZnkgYSBkZWVwIGNsb25lLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNsb25lZCBzZXQuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2xvbmVTZXQoc2V0LCBpc0RlZXAsIGNsb25lRnVuYykge1xuICAgICAgdmFyIGFycmF5ID0gaXNEZWVwID8gY2xvbmVGdW5jKHNldFRvQXJyYXkoc2V0KSwgQ0xPTkVfREVFUF9GTEFHKSA6IHNldFRvQXJyYXkoc2V0KTtcbiAgICAgIHJldHVybiBhcnJheVJlZHVjZShhcnJheSwgYWRkU2V0RW50cnksIG5ldyBzZXQuY29uc3RydWN0b3IpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBjbG9uZSBvZiB0aGUgYHN5bWJvbGAgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc3ltYm9sIFRoZSBzeW1ib2wgb2JqZWN0IHRvIGNsb25lLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNsb25lZCBzeW1ib2wgb2JqZWN0LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsb25lU3ltYm9sKHN5bWJvbCkge1xuICAgICAgcmV0dXJuIHN5bWJvbFZhbHVlT2YgPyBPYmplY3Qoc3ltYm9sVmFsdWVPZi5jYWxsKHN5bWJvbCkpIDoge307XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGNsb25lIG9mIGB0eXBlZEFycmF5YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHR5cGVkQXJyYXkgVGhlIHR5cGVkIGFycmF5IHRvIGNsb25lLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzRGVlcF0gU3BlY2lmeSBhIGRlZXAgY2xvbmUuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY2xvbmVkIHR5cGVkIGFycmF5LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsb25lVHlwZWRBcnJheSh0eXBlZEFycmF5LCBpc0RlZXApIHtcbiAgICAgIHZhciBidWZmZXIgPSBpc0RlZXAgPyBjbG9uZUFycmF5QnVmZmVyKHR5cGVkQXJyYXkuYnVmZmVyKSA6IHR5cGVkQXJyYXkuYnVmZmVyO1xuICAgICAgcmV0dXJuIG5ldyB0eXBlZEFycmF5LmNvbnN0cnVjdG9yKGJ1ZmZlciwgdHlwZWRBcnJheS5ieXRlT2Zmc2V0LCB0eXBlZEFycmF5Lmxlbmd0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29tcGFyZXMgdmFsdWVzIHRvIHNvcnQgdGhlbSBpbiBhc2NlbmRpbmcgb3JkZXIuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBzb3J0IG9yZGVyIGluZGljYXRvciBmb3IgYHZhbHVlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb21wYXJlQXNjZW5kaW5nKHZhbHVlLCBvdGhlcikge1xuICAgICAgaWYgKHZhbHVlICE9PSBvdGhlcikge1xuICAgICAgICB2YXIgdmFsSXNEZWZpbmVkID0gdmFsdWUgIT09IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHZhbElzTnVsbCA9IHZhbHVlID09PSBudWxsLFxuICAgICAgICAgICAgdmFsSXNSZWZsZXhpdmUgPSB2YWx1ZSA9PT0gdmFsdWUsXG4gICAgICAgICAgICB2YWxJc1N5bWJvbCA9IGlzU3ltYm9sKHZhbHVlKTtcblxuICAgICAgICB2YXIgb3RoSXNEZWZpbmVkID0gb3RoZXIgIT09IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIG90aElzTnVsbCA9IG90aGVyID09PSBudWxsLFxuICAgICAgICAgICAgb3RoSXNSZWZsZXhpdmUgPSBvdGhlciA9PT0gb3RoZXIsXG4gICAgICAgICAgICBvdGhJc1N5bWJvbCA9IGlzU3ltYm9sKG90aGVyKTtcblxuICAgICAgICBpZiAoKCFvdGhJc051bGwgJiYgIW90aElzU3ltYm9sICYmICF2YWxJc1N5bWJvbCAmJiB2YWx1ZSA+IG90aGVyKSB8fFxuICAgICAgICAgICAgKHZhbElzU3ltYm9sICYmIG90aElzRGVmaW5lZCAmJiBvdGhJc1JlZmxleGl2ZSAmJiAhb3RoSXNOdWxsICYmICFvdGhJc1N5bWJvbCkgfHxcbiAgICAgICAgICAgICh2YWxJc051bGwgJiYgb3RoSXNEZWZpbmVkICYmIG90aElzUmVmbGV4aXZlKSB8fFxuICAgICAgICAgICAgKCF2YWxJc0RlZmluZWQgJiYgb3RoSXNSZWZsZXhpdmUpIHx8XG4gICAgICAgICAgICAhdmFsSXNSZWZsZXhpdmUpIHtcbiAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoKCF2YWxJc051bGwgJiYgIXZhbElzU3ltYm9sICYmICFvdGhJc1N5bWJvbCAmJiB2YWx1ZSA8IG90aGVyKSB8fFxuICAgICAgICAgICAgKG90aElzU3ltYm9sICYmIHZhbElzRGVmaW5lZCAmJiB2YWxJc1JlZmxleGl2ZSAmJiAhdmFsSXNOdWxsICYmICF2YWxJc1N5bWJvbCkgfHxcbiAgICAgICAgICAgIChvdGhJc051bGwgJiYgdmFsSXNEZWZpbmVkICYmIHZhbElzUmVmbGV4aXZlKSB8fFxuICAgICAgICAgICAgKCFvdGhJc0RlZmluZWQgJiYgdmFsSXNSZWZsZXhpdmUpIHx8XG4gICAgICAgICAgICAhb3RoSXNSZWZsZXhpdmUpIHtcbiAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVzZWQgYnkgYF8ub3JkZXJCeWAgdG8gY29tcGFyZSBtdWx0aXBsZSBwcm9wZXJ0aWVzIG9mIGEgdmFsdWUgdG8gYW5vdGhlclxuICAgICAqIGFuZCBzdGFibGUgc29ydCB0aGVtLlxuICAgICAqXG4gICAgICogSWYgYG9yZGVyc2AgaXMgdW5zcGVjaWZpZWQsIGFsbCB2YWx1ZXMgYXJlIHNvcnRlZCBpbiBhc2NlbmRpbmcgb3JkZXIuIE90aGVyd2lzZSxcbiAgICAgKiBzcGVjaWZ5IGFuIG9yZGVyIG9mIFwiZGVzY1wiIGZvciBkZXNjZW5kaW5nIG9yIFwiYXNjXCIgZm9yIGFzY2VuZGluZyBzb3J0IG9yZGVyXG4gICAgICogb2YgY29ycmVzcG9uZGluZyB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvdGhlciBUaGUgb3RoZXIgb2JqZWN0IHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHtib29sZWFuW118c3RyaW5nW119IG9yZGVycyBUaGUgb3JkZXIgdG8gc29ydCBieSBmb3IgZWFjaCBwcm9wZXJ0eS5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBzb3J0IG9yZGVyIGluZGljYXRvciBmb3IgYG9iamVjdGAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29tcGFyZU11bHRpcGxlKG9iamVjdCwgb3RoZXIsIG9yZGVycykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgb2JqQ3JpdGVyaWEgPSBvYmplY3QuY3JpdGVyaWEsXG4gICAgICAgICAgb3RoQ3JpdGVyaWEgPSBvdGhlci5jcml0ZXJpYSxcbiAgICAgICAgICBsZW5ndGggPSBvYmpDcml0ZXJpYS5sZW5ndGgsXG4gICAgICAgICAgb3JkZXJzTGVuZ3RoID0gb3JkZXJzLmxlbmd0aDtcblxuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IGNvbXBhcmVBc2NlbmRpbmcob2JqQ3JpdGVyaWFbaW5kZXhdLCBvdGhDcml0ZXJpYVtpbmRleF0pO1xuICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgaWYgKGluZGV4ID49IG9yZGVyc0xlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIG9yZGVyID0gb3JkZXJzW2luZGV4XTtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0ICogKG9yZGVyID09ICdkZXNjJyA/IC0xIDogMSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIEZpeGVzIGFuIGBBcnJheSNzb3J0YCBidWcgaW4gdGhlIEpTIGVuZ2luZSBlbWJlZGRlZCBpbiBBZG9iZSBhcHBsaWNhdGlvbnNcbiAgICAgIC8vIHRoYXQgY2F1c2VzIGl0LCB1bmRlciBjZXJ0YWluIGNpcmN1bXN0YW5jZXMsIHRvIHByb3ZpZGUgdGhlIHNhbWUgdmFsdWUgZm9yXG4gICAgICAvLyBgb2JqZWN0YCBhbmQgYG90aGVyYC4gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9qYXNoa2VuYXMvdW5kZXJzY29yZS9wdWxsLzEyNDdcbiAgICAgIC8vIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICAvL1xuICAgICAgLy8gVGhpcyBhbHNvIGVuc3VyZXMgYSBzdGFibGUgc29ydCBpbiBWOCBhbmQgb3RoZXIgZW5naW5lcy5cbiAgICAgIC8vIFNlZSBodHRwczovL2J1Z3MuY2hyb21pdW0ub3JnL3AvdjgvaXNzdWVzL2RldGFpbD9pZD05MCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAgcmV0dXJuIG9iamVjdC5pbmRleCAtIG90aGVyLmluZGV4O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgdGhhdCBpcyB0aGUgY29tcG9zaXRpb24gb2YgcGFydGlhbGx5IGFwcGxpZWQgYXJndW1lbnRzLFxuICAgICAqIHBsYWNlaG9sZGVycywgYW5kIHByb3ZpZGVkIGFyZ3VtZW50cyBpbnRvIGEgc2luZ2xlIGFycmF5IG9mIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJncyBUaGUgcHJvdmlkZWQgYXJndW1lbnRzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHBhcnRpYWxzIFRoZSBhcmd1bWVudHMgdG8gcHJlcGVuZCB0byB0aG9zZSBwcm92aWRlZC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBob2xkZXJzIFRoZSBgcGFydGlhbHNgIHBsYWNlaG9sZGVyIGluZGV4ZXMuXG4gICAgICogQHBhcmFtcyB7Ym9vbGVhbn0gW2lzQ3VycmllZF0gU3BlY2lmeSBjb21wb3NpbmcgZm9yIGEgY3VycmllZCBmdW5jdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBjb21wb3NlZCBhcmd1bWVudHMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29tcG9zZUFyZ3MoYXJncywgcGFydGlhbHMsIGhvbGRlcnMsIGlzQ3VycmllZCkge1xuICAgICAgdmFyIGFyZ3NJbmRleCA9IC0xLFxuICAgICAgICAgIGFyZ3NMZW5ndGggPSBhcmdzLmxlbmd0aCxcbiAgICAgICAgICBob2xkZXJzTGVuZ3RoID0gaG9sZGVycy5sZW5ndGgsXG4gICAgICAgICAgbGVmdEluZGV4ID0gLTEsXG4gICAgICAgICAgbGVmdExlbmd0aCA9IHBhcnRpYWxzLmxlbmd0aCxcbiAgICAgICAgICByYW5nZUxlbmd0aCA9IG5hdGl2ZU1heChhcmdzTGVuZ3RoIC0gaG9sZGVyc0xlbmd0aCwgMCksXG4gICAgICAgICAgcmVzdWx0ID0gQXJyYXkobGVmdExlbmd0aCArIHJhbmdlTGVuZ3RoKSxcbiAgICAgICAgICBpc1VuY3VycmllZCA9ICFpc0N1cnJpZWQ7XG5cbiAgICAgIHdoaWxlICgrK2xlZnRJbmRleCA8IGxlZnRMZW5ndGgpIHtcbiAgICAgICAgcmVzdWx0W2xlZnRJbmRleF0gPSBwYXJ0aWFsc1tsZWZ0SW5kZXhdO1xuICAgICAgfVxuICAgICAgd2hpbGUgKCsrYXJnc0luZGV4IDwgaG9sZGVyc0xlbmd0aCkge1xuICAgICAgICBpZiAoaXNVbmN1cnJpZWQgfHwgYXJnc0luZGV4IDwgYXJnc0xlbmd0aCkge1xuICAgICAgICAgIHJlc3VsdFtob2xkZXJzW2FyZ3NJbmRleF1dID0gYXJnc1thcmdzSW5kZXhdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB3aGlsZSAocmFuZ2VMZW5ndGgtLSkge1xuICAgICAgICByZXN1bHRbbGVmdEluZGV4KytdID0gYXJnc1thcmdzSW5kZXgrK107XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gaXMgbGlrZSBgY29tcG9zZUFyZ3NgIGV4Y2VwdCB0aGF0IHRoZSBhcmd1bWVudHMgY29tcG9zaXRpb25cbiAgICAgKiBpcyB0YWlsb3JlZCBmb3IgYF8ucGFydGlhbFJpZ2h0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJncyBUaGUgcHJvdmlkZWQgYXJndW1lbnRzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHBhcnRpYWxzIFRoZSBhcmd1bWVudHMgdG8gYXBwZW5kIHRvIHRob3NlIHByb3ZpZGVkLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGhvbGRlcnMgVGhlIGBwYXJ0aWFsc2AgcGxhY2Vob2xkZXIgaW5kZXhlcy5cbiAgICAgKiBAcGFyYW1zIHtib29sZWFufSBbaXNDdXJyaWVkXSBTcGVjaWZ5IGNvbXBvc2luZyBmb3IgYSBjdXJyaWVkIGZ1bmN0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGNvbXBvc2VkIGFyZ3VtZW50cy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb21wb3NlQXJnc1JpZ2h0KGFyZ3MsIHBhcnRpYWxzLCBob2xkZXJzLCBpc0N1cnJpZWQpIHtcbiAgICAgIHZhciBhcmdzSW5kZXggPSAtMSxcbiAgICAgICAgICBhcmdzTGVuZ3RoID0gYXJncy5sZW5ndGgsXG4gICAgICAgICAgaG9sZGVyc0luZGV4ID0gLTEsXG4gICAgICAgICAgaG9sZGVyc0xlbmd0aCA9IGhvbGRlcnMubGVuZ3RoLFxuICAgICAgICAgIHJpZ2h0SW5kZXggPSAtMSxcbiAgICAgICAgICByaWdodExlbmd0aCA9IHBhcnRpYWxzLmxlbmd0aCxcbiAgICAgICAgICByYW5nZUxlbmd0aCA9IG5hdGl2ZU1heChhcmdzTGVuZ3RoIC0gaG9sZGVyc0xlbmd0aCwgMCksXG4gICAgICAgICAgcmVzdWx0ID0gQXJyYXkocmFuZ2VMZW5ndGggKyByaWdodExlbmd0aCksXG4gICAgICAgICAgaXNVbmN1cnJpZWQgPSAhaXNDdXJyaWVkO1xuXG4gICAgICB3aGlsZSAoKythcmdzSW5kZXggPCByYW5nZUxlbmd0aCkge1xuICAgICAgICByZXN1bHRbYXJnc0luZGV4XSA9IGFyZ3NbYXJnc0luZGV4XTtcbiAgICAgIH1cbiAgICAgIHZhciBvZmZzZXQgPSBhcmdzSW5kZXg7XG4gICAgICB3aGlsZSAoKytyaWdodEluZGV4IDwgcmlnaHRMZW5ndGgpIHtcbiAgICAgICAgcmVzdWx0W29mZnNldCArIHJpZ2h0SW5kZXhdID0gcGFydGlhbHNbcmlnaHRJbmRleF07XG4gICAgICB9XG4gICAgICB3aGlsZSAoKytob2xkZXJzSW5kZXggPCBob2xkZXJzTGVuZ3RoKSB7XG4gICAgICAgIGlmIChpc1VuY3VycmllZCB8fCBhcmdzSW5kZXggPCBhcmdzTGVuZ3RoKSB7XG4gICAgICAgICAgcmVzdWx0W29mZnNldCArIGhvbGRlcnNbaG9sZGVyc0luZGV4XV0gPSBhcmdzW2FyZ3NJbmRleCsrXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb3BpZXMgdGhlIHZhbHVlcyBvZiBgc291cmNlYCB0byBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBzb3VyY2UgVGhlIGFycmF5IHRvIGNvcHkgdmFsdWVzIGZyb20uXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2FycmF5PVtdXSBUaGUgYXJyYXkgdG8gY29weSB2YWx1ZXMgdG8uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29weUFycmF5KHNvdXJjZSwgYXJyYXkpIHtcbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IHNvdXJjZS5sZW5ndGg7XG5cbiAgICAgIGFycmF5IHx8IChhcnJheSA9IEFycmF5KGxlbmd0aCkpO1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgYXJyYXlbaW5kZXhdID0gc291cmNlW2luZGV4XTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhcnJheTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb3BpZXMgcHJvcGVydGllcyBvZiBgc291cmNlYCB0byBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IHRvIGNvcHkgcHJvcGVydGllcyBmcm9tLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHByb3BzIFRoZSBwcm9wZXJ0eSBpZGVudGlmaWVycyB0byBjb3B5LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0PXt9XSBUaGUgb2JqZWN0IHRvIGNvcHkgcHJvcGVydGllcyB0by5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb3BpZWQgdmFsdWVzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29weU9iamVjdChzb3VyY2UsIHByb3BzLCBvYmplY3QsIGN1c3RvbWl6ZXIpIHtcbiAgICAgIHZhciBpc05ldyA9ICFvYmplY3Q7XG4gICAgICBvYmplY3QgfHwgKG9iamVjdCA9IHt9KTtcblxuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gcHJvcHMubGVuZ3RoO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIga2V5ID0gcHJvcHNbaW5kZXhdO1xuXG4gICAgICAgIHZhciBuZXdWYWx1ZSA9IGN1c3RvbWl6ZXJcbiAgICAgICAgICA/IGN1c3RvbWl6ZXIob2JqZWN0W2tleV0sIHNvdXJjZVtrZXldLCBrZXksIG9iamVjdCwgc291cmNlKVxuICAgICAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgICAgIGlmIChuZXdWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgbmV3VmFsdWUgPSBzb3VyY2Vba2V5XTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNOZXcpIHtcbiAgICAgICAgICBiYXNlQXNzaWduVmFsdWUob2JqZWN0LCBrZXksIG5ld1ZhbHVlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhc3NpZ25WYWx1ZShvYmplY3QsIGtleSwgbmV3VmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gb2JqZWN0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvcGllcyBvd24gc3ltYm9scyBvZiBgc291cmNlYCB0byBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IHRvIGNvcHkgc3ltYm9scyBmcm9tLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0PXt9XSBUaGUgb2JqZWN0IHRvIGNvcHkgc3ltYm9scyB0by5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNvcHlTeW1ib2xzKHNvdXJjZSwgb2JqZWN0KSB7XG4gICAgICByZXR1cm4gY29weU9iamVjdChzb3VyY2UsIGdldFN5bWJvbHMoc291cmNlKSwgb2JqZWN0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb3BpZXMgb3duIGFuZCBpbmhlcml0ZWQgc3ltYm9scyBvZiBgc291cmNlYCB0byBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IHRvIGNvcHkgc3ltYm9scyBmcm9tLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0PXt9XSBUaGUgb2JqZWN0IHRvIGNvcHkgc3ltYm9scyB0by5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNvcHlTeW1ib2xzSW4oc291cmNlLCBvYmplY3QpIHtcbiAgICAgIHJldHVybiBjb3B5T2JqZWN0KHNvdXJjZSwgZ2V0U3ltYm9sc0luKHNvdXJjZSksIG9iamVjdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIGxpa2UgYF8uZ3JvdXBCeWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHNldHRlciBUaGUgZnVuY3Rpb24gdG8gc2V0IGFjY3VtdWxhdG9yIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaW5pdGlhbGl6ZXJdIFRoZSBhY2N1bXVsYXRvciBvYmplY3QgaW5pdGlhbGl6ZXIuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYWdncmVnYXRvciBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVBZ2dyZWdhdG9yKHNldHRlciwgaW5pdGlhbGl6ZXIpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihjb2xsZWN0aW9uLCBpdGVyYXRlZSkge1xuICAgICAgICB2YXIgZnVuYyA9IGlzQXJyYXkoY29sbGVjdGlvbikgPyBhcnJheUFnZ3JlZ2F0b3IgOiBiYXNlQWdncmVnYXRvcixcbiAgICAgICAgICAgIGFjY3VtdWxhdG9yID0gaW5pdGlhbGl6ZXIgPyBpbml0aWFsaXplcigpIDoge307XG5cbiAgICAgICAgcmV0dXJuIGZ1bmMoY29sbGVjdGlvbiwgc2V0dGVyLCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMiksIGFjY3VtdWxhdG9yKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIGxpa2UgYF8uYXNzaWduYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gYXNzaWduZXIgVGhlIGZ1bmN0aW9uIHRvIGFzc2lnbiB2YWx1ZXMuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYXNzaWduZXIgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlQXNzaWduZXIoYXNzaWduZXIpIHtcbiAgICAgIHJldHVybiBiYXNlUmVzdChmdW5jdGlvbihvYmplY3QsIHNvdXJjZXMpIHtcbiAgICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgICBsZW5ndGggPSBzb3VyY2VzLmxlbmd0aCxcbiAgICAgICAgICAgIGN1c3RvbWl6ZXIgPSBsZW5ndGggPiAxID8gc291cmNlc1tsZW5ndGggLSAxXSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGd1YXJkID0gbGVuZ3RoID4gMiA/IHNvdXJjZXNbMl0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgY3VzdG9taXplciA9IChhc3NpZ25lci5sZW5ndGggPiAzICYmIHR5cGVvZiBjdXN0b21pemVyID09ICdmdW5jdGlvbicpXG4gICAgICAgICAgPyAobGVuZ3RoLS0sIGN1c3RvbWl6ZXIpXG4gICAgICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgaWYgKGd1YXJkICYmIGlzSXRlcmF0ZWVDYWxsKHNvdXJjZXNbMF0sIHNvdXJjZXNbMV0sIGd1YXJkKSkge1xuICAgICAgICAgIGN1c3RvbWl6ZXIgPSBsZW5ndGggPCAzID8gdW5kZWZpbmVkIDogY3VzdG9taXplcjtcbiAgICAgICAgICBsZW5ndGggPSAxO1xuICAgICAgICB9XG4gICAgICAgIG9iamVjdCA9IE9iamVjdChvYmplY3QpO1xuICAgICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICAgIHZhciBzb3VyY2UgPSBzb3VyY2VzW2luZGV4XTtcbiAgICAgICAgICBpZiAoc291cmNlKSB7XG4gICAgICAgICAgICBhc3NpZ25lcihvYmplY3QsIHNvdXJjZSwgaW5kZXgsIGN1c3RvbWl6ZXIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGBiYXNlRWFjaGAgb3IgYGJhc2VFYWNoUmlnaHRgIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBlYWNoRnVuYyBUaGUgZnVuY3Rpb24gdG8gaXRlcmF0ZSBvdmVyIGEgY29sbGVjdGlvbi5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtmcm9tUmlnaHRdIFNwZWNpZnkgaXRlcmF0aW5nIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBiYXNlIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUJhc2VFYWNoKGVhY2hGdW5jLCBmcm9tUmlnaHQpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihjb2xsZWN0aW9uLCBpdGVyYXRlZSkge1xuICAgICAgICBpZiAoY29sbGVjdGlvbiA9PSBudWxsKSB7XG4gICAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc0FycmF5TGlrZShjb2xsZWN0aW9uKSkge1xuICAgICAgICAgIHJldHVybiBlYWNoRnVuYyhjb2xsZWN0aW9uLCBpdGVyYXRlZSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGxlbmd0aCA9IGNvbGxlY3Rpb24ubGVuZ3RoLFxuICAgICAgICAgICAgaW5kZXggPSBmcm9tUmlnaHQgPyBsZW5ndGggOiAtMSxcbiAgICAgICAgICAgIGl0ZXJhYmxlID0gT2JqZWN0KGNvbGxlY3Rpb24pO1xuXG4gICAgICAgIHdoaWxlICgoZnJvbVJpZ2h0ID8gaW5kZXgtLSA6ICsraW5kZXggPCBsZW5ndGgpKSB7XG4gICAgICAgICAgaWYgKGl0ZXJhdGVlKGl0ZXJhYmxlW2luZGV4XSwgaW5kZXgsIGl0ZXJhYmxlKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29sbGVjdGlvbjtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGJhc2UgZnVuY3Rpb24gZm9yIG1ldGhvZHMgbGlrZSBgXy5mb3JJbmAgYW5kIGBfLmZvck93bmAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW2Zyb21SaWdodF0gU3BlY2lmeSBpdGVyYXRpbmcgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGJhc2UgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlQmFzZUZvcihmcm9tUmlnaHQpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihvYmplY3QsIGl0ZXJhdGVlLCBrZXlzRnVuYykge1xuICAgICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICAgIGl0ZXJhYmxlID0gT2JqZWN0KG9iamVjdCksXG4gICAgICAgICAgICBwcm9wcyA9IGtleXNGdW5jKG9iamVjdCksXG4gICAgICAgICAgICBsZW5ndGggPSBwcm9wcy5sZW5ndGg7XG5cbiAgICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgICAgdmFyIGtleSA9IHByb3BzW2Zyb21SaWdodCA/IGxlbmd0aCA6ICsraW5kZXhdO1xuICAgICAgICAgIGlmIChpdGVyYXRlZShpdGVyYWJsZVtrZXldLCBrZXksIGl0ZXJhYmxlKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCB3cmFwcyBgZnVuY2AgdG8gaW52b2tlIGl0IHdpdGggdGhlIG9wdGlvbmFsIGB0aGlzYFxuICAgICAqIGJpbmRpbmcgb2YgYHRoaXNBcmdgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byB3cmFwLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIGZsYWdzLiBTZWUgYGNyZWF0ZVdyYXBgIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBmdW5jYC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyB3cmFwcGVkIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUJpbmQoZnVuYywgYml0bWFzaywgdGhpc0FyZykge1xuICAgICAgdmFyIGlzQmluZCA9IGJpdG1hc2sgJiBXUkFQX0JJTkRfRkxBRyxcbiAgICAgICAgICBDdG9yID0gY3JlYXRlQ3RvcihmdW5jKTtcblxuICAgICAgZnVuY3Rpb24gd3JhcHBlcigpIHtcbiAgICAgICAgdmFyIGZuID0gKHRoaXMgJiYgdGhpcyAhPT0gcm9vdCAmJiB0aGlzIGluc3RhbmNlb2Ygd3JhcHBlcikgPyBDdG9yIDogZnVuYztcbiAgICAgICAgcmV0dXJuIGZuLmFwcGx5KGlzQmluZCA/IHRoaXNBcmcgOiB0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHdyYXBwZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIGxpa2UgYF8ubG93ZXJGaXJzdGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2ROYW1lIFRoZSBuYW1lIG9mIHRoZSBgU3RyaW5nYCBjYXNlIG1ldGhvZCB0byB1c2UuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgY2FzZSBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVDYXNlRmlyc3QobWV0aG9kTmFtZSkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKHN0cmluZykge1xuICAgICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuXG4gICAgICAgIHZhciBzdHJTeW1ib2xzID0gaGFzVW5pY29kZShzdHJpbmcpXG4gICAgICAgICAgPyBzdHJpbmdUb0FycmF5KHN0cmluZylcbiAgICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgICAgICB2YXIgY2hyID0gc3RyU3ltYm9sc1xuICAgICAgICAgID8gc3RyU3ltYm9sc1swXVxuICAgICAgICAgIDogc3RyaW5nLmNoYXJBdCgwKTtcblxuICAgICAgICB2YXIgdHJhaWxpbmcgPSBzdHJTeW1ib2xzXG4gICAgICAgICAgPyBjYXN0U2xpY2Uoc3RyU3ltYm9scywgMSkuam9pbignJylcbiAgICAgICAgICA6IHN0cmluZy5zbGljZSgxKTtcblxuICAgICAgICByZXR1cm4gY2hyW21ldGhvZE5hbWVdKCkgKyB0cmFpbGluZztcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIGxpa2UgYF8uY2FtZWxDYXNlYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIHRvIGNvbWJpbmUgZWFjaCB3b3JkLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGNvbXBvdW5kZXIgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlQ29tcG91bmRlcihjYWxsYmFjaykge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKHN0cmluZykge1xuICAgICAgICByZXR1cm4gYXJyYXlSZWR1Y2Uod29yZHMoZGVidXJyKHN0cmluZykucmVwbGFjZShyZUFwb3MsICcnKSksIGNhbGxiYWNrLCAnJyk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHByb2R1Y2VzIGFuIGluc3RhbmNlIG9mIGBDdG9yYCByZWdhcmRsZXNzIG9mXG4gICAgICogd2hldGhlciBpdCB3YXMgaW52b2tlZCBhcyBwYXJ0IG9mIGEgYG5ld2AgZXhwcmVzc2lvbiBvciBieSBgY2FsbGAgb3IgYGFwcGx5YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gQ3RvciBUaGUgY29uc3RydWN0b3IgdG8gd3JhcC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyB3cmFwcGVkIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUN0b3IoQ3Rvcikge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICAvLyBVc2UgYSBgc3dpdGNoYCBzdGF0ZW1lbnQgdG8gd29yayB3aXRoIGNsYXNzIGNvbnN0cnVjdG9ycy4gU2VlXG4gICAgICAgIC8vIGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLWVjbWFzY3JpcHQtZnVuY3Rpb24tb2JqZWN0cy1jYWxsLXRoaXNhcmd1bWVudC1hcmd1bWVudHNsaXN0XG4gICAgICAgIC8vIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgICBzd2l0Y2ggKGFyZ3MubGVuZ3RoKSB7XG4gICAgICAgICAgY2FzZSAwOiByZXR1cm4gbmV3IEN0b3I7XG4gICAgICAgICAgY2FzZSAxOiByZXR1cm4gbmV3IEN0b3IoYXJnc1swXSk7XG4gICAgICAgICAgY2FzZSAyOiByZXR1cm4gbmV3IEN0b3IoYXJnc1swXSwgYXJnc1sxXSk7XG4gICAgICAgICAgY2FzZSAzOiByZXR1cm4gbmV3IEN0b3IoYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSk7XG4gICAgICAgICAgY2FzZSA0OiByZXR1cm4gbmV3IEN0b3IoYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSwgYXJnc1szXSk7XG4gICAgICAgICAgY2FzZSA1OiByZXR1cm4gbmV3IEN0b3IoYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSwgYXJnc1szXSwgYXJnc1s0XSk7XG4gICAgICAgICAgY2FzZSA2OiByZXR1cm4gbmV3IEN0b3IoYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSwgYXJnc1szXSwgYXJnc1s0XSwgYXJnc1s1XSk7XG4gICAgICAgICAgY2FzZSA3OiByZXR1cm4gbmV3IEN0b3IoYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSwgYXJnc1szXSwgYXJnc1s0XSwgYXJnc1s1XSwgYXJnc1s2XSk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHRoaXNCaW5kaW5nID0gYmFzZUNyZWF0ZShDdG9yLnByb3RvdHlwZSksXG4gICAgICAgICAgICByZXN1bHQgPSBDdG9yLmFwcGx5KHRoaXNCaW5kaW5nLCBhcmdzKTtcblxuICAgICAgICAvLyBNaW1pYyB0aGUgY29uc3RydWN0b3IncyBgcmV0dXJuYCBiZWhhdmlvci5cbiAgICAgICAgLy8gU2VlIGh0dHBzOi8vZXM1LmdpdGh1Yi5pby8jeDEzLjIuMiBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAgICByZXR1cm4gaXNPYmplY3QocmVzdWx0KSA/IHJlc3VsdCA6IHRoaXNCaW5kaW5nO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCB3cmFwcyBgZnVuY2AgdG8gZW5hYmxlIGN1cnJ5aW5nLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byB3cmFwLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIGZsYWdzLiBTZWUgYGNyZWF0ZVdyYXBgIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGFyaXR5IFRoZSBhcml0eSBvZiBgZnVuY2AuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgd3JhcHBlZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVDdXJyeShmdW5jLCBiaXRtYXNrLCBhcml0eSkge1xuICAgICAgdmFyIEN0b3IgPSBjcmVhdGVDdG9yKGZ1bmMpO1xuXG4gICAgICBmdW5jdGlvbiB3cmFwcGVyKCkge1xuICAgICAgICB2YXIgbGVuZ3RoID0gYXJndW1lbnRzLmxlbmd0aCxcbiAgICAgICAgICAgIGFyZ3MgPSBBcnJheShsZW5ndGgpLFxuICAgICAgICAgICAgaW5kZXggPSBsZW5ndGgsXG4gICAgICAgICAgICBwbGFjZWhvbGRlciA9IGdldEhvbGRlcih3cmFwcGVyKTtcblxuICAgICAgICB3aGlsZSAoaW5kZXgtLSkge1xuICAgICAgICAgIGFyZ3NbaW5kZXhdID0gYXJndW1lbnRzW2luZGV4XTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgaG9sZGVycyA9IChsZW5ndGggPCAzICYmIGFyZ3NbMF0gIT09IHBsYWNlaG9sZGVyICYmIGFyZ3NbbGVuZ3RoIC0gMV0gIT09IHBsYWNlaG9sZGVyKVxuICAgICAgICAgID8gW11cbiAgICAgICAgICA6IHJlcGxhY2VIb2xkZXJzKGFyZ3MsIHBsYWNlaG9sZGVyKTtcblxuICAgICAgICBsZW5ndGggLT0gaG9sZGVycy5sZW5ndGg7XG4gICAgICAgIGlmIChsZW5ndGggPCBhcml0eSkge1xuICAgICAgICAgIHJldHVybiBjcmVhdGVSZWN1cnJ5KFxuICAgICAgICAgICAgZnVuYywgYml0bWFzaywgY3JlYXRlSHlicmlkLCB3cmFwcGVyLnBsYWNlaG9sZGVyLCB1bmRlZmluZWQsXG4gICAgICAgICAgICBhcmdzLCBob2xkZXJzLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgYXJpdHkgLSBsZW5ndGgpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBmbiA9ICh0aGlzICYmIHRoaXMgIT09IHJvb3QgJiYgdGhpcyBpbnN0YW5jZW9mIHdyYXBwZXIpID8gQ3RvciA6IGZ1bmM7XG4gICAgICAgIHJldHVybiBhcHBseShmbiwgdGhpcywgYXJncyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gd3JhcHBlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgYF8uZmluZGAgb3IgYF8uZmluZExhc3RgIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmaW5kSW5kZXhGdW5jIFRoZSBmdW5jdGlvbiB0byBmaW5kIHRoZSBjb2xsZWN0aW9uIGluZGV4LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZpbmQgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlRmluZChmaW5kSW5kZXhGdW5jKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oY29sbGVjdGlvbiwgcHJlZGljYXRlLCBmcm9tSW5kZXgpIHtcbiAgICAgICAgdmFyIGl0ZXJhYmxlID0gT2JqZWN0KGNvbGxlY3Rpb24pO1xuICAgICAgICBpZiAoIWlzQXJyYXlMaWtlKGNvbGxlY3Rpb24pKSB7XG4gICAgICAgICAgdmFyIGl0ZXJhdGVlID0gZ2V0SXRlcmF0ZWUocHJlZGljYXRlLCAzKTtcbiAgICAgICAgICBjb2xsZWN0aW9uID0ga2V5cyhjb2xsZWN0aW9uKTtcbiAgICAgICAgICBwcmVkaWNhdGUgPSBmdW5jdGlvbihrZXkpIHsgcmV0dXJuIGl0ZXJhdGVlKGl0ZXJhYmxlW2tleV0sIGtleSwgaXRlcmFibGUpOyB9O1xuICAgICAgICB9XG4gICAgICAgIHZhciBpbmRleCA9IGZpbmRJbmRleEZ1bmMoY29sbGVjdGlvbiwgcHJlZGljYXRlLCBmcm9tSW5kZXgpO1xuICAgICAgICByZXR1cm4gaW5kZXggPiAtMSA/IGl0ZXJhYmxlW2l0ZXJhdGVlID8gY29sbGVjdGlvbltpbmRleF0gOiBpbmRleF0gOiB1bmRlZmluZWQ7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBgXy5mbG93YCBvciBgXy5mbG93UmlnaHRgIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtmcm9tUmlnaHRdIFNwZWNpZnkgaXRlcmF0aW5nIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmbG93IGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUZsb3coZnJvbVJpZ2h0KSB7XG4gICAgICByZXR1cm4gZmxhdFJlc3QoZnVuY3Rpb24oZnVuY3MpIHtcbiAgICAgICAgdmFyIGxlbmd0aCA9IGZ1bmNzLmxlbmd0aCxcbiAgICAgICAgICAgIGluZGV4ID0gbGVuZ3RoLFxuICAgICAgICAgICAgcHJlcmVxID0gTG9kYXNoV3JhcHBlci5wcm90b3R5cGUudGhydTtcblxuICAgICAgICBpZiAoZnJvbVJpZ2h0KSB7XG4gICAgICAgICAgZnVuY3MucmV2ZXJzZSgpO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlIChpbmRleC0tKSB7XG4gICAgICAgICAgdmFyIGZ1bmMgPSBmdW5jc1tpbmRleF07XG4gICAgICAgICAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHByZXJlcSAmJiAhd3JhcHBlciAmJiBnZXRGdW5jTmFtZShmdW5jKSA9PSAnd3JhcHBlcicpIHtcbiAgICAgICAgICAgIHZhciB3cmFwcGVyID0gbmV3IExvZGFzaFdyYXBwZXIoW10sIHRydWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpbmRleCA9IHdyYXBwZXIgPyBpbmRleCA6IGxlbmd0aDtcbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICBmdW5jID0gZnVuY3NbaW5kZXhdO1xuXG4gICAgICAgICAgdmFyIGZ1bmNOYW1lID0gZ2V0RnVuY05hbWUoZnVuYyksXG4gICAgICAgICAgICAgIGRhdGEgPSBmdW5jTmFtZSA9PSAnd3JhcHBlcicgPyBnZXREYXRhKGZ1bmMpIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgaWYgKGRhdGEgJiYgaXNMYXppYWJsZShkYXRhWzBdKSAmJlxuICAgICAgICAgICAgICAgIGRhdGFbMV0gPT0gKFdSQVBfQVJZX0ZMQUcgfCBXUkFQX0NVUlJZX0ZMQUcgfCBXUkFQX1BBUlRJQUxfRkxBRyB8IFdSQVBfUkVBUkdfRkxBRykgJiZcbiAgICAgICAgICAgICAgICAhZGF0YVs0XS5sZW5ndGggJiYgZGF0YVs5XSA9PSAxXG4gICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgd3JhcHBlciA9IHdyYXBwZXJbZ2V0RnVuY05hbWUoZGF0YVswXSldLmFwcGx5KHdyYXBwZXIsIGRhdGFbM10pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB3cmFwcGVyID0gKGZ1bmMubGVuZ3RoID09IDEgJiYgaXNMYXppYWJsZShmdW5jKSlcbiAgICAgICAgICAgICAgPyB3cmFwcGVyW2Z1bmNOYW1lXSgpXG4gICAgICAgICAgICAgIDogd3JhcHBlci50aHJ1KGZ1bmMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHMsXG4gICAgICAgICAgICAgIHZhbHVlID0gYXJnc1swXTtcblxuICAgICAgICAgIGlmICh3cmFwcGVyICYmIGFyZ3MubGVuZ3RoID09IDEgJiYgaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiB3cmFwcGVyLnBsYW50KHZhbHVlKS52YWx1ZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICB2YXIgaW5kZXggPSAwLFxuICAgICAgICAgICAgICByZXN1bHQgPSBsZW5ndGggPyBmdW5jc1tpbmRleF0uYXBwbHkodGhpcywgYXJncykgOiB2YWx1ZTtcblxuICAgICAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgICAgICByZXN1bHQgPSBmdW5jc1tpbmRleF0uY2FsbCh0aGlzLCByZXN1bHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgd3JhcHMgYGZ1bmNgIHRvIGludm9rZSBpdCB3aXRoIG9wdGlvbmFsIGB0aGlzYFxuICAgICAqIGJpbmRpbmcgb2YgYHRoaXNBcmdgLCBwYXJ0aWFsIGFwcGxpY2F0aW9uLCBhbmQgY3VycnlpbmcuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258c3RyaW5nfSBmdW5jIFRoZSBmdW5jdGlvbiBvciBtZXRob2QgbmFtZSB0byB3cmFwLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIGZsYWdzLiBTZWUgYGNyZWF0ZVdyYXBgIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBmdW5jYC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbcGFydGlhbHNdIFRoZSBhcmd1bWVudHMgdG8gcHJlcGVuZCB0byB0aG9zZSBwcm92aWRlZCB0b1xuICAgICAqICB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtob2xkZXJzXSBUaGUgYHBhcnRpYWxzYCBwbGFjZWhvbGRlciBpbmRleGVzLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtwYXJ0aWFsc1JpZ2h0XSBUaGUgYXJndW1lbnRzIHRvIGFwcGVuZCB0byB0aG9zZSBwcm92aWRlZFxuICAgICAqICB0byB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtob2xkZXJzUmlnaHRdIFRoZSBgcGFydGlhbHNSaWdodGAgcGxhY2Vob2xkZXIgaW5kZXhlcy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbYXJnUG9zXSBUaGUgYXJndW1lbnQgcG9zaXRpb25zIG9mIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFthcnldIFRoZSBhcml0eSBjYXAgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJpdHldIFRoZSBhcml0eSBvZiBgZnVuY2AuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgd3JhcHBlZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVIeWJyaWQoZnVuYywgYml0bWFzaywgdGhpc0FyZywgcGFydGlhbHMsIGhvbGRlcnMsIHBhcnRpYWxzUmlnaHQsIGhvbGRlcnNSaWdodCwgYXJnUG9zLCBhcnksIGFyaXR5KSB7XG4gICAgICB2YXIgaXNBcnkgPSBiaXRtYXNrICYgV1JBUF9BUllfRkxBRyxcbiAgICAgICAgICBpc0JpbmQgPSBiaXRtYXNrICYgV1JBUF9CSU5EX0ZMQUcsXG4gICAgICAgICAgaXNCaW5kS2V5ID0gYml0bWFzayAmIFdSQVBfQklORF9LRVlfRkxBRyxcbiAgICAgICAgICBpc0N1cnJpZWQgPSBiaXRtYXNrICYgKFdSQVBfQ1VSUllfRkxBRyB8IFdSQVBfQ1VSUllfUklHSFRfRkxBRyksXG4gICAgICAgICAgaXNGbGlwID0gYml0bWFzayAmIFdSQVBfRkxJUF9GTEFHLFxuICAgICAgICAgIEN0b3IgPSBpc0JpbmRLZXkgPyB1bmRlZmluZWQgOiBjcmVhdGVDdG9yKGZ1bmMpO1xuXG4gICAgICBmdW5jdGlvbiB3cmFwcGVyKCkge1xuICAgICAgICB2YXIgbGVuZ3RoID0gYXJndW1lbnRzLmxlbmd0aCxcbiAgICAgICAgICAgIGFyZ3MgPSBBcnJheShsZW5ndGgpLFxuICAgICAgICAgICAgaW5kZXggPSBsZW5ndGg7XG5cbiAgICAgICAgd2hpbGUgKGluZGV4LS0pIHtcbiAgICAgICAgICBhcmdzW2luZGV4XSA9IGFyZ3VtZW50c1tpbmRleF07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzQ3VycmllZCkge1xuICAgICAgICAgIHZhciBwbGFjZWhvbGRlciA9IGdldEhvbGRlcih3cmFwcGVyKSxcbiAgICAgICAgICAgICAgaG9sZGVyc0NvdW50ID0gY291bnRIb2xkZXJzKGFyZ3MsIHBsYWNlaG9sZGVyKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocGFydGlhbHMpIHtcbiAgICAgICAgICBhcmdzID0gY29tcG9zZUFyZ3MoYXJncywgcGFydGlhbHMsIGhvbGRlcnMsIGlzQ3VycmllZCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBhcnRpYWxzUmlnaHQpIHtcbiAgICAgICAgICBhcmdzID0gY29tcG9zZUFyZ3NSaWdodChhcmdzLCBwYXJ0aWFsc1JpZ2h0LCBob2xkZXJzUmlnaHQsIGlzQ3VycmllZCk7XG4gICAgICAgIH1cbiAgICAgICAgbGVuZ3RoIC09IGhvbGRlcnNDb3VudDtcbiAgICAgICAgaWYgKGlzQ3VycmllZCAmJiBsZW5ndGggPCBhcml0eSkge1xuICAgICAgICAgIHZhciBuZXdIb2xkZXJzID0gcmVwbGFjZUhvbGRlcnMoYXJncywgcGxhY2Vob2xkZXIpO1xuICAgICAgICAgIHJldHVybiBjcmVhdGVSZWN1cnJ5KFxuICAgICAgICAgICAgZnVuYywgYml0bWFzaywgY3JlYXRlSHlicmlkLCB3cmFwcGVyLnBsYWNlaG9sZGVyLCB0aGlzQXJnLFxuICAgICAgICAgICAgYXJncywgbmV3SG9sZGVycywgYXJnUG9zLCBhcnksIGFyaXR5IC0gbGVuZ3RoXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdGhpc0JpbmRpbmcgPSBpc0JpbmQgPyB0aGlzQXJnIDogdGhpcyxcbiAgICAgICAgICAgIGZuID0gaXNCaW5kS2V5ID8gdGhpc0JpbmRpbmdbZnVuY10gOiBmdW5jO1xuXG4gICAgICAgIGxlbmd0aCA9IGFyZ3MubGVuZ3RoO1xuICAgICAgICBpZiAoYXJnUG9zKSB7XG4gICAgICAgICAgYXJncyA9IHJlb3JkZXIoYXJncywgYXJnUG9zKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc0ZsaXAgJiYgbGVuZ3RoID4gMSkge1xuICAgICAgICAgIGFyZ3MucmV2ZXJzZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc0FyeSAmJiBhcnkgPCBsZW5ndGgpIHtcbiAgICAgICAgICBhcmdzLmxlbmd0aCA9IGFyeTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcyAmJiB0aGlzICE9PSByb290ICYmIHRoaXMgaW5zdGFuY2VvZiB3cmFwcGVyKSB7XG4gICAgICAgICAgZm4gPSBDdG9yIHx8IGNyZWF0ZUN0b3IoZm4pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmbi5hcHBseSh0aGlzQmluZGluZywgYXJncyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gd3JhcHBlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gbGlrZSBgXy5pbnZlcnRCeWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHNldHRlciBUaGUgZnVuY3Rpb24gdG8gc2V0IGFjY3VtdWxhdG9yIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSB0b0l0ZXJhdGVlIFRoZSBmdW5jdGlvbiB0byByZXNvbHZlIGl0ZXJhdGVlcy5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBpbnZlcnRlciBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVJbnZlcnRlcihzZXR0ZXIsIHRvSXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihvYmplY3QsIGl0ZXJhdGVlKSB7XG4gICAgICAgIHJldHVybiBiYXNlSW52ZXJ0ZXIob2JqZWN0LCBzZXR0ZXIsIHRvSXRlcmF0ZWUoaXRlcmF0ZWUpLCB7fSk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHBlcmZvcm1zIGEgbWF0aGVtYXRpY2FsIG9wZXJhdGlvbiBvbiB0d28gdmFsdWVzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBvcGVyYXRvciBUaGUgZnVuY3Rpb24gdG8gcGVyZm9ybSB0aGUgb3BlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZGVmYXVsdFZhbHVlXSBUaGUgdmFsdWUgdXNlZCBmb3IgYHVuZGVmaW5lZGAgYXJndW1lbnRzLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IG1hdGhlbWF0aWNhbCBvcGVyYXRpb24gZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlTWF0aE9wZXJhdGlvbihvcGVyYXRvciwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24odmFsdWUsIG90aGVyKSB7XG4gICAgICAgIHZhciByZXN1bHQ7XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkICYmIG90aGVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICByZXR1cm4gZGVmYXVsdFZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgcmVzdWx0ID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG90aGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBpZiAocmVzdWx0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBvdGhlcjtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJyB8fCB0eXBlb2Ygb3RoZXIgPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHZhbHVlID0gYmFzZVRvU3RyaW5nKHZhbHVlKTtcbiAgICAgICAgICAgIG90aGVyID0gYmFzZVRvU3RyaW5nKG90aGVyKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFsdWUgPSBiYXNlVG9OdW1iZXIodmFsdWUpO1xuICAgICAgICAgICAgb3RoZXIgPSBiYXNlVG9OdW1iZXIob3RoZXIpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXN1bHQgPSBvcGVyYXRvcih2YWx1ZSwgb3RoZXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiBsaWtlIGBfLm92ZXJgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBhcnJheUZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGl0ZXJhdGUgb3ZlciBpdGVyYXRlZXMuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgb3ZlciBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVPdmVyKGFycmF5RnVuYykge1xuICAgICAgcmV0dXJuIGZsYXRSZXN0KGZ1bmN0aW9uKGl0ZXJhdGVlcykge1xuICAgICAgICBpdGVyYXRlZXMgPSBhcnJheU1hcChpdGVyYXRlZXMsIGJhc2VVbmFyeShnZXRJdGVyYXRlZSgpKSk7XG4gICAgICAgIHJldHVybiBiYXNlUmVzdChmdW5jdGlvbihhcmdzKSB7XG4gICAgICAgICAgdmFyIHRoaXNBcmcgPSB0aGlzO1xuICAgICAgICAgIHJldHVybiBhcnJheUZ1bmMoaXRlcmF0ZWVzLCBmdW5jdGlvbihpdGVyYXRlZSkge1xuICAgICAgICAgICAgcmV0dXJuIGFwcGx5KGl0ZXJhdGVlLCB0aGlzQXJnLCBhcmdzKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIHRoZSBwYWRkaW5nIGZvciBgc3RyaW5nYCBiYXNlZCBvbiBgbGVuZ3RoYC4gVGhlIGBjaGFyc2Agc3RyaW5nXG4gICAgICogaXMgdHJ1bmNhdGVkIGlmIHRoZSBudW1iZXIgb2YgY2hhcmFjdGVycyBleGNlZWRzIGBsZW5ndGhgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbGVuZ3RoIFRoZSBwYWRkaW5nIGxlbmd0aC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW2NoYXJzPScgJ10gVGhlIHN0cmluZyB1c2VkIGFzIHBhZGRpbmcuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgcGFkZGluZyBmb3IgYHN0cmluZ2AuXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlUGFkZGluZyhsZW5ndGgsIGNoYXJzKSB7XG4gICAgICBjaGFycyA9IGNoYXJzID09PSB1bmRlZmluZWQgPyAnICcgOiBiYXNlVG9TdHJpbmcoY2hhcnMpO1xuXG4gICAgICB2YXIgY2hhcnNMZW5ndGggPSBjaGFycy5sZW5ndGg7XG4gICAgICBpZiAoY2hhcnNMZW5ndGggPCAyKSB7XG4gICAgICAgIHJldHVybiBjaGFyc0xlbmd0aCA/IGJhc2VSZXBlYXQoY2hhcnMsIGxlbmd0aCkgOiBjaGFycztcbiAgICAgIH1cbiAgICAgIHZhciByZXN1bHQgPSBiYXNlUmVwZWF0KGNoYXJzLCBuYXRpdmVDZWlsKGxlbmd0aCAvIHN0cmluZ1NpemUoY2hhcnMpKSk7XG4gICAgICByZXR1cm4gaGFzVW5pY29kZShjaGFycylcbiAgICAgICAgPyBjYXN0U2xpY2Uoc3RyaW5nVG9BcnJheShyZXN1bHQpLCAwLCBsZW5ndGgpLmpvaW4oJycpXG4gICAgICAgIDogcmVzdWx0LnNsaWNlKDAsIGxlbmd0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgd3JhcHMgYGZ1bmNgIHRvIGludm9rZSBpdCB3aXRoIHRoZSBgdGhpc2AgYmluZGluZ1xuICAgICAqIG9mIGB0aGlzQXJnYCBhbmQgYHBhcnRpYWxzYCBwcmVwZW5kZWQgdG8gdGhlIGFyZ3VtZW50cyBpdCByZWNlaXZlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gd3JhcC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy4gU2VlIGBjcmVhdGVXcmFwYCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqIEBwYXJhbSB7Kn0gdGhpc0FyZyBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHBhcnRpYWxzIFRoZSBhcmd1bWVudHMgdG8gcHJlcGVuZCB0byB0aG9zZSBwcm92aWRlZCB0b1xuICAgICAqICB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHdyYXBwZWQgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlUGFydGlhbChmdW5jLCBiaXRtYXNrLCB0aGlzQXJnLCBwYXJ0aWFscykge1xuICAgICAgdmFyIGlzQmluZCA9IGJpdG1hc2sgJiBXUkFQX0JJTkRfRkxBRyxcbiAgICAgICAgICBDdG9yID0gY3JlYXRlQ3RvcihmdW5jKTtcblxuICAgICAgZnVuY3Rpb24gd3JhcHBlcigpIHtcbiAgICAgICAgdmFyIGFyZ3NJbmRleCA9IC0xLFxuICAgICAgICAgICAgYXJnc0xlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGgsXG4gICAgICAgICAgICBsZWZ0SW5kZXggPSAtMSxcbiAgICAgICAgICAgIGxlZnRMZW5ndGggPSBwYXJ0aWFscy5sZW5ndGgsXG4gICAgICAgICAgICBhcmdzID0gQXJyYXkobGVmdExlbmd0aCArIGFyZ3NMZW5ndGgpLFxuICAgICAgICAgICAgZm4gPSAodGhpcyAmJiB0aGlzICE9PSByb290ICYmIHRoaXMgaW5zdGFuY2VvZiB3cmFwcGVyKSA/IEN0b3IgOiBmdW5jO1xuXG4gICAgICAgIHdoaWxlICgrK2xlZnRJbmRleCA8IGxlZnRMZW5ndGgpIHtcbiAgICAgICAgICBhcmdzW2xlZnRJbmRleF0gPSBwYXJ0aWFsc1tsZWZ0SW5kZXhdO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlIChhcmdzTGVuZ3RoLS0pIHtcbiAgICAgICAgICBhcmdzW2xlZnRJbmRleCsrXSA9IGFyZ3VtZW50c1srK2FyZ3NJbmRleF07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFwcGx5KGZuLCBpc0JpbmQgPyB0aGlzQXJnIDogdGhpcywgYXJncyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gd3JhcHBlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgYF8ucmFuZ2VgIG9yIGBfLnJhbmdlUmlnaHRgIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtmcm9tUmlnaHRdIFNwZWNpZnkgaXRlcmF0aW5nIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyByYW5nZSBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVSYW5nZShmcm9tUmlnaHQpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihzdGFydCwgZW5kLCBzdGVwKSB7XG4gICAgICAgIGlmIChzdGVwICYmIHR5cGVvZiBzdGVwICE9ICdudW1iZXInICYmIGlzSXRlcmF0ZWVDYWxsKHN0YXJ0LCBlbmQsIHN0ZXApKSB7XG4gICAgICAgICAgZW5kID0gc3RlcCA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICAvLyBFbnN1cmUgdGhlIHNpZ24gb2YgYC0wYCBpcyBwcmVzZXJ2ZWQuXG4gICAgICAgIHN0YXJ0ID0gdG9GaW5pdGUoc3RhcnQpO1xuICAgICAgICBpZiAoZW5kID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBlbmQgPSBzdGFydDtcbiAgICAgICAgICBzdGFydCA9IDA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZW5kID0gdG9GaW5pdGUoZW5kKTtcbiAgICAgICAgfVxuICAgICAgICBzdGVwID0gc3RlcCA9PT0gdW5kZWZpbmVkID8gKHN0YXJ0IDwgZW5kID8gMSA6IC0xKSA6IHRvRmluaXRlKHN0ZXApO1xuICAgICAgICByZXR1cm4gYmFzZVJhbmdlKHN0YXJ0LCBlbmQsIHN0ZXAsIGZyb21SaWdodCk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHBlcmZvcm1zIGEgcmVsYXRpb25hbCBvcGVyYXRpb24gb24gdHdvIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gb3BlcmF0b3IgVGhlIGZ1bmN0aW9uIHRvIHBlcmZvcm0gdGhlIG9wZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyByZWxhdGlvbmFsIG9wZXJhdGlvbiBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVSZWxhdGlvbmFsT3BlcmF0aW9uKG9wZXJhdG9yKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24odmFsdWUsIG90aGVyKSB7XG4gICAgICAgIGlmICghKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJyAmJiB0eXBlb2Ygb3RoZXIgPT0gJ3N0cmluZycpKSB7XG4gICAgICAgICAgdmFsdWUgPSB0b051bWJlcih2YWx1ZSk7XG4gICAgICAgICAgb3RoZXIgPSB0b051bWJlcihvdGhlcik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9wZXJhdG9yKHZhbHVlLCBvdGhlcik7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHdyYXBzIGBmdW5jYCB0byBjb250aW51ZSBjdXJyeWluZy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gd3JhcC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy4gU2VlIGBjcmVhdGVXcmFwYCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHdyYXBGdW5jIFRoZSBmdW5jdGlvbiB0byBjcmVhdGUgdGhlIGBmdW5jYCB3cmFwcGVyLlxuICAgICAqIEBwYXJhbSB7Kn0gcGxhY2Vob2xkZXIgVGhlIHBsYWNlaG9sZGVyIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgZnVuY2AuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW3BhcnRpYWxzXSBUaGUgYXJndW1lbnRzIHRvIHByZXBlbmQgdG8gdGhvc2UgcHJvdmlkZWQgdG9cbiAgICAgKiAgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbaG9sZGVyc10gVGhlIGBwYXJ0aWFsc2AgcGxhY2Vob2xkZXIgaW5kZXhlcy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbYXJnUG9zXSBUaGUgYXJndW1lbnQgcG9zaXRpb25zIG9mIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFthcnldIFRoZSBhcml0eSBjYXAgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJpdHldIFRoZSBhcml0eSBvZiBgZnVuY2AuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgd3JhcHBlZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVSZWN1cnJ5KGZ1bmMsIGJpdG1hc2ssIHdyYXBGdW5jLCBwbGFjZWhvbGRlciwgdGhpc0FyZywgcGFydGlhbHMsIGhvbGRlcnMsIGFyZ1BvcywgYXJ5LCBhcml0eSkge1xuICAgICAgdmFyIGlzQ3VycnkgPSBiaXRtYXNrICYgV1JBUF9DVVJSWV9GTEFHLFxuICAgICAgICAgIG5ld0hvbGRlcnMgPSBpc0N1cnJ5ID8gaG9sZGVycyA6IHVuZGVmaW5lZCxcbiAgICAgICAgICBuZXdIb2xkZXJzUmlnaHQgPSBpc0N1cnJ5ID8gdW5kZWZpbmVkIDogaG9sZGVycyxcbiAgICAgICAgICBuZXdQYXJ0aWFscyA9IGlzQ3VycnkgPyBwYXJ0aWFscyA6IHVuZGVmaW5lZCxcbiAgICAgICAgICBuZXdQYXJ0aWFsc1JpZ2h0ID0gaXNDdXJyeSA/IHVuZGVmaW5lZCA6IHBhcnRpYWxzO1xuXG4gICAgICBiaXRtYXNrIHw9IChpc0N1cnJ5ID8gV1JBUF9QQVJUSUFMX0ZMQUcgOiBXUkFQX1BBUlRJQUxfUklHSFRfRkxBRyk7XG4gICAgICBiaXRtYXNrICY9IH4oaXNDdXJyeSA/IFdSQVBfUEFSVElBTF9SSUdIVF9GTEFHIDogV1JBUF9QQVJUSUFMX0ZMQUcpO1xuXG4gICAgICBpZiAoIShiaXRtYXNrICYgV1JBUF9DVVJSWV9CT1VORF9GTEFHKSkge1xuICAgICAgICBiaXRtYXNrICY9IH4oV1JBUF9CSU5EX0ZMQUcgfCBXUkFQX0JJTkRfS0VZX0ZMQUcpO1xuICAgICAgfVxuICAgICAgdmFyIG5ld0RhdGEgPSBbXG4gICAgICAgIGZ1bmMsIGJpdG1hc2ssIHRoaXNBcmcsIG5ld1BhcnRpYWxzLCBuZXdIb2xkZXJzLCBuZXdQYXJ0aWFsc1JpZ2h0LFxuICAgICAgICBuZXdIb2xkZXJzUmlnaHQsIGFyZ1BvcywgYXJ5LCBhcml0eVxuICAgICAgXTtcblxuICAgICAgdmFyIHJlc3VsdCA9IHdyYXBGdW5jLmFwcGx5KHVuZGVmaW5lZCwgbmV3RGF0YSk7XG4gICAgICBpZiAoaXNMYXppYWJsZShmdW5jKSkge1xuICAgICAgICBzZXREYXRhKHJlc3VsdCwgbmV3RGF0YSk7XG4gICAgICB9XG4gICAgICByZXN1bHQucGxhY2Vob2xkZXIgPSBwbGFjZWhvbGRlcjtcbiAgICAgIHJldHVybiBzZXRXcmFwVG9TdHJpbmcocmVzdWx0LCBmdW5jLCBiaXRtYXNrKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gbGlrZSBgXy5yb3VuZGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2ROYW1lIFRoZSBuYW1lIG9mIHRoZSBgTWF0aGAgbWV0aG9kIHRvIHVzZSB3aGVuIHJvdW5kaW5nLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHJvdW5kIGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZVJvdW5kKG1ldGhvZE5hbWUpIHtcbiAgICAgIHZhciBmdW5jID0gTWF0aFttZXRob2ROYW1lXTtcbiAgICAgIHJldHVybiBmdW5jdGlvbihudW1iZXIsIHByZWNpc2lvbikge1xuICAgICAgICBudW1iZXIgPSB0b051bWJlcihudW1iZXIpO1xuICAgICAgICBwcmVjaXNpb24gPSBwcmVjaXNpb24gPT0gbnVsbCA/IDAgOiBuYXRpdmVNaW4odG9JbnRlZ2VyKHByZWNpc2lvbiksIDI5Mik7XG4gICAgICAgIGlmIChwcmVjaXNpb24pIHtcbiAgICAgICAgICAvLyBTaGlmdCB3aXRoIGV4cG9uZW50aWFsIG5vdGF0aW9uIHRvIGF2b2lkIGZsb2F0aW5nLXBvaW50IGlzc3Vlcy5cbiAgICAgICAgICAvLyBTZWUgW01ETl0oaHR0cHM6Ly9tZG4uaW8vcm91bmQjRXhhbXBsZXMpIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICAgICAgdmFyIHBhaXIgPSAodG9TdHJpbmcobnVtYmVyKSArICdlJykuc3BsaXQoJ2UnKSxcbiAgICAgICAgICAgICAgdmFsdWUgPSBmdW5jKHBhaXJbMF0gKyAnZScgKyAoK3BhaXJbMV0gKyBwcmVjaXNpb24pKTtcblxuICAgICAgICAgIHBhaXIgPSAodG9TdHJpbmcodmFsdWUpICsgJ2UnKS5zcGxpdCgnZScpO1xuICAgICAgICAgIHJldHVybiArKHBhaXJbMF0gKyAnZScgKyAoK3BhaXJbMV0gLSBwcmVjaXNpb24pKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnVuYyhudW1iZXIpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc2V0IG9iamVjdCBvZiBgdmFsdWVzYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gdmFsdWVzIFRoZSB2YWx1ZXMgdG8gYWRkIHRvIHRoZSBzZXQuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IHNldC5cbiAgICAgKi9cbiAgICB2YXIgY3JlYXRlU2V0ID0gIShTZXQgJiYgKDEgLyBzZXRUb0FycmF5KG5ldyBTZXQoWywtMF0pKVsxXSkgPT0gSU5GSU5JVFkpID8gbm9vcCA6IGZ1bmN0aW9uKHZhbHVlcykge1xuICAgICAgcmV0dXJuIG5ldyBTZXQodmFsdWVzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGBfLnRvUGFpcnNgIG9yIGBfLnRvUGFpcnNJbmAgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGtleXNGdW5jIFRoZSBmdW5jdGlvbiB0byBnZXQgdGhlIGtleXMgb2YgYSBnaXZlbiBvYmplY3QuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgcGFpcnMgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlVG9QYWlycyhrZXlzRnVuYykge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgICB2YXIgdGFnID0gZ2V0VGFnKG9iamVjdCk7XG4gICAgICAgIGlmICh0YWcgPT0gbWFwVGFnKSB7XG4gICAgICAgICAgcmV0dXJuIG1hcFRvQXJyYXkob2JqZWN0KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGFnID09IHNldFRhZykge1xuICAgICAgICAgIHJldHVybiBzZXRUb1BhaXJzKG9iamVjdCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGJhc2VUb1BhaXJzKG9iamVjdCwga2V5c0Z1bmMob2JqZWN0KSk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGVpdGhlciBjdXJyaWVzIG9yIGludm9rZXMgYGZ1bmNgIHdpdGggb3B0aW9uYWxcbiAgICAgKiBgdGhpc2AgYmluZGluZyBhbmQgcGFydGlhbGx5IGFwcGxpZWQgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufHN0cmluZ30gZnVuYyBUaGUgZnVuY3Rpb24gb3IgbWV0aG9kIG5hbWUgdG8gd3JhcC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy5cbiAgICAgKiAgICAxIC0gYF8uYmluZGBcbiAgICAgKiAgICAyIC0gYF8uYmluZEtleWBcbiAgICAgKiAgICA0IC0gYF8uY3VycnlgIG9yIGBfLmN1cnJ5UmlnaHRgIG9mIGEgYm91bmQgZnVuY3Rpb25cbiAgICAgKiAgICA4IC0gYF8uY3VycnlgXG4gICAgICogICAxNiAtIGBfLmN1cnJ5UmlnaHRgXG4gICAgICogICAzMiAtIGBfLnBhcnRpYWxgXG4gICAgICogICA2NCAtIGBfLnBhcnRpYWxSaWdodGBcbiAgICAgKiAgMTI4IC0gYF8ucmVhcmdgXG4gICAgICogIDI1NiAtIGBfLmFyeWBcbiAgICAgKiAgNTEyIC0gYF8uZmxpcGBcbiAgICAgKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFtwYXJ0aWFsc10gVGhlIGFyZ3VtZW50cyB0byBiZSBwYXJ0aWFsbHkgYXBwbGllZC5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbaG9sZGVyc10gVGhlIGBwYXJ0aWFsc2AgcGxhY2Vob2xkZXIgaW5kZXhlcy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbYXJnUG9zXSBUaGUgYXJndW1lbnQgcG9zaXRpb25zIG9mIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFthcnldIFRoZSBhcml0eSBjYXAgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJpdHldIFRoZSBhcml0eSBvZiBgZnVuY2AuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgd3JhcHBlZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVXcmFwKGZ1bmMsIGJpdG1hc2ssIHRoaXNBcmcsIHBhcnRpYWxzLCBob2xkZXJzLCBhcmdQb3MsIGFyeSwgYXJpdHkpIHtcbiAgICAgIHZhciBpc0JpbmRLZXkgPSBiaXRtYXNrICYgV1JBUF9CSU5EX0tFWV9GTEFHO1xuICAgICAgaWYgKCFpc0JpbmRLZXkgJiYgdHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gICAgICB9XG4gICAgICB2YXIgbGVuZ3RoID0gcGFydGlhbHMgPyBwYXJ0aWFscy5sZW5ndGggOiAwO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgYml0bWFzayAmPSB+KFdSQVBfUEFSVElBTF9GTEFHIHwgV1JBUF9QQVJUSUFMX1JJR0hUX0ZMQUcpO1xuICAgICAgICBwYXJ0aWFscyA9IGhvbGRlcnMgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICBhcnkgPSBhcnkgPT09IHVuZGVmaW5lZCA/IGFyeSA6IG5hdGl2ZU1heCh0b0ludGVnZXIoYXJ5KSwgMCk7XG4gICAgICBhcml0eSA9IGFyaXR5ID09PSB1bmRlZmluZWQgPyBhcml0eSA6IHRvSW50ZWdlcihhcml0eSk7XG4gICAgICBsZW5ndGggLT0gaG9sZGVycyA/IGhvbGRlcnMubGVuZ3RoIDogMDtcblxuICAgICAgaWYgKGJpdG1hc2sgJiBXUkFQX1BBUlRJQUxfUklHSFRfRkxBRykge1xuICAgICAgICB2YXIgcGFydGlhbHNSaWdodCA9IHBhcnRpYWxzLFxuICAgICAgICAgICAgaG9sZGVyc1JpZ2h0ID0gaG9sZGVycztcblxuICAgICAgICBwYXJ0aWFscyA9IGhvbGRlcnMgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICB2YXIgZGF0YSA9IGlzQmluZEtleSA/IHVuZGVmaW5lZCA6IGdldERhdGEoZnVuYyk7XG5cbiAgICAgIHZhciBuZXdEYXRhID0gW1xuICAgICAgICBmdW5jLCBiaXRtYXNrLCB0aGlzQXJnLCBwYXJ0aWFscywgaG9sZGVycywgcGFydGlhbHNSaWdodCwgaG9sZGVyc1JpZ2h0LFxuICAgICAgICBhcmdQb3MsIGFyeSwgYXJpdHlcbiAgICAgIF07XG5cbiAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgIG1lcmdlRGF0YShuZXdEYXRhLCBkYXRhKTtcbiAgICAgIH1cbiAgICAgIGZ1bmMgPSBuZXdEYXRhWzBdO1xuICAgICAgYml0bWFzayA9IG5ld0RhdGFbMV07XG4gICAgICB0aGlzQXJnID0gbmV3RGF0YVsyXTtcbiAgICAgIHBhcnRpYWxzID0gbmV3RGF0YVszXTtcbiAgICAgIGhvbGRlcnMgPSBuZXdEYXRhWzRdO1xuICAgICAgYXJpdHkgPSBuZXdEYXRhWzldID0gbmV3RGF0YVs5XSA9PT0gdW5kZWZpbmVkXG4gICAgICAgID8gKGlzQmluZEtleSA/IDAgOiBmdW5jLmxlbmd0aClcbiAgICAgICAgOiBuYXRpdmVNYXgobmV3RGF0YVs5XSAtIGxlbmd0aCwgMCk7XG5cbiAgICAgIGlmICghYXJpdHkgJiYgYml0bWFzayAmIChXUkFQX0NVUlJZX0ZMQUcgfCBXUkFQX0NVUlJZX1JJR0hUX0ZMQUcpKSB7XG4gICAgICAgIGJpdG1hc2sgJj0gfihXUkFQX0NVUlJZX0ZMQUcgfCBXUkFQX0NVUlJZX1JJR0hUX0ZMQUcpO1xuICAgICAgfVxuICAgICAgaWYgKCFiaXRtYXNrIHx8IGJpdG1hc2sgPT0gV1JBUF9CSU5EX0ZMQUcpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IGNyZWF0ZUJpbmQoZnVuYywgYml0bWFzaywgdGhpc0FyZyk7XG4gICAgICB9IGVsc2UgaWYgKGJpdG1hc2sgPT0gV1JBUF9DVVJSWV9GTEFHIHx8IGJpdG1hc2sgPT0gV1JBUF9DVVJSWV9SSUdIVF9GTEFHKSB7XG4gICAgICAgIHJlc3VsdCA9IGNyZWF0ZUN1cnJ5KGZ1bmMsIGJpdG1hc2ssIGFyaXR5KTtcbiAgICAgIH0gZWxzZSBpZiAoKGJpdG1hc2sgPT0gV1JBUF9QQVJUSUFMX0ZMQUcgfHwgYml0bWFzayA9PSAoV1JBUF9CSU5EX0ZMQUcgfCBXUkFQX1BBUlRJQUxfRkxBRykpICYmICFob2xkZXJzLmxlbmd0aCkge1xuICAgICAgICByZXN1bHQgPSBjcmVhdGVQYXJ0aWFsKGZ1bmMsIGJpdG1hc2ssIHRoaXNBcmcsIHBhcnRpYWxzKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdCA9IGNyZWF0ZUh5YnJpZC5hcHBseSh1bmRlZmluZWQsIG5ld0RhdGEpO1xuICAgICAgfVxuICAgICAgdmFyIHNldHRlciA9IGRhdGEgPyBiYXNlU2V0RGF0YSA6IHNldERhdGE7XG4gICAgICByZXR1cm4gc2V0V3JhcFRvU3RyaW5nKHNldHRlcihyZXN1bHQsIG5ld0RhdGEpLCBmdW5jLCBiaXRtYXNrKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVc2VkIGJ5IGBfLmRlZmF1bHRzYCB0byBjdXN0b21pemUgaXRzIGBfLmFzc2lnbkluYCB1c2UgdG8gYXNzaWduIHByb3BlcnRpZXNcbiAgICAgKiBvZiBzb3VyY2Ugb2JqZWN0cyB0byB0aGUgZGVzdGluYXRpb24gb2JqZWN0IGZvciBhbGwgZGVzdGluYXRpb24gcHJvcGVydGllc1xuICAgICAqIHRoYXQgcmVzb2x2ZSB0byBgdW5kZWZpbmVkYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSBvYmpWYWx1ZSBUaGUgZGVzdGluYXRpb24gdmFsdWUuXG4gICAgICogQHBhcmFtIHsqfSBzcmNWYWx1ZSBUaGUgc291cmNlIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgcHJvcGVydHkgdG8gYXNzaWduLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIHBhcmVudCBvYmplY3Qgb2YgYG9ialZhbHVlYC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgdmFsdWUgdG8gYXNzaWduLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGN1c3RvbURlZmF1bHRzQXNzaWduSW4ob2JqVmFsdWUsIHNyY1ZhbHVlLCBrZXksIG9iamVjdCkge1xuICAgICAgaWYgKG9ialZhbHVlID09PSB1bmRlZmluZWQgfHxcbiAgICAgICAgICAoZXEob2JqVmFsdWUsIG9iamVjdFByb3RvW2tleV0pICYmICFoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSkpIHtcbiAgICAgICAgcmV0dXJuIHNyY1ZhbHVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG9ialZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVzZWQgYnkgYF8uZGVmYXVsdHNEZWVwYCB0byBjdXN0b21pemUgaXRzIGBfLm1lcmdlYCB1c2UgdG8gbWVyZ2Ugc291cmNlXG4gICAgICogb2JqZWN0cyBpbnRvIGRlc3RpbmF0aW9uIG9iamVjdHMgdGhhdCBhcmUgcGFzc2VkIHRocnUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gb2JqVmFsdWUgVGhlIGRlc3RpbmF0aW9uIHZhbHVlLlxuICAgICAqIEBwYXJhbSB7Kn0gc3JjVmFsdWUgVGhlIHNvdXJjZSB2YWx1ZS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHByb3BlcnR5IHRvIG1lcmdlLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIHBhcmVudCBvYmplY3Qgb2YgYG9ialZhbHVlYC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBwYXJlbnQgb2JqZWN0IG9mIGBzcmNWYWx1ZWAuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtzdGFja10gVHJhY2tzIHRyYXZlcnNlZCBzb3VyY2UgdmFsdWVzIGFuZCB0aGVpciBtZXJnZWRcbiAgICAgKiAgY291bnRlcnBhcnRzLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSB2YWx1ZSB0byBhc3NpZ24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3VzdG9tRGVmYXVsdHNNZXJnZShvYmpWYWx1ZSwgc3JjVmFsdWUsIGtleSwgb2JqZWN0LCBzb3VyY2UsIHN0YWNrKSB7XG4gICAgICBpZiAoaXNPYmplY3Qob2JqVmFsdWUpICYmIGlzT2JqZWN0KHNyY1ZhbHVlKSkge1xuICAgICAgICAvLyBSZWN1cnNpdmVseSBtZXJnZSBvYmplY3RzIGFuZCBhcnJheXMgKHN1c2NlcHRpYmxlIHRvIGNhbGwgc3RhY2sgbGltaXRzKS5cbiAgICAgICAgc3RhY2suc2V0KHNyY1ZhbHVlLCBvYmpWYWx1ZSk7XG4gICAgICAgIGJhc2VNZXJnZShvYmpWYWx1ZSwgc3JjVmFsdWUsIHVuZGVmaW5lZCwgY3VzdG9tRGVmYXVsdHNNZXJnZSwgc3RhY2spO1xuICAgICAgICBzdGFja1snZGVsZXRlJ10oc3JjVmFsdWUpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG9ialZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVzZWQgYnkgYF8ub21pdGAgdG8gY3VzdG9taXplIGl0cyBgXy5jbG9uZURlZXBgIHVzZSB0byBvbmx5IGNsb25lIHBsYWluXG4gICAgICogb2JqZWN0cy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHByb3BlcnR5IHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHVuY2xvbmVkIHZhbHVlIG9yIGB1bmRlZmluZWRgIHRvIGRlZmVyIGNsb25pbmcgdG8gYF8uY2xvbmVEZWVwYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjdXN0b21PbWl0Q2xvbmUodmFsdWUsIGtleSkge1xuICAgICAgcmV0dXJuIChrZXkgIT09IHVuZGVmaW5lZCAmJiBpc1BsYWluT2JqZWN0KHZhbHVlKSkgPyB1bmRlZmluZWQgOiB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYGJhc2VJc0VxdWFsRGVlcGAgZm9yIGFycmF5cyB3aXRoIHN1cHBvcnQgZm9yXG4gICAgICogcGFydGlhbCBkZWVwIGNvbXBhcmlzb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBvdGhlciBUaGUgb3RoZXIgYXJyYXkgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy4gU2VlIGBiYXNlSXNFcXVhbGAgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjdXN0b21pemVyIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY29tcGFyaXNvbnMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXF1YWxGdW5jIFRoZSBmdW5jdGlvbiB0byBkZXRlcm1pbmUgZXF1aXZhbGVudHMgb2YgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzdGFjayBUcmFja3MgdHJhdmVyc2VkIGBhcnJheWAgYW5kIGBvdGhlcmAgb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGFycmF5cyBhcmUgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGVxdWFsQXJyYXlzKGFycmF5LCBvdGhlciwgYml0bWFzaywgY3VzdG9taXplciwgZXF1YWxGdW5jLCBzdGFjaykge1xuICAgICAgdmFyIGlzUGFydGlhbCA9IGJpdG1hc2sgJiBDT01QQVJFX1BBUlRJQUxfRkxBRyxcbiAgICAgICAgICBhcnJMZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgICAgb3RoTGVuZ3RoID0gb3RoZXIubGVuZ3RoO1xuXG4gICAgICBpZiAoYXJyTGVuZ3RoICE9IG90aExlbmd0aCAmJiAhKGlzUGFydGlhbCAmJiBvdGhMZW5ndGggPiBhcnJMZW5ndGgpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIC8vIEFzc3VtZSBjeWNsaWMgdmFsdWVzIGFyZSBlcXVhbC5cbiAgICAgIHZhciBzdGFja2VkID0gc3RhY2suZ2V0KGFycmF5KTtcbiAgICAgIGlmIChzdGFja2VkICYmIHN0YWNrLmdldChvdGhlcikpIHtcbiAgICAgICAgcmV0dXJuIHN0YWNrZWQgPT0gb3RoZXI7XG4gICAgICB9XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICByZXN1bHQgPSB0cnVlLFxuICAgICAgICAgIHNlZW4gPSAoYml0bWFzayAmIENPTVBBUkVfVU5PUkRFUkVEX0ZMQUcpID8gbmV3IFNldENhY2hlIDogdW5kZWZpbmVkO1xuXG4gICAgICBzdGFjay5zZXQoYXJyYXksIG90aGVyKTtcbiAgICAgIHN0YWNrLnNldChvdGhlciwgYXJyYXkpO1xuXG4gICAgICAvLyBJZ25vcmUgbm9uLWluZGV4IHByb3BlcnRpZXMuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGFyckxlbmd0aCkge1xuICAgICAgICB2YXIgYXJyVmFsdWUgPSBhcnJheVtpbmRleF0sXG4gICAgICAgICAgICBvdGhWYWx1ZSA9IG90aGVyW2luZGV4XTtcblxuICAgICAgICBpZiAoY3VzdG9taXplcikge1xuICAgICAgICAgIHZhciBjb21wYXJlZCA9IGlzUGFydGlhbFxuICAgICAgICAgICAgPyBjdXN0b21pemVyKG90aFZhbHVlLCBhcnJWYWx1ZSwgaW5kZXgsIG90aGVyLCBhcnJheSwgc3RhY2spXG4gICAgICAgICAgICA6IGN1c3RvbWl6ZXIoYXJyVmFsdWUsIG90aFZhbHVlLCBpbmRleCwgYXJyYXksIG90aGVyLCBzdGFjayk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbXBhcmVkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBpZiAoY29tcGFyZWQpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXN1bHQgPSBmYWxzZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICAvLyBSZWN1cnNpdmVseSBjb21wYXJlIGFycmF5cyAoc3VzY2VwdGlibGUgdG8gY2FsbCBzdGFjayBsaW1pdHMpLlxuICAgICAgICBpZiAoc2Vlbikge1xuICAgICAgICAgIGlmICghYXJyYXlTb21lKG90aGVyLCBmdW5jdGlvbihvdGhWYWx1ZSwgb3RoSW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWNhY2hlSGFzKHNlZW4sIG90aEluZGV4KSAmJlxuICAgICAgICAgICAgICAgICAgICAoYXJyVmFsdWUgPT09IG90aFZhbHVlIHx8IGVxdWFsRnVuYyhhcnJWYWx1ZSwgb3RoVmFsdWUsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIHN0YWNrKSkpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBzZWVuLnB1c2gob3RoSW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSkpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IGZhbHNlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKCEoXG4gICAgICAgICAgICAgIGFyclZhbHVlID09PSBvdGhWYWx1ZSB8fFxuICAgICAgICAgICAgICAgIGVxdWFsRnVuYyhhcnJWYWx1ZSwgb3RoVmFsdWUsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIHN0YWNrKVxuICAgICAgICAgICAgKSkge1xuICAgICAgICAgIHJlc3VsdCA9IGZhbHNlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBzdGFja1snZGVsZXRlJ10oYXJyYXkpO1xuICAgICAgc3RhY2tbJ2RlbGV0ZSddKG90aGVyKTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlSXNFcXVhbERlZXBgIGZvciBjb21wYXJpbmcgb2JqZWN0cyBvZlxuICAgICAqIHRoZSBzYW1lIGB0b1N0cmluZ1RhZ2AuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBmdW5jdGlvbiBvbmx5IHN1cHBvcnRzIGNvbXBhcmluZyB2YWx1ZXMgd2l0aCB0YWdzIG9mXG4gICAgICogYEJvb2xlYW5gLCBgRGF0ZWAsIGBFcnJvcmAsIGBOdW1iZXJgLCBgUmVnRXhwYCwgb3IgYFN0cmluZ2AuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvdGhlciBUaGUgb3RoZXIgb2JqZWN0IHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHRhZyBUaGUgYHRvU3RyaW5nVGFnYCBvZiB0aGUgb2JqZWN0cyB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIGZsYWdzLiBTZWUgYGJhc2VJc0VxdWFsYCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGN1c3RvbWl6ZXIgVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb21wYXJpc29ucy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBlcXVhbEZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRldGVybWluZSBlcXVpdmFsZW50cyBvZiB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHN0YWNrIFRyYWNrcyB0cmF2ZXJzZWQgYG9iamVjdGAgYW5kIGBvdGhlcmAgb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIG9iamVjdHMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBlcXVhbEJ5VGFnKG9iamVjdCwgb3RoZXIsIHRhZywgYml0bWFzaywgY3VzdG9taXplciwgZXF1YWxGdW5jLCBzdGFjaykge1xuICAgICAgc3dpdGNoICh0YWcpIHtcbiAgICAgICAgY2FzZSBkYXRhVmlld1RhZzpcbiAgICAgICAgICBpZiAoKG9iamVjdC5ieXRlTGVuZ3RoICE9IG90aGVyLmJ5dGVMZW5ndGgpIHx8XG4gICAgICAgICAgICAgIChvYmplY3QuYnl0ZU9mZnNldCAhPSBvdGhlci5ieXRlT2Zmc2V0KSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBvYmplY3QgPSBvYmplY3QuYnVmZmVyO1xuICAgICAgICAgIG90aGVyID0gb3RoZXIuYnVmZmVyO1xuXG4gICAgICAgIGNhc2UgYXJyYXlCdWZmZXJUYWc6XG4gICAgICAgICAgaWYgKChvYmplY3QuYnl0ZUxlbmd0aCAhPSBvdGhlci5ieXRlTGVuZ3RoKSB8fFxuICAgICAgICAgICAgICAhZXF1YWxGdW5jKG5ldyBVaW50OEFycmF5KG9iamVjdCksIG5ldyBVaW50OEFycmF5KG90aGVyKSkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG5cbiAgICAgICAgY2FzZSBib29sVGFnOlxuICAgICAgICBjYXNlIGRhdGVUYWc6XG4gICAgICAgIGNhc2UgbnVtYmVyVGFnOlxuICAgICAgICAgIC8vIENvZXJjZSBib29sZWFucyB0byBgMWAgb3IgYDBgIGFuZCBkYXRlcyB0byBtaWxsaXNlY29uZHMuXG4gICAgICAgICAgLy8gSW52YWxpZCBkYXRlcyBhcmUgY29lcmNlZCB0byBgTmFOYC5cbiAgICAgICAgICByZXR1cm4gZXEoK29iamVjdCwgK290aGVyKTtcblxuICAgICAgICBjYXNlIGVycm9yVGFnOlxuICAgICAgICAgIHJldHVybiBvYmplY3QubmFtZSA9PSBvdGhlci5uYW1lICYmIG9iamVjdC5tZXNzYWdlID09IG90aGVyLm1lc3NhZ2U7XG5cbiAgICAgICAgY2FzZSByZWdleHBUYWc6XG4gICAgICAgIGNhc2Ugc3RyaW5nVGFnOlxuICAgICAgICAgIC8vIENvZXJjZSByZWdleGVzIHRvIHN0cmluZ3MgYW5kIHRyZWF0IHN0cmluZ3MsIHByaW1pdGl2ZXMgYW5kIG9iamVjdHMsXG4gICAgICAgICAgLy8gYXMgZXF1YWwuIFNlZSBodHRwOi8vd3d3LmVjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtcmVnZXhwLnByb3RvdHlwZS50b3N0cmluZ1xuICAgICAgICAgIC8vIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICAgICAgcmV0dXJuIG9iamVjdCA9PSAob3RoZXIgKyAnJyk7XG5cbiAgICAgICAgY2FzZSBtYXBUYWc6XG4gICAgICAgICAgdmFyIGNvbnZlcnQgPSBtYXBUb0FycmF5O1xuXG4gICAgICAgIGNhc2Ugc2V0VGFnOlxuICAgICAgICAgIHZhciBpc1BhcnRpYWwgPSBiaXRtYXNrICYgQ09NUEFSRV9QQVJUSUFMX0ZMQUc7XG4gICAgICAgICAgY29udmVydCB8fCAoY29udmVydCA9IHNldFRvQXJyYXkpO1xuXG4gICAgICAgICAgaWYgKG9iamVjdC5zaXplICE9IG90aGVyLnNpemUgJiYgIWlzUGFydGlhbCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBBc3N1bWUgY3ljbGljIHZhbHVlcyBhcmUgZXF1YWwuXG4gICAgICAgICAgdmFyIHN0YWNrZWQgPSBzdGFjay5nZXQob2JqZWN0KTtcbiAgICAgICAgICBpZiAoc3RhY2tlZCkge1xuICAgICAgICAgICAgcmV0dXJuIHN0YWNrZWQgPT0gb3RoZXI7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJpdG1hc2sgfD0gQ09NUEFSRV9VTk9SREVSRURfRkxBRztcblxuICAgICAgICAgIC8vIFJlY3Vyc2l2ZWx5IGNvbXBhcmUgb2JqZWN0cyAoc3VzY2VwdGlibGUgdG8gY2FsbCBzdGFjayBsaW1pdHMpLlxuICAgICAgICAgIHN0YWNrLnNldChvYmplY3QsIG90aGVyKTtcbiAgICAgICAgICB2YXIgcmVzdWx0ID0gZXF1YWxBcnJheXMoY29udmVydChvYmplY3QpLCBjb252ZXJ0KG90aGVyKSwgYml0bWFzaywgY3VzdG9taXplciwgZXF1YWxGdW5jLCBzdGFjayk7XG4gICAgICAgICAgc3RhY2tbJ2RlbGV0ZSddKG9iamVjdCk7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcblxuICAgICAgICBjYXNlIHN5bWJvbFRhZzpcbiAgICAgICAgICBpZiAoc3ltYm9sVmFsdWVPZikge1xuICAgICAgICAgICAgcmV0dXJuIHN5bWJvbFZhbHVlT2YuY2FsbChvYmplY3QpID09IHN5bWJvbFZhbHVlT2YuY2FsbChvdGhlcik7XG4gICAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZUlzRXF1YWxEZWVwYCBmb3Igb2JqZWN0cyB3aXRoIHN1cHBvcnQgZm9yXG4gICAgICogcGFydGlhbCBkZWVwIGNvbXBhcmlzb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb3RoZXIgVGhlIG90aGVyIG9iamVjdCB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIGZsYWdzLiBTZWUgYGJhc2VJc0VxdWFsYCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGN1c3RvbWl6ZXIgVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb21wYXJpc29ucy5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBlcXVhbEZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRldGVybWluZSBlcXVpdmFsZW50cyBvZiB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHN0YWNrIFRyYWNrcyB0cmF2ZXJzZWQgYG9iamVjdGAgYW5kIGBvdGhlcmAgb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIG9iamVjdHMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBlcXVhbE9iamVjdHMob2JqZWN0LCBvdGhlciwgYml0bWFzaywgY3VzdG9taXplciwgZXF1YWxGdW5jLCBzdGFjaykge1xuICAgICAgdmFyIGlzUGFydGlhbCA9IGJpdG1hc2sgJiBDT01QQVJFX1BBUlRJQUxfRkxBRyxcbiAgICAgICAgICBvYmpQcm9wcyA9IGdldEFsbEtleXMob2JqZWN0KSxcbiAgICAgICAgICBvYmpMZW5ndGggPSBvYmpQcm9wcy5sZW5ndGgsXG4gICAgICAgICAgb3RoUHJvcHMgPSBnZXRBbGxLZXlzKG90aGVyKSxcbiAgICAgICAgICBvdGhMZW5ndGggPSBvdGhQcm9wcy5sZW5ndGg7XG5cbiAgICAgIGlmIChvYmpMZW5ndGggIT0gb3RoTGVuZ3RoICYmICFpc1BhcnRpYWwpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgdmFyIGluZGV4ID0gb2JqTGVuZ3RoO1xuICAgICAgd2hpbGUgKGluZGV4LS0pIHtcbiAgICAgICAgdmFyIGtleSA9IG9ialByb3BzW2luZGV4XTtcbiAgICAgICAgaWYgKCEoaXNQYXJ0aWFsID8ga2V5IGluIG90aGVyIDogaGFzT3duUHJvcGVydHkuY2FsbChvdGhlciwga2V5KSkpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIEFzc3VtZSBjeWNsaWMgdmFsdWVzIGFyZSBlcXVhbC5cbiAgICAgIHZhciBzdGFja2VkID0gc3RhY2suZ2V0KG9iamVjdCk7XG4gICAgICBpZiAoc3RhY2tlZCAmJiBzdGFjay5nZXQob3RoZXIpKSB7XG4gICAgICAgIHJldHVybiBzdGFja2VkID09IG90aGVyO1xuICAgICAgfVxuICAgICAgdmFyIHJlc3VsdCA9IHRydWU7XG4gICAgICBzdGFjay5zZXQob2JqZWN0LCBvdGhlcik7XG4gICAgICBzdGFjay5zZXQob3RoZXIsIG9iamVjdCk7XG5cbiAgICAgIHZhciBza2lwQ3RvciA9IGlzUGFydGlhbDtcbiAgICAgIHdoaWxlICgrK2luZGV4IDwgb2JqTGVuZ3RoKSB7XG4gICAgICAgIGtleSA9IG9ialByb3BzW2luZGV4XTtcbiAgICAgICAgdmFyIG9ialZhbHVlID0gb2JqZWN0W2tleV0sXG4gICAgICAgICAgICBvdGhWYWx1ZSA9IG90aGVyW2tleV07XG5cbiAgICAgICAgaWYgKGN1c3RvbWl6ZXIpIHtcbiAgICAgICAgICB2YXIgY29tcGFyZWQgPSBpc1BhcnRpYWxcbiAgICAgICAgICAgID8gY3VzdG9taXplcihvdGhWYWx1ZSwgb2JqVmFsdWUsIGtleSwgb3RoZXIsIG9iamVjdCwgc3RhY2spXG4gICAgICAgICAgICA6IGN1c3RvbWl6ZXIob2JqVmFsdWUsIG90aFZhbHVlLCBrZXksIG9iamVjdCwgb3RoZXIsIHN0YWNrKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBSZWN1cnNpdmVseSBjb21wYXJlIG9iamVjdHMgKHN1c2NlcHRpYmxlIHRvIGNhbGwgc3RhY2sgbGltaXRzKS5cbiAgICAgICAgaWYgKCEoY29tcGFyZWQgPT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgICA/IChvYmpWYWx1ZSA9PT0gb3RoVmFsdWUgfHwgZXF1YWxGdW5jKG9ialZhbHVlLCBvdGhWYWx1ZSwgYml0bWFzaywgY3VzdG9taXplciwgc3RhY2spKVxuICAgICAgICAgICAgICA6IGNvbXBhcmVkXG4gICAgICAgICAgICApKSB7XG4gICAgICAgICAgcmVzdWx0ID0gZmFsc2U7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgc2tpcEN0b3IgfHwgKHNraXBDdG9yID0ga2V5ID09ICdjb25zdHJ1Y3RvcicpO1xuICAgICAgfVxuICAgICAgaWYgKHJlc3VsdCAmJiAhc2tpcEN0b3IpIHtcbiAgICAgICAgdmFyIG9iakN0b3IgPSBvYmplY3QuY29uc3RydWN0b3IsXG4gICAgICAgICAgICBvdGhDdG9yID0gb3RoZXIuY29uc3RydWN0b3I7XG5cbiAgICAgICAgLy8gTm9uIGBPYmplY3RgIG9iamVjdCBpbnN0YW5jZXMgd2l0aCBkaWZmZXJlbnQgY29uc3RydWN0b3JzIGFyZSBub3QgZXF1YWwuXG4gICAgICAgIGlmIChvYmpDdG9yICE9IG90aEN0b3IgJiZcbiAgICAgICAgICAgICgnY29uc3RydWN0b3InIGluIG9iamVjdCAmJiAnY29uc3RydWN0b3InIGluIG90aGVyKSAmJlxuICAgICAgICAgICAgISh0eXBlb2Ygb2JqQ3RvciA9PSAnZnVuY3Rpb24nICYmIG9iakN0b3IgaW5zdGFuY2VvZiBvYmpDdG9yICYmXG4gICAgICAgICAgICAgIHR5cGVvZiBvdGhDdG9yID09ICdmdW5jdGlvbicgJiYgb3RoQ3RvciBpbnN0YW5jZW9mIG90aEN0b3IpKSB7XG4gICAgICAgICAgcmVzdWx0ID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHN0YWNrWydkZWxldGUnXShvYmplY3QpO1xuICAgICAgc3RhY2tbJ2RlbGV0ZSddKG90aGVyKTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlUmVzdGAgd2hpY2ggZmxhdHRlbnMgdGhlIHJlc3QgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGFwcGx5IGEgcmVzdCBwYXJhbWV0ZXIgdG8uXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmxhdFJlc3QoZnVuYykge1xuICAgICAgcmV0dXJuIHNldFRvU3RyaW5nKG92ZXJSZXN0KGZ1bmMsIHVuZGVmaW5lZCwgZmxhdHRlbiksIGZ1bmMgKyAnJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBvd24gZW51bWVyYWJsZSBwcm9wZXJ0eSBuYW1lcyBhbmQgc3ltYm9scyBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMgYW5kIHN5bWJvbHMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0QWxsS2V5cyhvYmplY3QpIHtcbiAgICAgIHJldHVybiBiYXNlR2V0QWxsS2V5cyhvYmplY3QsIGtleXMsIGdldFN5bWJvbHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2Ygb3duIGFuZCBpbmhlcml0ZWQgZW51bWVyYWJsZSBwcm9wZXJ0eSBuYW1lcyBhbmRcbiAgICAgKiBzeW1ib2xzIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcyBhbmQgc3ltYm9scy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRBbGxLZXlzSW4ob2JqZWN0KSB7XG4gICAgICByZXR1cm4gYmFzZUdldEFsbEtleXMob2JqZWN0LCBrZXlzSW4sIGdldFN5bWJvbHNJbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBtZXRhZGF0YSBmb3IgYGZ1bmNgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgbWV0YWRhdGEgZm9yIGBmdW5jYC5cbiAgICAgKi9cbiAgICB2YXIgZ2V0RGF0YSA9ICFtZXRhTWFwID8gbm9vcCA6IGZ1bmN0aW9uKGZ1bmMpIHtcbiAgICAgIHJldHVybiBtZXRhTWFwLmdldChmdW5jKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbmFtZSBvZiBgZnVuY2AuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGZ1bmN0aW9uIG5hbWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0RnVuY05hbWUoZnVuYykge1xuICAgICAgdmFyIHJlc3VsdCA9IChmdW5jLm5hbWUgKyAnJyksXG4gICAgICAgICAgYXJyYXkgPSByZWFsTmFtZXNbcmVzdWx0XSxcbiAgICAgICAgICBsZW5ndGggPSBoYXNPd25Qcm9wZXJ0eS5jYWxsKHJlYWxOYW1lcywgcmVzdWx0KSA/IGFycmF5Lmxlbmd0aCA6IDA7XG5cbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICB2YXIgZGF0YSA9IGFycmF5W2xlbmd0aF0sXG4gICAgICAgICAgICBvdGhlckZ1bmMgPSBkYXRhLmZ1bmM7XG4gICAgICAgIGlmIChvdGhlckZ1bmMgPT0gbnVsbCB8fCBvdGhlckZ1bmMgPT0gZnVuYykge1xuICAgICAgICAgIHJldHVybiBkYXRhLm5hbWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgYXJndW1lbnQgcGxhY2Vob2xkZXIgdmFsdWUgZm9yIGBmdW5jYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcGxhY2Vob2xkZXIgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0SG9sZGVyKGZ1bmMpIHtcbiAgICAgIHZhciBvYmplY3QgPSBoYXNPd25Qcm9wZXJ0eS5jYWxsKGxvZGFzaCwgJ3BsYWNlaG9sZGVyJykgPyBsb2Rhc2ggOiBmdW5jO1xuICAgICAgcmV0dXJuIG9iamVjdC5wbGFjZWhvbGRlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBhcHByb3ByaWF0ZSBcIml0ZXJhdGVlXCIgZnVuY3Rpb24uIElmIGBfLml0ZXJhdGVlYCBpcyBjdXN0b21pemVkLFxuICAgICAqIHRoaXMgZnVuY3Rpb24gcmV0dXJucyB0aGUgY3VzdG9tIG1ldGhvZCwgb3RoZXJ3aXNlIGl0IHJldHVybnMgYGJhc2VJdGVyYXRlZWAuXG4gICAgICogSWYgYXJndW1lbnRzIGFyZSBwcm92aWRlZCwgdGhlIGNob3NlbiBmdW5jdGlvbiBpcyBpbnZva2VkIHdpdGggdGhlbSBhbmRcbiAgICAgKiBpdHMgcmVzdWx0IGlzIHJldHVybmVkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IFt2YWx1ZV0gVGhlIHZhbHVlIHRvIGNvbnZlcnQgdG8gYW4gaXRlcmF0ZWUuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFthcml0eV0gVGhlIGFyaXR5IG9mIHRoZSBjcmVhdGVkIGl0ZXJhdGVlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgY2hvc2VuIGZ1bmN0aW9uIG9yIGl0cyByZXN1bHQuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0SXRlcmF0ZWUoKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gbG9kYXNoLml0ZXJhdGVlIHx8IGl0ZXJhdGVlO1xuICAgICAgcmVzdWx0ID0gcmVzdWx0ID09PSBpdGVyYXRlZSA/IGJhc2VJdGVyYXRlZSA6IHJlc3VsdDtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gcmVzdWx0KGFyZ3VtZW50c1swXSwgYXJndW1lbnRzWzFdKSA6IHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBkYXRhIGZvciBgbWFwYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG1hcCBUaGUgbWFwIHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIHJlZmVyZW5jZSBrZXkuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG1hcCBkYXRhLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldE1hcERhdGEobWFwLCBrZXkpIHtcbiAgICAgIHZhciBkYXRhID0gbWFwLl9fZGF0YV9fO1xuICAgICAgcmV0dXJuIGlzS2V5YWJsZShrZXkpXG4gICAgICAgID8gZGF0YVt0eXBlb2Yga2V5ID09ICdzdHJpbmcnID8gJ3N0cmluZycgOiAnaGFzaCddXG4gICAgICAgIDogZGF0YS5tYXA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgcHJvcGVydHkgbmFtZXMsIHZhbHVlcywgYW5kIGNvbXBhcmUgZmxhZ3Mgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG1hdGNoIGRhdGEgb2YgYG9iamVjdGAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0TWF0Y2hEYXRhKG9iamVjdCkge1xuICAgICAgdmFyIHJlc3VsdCA9IGtleXMob2JqZWN0KSxcbiAgICAgICAgICBsZW5ndGggPSByZXN1bHQubGVuZ3RoO1xuXG4gICAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgICAgdmFyIGtleSA9IHJlc3VsdFtsZW5ndGhdLFxuICAgICAgICAgICAgdmFsdWUgPSBvYmplY3Rba2V5XTtcblxuICAgICAgICByZXN1bHRbbGVuZ3RoXSA9IFtrZXksIHZhbHVlLCBpc1N0cmljdENvbXBhcmFibGUodmFsdWUpXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgbmF0aXZlIGZ1bmN0aW9uIGF0IGBrZXlgIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBtZXRob2QgdG8gZ2V0LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBmdW5jdGlvbiBpZiBpdCdzIG5hdGl2ZSwgZWxzZSBgdW5kZWZpbmVkYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXROYXRpdmUob2JqZWN0LCBrZXkpIHtcbiAgICAgIHZhciB2YWx1ZSA9IGdldFZhbHVlKG9iamVjdCwga2V5KTtcbiAgICAgIHJldHVybiBiYXNlSXNOYXRpdmUodmFsdWUpID8gdmFsdWUgOiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlR2V0VGFnYCB3aGljaCBpZ25vcmVzIGBTeW1ib2wudG9TdHJpbmdUYWdgIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgcmF3IGB0b1N0cmluZ1RhZ2AuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0UmF3VGFnKHZhbHVlKSB7XG4gICAgICB2YXIgaXNPd24gPSBoYXNPd25Qcm9wZXJ0eS5jYWxsKHZhbHVlLCBzeW1Ub1N0cmluZ1RhZyksXG4gICAgICAgICAgdGFnID0gdmFsdWVbc3ltVG9TdHJpbmdUYWddO1xuXG4gICAgICB0cnkge1xuICAgICAgICB2YWx1ZVtzeW1Ub1N0cmluZ1RhZ10gPSB1bmRlZmluZWQ7XG4gICAgICAgIHZhciB1bm1hc2tlZCA9IHRydWU7XG4gICAgICB9IGNhdGNoIChlKSB7fVxuXG4gICAgICB2YXIgcmVzdWx0ID0gbmF0aXZlT2JqZWN0VG9TdHJpbmcuY2FsbCh2YWx1ZSk7XG4gICAgICBpZiAodW5tYXNrZWQpIHtcbiAgICAgICAgaWYgKGlzT3duKSB7XG4gICAgICAgICAgdmFsdWVbc3ltVG9TdHJpbmdUYWddID0gdGFnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSB2YWx1ZVtzeW1Ub1N0cmluZ1RhZ107XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgb3duIGVudW1lcmFibGUgc3ltYm9scyBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2Ygc3ltYm9scy5cbiAgICAgKi9cbiAgICB2YXIgZ2V0U3ltYm9scyA9ICFuYXRpdmVHZXRTeW1ib2xzID8gc3R1YkFycmF5IDogZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICBpZiAob2JqZWN0ID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgb2JqZWN0ID0gT2JqZWN0KG9iamVjdCk7XG4gICAgICByZXR1cm4gYXJyYXlGaWx0ZXIobmF0aXZlR2V0U3ltYm9scyhvYmplY3QpLCBmdW5jdGlvbihzeW1ib2wpIHtcbiAgICAgICAgcmV0dXJuIHByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwob2JqZWN0LCBzeW1ib2wpO1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdGhlIG93biBhbmQgaW5oZXJpdGVkIGVudW1lcmFibGUgc3ltYm9scyBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2Ygc3ltYm9scy5cbiAgICAgKi9cbiAgICB2YXIgZ2V0U3ltYm9sc0luID0gIW5hdGl2ZUdldFN5bWJvbHMgPyBzdHViQXJyYXkgOiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgIHdoaWxlIChvYmplY3QpIHtcbiAgICAgICAgYXJyYXlQdXNoKHJlc3VsdCwgZ2V0U3ltYm9scyhvYmplY3QpKTtcbiAgICAgICAgb2JqZWN0ID0gZ2V0UHJvdG90eXBlKG9iamVjdCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBgdG9TdHJpbmdUYWdgIG9mIGB2YWx1ZWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGB0b1N0cmluZ1RhZ2AuXG4gICAgICovXG4gICAgdmFyIGdldFRhZyA9IGJhc2VHZXRUYWc7XG5cbiAgICAvLyBGYWxsYmFjayBmb3IgZGF0YSB2aWV3cywgbWFwcywgc2V0cywgYW5kIHdlYWsgbWFwcyBpbiBJRSAxMSBhbmQgcHJvbWlzZXMgaW4gTm9kZS5qcyA8IDYuXG4gICAgaWYgKChEYXRhVmlldyAmJiBnZXRUYWcobmV3IERhdGFWaWV3KG5ldyBBcnJheUJ1ZmZlcigxKSkpICE9IGRhdGFWaWV3VGFnKSB8fFxuICAgICAgICAoTWFwICYmIGdldFRhZyhuZXcgTWFwKSAhPSBtYXBUYWcpIHx8XG4gICAgICAgIChQcm9taXNlICYmIGdldFRhZyhQcm9taXNlLnJlc29sdmUoKSkgIT0gcHJvbWlzZVRhZykgfHxcbiAgICAgICAgKFNldCAmJiBnZXRUYWcobmV3IFNldCkgIT0gc2V0VGFnKSB8fFxuICAgICAgICAoV2Vha01hcCAmJiBnZXRUYWcobmV3IFdlYWtNYXApICE9IHdlYWtNYXBUYWcpKSB7XG4gICAgICBnZXRUYWcgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gYmFzZUdldFRhZyh2YWx1ZSksXG4gICAgICAgICAgICBDdG9yID0gcmVzdWx0ID09IG9iamVjdFRhZyA/IHZhbHVlLmNvbnN0cnVjdG9yIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgY3RvclN0cmluZyA9IEN0b3IgPyB0b1NvdXJjZShDdG9yKSA6ICcnO1xuXG4gICAgICAgIGlmIChjdG9yU3RyaW5nKSB7XG4gICAgICAgICAgc3dpdGNoIChjdG9yU3RyaW5nKSB7XG4gICAgICAgICAgICBjYXNlIGRhdGFWaWV3Q3RvclN0cmluZzogcmV0dXJuIGRhdGFWaWV3VGFnO1xuICAgICAgICAgICAgY2FzZSBtYXBDdG9yU3RyaW5nOiByZXR1cm4gbWFwVGFnO1xuICAgICAgICAgICAgY2FzZSBwcm9taXNlQ3RvclN0cmluZzogcmV0dXJuIHByb21pc2VUYWc7XG4gICAgICAgICAgICBjYXNlIHNldEN0b3JTdHJpbmc6IHJldHVybiBzZXRUYWc7XG4gICAgICAgICAgICBjYXNlIHdlYWtNYXBDdG9yU3RyaW5nOiByZXR1cm4gd2Vha01hcFRhZztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgdmlldywgYXBwbHlpbmcgYW55IGB0cmFuc2Zvcm1zYCB0byB0aGUgYHN0YXJ0YCBhbmQgYGVuZGAgcG9zaXRpb25zLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gc3RhcnQgVGhlIHN0YXJ0IG9mIHRoZSB2aWV3LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgVGhlIGVuZCBvZiB0aGUgdmlldy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB0cmFuc2Zvcm1zIFRoZSB0cmFuc2Zvcm1hdGlvbnMgdG8gYXBwbHkgdG8gdGhlIHZpZXcuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBhbiBvYmplY3QgY29udGFpbmluZyB0aGUgYHN0YXJ0YCBhbmQgYGVuZGBcbiAgICAgKiAgcG9zaXRpb25zIG9mIHRoZSB2aWV3LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldFZpZXcoc3RhcnQsIGVuZCwgdHJhbnNmb3Jtcykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gdHJhbnNmb3Jtcy5sZW5ndGg7XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBkYXRhID0gdHJhbnNmb3Jtc1tpbmRleF0sXG4gICAgICAgICAgICBzaXplID0gZGF0YS5zaXplO1xuXG4gICAgICAgIHN3aXRjaCAoZGF0YS50eXBlKSB7XG4gICAgICAgICAgY2FzZSAnZHJvcCc6ICAgICAgc3RhcnQgKz0gc2l6ZTsgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnZHJvcFJpZ2h0JzogZW5kIC09IHNpemU7IGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ3Rha2UnOiAgICAgIGVuZCA9IG5hdGl2ZU1pbihlbmQsIHN0YXJ0ICsgc2l6ZSk7IGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ3Rha2VSaWdodCc6IHN0YXJ0ID0gbmF0aXZlTWF4KHN0YXJ0LCBlbmQgLSBzaXplKTsgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB7ICdzdGFydCc6IHN0YXJ0LCAnZW5kJzogZW5kIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXh0cmFjdHMgd3JhcHBlciBkZXRhaWxzIGZyb20gdGhlIGBzb3VyY2VgIGJvZHkgY29tbWVudC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSBUaGUgc291cmNlIHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSB3cmFwcGVyIGRldGFpbHMuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0V3JhcERldGFpbHMoc291cmNlKSB7XG4gICAgICB2YXIgbWF0Y2ggPSBzb3VyY2UubWF0Y2gocmVXcmFwRGV0YWlscyk7XG4gICAgICByZXR1cm4gbWF0Y2ggPyBtYXRjaFsxXS5zcGxpdChyZVNwbGl0RGV0YWlscykgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHBhdGhgIGV4aXN0cyBvbiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIHRvIGNoZWNrLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGhhc0Z1bmMgVGhlIGZ1bmN0aW9uIHRvIGNoZWNrIHByb3BlcnRpZXMuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGBwYXRoYCBleGlzdHMsIGVsc2UgYGZhbHNlYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBoYXNQYXRoKG9iamVjdCwgcGF0aCwgaGFzRnVuYykge1xuICAgICAgcGF0aCA9IGNhc3RQYXRoKHBhdGgsIG9iamVjdCk7XG5cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IHBhdGgubGVuZ3RoLFxuICAgICAgICAgIHJlc3VsdCA9IGZhbHNlO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIga2V5ID0gdG9LZXkocGF0aFtpbmRleF0pO1xuICAgICAgICBpZiAoIShyZXN1bHQgPSBvYmplY3QgIT0gbnVsbCAmJiBoYXNGdW5jKG9iamVjdCwga2V5KSkpIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBvYmplY3QgPSBvYmplY3Rba2V5XTtcbiAgICAgIH1cbiAgICAgIGlmIChyZXN1bHQgfHwgKytpbmRleCAhPSBsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIGxlbmd0aCA9IG9iamVjdCA9PSBudWxsID8gMCA6IG9iamVjdC5sZW5ndGg7XG4gICAgICByZXR1cm4gISFsZW5ndGggJiYgaXNMZW5ndGgobGVuZ3RoKSAmJiBpc0luZGV4KGtleSwgbGVuZ3RoKSAmJlxuICAgICAgICAoaXNBcnJheShvYmplY3QpIHx8IGlzQXJndW1lbnRzKG9iamVjdCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemVzIGFuIGFycmF5IGNsb25lLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gY2xvbmUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBpbml0aWFsaXplZCBjbG9uZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbml0Q2xvbmVBcnJheShhcnJheSkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAgICByZXN1bHQgPSBhcnJheS5jb25zdHJ1Y3RvcihsZW5ndGgpO1xuXG4gICAgICAvLyBBZGQgcHJvcGVydGllcyBhc3NpZ25lZCBieSBgUmVnRXhwI2V4ZWNgLlxuICAgICAgaWYgKGxlbmd0aCAmJiB0eXBlb2YgYXJyYXlbMF0gPT0gJ3N0cmluZycgJiYgaGFzT3duUHJvcGVydHkuY2FsbChhcnJheSwgJ2luZGV4JykpIHtcbiAgICAgICAgcmVzdWx0LmluZGV4ID0gYXJyYXkuaW5kZXg7XG4gICAgICAgIHJlc3VsdC5pbnB1dCA9IGFycmF5LmlucHV0O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyBhbiBvYmplY3QgY2xvbmUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBpbml0aWFsaXplZCBjbG9uZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbml0Q2xvbmVPYmplY3Qob2JqZWN0KSB7XG4gICAgICByZXR1cm4gKHR5cGVvZiBvYmplY3QuY29uc3RydWN0b3IgPT0gJ2Z1bmN0aW9uJyAmJiAhaXNQcm90b3R5cGUob2JqZWN0KSlcbiAgICAgICAgPyBiYXNlQ3JlYXRlKGdldFByb3RvdHlwZShvYmplY3QpKVxuICAgICAgICA6IHt9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemVzIGFuIG9iamVjdCBjbG9uZSBiYXNlZCBvbiBpdHMgYHRvU3RyaW5nVGFnYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIGZ1bmN0aW9uIG9ubHkgc3VwcG9ydHMgY2xvbmluZyB2YWx1ZXMgd2l0aCB0YWdzIG9mXG4gICAgICogYEJvb2xlYW5gLCBgRGF0ZWAsIGBFcnJvcmAsIGBOdW1iZXJgLCBgUmVnRXhwYCwgb3IgYFN0cmluZ2AuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBjbG9uZS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdGFnIFRoZSBgdG9TdHJpbmdUYWdgIG9mIHRoZSBvYmplY3QgdG8gY2xvbmUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2xvbmVGdW5jIFRoZSBmdW5jdGlvbiB0byBjbG9uZSB2YWx1ZXMuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbaXNEZWVwXSBTcGVjaWZ5IGEgZGVlcCBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBpbml0aWFsaXplZCBjbG9uZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbml0Q2xvbmVCeVRhZyhvYmplY3QsIHRhZywgY2xvbmVGdW5jLCBpc0RlZXApIHtcbiAgICAgIHZhciBDdG9yID0gb2JqZWN0LmNvbnN0cnVjdG9yO1xuICAgICAgc3dpdGNoICh0YWcpIHtcbiAgICAgICAgY2FzZSBhcnJheUJ1ZmZlclRhZzpcbiAgICAgICAgICByZXR1cm4gY2xvbmVBcnJheUJ1ZmZlcihvYmplY3QpO1xuXG4gICAgICAgIGNhc2UgYm9vbFRhZzpcbiAgICAgICAgY2FzZSBkYXRlVGFnOlxuICAgICAgICAgIHJldHVybiBuZXcgQ3Rvcigrb2JqZWN0KTtcblxuICAgICAgICBjYXNlIGRhdGFWaWV3VGFnOlxuICAgICAgICAgIHJldHVybiBjbG9uZURhdGFWaWV3KG9iamVjdCwgaXNEZWVwKTtcblxuICAgICAgICBjYXNlIGZsb2F0MzJUYWc6IGNhc2UgZmxvYXQ2NFRhZzpcbiAgICAgICAgY2FzZSBpbnQ4VGFnOiBjYXNlIGludDE2VGFnOiBjYXNlIGludDMyVGFnOlxuICAgICAgICBjYXNlIHVpbnQ4VGFnOiBjYXNlIHVpbnQ4Q2xhbXBlZFRhZzogY2FzZSB1aW50MTZUYWc6IGNhc2UgdWludDMyVGFnOlxuICAgICAgICAgIHJldHVybiBjbG9uZVR5cGVkQXJyYXkob2JqZWN0LCBpc0RlZXApO1xuXG4gICAgICAgIGNhc2UgbWFwVGFnOlxuICAgICAgICAgIHJldHVybiBjbG9uZU1hcChvYmplY3QsIGlzRGVlcCwgY2xvbmVGdW5jKTtcblxuICAgICAgICBjYXNlIG51bWJlclRhZzpcbiAgICAgICAgY2FzZSBzdHJpbmdUYWc6XG4gICAgICAgICAgcmV0dXJuIG5ldyBDdG9yKG9iamVjdCk7XG5cbiAgICAgICAgY2FzZSByZWdleHBUYWc6XG4gICAgICAgICAgcmV0dXJuIGNsb25lUmVnRXhwKG9iamVjdCk7XG5cbiAgICAgICAgY2FzZSBzZXRUYWc6XG4gICAgICAgICAgcmV0dXJuIGNsb25lU2V0KG9iamVjdCwgaXNEZWVwLCBjbG9uZUZ1bmMpO1xuXG4gICAgICAgIGNhc2Ugc3ltYm9sVGFnOlxuICAgICAgICAgIHJldHVybiBjbG9uZVN5bWJvbChvYmplY3QpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluc2VydHMgd3JhcHBlciBgZGV0YWlsc2AgaW4gYSBjb21tZW50IGF0IHRoZSB0b3Agb2YgdGhlIGBzb3VyY2VgIGJvZHkuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzb3VyY2UgVGhlIHNvdXJjZSB0byBtb2RpZnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBkZXRhaWxzIFRoZSBkZXRhaWxzIHRvIGluc2VydC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBtb2RpZmllZCBzb3VyY2UuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaW5zZXJ0V3JhcERldGFpbHMoc291cmNlLCBkZXRhaWxzKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gZGV0YWlscy5sZW5ndGg7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm4gc291cmNlO1xuICAgICAgfVxuICAgICAgdmFyIGxhc3RJbmRleCA9IGxlbmd0aCAtIDE7XG4gICAgICBkZXRhaWxzW2xhc3RJbmRleF0gPSAobGVuZ3RoID4gMSA/ICcmICcgOiAnJykgKyBkZXRhaWxzW2xhc3RJbmRleF07XG4gICAgICBkZXRhaWxzID0gZGV0YWlscy5qb2luKGxlbmd0aCA+IDIgPyAnLCAnIDogJyAnKTtcbiAgICAgIHJldHVybiBzb3VyY2UucmVwbGFjZShyZVdyYXBDb21tZW50LCAne1xcbi8qIFt3cmFwcGVkIHdpdGggJyArIGRldGFpbHMgKyAnXSAqL1xcbicpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgZmxhdHRlbmFibGUgYGFyZ3VtZW50c2Agb2JqZWN0IG9yIGFycmF5LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBmbGF0dGVuYWJsZSwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzRmxhdHRlbmFibGUodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc0FycmF5KHZhbHVlKSB8fCBpc0FyZ3VtZW50cyh2YWx1ZSkgfHxcbiAgICAgICAgISEoc3ByZWFkYWJsZVN5bWJvbCAmJiB2YWx1ZSAmJiB2YWx1ZVtzcHJlYWRhYmxlU3ltYm9sXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYSB2YWxpZCBhcnJheS1saWtlIGluZGV4LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xlbmd0aD1NQVhfU0FGRV9JTlRFR0VSXSBUaGUgdXBwZXIgYm91bmRzIG9mIGEgdmFsaWQgaW5kZXguXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSB2YWxpZCBpbmRleCwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzSW5kZXgodmFsdWUsIGxlbmd0aCkge1xuICAgICAgbGVuZ3RoID0gbGVuZ3RoID09IG51bGwgPyBNQVhfU0FGRV9JTlRFR0VSIDogbGVuZ3RoO1xuICAgICAgcmV0dXJuICEhbGVuZ3RoICYmXG4gICAgICAgICh0eXBlb2YgdmFsdWUgPT0gJ251bWJlcicgfHwgcmVJc1VpbnQudGVzdCh2YWx1ZSkpICYmXG4gICAgICAgICh2YWx1ZSA+IC0xICYmIHZhbHVlICUgMSA9PSAwICYmIHZhbHVlIDwgbGVuZ3RoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgdGhlIGdpdmVuIGFyZ3VtZW50cyBhcmUgZnJvbSBhbiBpdGVyYXRlZSBjYWxsLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBwb3RlbnRpYWwgaXRlcmF0ZWUgdmFsdWUgYXJndW1lbnQuXG4gICAgICogQHBhcmFtIHsqfSBpbmRleCBUaGUgcG90ZW50aWFsIGl0ZXJhdGVlIGluZGV4IG9yIGtleSBhcmd1bWVudC5cbiAgICAgKiBAcGFyYW0geyp9IG9iamVjdCBUaGUgcG90ZW50aWFsIGl0ZXJhdGVlIG9iamVjdCBhcmd1bWVudC5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGFyZ3VtZW50cyBhcmUgZnJvbSBhbiBpdGVyYXRlZSBjYWxsLFxuICAgICAqICBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNJdGVyYXRlZUNhbGwodmFsdWUsIGluZGV4LCBvYmplY3QpIHtcbiAgICAgIGlmICghaXNPYmplY3Qob2JqZWN0KSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICB2YXIgdHlwZSA9IHR5cGVvZiBpbmRleDtcbiAgICAgIGlmICh0eXBlID09ICdudW1iZXInXG4gICAgICAgICAgICA/IChpc0FycmF5TGlrZShvYmplY3QpICYmIGlzSW5kZXgoaW5kZXgsIG9iamVjdC5sZW5ndGgpKVxuICAgICAgICAgICAgOiAodHlwZSA9PSAnc3RyaW5nJyAmJiBpbmRleCBpbiBvYmplY3QpXG4gICAgICAgICAgKSB7XG4gICAgICAgIHJldHVybiBlcShvYmplY3RbaW5kZXhdLCB2YWx1ZSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYSBwcm9wZXJ0eSBuYW1lIGFuZCBub3QgYSBwcm9wZXJ0eSBwYXRoLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29iamVjdF0gVGhlIG9iamVjdCB0byBxdWVyeSBrZXlzIG9uLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgcHJvcGVydHkgbmFtZSwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzS2V5KHZhbHVlLCBvYmplY3QpIHtcbiAgICAgIGlmIChpc0FycmF5KHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICB2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZTtcbiAgICAgIGlmICh0eXBlID09ICdudW1iZXInIHx8IHR5cGUgPT0gJ3N5bWJvbCcgfHwgdHlwZSA9PSAnYm9vbGVhbicgfHxcbiAgICAgICAgICB2YWx1ZSA9PSBudWxsIHx8IGlzU3ltYm9sKHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZUlzUGxhaW5Qcm9wLnRlc3QodmFsdWUpIHx8ICFyZUlzRGVlcFByb3AudGVzdCh2YWx1ZSkgfHxcbiAgICAgICAgKG9iamVjdCAhPSBudWxsICYmIHZhbHVlIGluIE9iamVjdChvYmplY3QpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBzdWl0YWJsZSBmb3IgdXNlIGFzIHVuaXF1ZSBvYmplY3Qga2V5LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBzdWl0YWJsZSwgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzS2V5YWJsZSh2YWx1ZSkge1xuICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgdmFsdWU7XG4gICAgICByZXR1cm4gKHR5cGUgPT0gJ3N0cmluZycgfHwgdHlwZSA9PSAnbnVtYmVyJyB8fCB0eXBlID09ICdzeW1ib2wnIHx8IHR5cGUgPT0gJ2Jvb2xlYW4nKVxuICAgICAgICA/ICh2YWx1ZSAhPT0gJ19fcHJvdG9fXycpXG4gICAgICAgIDogKHZhbHVlID09PSBudWxsKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYGZ1bmNgIGhhcyBhIGxhenkgY291bnRlcnBhcnQuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgZnVuY2AgaGFzIGEgbGF6eSBjb3VudGVycGFydCxcbiAgICAgKiAgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTGF6aWFibGUoZnVuYykge1xuICAgICAgdmFyIGZ1bmNOYW1lID0gZ2V0RnVuY05hbWUoZnVuYyksXG4gICAgICAgICAgb3RoZXIgPSBsb2Rhc2hbZnVuY05hbWVdO1xuXG4gICAgICBpZiAodHlwZW9mIG90aGVyICE9ICdmdW5jdGlvbicgfHwgIShmdW5jTmFtZSBpbiBMYXp5V3JhcHBlci5wcm90b3R5cGUpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGlmIChmdW5jID09PSBvdGhlcikge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIHZhciBkYXRhID0gZ2V0RGF0YShvdGhlcik7XG4gICAgICByZXR1cm4gISFkYXRhICYmIGZ1bmMgPT09IGRhdGFbMF07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGBmdW5jYCBoYXMgaXRzIHNvdXJjZSBtYXNrZWQuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgZnVuY2AgaXMgbWFza2VkLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNNYXNrZWQoZnVuYykge1xuICAgICAgcmV0dXJuICEhbWFza1NyY0tleSAmJiAobWFza1NyY0tleSBpbiBmdW5jKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYGZ1bmNgIGlzIGNhcGFibGUgb2YgYmVpbmcgbWFza2VkLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYGZ1bmNgIGlzIG1hc2thYmxlLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgdmFyIGlzTWFza2FibGUgPSBjb3JlSnNEYXRhID8gaXNGdW5jdGlvbiA6IHN0dWJGYWxzZTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGxpa2VseSBhIHByb3RvdHlwZSBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgcHJvdG90eXBlLCBlbHNlIGBmYWxzZWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgIHZhciBDdG9yID0gdmFsdWUgJiYgdmFsdWUuY29uc3RydWN0b3IsXG4gICAgICAgICAgcHJvdG8gPSAodHlwZW9mIEN0b3IgPT0gJ2Z1bmN0aW9uJyAmJiBDdG9yLnByb3RvdHlwZSkgfHwgb2JqZWN0UHJvdG87XG5cbiAgICAgIHJldHVybiB2YWx1ZSA9PT0gcHJvdG87XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgc3VpdGFibGUgZm9yIHN0cmljdCBlcXVhbGl0eSBjb21wYXJpc29ucywgaS5lLiBgPT09YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaWYgc3VpdGFibGUgZm9yIHN0cmljdFxuICAgICAqICBlcXVhbGl0eSBjb21wYXJpc29ucywgZWxzZSBgZmFsc2VgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzU3RyaWN0Q29tcGFyYWJsZSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlID09PSB2YWx1ZSAmJiAhaXNPYmplY3QodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgbWF0Y2hlc1Byb3BlcnR5YCBmb3Igc291cmNlIHZhbHVlcyBzdWl0YWJsZVxuICAgICAqIGZvciBzdHJpY3QgZXF1YWxpdHkgY29tcGFyaXNvbnMsIGkuZS4gYD09PWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICAgICAqIEBwYXJhbSB7Kn0gc3JjVmFsdWUgVGhlIHZhbHVlIHRvIG1hdGNoLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHNwZWMgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWF0Y2hlc1N0cmljdENvbXBhcmFibGUoa2V5LCBzcmNWYWx1ZSkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgICAgICBpZiAob2JqZWN0ID09IG51bGwpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9iamVjdFtrZXldID09PSBzcmNWYWx1ZSAmJlxuICAgICAgICAgIChzcmNWYWx1ZSAhPT0gdW5kZWZpbmVkIHx8IChrZXkgaW4gT2JqZWN0KG9iamVjdCkpKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLm1lbW9pemVgIHdoaWNoIGNsZWFycyB0aGUgbWVtb2l6ZWQgZnVuY3Rpb24nc1xuICAgICAqIGNhY2hlIHdoZW4gaXQgZXhjZWVkcyBgTUFYX01FTU9JWkVfU0laRWAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGhhdmUgaXRzIG91dHB1dCBtZW1vaXplZC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBtZW1vaXplZCBmdW5jdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtZW1vaXplQ2FwcGVkKGZ1bmMpIHtcbiAgICAgIHZhciByZXN1bHQgPSBtZW1vaXplKGZ1bmMsIGZ1bmN0aW9uKGtleSkge1xuICAgICAgICBpZiAoY2FjaGUuc2l6ZSA9PT0gTUFYX01FTU9JWkVfU0laRSkge1xuICAgICAgICAgIGNhY2hlLmNsZWFyKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGtleTtcbiAgICAgIH0pO1xuXG4gICAgICB2YXIgY2FjaGUgPSByZXN1bHQuY2FjaGU7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1lcmdlcyB0aGUgZnVuY3Rpb24gbWV0YWRhdGEgb2YgYHNvdXJjZWAgaW50byBgZGF0YWAuXG4gICAgICpcbiAgICAgKiBNZXJnaW5nIG1ldGFkYXRhIHJlZHVjZXMgdGhlIG51bWJlciBvZiB3cmFwcGVycyB1c2VkIHRvIGludm9rZSBhIGZ1bmN0aW9uLlxuICAgICAqIFRoaXMgaXMgcG9zc2libGUgYmVjYXVzZSBtZXRob2RzIGxpa2UgYF8uYmluZGAsIGBfLmN1cnJ5YCwgYW5kIGBfLnBhcnRpYWxgXG4gICAgICogbWF5IGJlIGFwcGxpZWQgcmVnYXJkbGVzcyBvZiBleGVjdXRpb24gb3JkZXIuIE1ldGhvZHMgbGlrZSBgXy5hcnlgIGFuZFxuICAgICAqIGBfLnJlYXJnYCBtb2RpZnkgZnVuY3Rpb24gYXJndW1lbnRzLCBtYWtpbmcgdGhlIG9yZGVyIGluIHdoaWNoIHRoZXkgYXJlXG4gICAgICogZXhlY3V0ZWQgaW1wb3J0YW50LCBwcmV2ZW50aW5nIHRoZSBtZXJnaW5nIG9mIG1ldGFkYXRhLiBIb3dldmVyLCB3ZSBtYWtlXG4gICAgICogYW4gZXhjZXB0aW9uIGZvciBhIHNhZmUgY29tYmluZWQgY2FzZSB3aGVyZSBjdXJyaWVkIGZ1bmN0aW9ucyBoYXZlIGBfLmFyeWBcbiAgICAgKiBhbmQgb3IgYF8ucmVhcmdgIGFwcGxpZWQuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGRhdGEgVGhlIGRlc3RpbmF0aW9uIG1ldGFkYXRhLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHNvdXJjZSBUaGUgc291cmNlIG1ldGFkYXRhLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgZGF0YWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gbWVyZ2VEYXRhKGRhdGEsIHNvdXJjZSkge1xuICAgICAgdmFyIGJpdG1hc2sgPSBkYXRhWzFdLFxuICAgICAgICAgIHNyY0JpdG1hc2sgPSBzb3VyY2VbMV0sXG4gICAgICAgICAgbmV3Qml0bWFzayA9IGJpdG1hc2sgfCBzcmNCaXRtYXNrLFxuICAgICAgICAgIGlzQ29tbW9uID0gbmV3Qml0bWFzayA8IChXUkFQX0JJTkRfRkxBRyB8IFdSQVBfQklORF9LRVlfRkxBRyB8IFdSQVBfQVJZX0ZMQUcpO1xuXG4gICAgICB2YXIgaXNDb21ibyA9XG4gICAgICAgICgoc3JjQml0bWFzayA9PSBXUkFQX0FSWV9GTEFHKSAmJiAoYml0bWFzayA9PSBXUkFQX0NVUlJZX0ZMQUcpKSB8fFxuICAgICAgICAoKHNyY0JpdG1hc2sgPT0gV1JBUF9BUllfRkxBRykgJiYgKGJpdG1hc2sgPT0gV1JBUF9SRUFSR19GTEFHKSAmJiAoZGF0YVs3XS5sZW5ndGggPD0gc291cmNlWzhdKSkgfHxcbiAgICAgICAgKChzcmNCaXRtYXNrID09IChXUkFQX0FSWV9GTEFHIHwgV1JBUF9SRUFSR19GTEFHKSkgJiYgKHNvdXJjZVs3XS5sZW5ndGggPD0gc291cmNlWzhdKSAmJiAoYml0bWFzayA9PSBXUkFQX0NVUlJZX0ZMQUcpKTtcblxuICAgICAgLy8gRXhpdCBlYXJseSBpZiBtZXRhZGF0YSBjYW4ndCBiZSBtZXJnZWQuXG4gICAgICBpZiAoIShpc0NvbW1vbiB8fCBpc0NvbWJvKSkge1xuICAgICAgICByZXR1cm4gZGF0YTtcbiAgICAgIH1cbiAgICAgIC8vIFVzZSBzb3VyY2UgYHRoaXNBcmdgIGlmIGF2YWlsYWJsZS5cbiAgICAgIGlmIChzcmNCaXRtYXNrICYgV1JBUF9CSU5EX0ZMQUcpIHtcbiAgICAgICAgZGF0YVsyXSA9IHNvdXJjZVsyXTtcbiAgICAgICAgLy8gU2V0IHdoZW4gY3VycnlpbmcgYSBib3VuZCBmdW5jdGlvbi5cbiAgICAgICAgbmV3Qml0bWFzayB8PSBiaXRtYXNrICYgV1JBUF9CSU5EX0ZMQUcgPyAwIDogV1JBUF9DVVJSWV9CT1VORF9GTEFHO1xuICAgICAgfVxuICAgICAgLy8gQ29tcG9zZSBwYXJ0aWFsIGFyZ3VtZW50cy5cbiAgICAgIHZhciB2YWx1ZSA9IHNvdXJjZVszXTtcbiAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICB2YXIgcGFydGlhbHMgPSBkYXRhWzNdO1xuICAgICAgICBkYXRhWzNdID0gcGFydGlhbHMgPyBjb21wb3NlQXJncyhwYXJ0aWFscywgdmFsdWUsIHNvdXJjZVs0XSkgOiB2YWx1ZTtcbiAgICAgICAgZGF0YVs0XSA9IHBhcnRpYWxzID8gcmVwbGFjZUhvbGRlcnMoZGF0YVszXSwgUExBQ0VIT0xERVIpIDogc291cmNlWzRdO1xuICAgICAgfVxuICAgICAgLy8gQ29tcG9zZSBwYXJ0aWFsIHJpZ2h0IGFyZ3VtZW50cy5cbiAgICAgIHZhbHVlID0gc291cmNlWzVdO1xuICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgIHBhcnRpYWxzID0gZGF0YVs1XTtcbiAgICAgICAgZGF0YVs1XSA9IHBhcnRpYWxzID8gY29tcG9zZUFyZ3NSaWdodChwYXJ0aWFscywgdmFsdWUsIHNvdXJjZVs2XSkgOiB2YWx1ZTtcbiAgICAgICAgZGF0YVs2XSA9IHBhcnRpYWxzID8gcmVwbGFjZUhvbGRlcnMoZGF0YVs1XSwgUExBQ0VIT0xERVIpIDogc291cmNlWzZdO1xuICAgICAgfVxuICAgICAgLy8gVXNlIHNvdXJjZSBgYXJnUG9zYCBpZiBhdmFpbGFibGUuXG4gICAgICB2YWx1ZSA9IHNvdXJjZVs3XTtcbiAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICBkYXRhWzddID0gdmFsdWU7XG4gICAgICB9XG4gICAgICAvLyBVc2Ugc291cmNlIGBhcnlgIGlmIGl0J3Mgc21hbGxlci5cbiAgICAgIGlmIChzcmNCaXRtYXNrICYgV1JBUF9BUllfRkxBRykge1xuICAgICAgICBkYXRhWzhdID0gZGF0YVs4XSA9PSBudWxsID8gc291cmNlWzhdIDogbmF0aXZlTWluKGRhdGFbOF0sIHNvdXJjZVs4XSk7XG4gICAgICB9XG4gICAgICAvLyBVc2Ugc291cmNlIGBhcml0eWAgaWYgb25lIGlzIG5vdCBwcm92aWRlZC5cbiAgICAgIGlmIChkYXRhWzldID09IG51bGwpIHtcbiAgICAgICAgZGF0YVs5XSA9IHNvdXJjZVs5XTtcbiAgICAgIH1cbiAgICAgIC8vIFVzZSBzb3VyY2UgYGZ1bmNgIGFuZCBtZXJnZSBiaXRtYXNrcy5cbiAgICAgIGRhdGFbMF0gPSBzb3VyY2VbMF07XG4gICAgICBkYXRhWzFdID0gbmV3Qml0bWFzaztcblxuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiBpcyBsaWtlXG4gICAgICogW2BPYmplY3Qua2V5c2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLW9iamVjdC5rZXlzKVxuICAgICAqIGV4Y2VwdCB0aGF0IGl0IGluY2x1ZGVzIGluaGVyaXRlZCBlbnVtZXJhYmxlIHByb3BlcnRpZXMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG5hdGl2ZUtleXNJbihvYmplY3QpIHtcbiAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChvYmplY3QgIT0gbnVsbCkge1xuICAgICAgICBmb3IgKHZhciBrZXkgaW4gT2JqZWN0KG9iamVjdCkpIHtcbiAgICAgICAgICByZXN1bHQucHVzaChrZXkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGB2YWx1ZWAgdG8gYSBzdHJpbmcgdXNpbmcgYE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmdgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBzdHJpbmcuXG4gICAgICovXG4gICAgZnVuY3Rpb24gb2JqZWN0VG9TdHJpbmcodmFsdWUpIHtcbiAgICAgIHJldHVybiBuYXRpdmVPYmplY3RUb1N0cmluZy5jYWxsKHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYGJhc2VSZXN0YCB3aGljaCB0cmFuc2Zvcm1zIHRoZSByZXN0IGFycmF5LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBhcHBseSBhIHJlc3QgcGFyYW1ldGVyIHRvLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbc3RhcnQ9ZnVuYy5sZW5ndGgtMV0gVGhlIHN0YXJ0IHBvc2l0aW9uIG9mIHRoZSByZXN0IHBhcmFtZXRlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSB0cmFuc2Zvcm0gVGhlIHJlc3QgYXJyYXkgdHJhbnNmb3JtLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG92ZXJSZXN0KGZ1bmMsIHN0YXJ0LCB0cmFuc2Zvcm0pIHtcbiAgICAgIHN0YXJ0ID0gbmF0aXZlTWF4KHN0YXJ0ID09PSB1bmRlZmluZWQgPyAoZnVuYy5sZW5ndGggLSAxKSA6IHN0YXJ0LCAwKTtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHMsXG4gICAgICAgICAgICBpbmRleCA9IC0xLFxuICAgICAgICAgICAgbGVuZ3RoID0gbmF0aXZlTWF4KGFyZ3MubGVuZ3RoIC0gc3RhcnQsIDApLFxuICAgICAgICAgICAgYXJyYXkgPSBBcnJheShsZW5ndGgpO1xuXG4gICAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgICAgYXJyYXlbaW5kZXhdID0gYXJnc1tzdGFydCArIGluZGV4XTtcbiAgICAgICAgfVxuICAgICAgICBpbmRleCA9IC0xO1xuICAgICAgICB2YXIgb3RoZXJBcmdzID0gQXJyYXkoc3RhcnQgKyAxKTtcbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBzdGFydCkge1xuICAgICAgICAgIG90aGVyQXJnc1tpbmRleF0gPSBhcmdzW2luZGV4XTtcbiAgICAgICAgfVxuICAgICAgICBvdGhlckFyZ3Nbc3RhcnRdID0gdHJhbnNmb3JtKGFycmF5KTtcbiAgICAgICAgcmV0dXJuIGFwcGx5KGZ1bmMsIHRoaXMsIG90aGVyQXJncyk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHBhcmVudCB2YWx1ZSBhdCBgcGF0aGAgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwYXRoIFRoZSBwYXRoIHRvIGdldCB0aGUgcGFyZW50IHZhbHVlIG9mLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBwYXJlbnQgdmFsdWUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gcGFyZW50KG9iamVjdCwgcGF0aCkge1xuICAgICAgcmV0dXJuIHBhdGgubGVuZ3RoIDwgMiA/IG9iamVjdCA6IGJhc2VHZXQob2JqZWN0LCBiYXNlU2xpY2UocGF0aCwgMCwgLTEpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW9yZGVyIGBhcnJheWAgYWNjb3JkaW5nIHRvIHRoZSBzcGVjaWZpZWQgaW5kZXhlcyB3aGVyZSB0aGUgZWxlbWVudCBhdFxuICAgICAqIHRoZSBmaXJzdCBpbmRleCBpcyBhc3NpZ25lZCBhcyB0aGUgZmlyc3QgZWxlbWVudCwgdGhlIGVsZW1lbnQgYXRcbiAgICAgKiB0aGUgc2Vjb25kIGluZGV4IGlzIGFzc2lnbmVkIGFzIHRoZSBzZWNvbmQgZWxlbWVudCwgYW5kIHNvIG9uLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcmVvcmRlci5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBpbmRleGVzIFRoZSBhcnJhbmdlZCBhcnJheSBpbmRleGVzLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgYXJyYXlgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJlb3JkZXIoYXJyYXksIGluZGV4ZXMpIHtcbiAgICAgIHZhciBhcnJMZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICAgICAgbGVuZ3RoID0gbmF0aXZlTWluKGluZGV4ZXMubGVuZ3RoLCBhcnJMZW5ndGgpLFxuICAgICAgICAgIG9sZEFycmF5ID0gY29weUFycmF5KGFycmF5KTtcblxuICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgIHZhciBpbmRleCA9IGluZGV4ZXNbbGVuZ3RoXTtcbiAgICAgICAgYXJyYXlbbGVuZ3RoXSA9IGlzSW5kZXgoaW5kZXgsIGFyckxlbmd0aCkgPyBvbGRBcnJheVtpbmRleF0gOiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gYXJyYXk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyBtZXRhZGF0YSBmb3IgYGZ1bmNgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIElmIHRoaXMgZnVuY3Rpb24gYmVjb21lcyBob3QsIGkuZS4gaXMgaW52b2tlZCBhIGxvdCBpbiBhIHNob3J0XG4gICAgICogcGVyaW9kIG9mIHRpbWUsIGl0IHdpbGwgdHJpcCBpdHMgYnJlYWtlciBhbmQgdHJhbnNpdGlvbiB0byBhbiBpZGVudGl0eVxuICAgICAqIGZ1bmN0aW9uIHRvIGF2b2lkIGdhcmJhZ2UgY29sbGVjdGlvbiBwYXVzZXMgaW4gVjguIFNlZVxuICAgICAqIFtWOCBpc3N1ZSAyMDcwXShodHRwczovL2J1Z3MuY2hyb21pdW0ub3JnL3AvdjgvaXNzdWVzL2RldGFpbD9pZD0yMDcwKVxuICAgICAqIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGFzc29jaWF0ZSBtZXRhZGF0YSB3aXRoLlxuICAgICAqIEBwYXJhbSB7Kn0gZGF0YSBUaGUgbWV0YWRhdGEuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIGBmdW5jYC5cbiAgICAgKi9cbiAgICB2YXIgc2V0RGF0YSA9IHNob3J0T3V0KGJhc2VTZXREYXRhKTtcblxuICAgIC8qKlxuICAgICAqIEEgc2ltcGxlIHdyYXBwZXIgYXJvdW5kIHRoZSBnbG9iYWwgW2BzZXRUaW1lb3V0YF0oaHR0cHM6Ly9tZG4uaW8vc2V0VGltZW91dCkuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRlbGF5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB3YWl0IFRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIGRlbGF5IGludm9jYXRpb24uXG4gICAgICogQHJldHVybnMge251bWJlcnxPYmplY3R9IFJldHVybnMgdGhlIHRpbWVyIGlkIG9yIHRpbWVvdXQgb2JqZWN0LlxuICAgICAqL1xuICAgIHZhciBzZXRUaW1lb3V0ID0gY3R4U2V0VGltZW91dCB8fCBmdW5jdGlvbihmdW5jLCB3YWl0KSB7XG4gICAgICByZXR1cm4gcm9vdC5zZXRUaW1lb3V0KGZ1bmMsIHdhaXQpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBgdG9TdHJpbmdgIG1ldGhvZCBvZiBgZnVuY2AgdG8gcmV0dXJuIGBzdHJpbmdgLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gc3RyaW5nIFRoZSBgdG9TdHJpbmdgIHJlc3VsdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgYGZ1bmNgLlxuICAgICAqL1xuICAgIHZhciBzZXRUb1N0cmluZyA9IHNob3J0T3V0KGJhc2VTZXRUb1N0cmluZyk7XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBgdG9TdHJpbmdgIG1ldGhvZCBvZiBgd3JhcHBlcmAgdG8gbWltaWMgdGhlIHNvdXJjZSBvZiBgcmVmZXJlbmNlYFxuICAgICAqIHdpdGggd3JhcHBlciBkZXRhaWxzIGluIGEgY29tbWVudCBhdCB0aGUgdG9wIG9mIHRoZSBzb3VyY2UgYm9keS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gd3JhcHBlciBUaGUgZnVuY3Rpb24gdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHJlZmVyZW5jZSBUaGUgcmVmZXJlbmNlIGZ1bmN0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIGZsYWdzLiBTZWUgYGNyZWF0ZVdyYXBgIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIGB3cmFwcGVyYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzZXRXcmFwVG9TdHJpbmcod3JhcHBlciwgcmVmZXJlbmNlLCBiaXRtYXNrKSB7XG4gICAgICB2YXIgc291cmNlID0gKHJlZmVyZW5jZSArICcnKTtcbiAgICAgIHJldHVybiBzZXRUb1N0cmluZyh3cmFwcGVyLCBpbnNlcnRXcmFwRGV0YWlscyhzb3VyY2UsIHVwZGF0ZVdyYXBEZXRhaWxzKGdldFdyYXBEZXRhaWxzKHNvdXJjZSksIGJpdG1hc2spKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQnbGwgc2hvcnQgb3V0IGFuZCBpbnZva2UgYGlkZW50aXR5YCBpbnN0ZWFkXG4gICAgICogb2YgYGZ1bmNgIHdoZW4gaXQncyBjYWxsZWQgYEhPVF9DT1VOVGAgb3IgbW9yZSB0aW1lcyBpbiBgSE9UX1NQQU5gXG4gICAgICogbWlsbGlzZWNvbmRzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byByZXN0cmljdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBzaG9ydGFibGUgZnVuY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gc2hvcnRPdXQoZnVuYykge1xuICAgICAgdmFyIGNvdW50ID0gMCxcbiAgICAgICAgICBsYXN0Q2FsbGVkID0gMDtcblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgc3RhbXAgPSBuYXRpdmVOb3coKSxcbiAgICAgICAgICAgIHJlbWFpbmluZyA9IEhPVF9TUEFOIC0gKHN0YW1wIC0gbGFzdENhbGxlZCk7XG5cbiAgICAgICAgbGFzdENhbGxlZCA9IHN0YW1wO1xuICAgICAgICBpZiAocmVtYWluaW5nID4gMCkge1xuICAgICAgICAgIGlmICgrK2NvdW50ID49IEhPVF9DT1VOVCkge1xuICAgICAgICAgICAgcmV0dXJuIGFyZ3VtZW50c1swXTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY291bnQgPSAwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmdW5jLmFwcGx5KHVuZGVmaW5lZCwgYXJndW1lbnRzKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLnNodWZmbGVgIHdoaWNoIG11dGF0ZXMgYW5kIHNldHMgdGhlIHNpemUgb2YgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNodWZmbGUuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzaXplPWFycmF5Lmxlbmd0aF0gVGhlIHNpemUgb2YgYGFycmF5YC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzaHVmZmxlU2VsZihhcnJheSwgc2l6ZSkge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgICAgIGxhc3RJbmRleCA9IGxlbmd0aCAtIDE7XG5cbiAgICAgIHNpemUgPSBzaXplID09PSB1bmRlZmluZWQgPyBsZW5ndGggOiBzaXplO1xuICAgICAgd2hpbGUgKCsraW5kZXggPCBzaXplKSB7XG4gICAgICAgIHZhciByYW5kID0gYmFzZVJhbmRvbShpbmRleCwgbGFzdEluZGV4KSxcbiAgICAgICAgICAgIHZhbHVlID0gYXJyYXlbcmFuZF07XG5cbiAgICAgICAgYXJyYXlbcmFuZF0gPSBhcnJheVtpbmRleF07XG4gICAgICAgIGFycmF5W2luZGV4XSA9IHZhbHVlO1xuICAgICAgfVxuICAgICAgYXJyYXkubGVuZ3RoID0gc2l6ZTtcbiAgICAgIHJldHVybiBhcnJheTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgc3RyaW5nYCB0byBhIHByb3BlcnR5IHBhdGggYXJyYXkuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgcHJvcGVydHkgcGF0aCBhcnJheS5cbiAgICAgKi9cbiAgICB2YXIgc3RyaW5nVG9QYXRoID0gbWVtb2l6ZUNhcHBlZChmdW5jdGlvbihzdHJpbmcpIHtcbiAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChyZUxlYWRpbmdEb3QudGVzdChzdHJpbmcpKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKCcnKTtcbiAgICAgIH1cbiAgICAgIHN0cmluZy5yZXBsYWNlKHJlUHJvcE5hbWUsIGZ1bmN0aW9uKG1hdGNoLCBudW1iZXIsIHF1b3RlLCBzdHJpbmcpIHtcbiAgICAgICAgcmVzdWx0LnB1c2gocXVvdGUgPyBzdHJpbmcucmVwbGFjZShyZUVzY2FwZUNoYXIsICckMScpIDogKG51bWJlciB8fCBtYXRjaCkpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHZhbHVlYCB0byBhIHN0cmluZyBrZXkgaWYgaXQncyBub3QgYSBzdHJpbmcgb3Igc3ltYm9sLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBpbnNwZWN0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8c3ltYm9sfSBSZXR1cm5zIHRoZSBrZXkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9LZXkodmFsdWUpIHtcbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT0gJ3N0cmluZycgfHwgaXNTeW1ib2wodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIHZhciByZXN1bHQgPSAodmFsdWUgKyAnJyk7XG4gICAgICByZXR1cm4gKHJlc3VsdCA9PSAnMCcgJiYgKDEgLyB2YWx1ZSkgPT0gLUlORklOSVRZKSA/ICctMCcgOiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYGZ1bmNgIHRvIGl0cyBzb3VyY2UgY29kZS5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBzb3VyY2UgY29kZS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b1NvdXJjZShmdW5jKSB7XG4gICAgICBpZiAoZnVuYyAhPSBudWxsKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIGZ1bmNUb1N0cmluZy5jYWxsKGZ1bmMpO1xuICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICB0cnkge1xuICAgICAgICAgIHJldHVybiAoZnVuYyArICcnKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgIH1cbiAgICAgIHJldHVybiAnJztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGVzIHdyYXBwZXIgYGRldGFpbHNgIGJhc2VkIG9uIGBiaXRtYXNrYCBmbGFncy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHJldHVybnMge0FycmF5fSBkZXRhaWxzIFRoZSBkZXRhaWxzIHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy4gU2VlIGBjcmVhdGVXcmFwYCBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgZGV0YWlsc2AuXG4gICAgICovXG4gICAgZnVuY3Rpb24gdXBkYXRlV3JhcERldGFpbHMoZGV0YWlscywgYml0bWFzaykge1xuICAgICAgYXJyYXlFYWNoKHdyYXBGbGFncywgZnVuY3Rpb24ocGFpcikge1xuICAgICAgICB2YXIgdmFsdWUgPSAnXy4nICsgcGFpclswXTtcbiAgICAgICAgaWYgKChiaXRtYXNrICYgcGFpclsxXSkgJiYgIWFycmF5SW5jbHVkZXMoZGV0YWlscywgdmFsdWUpKSB7XG4gICAgICAgICAgZGV0YWlscy5wdXNoKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gZGV0YWlscy5zb3J0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGNsb25lIG9mIGB3cmFwcGVyYC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtPYmplY3R9IHdyYXBwZXIgVGhlIHdyYXBwZXIgdG8gY2xvbmUuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY2xvbmVkIHdyYXBwZXIuXG4gICAgICovXG4gICAgZnVuY3Rpb24gd3JhcHBlckNsb25lKHdyYXBwZXIpIHtcbiAgICAgIGlmICh3cmFwcGVyIGluc3RhbmNlb2YgTGF6eVdyYXBwZXIpIHtcbiAgICAgICAgcmV0dXJuIHdyYXBwZXIuY2xvbmUoKTtcbiAgICAgIH1cbiAgICAgIHZhciByZXN1bHQgPSBuZXcgTG9kYXNoV3JhcHBlcih3cmFwcGVyLl9fd3JhcHBlZF9fLCB3cmFwcGVyLl9fY2hhaW5fXyk7XG4gICAgICByZXN1bHQuX19hY3Rpb25zX18gPSBjb3B5QXJyYXkod3JhcHBlci5fX2FjdGlvbnNfXyk7XG4gICAgICByZXN1bHQuX19pbmRleF9fICA9IHdyYXBwZXIuX19pbmRleF9fO1xuICAgICAgcmVzdWx0Ll9fdmFsdWVzX18gPSB3cmFwcGVyLl9fdmFsdWVzX187XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgZWxlbWVudHMgc3BsaXQgaW50byBncm91cHMgdGhlIGxlbmd0aCBvZiBgc2l6ZWAuXG4gICAgICogSWYgYGFycmF5YCBjYW4ndCBiZSBzcGxpdCBldmVubHksIHRoZSBmaW5hbCBjaHVuayB3aWxsIGJlIHRoZSByZW1haW5pbmdcbiAgICAgKiBlbGVtZW50cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBwcm9jZXNzLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbc2l6ZT0xXSBUaGUgbGVuZ3RoIG9mIGVhY2ggY2h1bmtcbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYW4gaXRlcmF0ZWUgZm9yIG1ldGhvZHMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGNodW5rcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5jaHVuayhbJ2EnLCAnYicsICdjJywgJ2QnXSwgMik7XG4gICAgICogLy8gPT4gW1snYScsICdiJ10sIFsnYycsICdkJ11dXG4gICAgICpcbiAgICAgKiBfLmNodW5rKFsnYScsICdiJywgJ2MnLCAnZCddLCAzKTtcbiAgICAgKiAvLyA9PiBbWydhJywgJ2InLCAnYyddLCBbJ2QnXV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjaHVuayhhcnJheSwgc2l6ZSwgZ3VhcmQpIHtcbiAgICAgIGlmICgoZ3VhcmQgPyBpc0l0ZXJhdGVlQ2FsbChhcnJheSwgc2l6ZSwgZ3VhcmQpIDogc2l6ZSA9PT0gdW5kZWZpbmVkKSkge1xuICAgICAgICBzaXplID0gMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNpemUgPSBuYXRpdmVNYXgodG9JbnRlZ2VyKHNpemUpLCAwKTtcbiAgICAgIH1cbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICAgIGlmICghbGVuZ3RoIHx8IHNpemUgPCAxKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIHZhciBpbmRleCA9IDAsXG4gICAgICAgICAgcmVzSW5kZXggPSAwLFxuICAgICAgICAgIHJlc3VsdCA9IEFycmF5KG5hdGl2ZUNlaWwobGVuZ3RoIC8gc2l6ZSkpO1xuXG4gICAgICB3aGlsZSAoaW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgcmVzdWx0W3Jlc0luZGV4KytdID0gYmFzZVNsaWNlKGFycmF5LCBpbmRleCwgKGluZGV4ICs9IHNpemUpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSB3aXRoIGFsbCBmYWxzZXkgdmFsdWVzIHJlbW92ZWQuIFRoZSB2YWx1ZXMgYGZhbHNlYCwgYG51bGxgLFxuICAgICAqIGAwYCwgYFwiXCJgLCBgdW5kZWZpbmVkYCwgYW5kIGBOYU5gIGFyZSBmYWxzZXkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gY29tcGFjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBmaWx0ZXJlZCB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uY29tcGFjdChbMCwgMSwgZmFsc2UsIDIsICcnLCAzXSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29tcGFjdChhcnJheSkge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGgsXG4gICAgICAgICAgcmVzSW5kZXggPSAwLFxuICAgICAgICAgIHJlc3VsdCA9IFtdO1xuXG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIgdmFsdWUgPSBhcnJheVtpbmRleF07XG4gICAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICAgIHJlc3VsdFtyZXNJbmRleCsrXSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgYXJyYXkgY29uY2F0ZW5hdGluZyBgYXJyYXlgIHdpdGggYW55IGFkZGl0aW9uYWwgYXJyYXlzXG4gICAgICogYW5kL29yIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBjb25jYXRlbmF0ZS5cbiAgICAgKiBAcGFyYW0gey4uLip9IFt2YWx1ZXNdIFRoZSB2YWx1ZXMgdG8gY29uY2F0ZW5hdGUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgY29uY2F0ZW5hdGVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbMV07XG4gICAgICogdmFyIG90aGVyID0gXy5jb25jYXQoYXJyYXksIDIsIFszXSwgW1s0XV0pO1xuICAgICAqXG4gICAgICogY29uc29sZS5sb2cob3RoZXIpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzLCBbNF1dXG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheSk7XG4gICAgICogLy8gPT4gWzFdXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29uY2F0KCkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICB2YXIgYXJncyA9IEFycmF5KGxlbmd0aCAtIDEpLFxuICAgICAgICAgIGFycmF5ID0gYXJndW1lbnRzWzBdLFxuICAgICAgICAgIGluZGV4ID0gbGVuZ3RoO1xuXG4gICAgICB3aGlsZSAoaW5kZXgtLSkge1xuICAgICAgICBhcmdzW2luZGV4IC0gMV0gPSBhcmd1bWVudHNbaW5kZXhdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFycmF5UHVzaChpc0FycmF5KGFycmF5KSA/IGNvcHlBcnJheShhcnJheSkgOiBbYXJyYXldLCBiYXNlRmxhdHRlbihhcmdzLCAxKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBgYXJyYXlgIHZhbHVlcyBub3QgaW5jbHVkZWQgaW4gdGhlIG90aGVyIGdpdmVuIGFycmF5c1xuICAgICAqIHVzaW5nIFtgU2FtZVZhbHVlWmVyb2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLXNhbWV2YWx1ZXplcm8pXG4gICAgICogZm9yIGVxdWFsaXR5IGNvbXBhcmlzb25zLiBUaGUgb3JkZXIgYW5kIHJlZmVyZW5jZXMgb2YgcmVzdWx0IHZhbHVlcyBhcmVcbiAgICAgKiBkZXRlcm1pbmVkIGJ5IHRoZSBmaXJzdCBhcnJheS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBVbmxpa2UgYF8ucHVsbEFsbGAsIHRoaXMgbWV0aG9kIHJldHVybnMgYSBuZXcgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0gey4uLkFycmF5fSBbdmFsdWVzXSBUaGUgdmFsdWVzIHRvIGV4Y2x1ZGUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgZmlsdGVyZWQgdmFsdWVzLlxuICAgICAqIEBzZWUgXy53aXRob3V0LCBfLnhvclxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRpZmZlcmVuY2UoWzIsIDFdLCBbMiwgM10pO1xuICAgICAqIC8vID0+IFsxXVxuICAgICAqL1xuICAgIHZhciBkaWZmZXJlbmNlID0gYmFzZVJlc3QoZnVuY3Rpb24oYXJyYXksIHZhbHVlcykge1xuICAgICAgcmV0dXJuIGlzQXJyYXlMaWtlT2JqZWN0KGFycmF5KVxuICAgICAgICA/IGJhc2VEaWZmZXJlbmNlKGFycmF5LCBiYXNlRmxhdHRlbih2YWx1ZXMsIDEsIGlzQXJyYXlMaWtlT2JqZWN0LCB0cnVlKSlcbiAgICAgICAgOiBbXTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZGlmZmVyZW5jZWAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgIHdoaWNoXG4gICAgICogaXMgaW52b2tlZCBmb3IgZWFjaCBlbGVtZW50IG9mIGBhcnJheWAgYW5kIGB2YWx1ZXNgIHRvIGdlbmVyYXRlIHRoZSBjcml0ZXJpb25cbiAgICAgKiBieSB3aGljaCB0aGV5J3JlIGNvbXBhcmVkLiBUaGUgb3JkZXIgYW5kIHJlZmVyZW5jZXMgb2YgcmVzdWx0IHZhbHVlcyBhcmVcbiAgICAgKiBkZXRlcm1pbmVkIGJ5IHRoZSBmaXJzdCBhcnJheS4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ6XG4gICAgICogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBVbmxpa2UgYF8ucHVsbEFsbEJ5YCwgdGhpcyBtZXRob2QgcmV0dXJucyBhIG5ldyBhcnJheS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7Li4uQXJyYXl9IFt2YWx1ZXNdIFRoZSB2YWx1ZXMgdG8gZXhjbHVkZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgZmlsdGVyZWQgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRpZmZlcmVuY2VCeShbMi4xLCAxLjJdLCBbMi4zLCAzLjRdLCBNYXRoLmZsb29yKTtcbiAgICAgKiAvLyA9PiBbMS4yXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5kaWZmZXJlbmNlQnkoW3sgJ3gnOiAyIH0sIHsgJ3gnOiAxIH1dLCBbeyAneCc6IDEgfV0sICd4Jyk7XG4gICAgICogLy8gPT4gW3sgJ3gnOiAyIH1dXG4gICAgICovXG4gICAgdmFyIGRpZmZlcmVuY2VCeSA9IGJhc2VSZXN0KGZ1bmN0aW9uKGFycmF5LCB2YWx1ZXMpIHtcbiAgICAgIHZhciBpdGVyYXRlZSA9IGxhc3QodmFsdWVzKTtcbiAgICAgIGlmIChpc0FycmF5TGlrZU9iamVjdChpdGVyYXRlZSkpIHtcbiAgICAgICAgaXRlcmF0ZWUgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gaXNBcnJheUxpa2VPYmplY3QoYXJyYXkpXG4gICAgICAgID8gYmFzZURpZmZlcmVuY2UoYXJyYXksIGJhc2VGbGF0dGVuKHZhbHVlcywgMSwgaXNBcnJheUxpa2VPYmplY3QsIHRydWUpLCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMikpXG4gICAgICAgIDogW107XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmRpZmZlcmVuY2VgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGNvbXBhcmF0b3JgXG4gICAgICogd2hpY2ggaXMgaW52b2tlZCB0byBjb21wYXJlIGVsZW1lbnRzIG9mIGBhcnJheWAgdG8gYHZhbHVlc2AuIFRoZSBvcmRlciBhbmRcbiAgICAgKiByZWZlcmVuY2VzIG9mIHJlc3VsdCB2YWx1ZXMgYXJlIGRldGVybWluZWQgYnkgdGhlIGZpcnN0IGFycmF5LiBUaGUgY29tcGFyYXRvclxuICAgICAqIGlzIGludm9rZWQgd2l0aCB0d28gYXJndW1lbnRzOiAoYXJyVmFsLCBvdGhWYWwpLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFVubGlrZSBgXy5wdWxsQWxsV2l0aGAsIHRoaXMgbWV0aG9kIHJldHVybnMgYSBuZXcgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0gey4uLkFycmF5fSBbdmFsdWVzXSBUaGUgdmFsdWVzIHRvIGV4Y2x1ZGUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2NvbXBhcmF0b3JdIFRoZSBjb21wYXJhdG9yIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgZmlsdGVyZWQgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IFt7ICd4JzogMSwgJ3knOiAyIH0sIHsgJ3gnOiAyLCAneSc6IDEgfV07XG4gICAgICpcbiAgICAgKiBfLmRpZmZlcmVuY2VXaXRoKG9iamVjdHMsIFt7ICd4JzogMSwgJ3knOiAyIH1dLCBfLmlzRXF1YWwpO1xuICAgICAqIC8vID0+IFt7ICd4JzogMiwgJ3knOiAxIH1dXG4gICAgICovXG4gICAgdmFyIGRpZmZlcmVuY2VXaXRoID0gYmFzZVJlc3QoZnVuY3Rpb24oYXJyYXksIHZhbHVlcykge1xuICAgICAgdmFyIGNvbXBhcmF0b3IgPSBsYXN0KHZhbHVlcyk7XG4gICAgICBpZiAoaXNBcnJheUxpa2VPYmplY3QoY29tcGFyYXRvcikpIHtcbiAgICAgICAgY29tcGFyYXRvciA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpc0FycmF5TGlrZU9iamVjdChhcnJheSlcbiAgICAgICAgPyBiYXNlRGlmZmVyZW5jZShhcnJheSwgYmFzZUZsYXR0ZW4odmFsdWVzLCAxLCBpc0FycmF5TGlrZU9iamVjdCwgdHJ1ZSksIHVuZGVmaW5lZCwgY29tcGFyYXRvcilcbiAgICAgICAgOiBbXTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBzbGljZSBvZiBgYXJyYXlgIHdpdGggYG5gIGVsZW1lbnRzIGRyb3BwZWQgZnJvbSB0aGUgYmVnaW5uaW5nLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuNS4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbj0xXSBUaGUgbnVtYmVyIG9mIGVsZW1lbnRzIHRvIGRyb3AuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZHJvcChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IFsyLCAzXVxuICAgICAqXG4gICAgICogXy5kcm9wKFsxLCAyLCAzXSwgMik7XG4gICAgICogLy8gPT4gWzNdXG4gICAgICpcbiAgICAgKiBfLmRyb3AoWzEsIDIsIDNdLCA1KTtcbiAgICAgKiAvLyA9PiBbXVxuICAgICAqXG4gICAgICogXy5kcm9wKFsxLCAyLCAzXSwgMCk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICovXG4gICAgZnVuY3Rpb24gZHJvcChhcnJheSwgbiwgZ3VhcmQpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIG4gPSAoZ3VhcmQgfHwgbiA9PT0gdW5kZWZpbmVkKSA/IDEgOiB0b0ludGVnZXIobik7XG4gICAgICByZXR1cm4gYmFzZVNsaWNlKGFycmF5LCBuIDwgMCA/IDAgOiBuLCBsZW5ndGgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBzbGljZSBvZiBgYXJyYXlgIHdpdGggYG5gIGVsZW1lbnRzIGRyb3BwZWQgZnJvbSB0aGUgZW5kLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbj0xXSBUaGUgbnVtYmVyIG9mIGVsZW1lbnRzIHRvIGRyb3AuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZHJvcFJpZ2h0KFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gWzEsIDJdXG4gICAgICpcbiAgICAgKiBfLmRyb3BSaWdodChbMSwgMiwgM10sIDIpO1xuICAgICAqIC8vID0+IFsxXVxuICAgICAqXG4gICAgICogXy5kcm9wUmlnaHQoWzEsIDIsIDNdLCA1KTtcbiAgICAgKiAvLyA9PiBbXVxuICAgICAqXG4gICAgICogXy5kcm9wUmlnaHQoWzEsIDIsIDNdLCAwKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBkcm9wUmlnaHQoYXJyYXksIG4sIGd1YXJkKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICBuID0gKGd1YXJkIHx8IG4gPT09IHVuZGVmaW5lZCkgPyAxIDogdG9JbnRlZ2VyKG4pO1xuICAgICAgbiA9IGxlbmd0aCAtIG47XG4gICAgICByZXR1cm4gYmFzZVNsaWNlKGFycmF5LCAwLCBuIDwgMCA/IDAgOiBuKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc2xpY2Ugb2YgYGFycmF5YCBleGNsdWRpbmcgZWxlbWVudHMgZHJvcHBlZCBmcm9tIHRoZSBlbmQuXG4gICAgICogRWxlbWVudHMgYXJlIGRyb3BwZWQgdW50aWwgYHByZWRpY2F0ZWAgcmV0dXJucyBmYWxzZXkuIFRoZSBwcmVkaWNhdGUgaXNcbiAgICAgKiBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzOiAodmFsdWUsIGluZGV4LCBhcnJheSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAgJ2FjdGl2ZSc6IHRydWUgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdwZWJibGVzJywgJ2FjdGl2ZSc6IGZhbHNlIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5kcm9wUmlnaHRXaGlsZSh1c2VycywgZnVuY3Rpb24obykgeyByZXR1cm4gIW8uYWN0aXZlOyB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2Jhcm5leSddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc2AgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZHJvcFJpZ2h0V2hpbGUodXNlcnMsIHsgJ3VzZXInOiAncGViYmxlcycsICdhY3RpdmUnOiBmYWxzZSB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2Jhcm5leScsICdmcmVkJ11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmRyb3BSaWdodFdoaWxlKHVzZXJzLCBbJ2FjdGl2ZScsIGZhbHNlXSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydiYXJuZXknXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5kcm9wUmlnaHRXaGlsZSh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnYmFybmV5JywgJ2ZyZWQnLCAncGViYmxlcyddXG4gICAgICovXG4gICAgZnVuY3Rpb24gZHJvcFJpZ2h0V2hpbGUoYXJyYXksIHByZWRpY2F0ZSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpXG4gICAgICAgID8gYmFzZVdoaWxlKGFycmF5LCBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpLCB0cnVlLCB0cnVlKVxuICAgICAgICA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBzbGljZSBvZiBgYXJyYXlgIGV4Y2x1ZGluZyBlbGVtZW50cyBkcm9wcGVkIGZyb20gdGhlIGJlZ2lubmluZy5cbiAgICAgKiBFbGVtZW50cyBhcmUgZHJvcHBlZCB1bnRpbCBgcHJlZGljYXRlYCByZXR1cm5zIGZhbHNleS4gVGhlIHByZWRpY2F0ZSBpc1xuICAgICAqIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwgaW5kZXgsIGFycmF5KS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdwZWJibGVzJywgJ2FjdGl2ZSc6IHRydWUgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLmRyb3BXaGlsZSh1c2VycywgZnVuY3Rpb24obykgeyByZXR1cm4gIW8uYWN0aXZlOyB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ3BlYmJsZXMnXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmRyb3BXaGlsZSh1c2VycywgeyAndXNlcic6ICdiYXJuZXknLCAnYWN0aXZlJzogZmFsc2UgfSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydmcmVkJywgJ3BlYmJsZXMnXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZHJvcFdoaWxlKHVzZXJzLCBbJ2FjdGl2ZScsIGZhbHNlXSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydwZWJibGVzJ11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZHJvcFdoaWxlKHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydiYXJuZXknLCAnZnJlZCcsICdwZWJibGVzJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBkcm9wV2hpbGUoYXJyYXksIHByZWRpY2F0ZSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpXG4gICAgICAgID8gYmFzZVdoaWxlKGFycmF5LCBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpLCB0cnVlKVxuICAgICAgICA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZpbGxzIGVsZW1lbnRzIG9mIGBhcnJheWAgd2l0aCBgdmFsdWVgIGZyb20gYHN0YXJ0YCB1cCB0bywgYnV0IG5vdFxuICAgICAqIGluY2x1ZGluZywgYGVuZGAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMi4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGZpbGwuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gZmlsbCBgYXJyYXlgIHdpdGguXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGFydD0wXSBUaGUgc3RhcnQgcG9zaXRpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtlbmQ9YXJyYXkubGVuZ3RoXSBUaGUgZW5kIHBvc2l0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbMSwgMiwgM107XG4gICAgICpcbiAgICAgKiBfLmZpbGwoYXJyYXksICdhJyk7XG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFsnYScsICdhJywgJ2EnXVxuICAgICAqXG4gICAgICogXy5maWxsKEFycmF5KDMpLCAyKTtcbiAgICAgKiAvLyA9PiBbMiwgMiwgMl1cbiAgICAgKlxuICAgICAqIF8uZmlsbChbNCwgNiwgOCwgMTBdLCAnKicsIDEsIDMpO1xuICAgICAqIC8vID0+IFs0LCAnKicsICcqJywgMTBdXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmlsbChhcnJheSwgdmFsdWUsIHN0YXJ0LCBlbmQpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIGlmIChzdGFydCAmJiB0eXBlb2Ygc3RhcnQgIT0gJ251bWJlcicgJiYgaXNJdGVyYXRlZUNhbGwoYXJyYXksIHZhbHVlLCBzdGFydCkpIHtcbiAgICAgICAgc3RhcnQgPSAwO1xuICAgICAgICBlbmQgPSBsZW5ndGg7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZUZpbGwoYXJyYXksIHZhbHVlLCBzdGFydCwgZW5kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZpbmRgIGV4Y2VwdCB0aGF0IGl0IHJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBmaXJzdFxuICAgICAqIGVsZW1lbnQgYHByZWRpY2F0ZWAgcmV0dXJucyB0cnV0aHkgZm9yIGluc3RlYWQgb2YgdGhlIGVsZW1lbnQgaXRzZWxmLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDEuMS4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZnJvbUluZGV4PTBdIFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgZm91bmQgZWxlbWVudCwgZWxzZSBgLTFgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdwZWJibGVzJywgJ2FjdGl2ZSc6IHRydWUgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLmZpbmRJbmRleCh1c2VycywgZnVuY3Rpb24obykgeyByZXR1cm4gby51c2VyID09ICdiYXJuZXknOyB9KTtcbiAgICAgKiAvLyA9PiAwXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc2AgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmluZEluZGV4KHVzZXJzLCB7ICd1c2VyJzogJ2ZyZWQnLCAnYWN0aXZlJzogZmFsc2UgfSk7XG4gICAgICogLy8gPT4gMVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmluZEluZGV4KHVzZXJzLCBbJ2FjdGl2ZScsIGZhbHNlXSk7XG4gICAgICogLy8gPT4gMFxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kSW5kZXgodXNlcnMsICdhY3RpdmUnKTtcbiAgICAgKiAvLyA9PiAyXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmluZEluZGV4KGFycmF5LCBwcmVkaWNhdGUsIGZyb21JbmRleCkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuICAgICAgdmFyIGluZGV4ID0gZnJvbUluZGV4ID09IG51bGwgPyAwIDogdG9JbnRlZ2VyKGZyb21JbmRleCk7XG4gICAgICBpZiAoaW5kZXggPCAwKSB7XG4gICAgICAgIGluZGV4ID0gbmF0aXZlTWF4KGxlbmd0aCArIGluZGV4LCAwKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlRmluZEluZGV4KGFycmF5LCBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpLCBpbmRleCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5maW5kSW5kZXhgIGV4Y2VwdCB0aGF0IGl0IGl0ZXJhdGVzIG92ZXIgZWxlbWVudHNcbiAgICAgKiBvZiBgY29sbGVjdGlvbmAgZnJvbSByaWdodCB0byBsZWZ0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDIuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZnJvbUluZGV4PWFycmF5Lmxlbmd0aC0xXSBUaGUgaW5kZXggdG8gc2VhcmNoIGZyb20uXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIGZvdW5kIGVsZW1lbnQsIGVsc2UgYC0xYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAgJ2FjdGl2ZSc6IHRydWUgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdwZWJibGVzJywgJ2FjdGl2ZSc6IGZhbHNlIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5maW5kTGFzdEluZGV4KHVzZXJzLCBmdW5jdGlvbihvKSB7IHJldHVybiBvLnVzZXIgPT0gJ3BlYmJsZXMnOyB9KTtcbiAgICAgKiAvLyA9PiAyXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc2AgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmluZExhc3RJbmRleCh1c2VycywgeyAndXNlcic6ICdiYXJuZXknLCAnYWN0aXZlJzogdHJ1ZSB9KTtcbiAgICAgKiAvLyA9PiAwXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kTGFzdEluZGV4KHVzZXJzLCBbJ2FjdGl2ZScsIGZhbHNlXSk7XG4gICAgICogLy8gPT4gMlxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kTGFzdEluZGV4KHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gMFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZpbmRMYXN0SW5kZXgoYXJyYXksIHByZWRpY2F0ZSwgZnJvbUluZGV4KSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG4gICAgICB2YXIgaW5kZXggPSBsZW5ndGggLSAxO1xuICAgICAgaWYgKGZyb21JbmRleCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGluZGV4ID0gdG9JbnRlZ2VyKGZyb21JbmRleCk7XG4gICAgICAgIGluZGV4ID0gZnJvbUluZGV4IDwgMFxuICAgICAgICAgID8gbmF0aXZlTWF4KGxlbmd0aCArIGluZGV4LCAwKVxuICAgICAgICAgIDogbmF0aXZlTWluKGluZGV4LCBsZW5ndGggLSAxKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlRmluZEluZGV4KGFycmF5LCBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpLCBpbmRleCwgdHJ1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRmxhdHRlbnMgYGFycmF5YCBhIHNpbmdsZSBsZXZlbCBkZWVwLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGZsYXR0ZW4uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgZmxhdHRlbmVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmZsYXR0ZW4oWzEsIFsyLCBbMywgWzRdXSwgNV1dKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgWzMsIFs0XV0sIDVdXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmxhdHRlbihhcnJheSkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuICAgICAgcmV0dXJuIGxlbmd0aCA/IGJhc2VGbGF0dGVuKGFycmF5LCAxKSA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlY3Vyc2l2ZWx5IGZsYXR0ZW5zIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gZmxhdHRlbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmbGF0dGVuZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZmxhdHRlbkRlZXAoWzEsIFsyLCBbMywgWzRdXSwgNV1dKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgMywgNCwgNV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmbGF0dGVuRGVlcChhcnJheSkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuICAgICAgcmV0dXJuIGxlbmd0aCA/IGJhc2VGbGF0dGVuKGFycmF5LCBJTkZJTklUWSkgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWN1cnNpdmVseSBmbGF0dGVuIGBhcnJheWAgdXAgdG8gYGRlcHRoYCB0aW1lcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjQuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBmbGF0dGVuLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZGVwdGg9MV0gVGhlIG1heGltdW0gcmVjdXJzaW9uIGRlcHRoLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGZsYXR0ZW5lZCBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWzEsIFsyLCBbMywgWzRdXSwgNV1dO1xuICAgICAqXG4gICAgICogXy5mbGF0dGVuRGVwdGgoYXJyYXksIDEpO1xuICAgICAqIC8vID0+IFsxLCAyLCBbMywgWzRdXSwgNV1cbiAgICAgKlxuICAgICAqIF8uZmxhdHRlbkRlcHRoKGFycmF5LCAyKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgMywgWzRdLCA1XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZsYXR0ZW5EZXB0aChhcnJheSwgZGVwdGgpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIGRlcHRoID0gZGVwdGggPT09IHVuZGVmaW5lZCA/IDEgOiB0b0ludGVnZXIoZGVwdGgpO1xuICAgICAgcmV0dXJuIGJhc2VGbGF0dGVuKGFycmF5LCBkZXB0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGludmVyc2Ugb2YgYF8udG9QYWlyc2A7IHRoaXMgbWV0aG9kIHJldHVybnMgYW4gb2JqZWN0IGNvbXBvc2VkXG4gICAgICogZnJvbSBrZXktdmFsdWUgYHBhaXJzYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IHBhaXJzIFRoZSBrZXktdmFsdWUgcGFpcnMuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5mcm9tUGFpcnMoW1snYScsIDFdLCBbJ2InLCAyXV0pO1xuICAgICAqIC8vID0+IHsgJ2EnOiAxLCAnYic6IDIgfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZyb21QYWlycyhwYWlycykge1xuICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgbGVuZ3RoID0gcGFpcnMgPT0gbnVsbCA/IDAgOiBwYWlycy5sZW5ndGgsXG4gICAgICAgICAgcmVzdWx0ID0ge307XG5cbiAgICAgIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIHZhciBwYWlyID0gcGFpcnNbaW5kZXhdO1xuICAgICAgICByZXN1bHRbcGFpclswXV0gPSBwYWlyWzFdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBmaXJzdCBlbGVtZW50IG9mIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAYWxpYXMgZmlyc3RcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGZpcnN0IGVsZW1lbnQgb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5oZWFkKFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gMVxuICAgICAqXG4gICAgICogXy5oZWFkKFtdKTtcbiAgICAgKiAvLyA9PiB1bmRlZmluZWRcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBoZWFkKGFycmF5KSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aCkgPyBhcnJheVswXSA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBpbmRleCBhdCB3aGljaCB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiBgdmFsdWVgIGlzIGZvdW5kIGluIGBhcnJheWBcbiAgICAgKiB1c2luZyBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICAgICAqIGZvciBlcXVhbGl0eSBjb21wYXJpc29ucy4gSWYgYGZyb21JbmRleGAgaXMgbmVnYXRpdmUsIGl0J3MgdXNlZCBhcyB0aGVcbiAgICAgKiBvZmZzZXQgZnJvbSB0aGUgZW5kIG9mIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZnJvbUluZGV4PTBdIFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgbWF0Y2hlZCB2YWx1ZSwgZWxzZSBgLTFgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmluZGV4T2YoWzEsIDIsIDEsIDJdLCAyKTtcbiAgICAgKiAvLyA9PiAxXG4gICAgICpcbiAgICAgKiAvLyBTZWFyY2ggZnJvbSB0aGUgYGZyb21JbmRleGAuXG4gICAgICogXy5pbmRleE9mKFsxLCAyLCAxLCAyXSwgMiwgMik7XG4gICAgICogLy8gPT4gM1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluZGV4T2YoYXJyYXksIHZhbHVlLCBmcm9tSW5kZXgpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cbiAgICAgIHZhciBpbmRleCA9IGZyb21JbmRleCA9PSBudWxsID8gMCA6IHRvSW50ZWdlcihmcm9tSW5kZXgpO1xuICAgICAgaWYgKGluZGV4IDwgMCkge1xuICAgICAgICBpbmRleCA9IG5hdGl2ZU1heChsZW5ndGggKyBpbmRleCwgMCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZUluZGV4T2YoYXJyYXksIHZhbHVlLCBpbmRleCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBhbGwgYnV0IHRoZSBsYXN0IGVsZW1lbnQgb2YgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaW5pdGlhbChbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IFsxLCAyXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluaXRpYWwoYXJyYXkpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICAgIHJldHVybiBsZW5ndGggPyBiYXNlU2xpY2UoYXJyYXksIDAsIC0xKSA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdW5pcXVlIHZhbHVlcyB0aGF0IGFyZSBpbmNsdWRlZCBpbiBhbGwgZ2l2ZW4gYXJyYXlzXG4gICAgICogdXNpbmcgW2BTYW1lVmFsdWVaZXJvYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtc2FtZXZhbHVlemVybylcbiAgICAgKiBmb3IgZXF1YWxpdHkgY29tcGFyaXNvbnMuIFRoZSBvcmRlciBhbmQgcmVmZXJlbmNlcyBvZiByZXN1bHQgdmFsdWVzIGFyZVxuICAgICAqIGRldGVybWluZWQgYnkgdGhlIGZpcnN0IGFycmF5LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBpbnNwZWN0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGludGVyc2VjdGluZyB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaW50ZXJzZWN0aW9uKFsyLCAxXSwgWzIsIDNdKTtcbiAgICAgKiAvLyA9PiBbMl1cbiAgICAgKi9cbiAgICB2YXIgaW50ZXJzZWN0aW9uID0gYmFzZVJlc3QoZnVuY3Rpb24oYXJyYXlzKSB7XG4gICAgICB2YXIgbWFwcGVkID0gYXJyYXlNYXAoYXJyYXlzLCBjYXN0QXJyYXlMaWtlT2JqZWN0KTtcbiAgICAgIHJldHVybiAobWFwcGVkLmxlbmd0aCAmJiBtYXBwZWRbMF0gPT09IGFycmF5c1swXSlcbiAgICAgICAgPyBiYXNlSW50ZXJzZWN0aW9uKG1hcHBlZClcbiAgICAgICAgOiBbXTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uaW50ZXJzZWN0aW9uYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBpdGVyYXRlZWBcbiAgICAgKiB3aGljaCBpcyBpbnZva2VkIGZvciBlYWNoIGVsZW1lbnQgb2YgZWFjaCBgYXJyYXlzYCB0byBnZW5lcmF0ZSB0aGUgY3JpdGVyaW9uXG4gICAgICogYnkgd2hpY2ggdGhleSdyZSBjb21wYXJlZC4gVGhlIG9yZGVyIGFuZCByZWZlcmVuY2VzIG9mIHJlc3VsdCB2YWx1ZXMgYXJlXG4gICAgICogZGV0ZXJtaW5lZCBieSB0aGUgZmlyc3QgYXJyYXkuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OlxuICAgICAqICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0gey4uLkFycmF5fSBbYXJyYXlzXSBUaGUgYXJyYXlzIHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGludGVyc2VjdGluZyB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaW50ZXJzZWN0aW9uQnkoWzIuMSwgMS4yXSwgWzIuMywgMy40XSwgTWF0aC5mbG9vcik7XG4gICAgICogLy8gPT4gWzIuMV1cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uaW50ZXJzZWN0aW9uQnkoW3sgJ3gnOiAxIH1dLCBbeyAneCc6IDIgfSwgeyAneCc6IDEgfV0sICd4Jyk7XG4gICAgICogLy8gPT4gW3sgJ3gnOiAxIH1dXG4gICAgICovXG4gICAgdmFyIGludGVyc2VjdGlvbkJ5ID0gYmFzZVJlc3QoZnVuY3Rpb24oYXJyYXlzKSB7XG4gICAgICB2YXIgaXRlcmF0ZWUgPSBsYXN0KGFycmF5cyksXG4gICAgICAgICAgbWFwcGVkID0gYXJyYXlNYXAoYXJyYXlzLCBjYXN0QXJyYXlMaWtlT2JqZWN0KTtcblxuICAgICAgaWYgKGl0ZXJhdGVlID09PSBsYXN0KG1hcHBlZCkpIHtcbiAgICAgICAgaXRlcmF0ZWUgPSB1bmRlZmluZWQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBtYXBwZWQucG9wKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gKG1hcHBlZC5sZW5ndGggJiYgbWFwcGVkWzBdID09PSBhcnJheXNbMF0pXG4gICAgICAgID8gYmFzZUludGVyc2VjdGlvbihtYXBwZWQsIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAyKSlcbiAgICAgICAgOiBbXTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uaW50ZXJzZWN0aW9uYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBjb21wYXJhdG9yYFxuICAgICAqIHdoaWNoIGlzIGludm9rZWQgdG8gY29tcGFyZSBlbGVtZW50cyBvZiBgYXJyYXlzYC4gVGhlIG9yZGVyIGFuZCByZWZlcmVuY2VzXG4gICAgICogb2YgcmVzdWx0IHZhbHVlcyBhcmUgZGV0ZXJtaW5lZCBieSB0aGUgZmlyc3QgYXJyYXkuIFRoZSBjb21wYXJhdG9yIGlzXG4gICAgICogaW52b2tlZCB3aXRoIHR3byBhcmd1bWVudHM6IChhcnJWYWwsIG90aFZhbCkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0gey4uLkFycmF5fSBbYXJyYXlzXSBUaGUgYXJyYXlzIHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2NvbXBhcmF0b3JdIFRoZSBjb21wYXJhdG9yIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgaW50ZXJzZWN0aW5nIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbeyAneCc6IDEsICd5JzogMiB9LCB7ICd4JzogMiwgJ3knOiAxIH1dO1xuICAgICAqIHZhciBvdGhlcnMgPSBbeyAneCc6IDEsICd5JzogMSB9LCB7ICd4JzogMSwgJ3knOiAyIH1dO1xuICAgICAqXG4gICAgICogXy5pbnRlcnNlY3Rpb25XaXRoKG9iamVjdHMsIG90aGVycywgXy5pc0VxdWFsKTtcbiAgICAgKiAvLyA9PiBbeyAneCc6IDEsICd5JzogMiB9XVxuICAgICAqL1xuICAgIHZhciBpbnRlcnNlY3Rpb25XaXRoID0gYmFzZVJlc3QoZnVuY3Rpb24oYXJyYXlzKSB7XG4gICAgICB2YXIgY29tcGFyYXRvciA9IGxhc3QoYXJyYXlzKSxcbiAgICAgICAgICBtYXBwZWQgPSBhcnJheU1hcChhcnJheXMsIGNhc3RBcnJheUxpa2VPYmplY3QpO1xuXG4gICAgICBjb21wYXJhdG9yID0gdHlwZW9mIGNvbXBhcmF0b3IgPT0gJ2Z1bmN0aW9uJyA/IGNvbXBhcmF0b3IgOiB1bmRlZmluZWQ7XG4gICAgICBpZiAoY29tcGFyYXRvcikge1xuICAgICAgICBtYXBwZWQucG9wKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gKG1hcHBlZC5sZW5ndGggJiYgbWFwcGVkWzBdID09PSBhcnJheXNbMF0pXG4gICAgICAgID8gYmFzZUludGVyc2VjdGlvbihtYXBwZWQsIHVuZGVmaW5lZCwgY29tcGFyYXRvcilcbiAgICAgICAgOiBbXTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGFsbCBlbGVtZW50cyBpbiBgYXJyYXlgIGludG8gYSBzdHJpbmcgc2VwYXJhdGVkIGJ5IGBzZXBhcmF0b3JgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGNvbnZlcnQuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzZXBhcmF0b3I9JywnXSBUaGUgZWxlbWVudCBzZXBhcmF0b3IuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgam9pbmVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5qb2luKFsnYScsICdiJywgJ2MnXSwgJ34nKTtcbiAgICAgKiAvLyA9PiAnYX5ifmMnXG4gICAgICovXG4gICAgZnVuY3Rpb24gam9pbihhcnJheSwgc2VwYXJhdG9yKSB7XG4gICAgICByZXR1cm4gYXJyYXkgPT0gbnVsbCA/ICcnIDogbmF0aXZlSm9pbi5jYWxsKGFycmF5LCBzZXBhcmF0b3IpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGxhc3QgZWxlbWVudCBvZiBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBsYXN0IGVsZW1lbnQgb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5sYXN0KFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gM1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGxhc3QoYXJyYXkpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICAgIHJldHVybiBsZW5ndGggPyBhcnJheVtsZW5ndGggLSAxXSA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmluZGV4T2ZgIGV4Y2VwdCB0aGF0IGl0IGl0ZXJhdGVzIG92ZXIgZWxlbWVudHMgb2ZcbiAgICAgKiBgYXJyYXlgIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNlYXJjaCBmb3IuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtmcm9tSW5kZXg9YXJyYXkubGVuZ3RoLTFdIFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgbWF0Y2hlZCB2YWx1ZSwgZWxzZSBgLTFgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmxhc3RJbmRleE9mKFsxLCAyLCAxLCAyXSwgMik7XG4gICAgICogLy8gPT4gM1xuICAgICAqXG4gICAgICogLy8gU2VhcmNoIGZyb20gdGhlIGBmcm9tSW5kZXhgLlxuICAgICAqIF8ubGFzdEluZGV4T2YoWzEsIDIsIDEsIDJdLCAyLCAyKTtcbiAgICAgKiAvLyA9PiAxXG4gICAgICovXG4gICAgZnVuY3Rpb24gbGFzdEluZGV4T2YoYXJyYXksIHZhbHVlLCBmcm9tSW5kZXgpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cbiAgICAgIHZhciBpbmRleCA9IGxlbmd0aDtcbiAgICAgIGlmIChmcm9tSW5kZXggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpbmRleCA9IHRvSW50ZWdlcihmcm9tSW5kZXgpO1xuICAgICAgICBpbmRleCA9IGluZGV4IDwgMCA/IG5hdGl2ZU1heChsZW5ndGggKyBpbmRleCwgMCkgOiBuYXRpdmVNaW4oaW5kZXgsIGxlbmd0aCAtIDEpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHZhbHVlID09PSB2YWx1ZVxuICAgICAgICA/IHN0cmljdExhc3RJbmRleE9mKGFycmF5LCB2YWx1ZSwgaW5kZXgpXG4gICAgICAgIDogYmFzZUZpbmRJbmRleChhcnJheSwgYmFzZUlzTmFOLCBpbmRleCwgdHJ1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgZWxlbWVudCBhdCBpbmRleCBgbmAgb2YgYGFycmF5YC4gSWYgYG5gIGlzIG5lZ2F0aXZlLCB0aGUgbnRoXG4gICAgICogZWxlbWVudCBmcm9tIHRoZSBlbmQgaXMgcmV0dXJuZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4xMS4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbj0wXSBUaGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gcmV0dXJuLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBudGggZWxlbWVudCBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbJ2EnLCAnYicsICdjJywgJ2QnXTtcbiAgICAgKlxuICAgICAqIF8ubnRoKGFycmF5LCAxKTtcbiAgICAgKiAvLyA9PiAnYidcbiAgICAgKlxuICAgICAqIF8ubnRoKGFycmF5LCAtMik7XG4gICAgICogLy8gPT4gJ2MnO1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIG50aChhcnJheSwgbikge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpID8gYmFzZU50aChhcnJheSwgdG9JbnRlZ2VyKG4pKSA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFsbCBnaXZlbiB2YWx1ZXMgZnJvbSBgYXJyYXlgIHVzaW5nXG4gICAgICogW2BTYW1lVmFsdWVaZXJvYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtc2FtZXZhbHVlemVybylcbiAgICAgKiBmb3IgZXF1YWxpdHkgY29tcGFyaXNvbnMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVW5saWtlIGBfLndpdGhvdXRgLCB0aGlzIG1ldGhvZCBtdXRhdGVzIGBhcnJheWAuIFVzZSBgXy5yZW1vdmVgXG4gICAgICogdG8gcmVtb3ZlIGVsZW1lbnRzIGZyb20gYW4gYXJyYXkgYnkgcHJlZGljYXRlLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDIuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0gey4uLip9IFt2YWx1ZXNdIFRoZSB2YWx1ZXMgdG8gcmVtb3ZlLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbJ2EnLCAnYicsICdjJywgJ2EnLCAnYicsICdjJ107XG4gICAgICpcbiAgICAgKiBfLnB1bGwoYXJyYXksICdhJywgJ2MnKTtcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheSk7XG4gICAgICogLy8gPT4gWydiJywgJ2InXVxuICAgICAqL1xuICAgIHZhciBwdWxsID0gYmFzZVJlc3QocHVsbEFsbCk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnB1bGxgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYW4gYXJyYXkgb2YgdmFsdWVzIHRvIHJlbW92ZS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBVbmxpa2UgYF8uZGlmZmVyZW5jZWAsIHRoaXMgbWV0aG9kIG11dGF0ZXMgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtBcnJheX0gdmFsdWVzIFRoZSB2YWx1ZXMgdG8gcmVtb3ZlLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbJ2EnLCAnYicsICdjJywgJ2EnLCAnYicsICdjJ107XG4gICAgICpcbiAgICAgKiBfLnB1bGxBbGwoYXJyYXksIFsnYScsICdjJ10pO1xuICAgICAqIGNvbnNvbGUubG9nKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbJ2InLCAnYiddXG4gICAgICovXG4gICAgZnVuY3Rpb24gcHVsbEFsbChhcnJheSwgdmFsdWVzKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aCAmJiB2YWx1ZXMgJiYgdmFsdWVzLmxlbmd0aClcbiAgICAgICAgPyBiYXNlUHVsbEFsbChhcnJheSwgdmFsdWVzKVxuICAgICAgICA6IGFycmF5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8ucHVsbEFsbGAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgIHdoaWNoIGlzXG4gICAgICogaW52b2tlZCBmb3IgZWFjaCBlbGVtZW50IG9mIGBhcnJheWAgYW5kIGB2YWx1ZXNgIHRvIGdlbmVyYXRlIHRoZSBjcml0ZXJpb25cbiAgICAgKiBieSB3aGljaCB0aGV5J3JlIGNvbXBhcmVkLiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBVbmxpa2UgYF8uZGlmZmVyZW5jZUJ5YCwgdGhpcyBtZXRob2QgbXV0YXRlcyBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB2YWx1ZXMgVGhlIHZhbHVlcyB0byByZW1vdmUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbeyAneCc6IDEgfSwgeyAneCc6IDIgfSwgeyAneCc6IDMgfSwgeyAneCc6IDEgfV07XG4gICAgICpcbiAgICAgKiBfLnB1bGxBbGxCeShhcnJheSwgW3sgJ3gnOiAxIH0sIHsgJ3gnOiAzIH1dLCAneCcpO1xuICAgICAqIGNvbnNvbGUubG9nKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbeyAneCc6IDIgfV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwdWxsQWxsQnkoYXJyYXksIHZhbHVlcywgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoICYmIHZhbHVlcyAmJiB2YWx1ZXMubGVuZ3RoKVxuICAgICAgICA/IGJhc2VQdWxsQWxsKGFycmF5LCB2YWx1ZXMsIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAyKSlcbiAgICAgICAgOiBhcnJheTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnB1bGxBbGxgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGNvbXBhcmF0b3JgIHdoaWNoXG4gICAgICogaXMgaW52b2tlZCB0byBjb21wYXJlIGVsZW1lbnRzIG9mIGBhcnJheWAgdG8gYHZhbHVlc2AuIFRoZSBjb21wYXJhdG9yIGlzXG4gICAgICogaW52b2tlZCB3aXRoIHR3byBhcmd1bWVudHM6IChhcnJWYWwsIG90aFZhbCkuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVW5saWtlIGBfLmRpZmZlcmVuY2VXaXRoYCwgdGhpcyBtZXRob2QgbXV0YXRlcyBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuNi4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSB2YWx1ZXMgVGhlIHZhbHVlcyB0byByZW1vdmUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2NvbXBhcmF0b3JdIFRoZSBjb21wYXJhdG9yIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFt7ICd4JzogMSwgJ3knOiAyIH0sIHsgJ3gnOiAzLCAneSc6IDQgfSwgeyAneCc6IDUsICd5JzogNiB9XTtcbiAgICAgKlxuICAgICAqIF8ucHVsbEFsbFdpdGgoYXJyYXksIFt7ICd4JzogMywgJ3knOiA0IH1dLCBfLmlzRXF1YWwpO1xuICAgICAqIGNvbnNvbGUubG9nKGFycmF5KTtcbiAgICAgKiAvLyA9PiBbeyAneCc6IDEsICd5JzogMiB9LCB7ICd4JzogNSwgJ3knOiA2IH1dXG4gICAgICovXG4gICAgZnVuY3Rpb24gcHVsbEFsbFdpdGgoYXJyYXksIHZhbHVlcywgY29tcGFyYXRvcikge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGggJiYgdmFsdWVzICYmIHZhbHVlcy5sZW5ndGgpXG4gICAgICAgID8gYmFzZVB1bGxBbGwoYXJyYXksIHZhbHVlcywgdW5kZWZpbmVkLCBjb21wYXJhdG9yKVxuICAgICAgICA6IGFycmF5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgZWxlbWVudHMgZnJvbSBgYXJyYXlgIGNvcnJlc3BvbmRpbmcgdG8gYGluZGV4ZXNgIGFuZCByZXR1cm5zIGFuXG4gICAgICogYXJyYXkgb2YgcmVtb3ZlZCBlbGVtZW50cy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBVbmxpa2UgYF8uYXRgLCB0aGlzIG1ldGhvZCBtdXRhdGVzIGBhcnJheWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7Li4uKG51bWJlcnxudW1iZXJbXSl9IFtpbmRleGVzXSBUaGUgaW5kZXhlcyBvZiBlbGVtZW50cyB0byByZW1vdmUuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgcmVtb3ZlZCBlbGVtZW50cy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gWydhJywgJ2InLCAnYycsICdkJ107XG4gICAgICogdmFyIHB1bGxlZCA9IF8ucHVsbEF0KGFycmF5LCBbMSwgM10pO1xuICAgICAqXG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFsnYScsICdjJ11cbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKHB1bGxlZCk7XG4gICAgICogLy8gPT4gWydiJywgJ2QnXVxuICAgICAqL1xuICAgIHZhciBwdWxsQXQgPSBmbGF0UmVzdChmdW5jdGlvbihhcnJheSwgaW5kZXhlcykge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoLFxuICAgICAgICAgIHJlc3VsdCA9IGJhc2VBdChhcnJheSwgaW5kZXhlcyk7XG5cbiAgICAgIGJhc2VQdWxsQXQoYXJyYXksIGFycmF5TWFwKGluZGV4ZXMsIGZ1bmN0aW9uKGluZGV4KSB7XG4gICAgICAgIHJldHVybiBpc0luZGV4KGluZGV4LCBsZW5ndGgpID8gK2luZGV4IDogaW5kZXg7XG4gICAgICB9KS5zb3J0KGNvbXBhcmVBc2NlbmRpbmcpKTtcblxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGVsZW1lbnRzIGZyb20gYGFycmF5YCB0aGF0IGBwcmVkaWNhdGVgIHJldHVybnMgdHJ1dGh5IGZvclxuICAgICAqIGFuZCByZXR1cm5zIGFuIGFycmF5IG9mIHRoZSByZW1vdmVkIGVsZW1lbnRzLiBUaGUgcHJlZGljYXRlIGlzIGludm9rZWRcbiAgICAgKiB3aXRoIHRocmVlIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleCwgYXJyYXkpLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFVubGlrZSBgXy5maWx0ZXJgLCB0aGlzIG1ldGhvZCBtdXRhdGVzIGBhcnJheWAuIFVzZSBgXy5wdWxsYFxuICAgICAqIHRvIHB1bGwgZWxlbWVudHMgZnJvbSBhbiBhcnJheSBieSB2YWx1ZS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAyLjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBtb2RpZnkuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIHJlbW92ZWQgZWxlbWVudHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFsxLCAyLCAzLCA0XTtcbiAgICAgKiB2YXIgZXZlbnMgPSBfLnJlbW92ZShhcnJheSwgZnVuY3Rpb24obikge1xuICAgICAqICAgcmV0dXJuIG4gJSAyID09IDA7XG4gICAgICogfSk7XG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheSk7XG4gICAgICogLy8gPT4gWzEsIDNdXG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhldmVucyk7XG4gICAgICogLy8gPT4gWzIsIDRdXG4gICAgICovXG4gICAgZnVuY3Rpb24gcmVtb3ZlKGFycmF5LCBwcmVkaWNhdGUpIHtcbiAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgIGlmICghKGFycmF5ICYmIGFycmF5Lmxlbmd0aCkpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGluZGV4ZXMgPSBbXSxcbiAgICAgICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgICAgIHByZWRpY2F0ZSA9IGdldEl0ZXJhdGVlKHByZWRpY2F0ZSwgMyk7XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIgdmFsdWUgPSBhcnJheVtpbmRleF07XG4gICAgICAgIGlmIChwcmVkaWNhdGUodmFsdWUsIGluZGV4LCBhcnJheSkpIHtcbiAgICAgICAgICByZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICAgICAgaW5kZXhlcy5wdXNoKGluZGV4KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYmFzZVB1bGxBdChhcnJheSwgaW5kZXhlcyk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldmVyc2VzIGBhcnJheWAgc28gdGhhdCB0aGUgZmlyc3QgZWxlbWVudCBiZWNvbWVzIHRoZSBsYXN0LCB0aGUgc2Vjb25kXG4gICAgICogZWxlbWVudCBiZWNvbWVzIHRoZSBzZWNvbmQgdG8gbGFzdCwgYW5kIHNvIG9uLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYGFycmF5YCBhbmQgaXMgYmFzZWQgb25cbiAgICAgKiBbYEFycmF5I3JldmVyc2VgXShodHRwczovL21kbi5pby9BcnJheS9yZXZlcnNlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBtb2RpZnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFsxLCAyLCAzXTtcbiAgICAgKlxuICAgICAqIF8ucmV2ZXJzZShhcnJheSk7XG4gICAgICogLy8gPT4gWzMsIDIsIDFdXG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheSk7XG4gICAgICogLy8gPT4gWzMsIDIsIDFdXG4gICAgICovXG4gICAgZnVuY3Rpb24gcmV2ZXJzZShhcnJheSkge1xuICAgICAgcmV0dXJuIGFycmF5ID09IG51bGwgPyBhcnJheSA6IG5hdGl2ZVJldmVyc2UuY2FsbChhcnJheSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHNsaWNlIG9mIGBhcnJheWAgZnJvbSBgc3RhcnRgIHVwIHRvLCBidXQgbm90IGluY2x1ZGluZywgYGVuZGAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgdXNlZCBpbnN0ZWFkIG9mXG4gICAgICogW2BBcnJheSNzbGljZWBdKGh0dHBzOi8vbWRuLmlvL0FycmF5L3NsaWNlKSB0byBlbnN1cmUgZGVuc2UgYXJyYXlzIGFyZVxuICAgICAqIHJldHVybmVkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNsaWNlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbc3RhcnQ9MF0gVGhlIHN0YXJ0IHBvc2l0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZW5kPWFycmF5Lmxlbmd0aF0gVGhlIGVuZCBwb3NpdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gc2xpY2UoYXJyYXksIHN0YXJ0LCBlbmQpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIGlmIChlbmQgJiYgdHlwZW9mIGVuZCAhPSAnbnVtYmVyJyAmJiBpc0l0ZXJhdGVlQ2FsbChhcnJheSwgc3RhcnQsIGVuZCkpIHtcbiAgICAgICAgc3RhcnQgPSAwO1xuICAgICAgICBlbmQgPSBsZW5ndGg7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgc3RhcnQgPSBzdGFydCA9PSBudWxsID8gMCA6IHRvSW50ZWdlcihzdGFydCk7XG4gICAgICAgIGVuZCA9IGVuZCA9PT0gdW5kZWZpbmVkID8gbGVuZ3RoIDogdG9JbnRlZ2VyKGVuZCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZVNsaWNlKGFycmF5LCBzdGFydCwgZW5kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVc2VzIGEgYmluYXJ5IHNlYXJjaCB0byBkZXRlcm1pbmUgdGhlIGxvd2VzdCBpbmRleCBhdCB3aGljaCBgdmFsdWVgXG4gICAgICogc2hvdWxkIGJlIGluc2VydGVkIGludG8gYGFycmF5YCBpbiBvcmRlciB0byBtYWludGFpbiBpdHMgc29ydCBvcmRlci5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBzb3J0ZWQgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBldmFsdWF0ZS5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBhdCB3aGljaCBgdmFsdWVgIHNob3VsZCBiZSBpbnNlcnRlZFxuICAgICAqICBpbnRvIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc29ydGVkSW5kZXgoWzMwLCA1MF0sIDQwKTtcbiAgICAgKiAvLyA9PiAxXG4gICAgICovXG4gICAgZnVuY3Rpb24gc29ydGVkSW5kZXgoYXJyYXksIHZhbHVlKSB7XG4gICAgICByZXR1cm4gYmFzZVNvcnRlZEluZGV4KGFycmF5LCB2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5zb3J0ZWRJbmRleGAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgXG4gICAgICogd2hpY2ggaXMgaW52b2tlZCBmb3IgYHZhbHVlYCBhbmQgZWFjaCBlbGVtZW50IG9mIGBhcnJheWAgdG8gY29tcHV0ZSB0aGVpclxuICAgICAqIHNvcnQgcmFua2luZy4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ6ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgc29ydGVkIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gZXZhbHVhdGUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IGF0IHdoaWNoIGB2YWx1ZWAgc2hvdWxkIGJlIGluc2VydGVkXG4gICAgICogIGludG8gYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbeyAneCc6IDQgfSwgeyAneCc6IDUgfV07XG4gICAgICpcbiAgICAgKiBfLnNvcnRlZEluZGV4Qnkob2JqZWN0cywgeyAneCc6IDQgfSwgZnVuY3Rpb24obykgeyByZXR1cm4gby54OyB9KTtcbiAgICAgKiAvLyA9PiAwXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnNvcnRlZEluZGV4Qnkob2JqZWN0cywgeyAneCc6IDQgfSwgJ3gnKTtcbiAgICAgKiAvLyA9PiAwXG4gICAgICovXG4gICAgZnVuY3Rpb24gc29ydGVkSW5kZXhCeShhcnJheSwgdmFsdWUsIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gYmFzZVNvcnRlZEluZGV4QnkoYXJyYXksIHZhbHVlLCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMikpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uaW5kZXhPZmAgZXhjZXB0IHRoYXQgaXQgcGVyZm9ybXMgYSBiaW5hcnlcbiAgICAgKiBzZWFyY2ggb24gYSBzb3J0ZWQgYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNlYXJjaCBmb3IuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUsIGVsc2UgYC0xYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zb3J0ZWRJbmRleE9mKFs0LCA1LCA1LCA1LCA2XSwgNSk7XG4gICAgICogLy8gPT4gMVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNvcnRlZEluZGV4T2YoYXJyYXksIHZhbHVlKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG4gICAgICBpZiAobGVuZ3RoKSB7XG4gICAgICAgIHZhciBpbmRleCA9IGJhc2VTb3J0ZWRJbmRleChhcnJheSwgdmFsdWUpO1xuICAgICAgICBpZiAoaW5kZXggPCBsZW5ndGggJiYgZXEoYXJyYXlbaW5kZXhdLCB2YWx1ZSkpIHtcbiAgICAgICAgICByZXR1cm4gaW5kZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiAtMTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnNvcnRlZEluZGV4YCBleGNlcHQgdGhhdCBpdCByZXR1cm5zIHRoZSBoaWdoZXN0XG4gICAgICogaW5kZXggYXQgd2hpY2ggYHZhbHVlYCBzaG91bGQgYmUgaW5zZXJ0ZWQgaW50byBgYXJyYXlgIGluIG9yZGVyIHRvXG4gICAgICogbWFpbnRhaW4gaXRzIHNvcnQgb3JkZXIuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgc29ydGVkIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gZXZhbHVhdGUuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggYXQgd2hpY2ggYHZhbHVlYCBzaG91bGQgYmUgaW5zZXJ0ZWRcbiAgICAgKiAgaW50byBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNvcnRlZExhc3RJbmRleChbNCwgNSwgNSwgNSwgNl0sIDUpO1xuICAgICAqIC8vID0+IDRcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzb3J0ZWRMYXN0SW5kZXgoYXJyYXksIHZhbHVlKSB7XG4gICAgICByZXR1cm4gYmFzZVNvcnRlZEluZGV4KGFycmF5LCB2YWx1ZSwgdHJ1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5zb3J0ZWRMYXN0SW5kZXhgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGl0ZXJhdGVlYFxuICAgICAqIHdoaWNoIGlzIGludm9rZWQgZm9yIGB2YWx1ZWAgYW5kIGVhY2ggZWxlbWVudCBvZiBgYXJyYXlgIHRvIGNvbXB1dGUgdGhlaXJcbiAgICAgKiBzb3J0IHJhbmtpbmcuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIHNvcnRlZCBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGV2YWx1YXRlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBhdCB3aGljaCBgdmFsdWVgIHNob3VsZCBiZSBpbnNlcnRlZFxuICAgICAqICBpbnRvIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW3sgJ3gnOiA0IH0sIHsgJ3gnOiA1IH1dO1xuICAgICAqXG4gICAgICogXy5zb3J0ZWRMYXN0SW5kZXhCeShvYmplY3RzLCB7ICd4JzogNCB9LCBmdW5jdGlvbihvKSB7IHJldHVybiBvLng7IH0pO1xuICAgICAqIC8vID0+IDFcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uc29ydGVkTGFzdEluZGV4Qnkob2JqZWN0cywgeyAneCc6IDQgfSwgJ3gnKTtcbiAgICAgKiAvLyA9PiAxXG4gICAgICovXG4gICAgZnVuY3Rpb24gc29ydGVkTGFzdEluZGV4QnkoYXJyYXksIHZhbHVlLCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIGJhc2VTb3J0ZWRJbmRleEJ5KGFycmF5LCB2YWx1ZSwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDIpLCB0cnVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmxhc3RJbmRleE9mYCBleGNlcHQgdGhhdCBpdCBwZXJmb3JtcyBhIGJpbmFyeVxuICAgICAqIHNlYXJjaCBvbiBhIHNvcnRlZCBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2VhcmNoIGZvci5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgbWF0Y2hlZCB2YWx1ZSwgZWxzZSBgLTFgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNvcnRlZExhc3RJbmRleE9mKFs0LCA1LCA1LCA1LCA2XSwgNSk7XG4gICAgICogLy8gPT4gM1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNvcnRlZExhc3RJbmRleE9mKGFycmF5LCB2YWx1ZSkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuICAgICAgaWYgKGxlbmd0aCkge1xuICAgICAgICB2YXIgaW5kZXggPSBiYXNlU29ydGVkSW5kZXgoYXJyYXksIHZhbHVlLCB0cnVlKSAtIDE7XG4gICAgICAgIGlmIChlcShhcnJheVtpbmRleF0sIHZhbHVlKSkge1xuICAgICAgICAgIHJldHVybiBpbmRleDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIC0xO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8udW5pcWAgZXhjZXB0IHRoYXQgaXQncyBkZXNpZ25lZCBhbmQgb3B0aW1pemVkXG4gICAgICogZm9yIHNvcnRlZCBhcnJheXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBkdXBsaWNhdGUgZnJlZSBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zb3J0ZWRVbmlxKFsxLCAxLCAyXSk7XG4gICAgICogLy8gPT4gWzEsIDJdXG4gICAgICovXG4gICAgZnVuY3Rpb24gc29ydGVkVW5pcShhcnJheSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpXG4gICAgICAgID8gYmFzZVNvcnRlZFVuaXEoYXJyYXkpXG4gICAgICAgIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy51bmlxQnlgIGV4Y2VwdCB0aGF0IGl0J3MgZGVzaWduZWQgYW5kIG9wdGltaXplZFxuICAgICAqIGZvciBzb3J0ZWQgYXJyYXlzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlXSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBkdXBsaWNhdGUgZnJlZSBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zb3J0ZWRVbmlxQnkoWzEuMSwgMS4yLCAyLjMsIDIuNF0sIE1hdGguZmxvb3IpO1xuICAgICAqIC8vID0+IFsxLjEsIDIuM11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzb3J0ZWRVbmlxQnkoYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aClcbiAgICAgICAgPyBiYXNlU29ydGVkVW5pcShhcnJheSwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDIpKVxuICAgICAgICA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgYWxsIGJ1dCB0aGUgZmlyc3QgZWxlbWVudCBvZiBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50YWlsKFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gWzIsIDNdXG4gICAgICovXG4gICAgZnVuY3Rpb24gdGFpbChhcnJheSkge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoO1xuICAgICAgcmV0dXJuIGxlbmd0aCA/IGJhc2VTbGljZShhcnJheSwgMSwgbGVuZ3RoKSA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBzbGljZSBvZiBgYXJyYXlgIHdpdGggYG5gIGVsZW1lbnRzIHRha2VuIGZyb20gdGhlIGJlZ2lubmluZy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW249MV0gVGhlIG51bWJlciBvZiBlbGVtZW50cyB0byB0YWtlLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBzbGljZSBvZiBgYXJyYXlgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRha2UoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBbMV1cbiAgICAgKlxuICAgICAqIF8udGFrZShbMSwgMiwgM10sIDIpO1xuICAgICAqIC8vID0+IFsxLCAyXVxuICAgICAqXG4gICAgICogXy50YWtlKFsxLCAyLCAzXSwgNSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICpcbiAgICAgKiBfLnRha2UoWzEsIDIsIDNdLCAwKTtcbiAgICAgKiAvLyA9PiBbXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRha2UoYXJyYXksIG4sIGd1YXJkKSB7XG4gICAgICBpZiAoIShhcnJheSAmJiBhcnJheS5sZW5ndGgpKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIG4gPSAoZ3VhcmQgfHwgbiA9PT0gdW5kZWZpbmVkKSA/IDEgOiB0b0ludGVnZXIobik7XG4gICAgICByZXR1cm4gYmFzZVNsaWNlKGFycmF5LCAwLCBuIDwgMCA/IDAgOiBuKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc2xpY2Ugb2YgYGFycmF5YCB3aXRoIGBuYCBlbGVtZW50cyB0YWtlbiBmcm9tIHRoZSBlbmQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtuPTFdIFRoZSBudW1iZXIgb2YgZWxlbWVudHMgdG8gdGFrZS5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYW4gaXRlcmF0ZWUgZm9yIG1ldGhvZHMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50YWtlUmlnaHQoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiBbM11cbiAgICAgKlxuICAgICAqIF8udGFrZVJpZ2h0KFsxLCAyLCAzXSwgMik7XG4gICAgICogLy8gPT4gWzIsIDNdXG4gICAgICpcbiAgICAgKiBfLnRha2VSaWdodChbMSwgMiwgM10sIDUpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqXG4gICAgICogXy50YWtlUmlnaHQoWzEsIDIsIDNdLCAwKTtcbiAgICAgKiAvLyA9PiBbXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRha2VSaWdodChhcnJheSwgbiwgZ3VhcmQpIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcbiAgICAgIGlmICghbGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIG4gPSAoZ3VhcmQgfHwgbiA9PT0gdW5kZWZpbmVkKSA/IDEgOiB0b0ludGVnZXIobik7XG4gICAgICBuID0gbGVuZ3RoIC0gbjtcbiAgICAgIHJldHVybiBiYXNlU2xpY2UoYXJyYXksIG4gPCAwID8gMCA6IG4sIGxlbmd0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHNsaWNlIG9mIGBhcnJheWAgd2l0aCBlbGVtZW50cyB0YWtlbiBmcm9tIHRoZSBlbmQuIEVsZW1lbnRzIGFyZVxuICAgICAqIHRha2VuIHVudGlsIGBwcmVkaWNhdGVgIHJldHVybnMgZmFsc2V5LiBUaGUgcHJlZGljYXRlIGlzIGludm9rZWQgd2l0aFxuICAgICAqIHRocmVlIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleCwgYXJyYXkpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgICdhY3RpdmUnOiB0cnVlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAncGViYmxlcycsICdhY3RpdmUnOiBmYWxzZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8udGFrZVJpZ2h0V2hpbGUodXNlcnMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuICFvLmFjdGl2ZTsgfSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydmcmVkJywgJ3BlYmJsZXMnXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnRha2VSaWdodFdoaWxlKHVzZXJzLCB7ICd1c2VyJzogJ3BlYmJsZXMnLCAnYWN0aXZlJzogZmFsc2UgfSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydwZWJibGVzJ11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnRha2VSaWdodFdoaWxlKHVzZXJzLCBbJ2FjdGl2ZScsIGZhbHNlXSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydmcmVkJywgJ3BlYmJsZXMnXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy50YWtlUmlnaHRXaGlsZSh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+IFtdXG4gICAgICovXG4gICAgZnVuY3Rpb24gdGFrZVJpZ2h0V2hpbGUoYXJyYXksIHByZWRpY2F0ZSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpXG4gICAgICAgID8gYmFzZVdoaWxlKGFycmF5LCBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpLCBmYWxzZSwgdHJ1ZSlcbiAgICAgICAgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc2xpY2Ugb2YgYGFycmF5YCB3aXRoIGVsZW1lbnRzIHRha2VuIGZyb20gdGhlIGJlZ2lubmluZy4gRWxlbWVudHNcbiAgICAgKiBhcmUgdGFrZW4gdW50aWwgYHByZWRpY2F0ZWAgcmV0dXJucyBmYWxzZXkuIFRoZSBwcmVkaWNhdGUgaXMgaW52b2tlZCB3aXRoXG4gICAgICogdGhyZWUgYXJndW1lbnRzOiAodmFsdWUsIGluZGV4LCBhcnJheSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgc2xpY2Ugb2YgYGFycmF5YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAncGViYmxlcycsICdhY3RpdmUnOiB0cnVlIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy50YWtlV2hpbGUodXNlcnMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuICFvLmFjdGl2ZTsgfSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydiYXJuZXknLCAnZnJlZCddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc2AgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8udGFrZVdoaWxlKHVzZXJzLCB7ICd1c2VyJzogJ2Jhcm5leScsICdhY3RpdmUnOiBmYWxzZSB9KTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2Jhcm5leSddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy50YWtlV2hpbGUodXNlcnMsIFsnYWN0aXZlJywgZmFsc2VdKTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbJ2Jhcm5leScsICdmcmVkJ11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8udGFrZVdoaWxlKHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0YWtlV2hpbGUoYXJyYXksIHByZWRpY2F0ZSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpXG4gICAgICAgID8gYmFzZVdoaWxlKGFycmF5LCBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpKVxuICAgICAgICA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdW5pcXVlIHZhbHVlcywgaW4gb3JkZXIsIGZyb20gYWxsIGdpdmVuIGFycmF5cyB1c2luZ1xuICAgICAqIFtgU2FtZVZhbHVlWmVyb2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLXNhbWV2YWx1ZXplcm8pXG4gICAgICogZm9yIGVxdWFsaXR5IGNvbXBhcmlzb25zLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBpbnNwZWN0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGNvbWJpbmVkIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy51bmlvbihbMl0sIFsxLCAyXSk7XG4gICAgICogLy8gPT4gWzIsIDFdXG4gICAgICovXG4gICAgdmFyIHVuaW9uID0gYmFzZVJlc3QoZnVuY3Rpb24oYXJyYXlzKSB7XG4gICAgICByZXR1cm4gYmFzZVVuaXEoYmFzZUZsYXR0ZW4oYXJyYXlzLCAxLCBpc0FycmF5TGlrZU9iamVjdCwgdHJ1ZSkpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy51bmlvbmAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgIHdoaWNoIGlzXG4gICAgICogaW52b2tlZCBmb3IgZWFjaCBlbGVtZW50IG9mIGVhY2ggYGFycmF5c2AgdG8gZ2VuZXJhdGUgdGhlIGNyaXRlcmlvbiBieVxuICAgICAqIHdoaWNoIHVuaXF1ZW5lc3MgaXMgY29tcHV0ZWQuIFJlc3VsdCB2YWx1ZXMgYXJlIGNob3NlbiBmcm9tIHRoZSBmaXJzdFxuICAgICAqIGFycmF5IGluIHdoaWNoIHRoZSB2YWx1ZSBvY2N1cnMuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OlxuICAgICAqICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0gey4uLkFycmF5fSBbYXJyYXlzXSBUaGUgYXJyYXlzIHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGNvbWJpbmVkIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy51bmlvbkJ5KFsyLjFdLCBbMS4yLCAyLjNdLCBNYXRoLmZsb29yKTtcbiAgICAgKiAvLyA9PiBbMi4xLCAxLjJdXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnVuaW9uQnkoW3sgJ3gnOiAxIH1dLCBbeyAneCc6IDIgfSwgeyAneCc6IDEgfV0sICd4Jyk7XG4gICAgICogLy8gPT4gW3sgJ3gnOiAxIH0sIHsgJ3gnOiAyIH1dXG4gICAgICovXG4gICAgdmFyIHVuaW9uQnkgPSBiYXNlUmVzdChmdW5jdGlvbihhcnJheXMpIHtcbiAgICAgIHZhciBpdGVyYXRlZSA9IGxhc3QoYXJyYXlzKTtcbiAgICAgIGlmIChpc0FycmF5TGlrZU9iamVjdChpdGVyYXRlZSkpIHtcbiAgICAgICAgaXRlcmF0ZWUgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZVVuaXEoYmFzZUZsYXR0ZW4oYXJyYXlzLCAxLCBpc0FycmF5TGlrZU9iamVjdCwgdHJ1ZSksIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAyKSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnVuaW9uYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBjb21wYXJhdG9yYCB3aGljaFxuICAgICAqIGlzIGludm9rZWQgdG8gY29tcGFyZSBlbGVtZW50cyBvZiBgYXJyYXlzYC4gUmVzdWx0IHZhbHVlcyBhcmUgY2hvc2VuIGZyb21cbiAgICAgKiB0aGUgZmlyc3QgYXJyYXkgaW4gd2hpY2ggdGhlIHZhbHVlIG9jY3Vycy4gVGhlIGNvbXBhcmF0b3IgaXMgaW52b2tlZFxuICAgICAqIHdpdGggdHdvIGFyZ3VtZW50czogKGFyclZhbCwgb3RoVmFsKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7Li4uQXJyYXl9IFthcnJheXNdIFRoZSBhcnJheXMgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY29tcGFyYXRvcl0gVGhlIGNvbXBhcmF0b3IgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBjb21iaW5lZCB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW3sgJ3gnOiAxLCAneSc6IDIgfSwgeyAneCc6IDIsICd5JzogMSB9XTtcbiAgICAgKiB2YXIgb3RoZXJzID0gW3sgJ3gnOiAxLCAneSc6IDEgfSwgeyAneCc6IDEsICd5JzogMiB9XTtcbiAgICAgKlxuICAgICAqIF8udW5pb25XaXRoKG9iamVjdHMsIG90aGVycywgXy5pc0VxdWFsKTtcbiAgICAgKiAvLyA9PiBbeyAneCc6IDEsICd5JzogMiB9LCB7ICd4JzogMiwgJ3knOiAxIH0sIHsgJ3gnOiAxLCAneSc6IDEgfV1cbiAgICAgKi9cbiAgICB2YXIgdW5pb25XaXRoID0gYmFzZVJlc3QoZnVuY3Rpb24oYXJyYXlzKSB7XG4gICAgICB2YXIgY29tcGFyYXRvciA9IGxhc3QoYXJyYXlzKTtcbiAgICAgIGNvbXBhcmF0b3IgPSB0eXBlb2YgY29tcGFyYXRvciA9PSAnZnVuY3Rpb24nID8gY29tcGFyYXRvciA6IHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiBiYXNlVW5pcShiYXNlRmxhdHRlbihhcnJheXMsIDEsIGlzQXJyYXlMaWtlT2JqZWN0LCB0cnVlKSwgdW5kZWZpbmVkLCBjb21wYXJhdG9yKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBkdXBsaWNhdGUtZnJlZSB2ZXJzaW9uIG9mIGFuIGFycmF5LCB1c2luZ1xuICAgICAqIFtgU2FtZVZhbHVlWmVyb2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLXNhbWV2YWx1ZXplcm8pXG4gICAgICogZm9yIGVxdWFsaXR5IGNvbXBhcmlzb25zLCBpbiB3aGljaCBvbmx5IHRoZSBmaXJzdCBvY2N1cnJlbmNlIG9mIGVhY2ggZWxlbWVudFxuICAgICAqIGlzIGtlcHQuIFRoZSBvcmRlciBvZiByZXN1bHQgdmFsdWVzIGlzIGRldGVybWluZWQgYnkgdGhlIG9yZGVyIHRoZXkgb2NjdXJcbiAgICAgKiBpbiB0aGUgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBkdXBsaWNhdGUgZnJlZSBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy51bmlxKFsyLCAxLCAyXSk7XG4gICAgICogLy8gPT4gWzIsIDFdXG4gICAgICovXG4gICAgZnVuY3Rpb24gdW5pcShhcnJheSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpID8gYmFzZVVuaXEoYXJyYXkpIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy51bmlxYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBpdGVyYXRlZWAgd2hpY2ggaXNcbiAgICAgKiBpbnZva2VkIGZvciBlYWNoIGVsZW1lbnQgaW4gYGFycmF5YCB0byBnZW5lcmF0ZSB0aGUgY3JpdGVyaW9uIGJ5IHdoaWNoXG4gICAgICogdW5pcXVlbmVzcyBpcyBjb21wdXRlZC4gVGhlIG9yZGVyIG9mIHJlc3VsdCB2YWx1ZXMgaXMgZGV0ZXJtaW5lZCBieSB0aGVcbiAgICAgKiBvcmRlciB0aGV5IG9jY3VyIGluIHRoZSBhcnJheS4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ6XG4gICAgICogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBkdXBsaWNhdGUgZnJlZSBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy51bmlxQnkoWzIuMSwgMS4yLCAyLjNdLCBNYXRoLmZsb29yKTtcbiAgICAgKiAvLyA9PiBbMi4xLCAxLjJdXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnVuaXFCeShbeyAneCc6IDEgfSwgeyAneCc6IDIgfSwgeyAneCc6IDEgfV0sICd4Jyk7XG4gICAgICogLy8gPT4gW3sgJ3gnOiAxIH0sIHsgJ3gnOiAyIH1dXG4gICAgICovXG4gICAgZnVuY3Rpb24gdW5pcUJ5KGFycmF5LCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpID8gYmFzZVVuaXEoYXJyYXksIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAyKSkgOiBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnVuaXFgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGNvbXBhcmF0b3JgIHdoaWNoXG4gICAgICogaXMgaW52b2tlZCB0byBjb21wYXJlIGVsZW1lbnRzIG9mIGBhcnJheWAuIFRoZSBvcmRlciBvZiByZXN1bHQgdmFsdWVzIGlzXG4gICAgICogZGV0ZXJtaW5lZCBieSB0aGUgb3JkZXIgdGhleSBvY2N1ciBpbiB0aGUgYXJyYXkuVGhlIGNvbXBhcmF0b3IgaXMgaW52b2tlZFxuICAgICAqIHdpdGggdHdvIGFyZ3VtZW50czogKGFyclZhbCwgb3RoVmFsKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjb21wYXJhdG9yXSBUaGUgY29tcGFyYXRvciBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGR1cGxpY2F0ZSBmcmVlIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IFt7ICd4JzogMSwgJ3knOiAyIH0sIHsgJ3gnOiAyLCAneSc6IDEgfSwgeyAneCc6IDEsICd5JzogMiB9XTtcbiAgICAgKlxuICAgICAqIF8udW5pcVdpdGgob2JqZWN0cywgXy5pc0VxdWFsKTtcbiAgICAgKiAvLyA9PiBbeyAneCc6IDEsICd5JzogMiB9LCB7ICd4JzogMiwgJ3knOiAxIH1dXG4gICAgICovXG4gICAgZnVuY3Rpb24gdW5pcVdpdGgoYXJyYXksIGNvbXBhcmF0b3IpIHtcbiAgICAgIGNvbXBhcmF0b3IgPSB0eXBlb2YgY29tcGFyYXRvciA9PSAnZnVuY3Rpb24nID8gY29tcGFyYXRvciA6IHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKSA/IGJhc2VVbmlxKGFycmF5LCB1bmRlZmluZWQsIGNvbXBhcmF0b3IpIDogW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy56aXBgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYW4gYXJyYXkgb2YgZ3JvdXBlZFxuICAgICAqIGVsZW1lbnRzIGFuZCBjcmVhdGVzIGFuIGFycmF5IHJlZ3JvdXBpbmcgdGhlIGVsZW1lbnRzIHRvIHRoZWlyIHByZS16aXBcbiAgICAgKiBjb25maWd1cmF0aW9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDEuMi4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IG9mIGdyb3VwZWQgZWxlbWVudHMgdG8gcHJvY2Vzcy5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiByZWdyb3VwZWQgZWxlbWVudHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB6aXBwZWQgPSBfLnppcChbJ2EnLCAnYiddLCBbMSwgMl0sIFt0cnVlLCBmYWxzZV0pO1xuICAgICAqIC8vID0+IFtbJ2EnLCAxLCB0cnVlXSwgWydiJywgMiwgZmFsc2VdXVxuICAgICAqXG4gICAgICogXy51bnppcCh6aXBwZWQpO1xuICAgICAqIC8vID0+IFtbJ2EnLCAnYiddLCBbMSwgMl0sIFt0cnVlLCBmYWxzZV1dXG4gICAgICovXG4gICAgZnVuY3Rpb24gdW56aXAoYXJyYXkpIHtcbiAgICAgIGlmICghKGFycmF5ICYmIGFycmF5Lmxlbmd0aCkpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgdmFyIGxlbmd0aCA9IDA7XG4gICAgICBhcnJheSA9IGFycmF5RmlsdGVyKGFycmF5LCBmdW5jdGlvbihncm91cCkge1xuICAgICAgICBpZiAoaXNBcnJheUxpa2VPYmplY3QoZ3JvdXApKSB7XG4gICAgICAgICAgbGVuZ3RoID0gbmF0aXZlTWF4KGdyb3VwLmxlbmd0aCwgbGVuZ3RoKTtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gYmFzZVRpbWVzKGxlbmd0aCwgZnVuY3Rpb24oaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIGFycmF5TWFwKGFycmF5LCBiYXNlUHJvcGVydHkoaW5kZXgpKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8udW56aXBgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGl0ZXJhdGVlYCB0byBzcGVjaWZ5XG4gICAgICogaG93IHJlZ3JvdXBlZCB2YWx1ZXMgc2hvdWxkIGJlIGNvbWJpbmVkLiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIHRoZVxuICAgICAqIGVsZW1lbnRzIG9mIGVhY2ggZ3JvdXA6ICguLi5ncm91cCkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy44LjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgb2YgZ3JvdXBlZCBlbGVtZW50cyB0byBwcm9jZXNzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gdG8gY29tYmluZVxuICAgICAqICByZWdyb3VwZWQgdmFsdWVzLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIHJlZ3JvdXBlZCBlbGVtZW50cy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHppcHBlZCA9IF8uemlwKFsxLCAyXSwgWzEwLCAyMF0sIFsxMDAsIDIwMF0pO1xuICAgICAqIC8vID0+IFtbMSwgMTAsIDEwMF0sIFsyLCAyMCwgMjAwXV1cbiAgICAgKlxuICAgICAqIF8udW56aXBXaXRoKHppcHBlZCwgXy5hZGQpO1xuICAgICAqIC8vID0+IFszLCAzMCwgMzAwXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVuemlwV2l0aChhcnJheSwgaXRlcmF0ZWUpIHtcbiAgICAgIGlmICghKGFycmF5ICYmIGFycmF5Lmxlbmd0aCkpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgdmFyIHJlc3VsdCA9IHVuemlwKGFycmF5KTtcbiAgICAgIGlmIChpdGVyYXRlZSA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gYXJyYXlNYXAocmVzdWx0LCBmdW5jdGlvbihncm91cCkge1xuICAgICAgICByZXR1cm4gYXBwbHkoaXRlcmF0ZWUsIHVuZGVmaW5lZCwgZ3JvdXApO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBleGNsdWRpbmcgYWxsIGdpdmVuIHZhbHVlcyB1c2luZ1xuICAgICAqIFtgU2FtZVZhbHVlWmVyb2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLXNhbWV2YWx1ZXplcm8pXG4gICAgICogZm9yIGVxdWFsaXR5IGNvbXBhcmlzb25zLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFVubGlrZSBgXy5wdWxsYCwgdGhpcyBtZXRob2QgcmV0dXJucyBhIG5ldyBhcnJheS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW3ZhbHVlc10gVGhlIHZhbHVlcyB0byBleGNsdWRlLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGZpbHRlcmVkIHZhbHVlcy5cbiAgICAgKiBAc2VlIF8uZGlmZmVyZW5jZSwgXy54b3JcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy53aXRob3V0KFsyLCAxLCAyLCAzXSwgMSwgMik7XG4gICAgICogLy8gPT4gWzNdXG4gICAgICovXG4gICAgdmFyIHdpdGhvdXQgPSBiYXNlUmVzdChmdW5jdGlvbihhcnJheSwgdmFsdWVzKSB7XG4gICAgICByZXR1cm4gaXNBcnJheUxpa2VPYmplY3QoYXJyYXkpXG4gICAgICAgID8gYmFzZURpZmZlcmVuY2UoYXJyYXksIHZhbHVlcylcbiAgICAgICAgOiBbXTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdW5pcXVlIHZhbHVlcyB0aGF0IGlzIHRoZVxuICAgICAqIFtzeW1tZXRyaWMgZGlmZmVyZW5jZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU3ltbWV0cmljX2RpZmZlcmVuY2UpXG4gICAgICogb2YgdGhlIGdpdmVuIGFycmF5cy4gVGhlIG9yZGVyIG9mIHJlc3VsdCB2YWx1ZXMgaXMgZGV0ZXJtaW5lZCBieSB0aGUgb3JkZXJcbiAgICAgKiB0aGV5IG9jY3VyIGluIHRoZSBhcnJheXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMi40LjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0gey4uLkFycmF5fSBbYXJyYXlzXSBUaGUgYXJyYXlzIHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgZmlsdGVyZWQgdmFsdWVzLlxuICAgICAqIEBzZWUgXy5kaWZmZXJlbmNlLCBfLndpdGhvdXRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy54b3IoWzIsIDFdLCBbMiwgM10pO1xuICAgICAqIC8vID0+IFsxLCAzXVxuICAgICAqL1xuICAgIHZhciB4b3IgPSBiYXNlUmVzdChmdW5jdGlvbihhcnJheXMpIHtcbiAgICAgIHJldHVybiBiYXNlWG9yKGFycmF5RmlsdGVyKGFycmF5cywgaXNBcnJheUxpa2VPYmplY3QpKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8ueG9yYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBpdGVyYXRlZWAgd2hpY2ggaXNcbiAgICAgKiBpbnZva2VkIGZvciBlYWNoIGVsZW1lbnQgb2YgZWFjaCBgYXJyYXlzYCB0byBnZW5lcmF0ZSB0aGUgY3JpdGVyaW9uIGJ5XG4gICAgICogd2hpY2ggYnkgd2hpY2ggdGhleSdyZSBjb21wYXJlZC4gVGhlIG9yZGVyIG9mIHJlc3VsdCB2YWx1ZXMgaXMgZGV0ZXJtaW5lZFxuICAgICAqIGJ5IHRoZSBvcmRlciB0aGV5IG9jY3VyIGluIHRoZSBhcnJheXMuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lXG4gICAgICogYXJndW1lbnQ6ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0gey4uLkFycmF5fSBbYXJyYXlzXSBUaGUgYXJyYXlzIHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGZpbHRlcmVkIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy54b3JCeShbMi4xLCAxLjJdLCBbMi4zLCAzLjRdLCBNYXRoLmZsb29yKTtcbiAgICAgKiAvLyA9PiBbMS4yLCAzLjRdXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnhvckJ5KFt7ICd4JzogMSB9XSwgW3sgJ3gnOiAyIH0sIHsgJ3gnOiAxIH1dLCAneCcpO1xuICAgICAqIC8vID0+IFt7ICd4JzogMiB9XVxuICAgICAqL1xuICAgIHZhciB4b3JCeSA9IGJhc2VSZXN0KGZ1bmN0aW9uKGFycmF5cykge1xuICAgICAgdmFyIGl0ZXJhdGVlID0gbGFzdChhcnJheXMpO1xuICAgICAgaWYgKGlzQXJyYXlMaWtlT2JqZWN0KGl0ZXJhdGVlKSkge1xuICAgICAgICBpdGVyYXRlZSA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlWG9yKGFycmF5RmlsdGVyKGFycmF5cywgaXNBcnJheUxpa2VPYmplY3QpLCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMikpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy54b3JgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGNvbXBhcmF0b3JgIHdoaWNoIGlzXG4gICAgICogaW52b2tlZCB0byBjb21wYXJlIGVsZW1lbnRzIG9mIGBhcnJheXNgLiBUaGUgb3JkZXIgb2YgcmVzdWx0IHZhbHVlcyBpc1xuICAgICAqIGRldGVybWluZWQgYnkgdGhlIG9yZGVyIHRoZXkgb2NjdXIgaW4gdGhlIGFycmF5cy4gVGhlIGNvbXBhcmF0b3IgaXMgaW52b2tlZFxuICAgICAqIHdpdGggdHdvIGFyZ3VtZW50czogKGFyclZhbCwgb3RoVmFsKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBBcnJheVxuICAgICAqIEBwYXJhbSB7Li4uQXJyYXl9IFthcnJheXNdIFRoZSBhcnJheXMgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY29tcGFyYXRvcl0gVGhlIGNvbXBhcmF0b3IgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBhcnJheSBvZiBmaWx0ZXJlZCB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW3sgJ3gnOiAxLCAneSc6IDIgfSwgeyAneCc6IDIsICd5JzogMSB9XTtcbiAgICAgKiB2YXIgb3RoZXJzID0gW3sgJ3gnOiAxLCAneSc6IDEgfSwgeyAneCc6IDEsICd5JzogMiB9XTtcbiAgICAgKlxuICAgICAqIF8ueG9yV2l0aChvYmplY3RzLCBvdGhlcnMsIF8uaXNFcXVhbCk7XG4gICAgICogLy8gPT4gW3sgJ3gnOiAyLCAneSc6IDEgfSwgeyAneCc6IDEsICd5JzogMSB9XVxuICAgICAqL1xuICAgIHZhciB4b3JXaXRoID0gYmFzZVJlc3QoZnVuY3Rpb24oYXJyYXlzKSB7XG4gICAgICB2YXIgY29tcGFyYXRvciA9IGxhc3QoYXJyYXlzKTtcbiAgICAgIGNvbXBhcmF0b3IgPSB0eXBlb2YgY29tcGFyYXRvciA9PSAnZnVuY3Rpb24nID8gY29tcGFyYXRvciA6IHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiBiYXNlWG9yKGFycmF5RmlsdGVyKGFycmF5cywgaXNBcnJheUxpa2VPYmplY3QpLCB1bmRlZmluZWQsIGNvbXBhcmF0b3IpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBncm91cGVkIGVsZW1lbnRzLCB0aGUgZmlyc3Qgb2Ygd2hpY2ggY29udGFpbnMgdGhlXG4gICAgICogZmlyc3QgZWxlbWVudHMgb2YgdGhlIGdpdmVuIGFycmF5cywgdGhlIHNlY29uZCBvZiB3aGljaCBjb250YWlucyB0aGVcbiAgICAgKiBzZWNvbmQgZWxlbWVudHMgb2YgdGhlIGdpdmVuIGFycmF5cywgYW5kIHNvIG9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEFycmF5XG4gICAgICogQHBhcmFtIHsuLi5BcnJheX0gW2FycmF5c10gVGhlIGFycmF5cyB0byBwcm9jZXNzLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGdyb3VwZWQgZWxlbWVudHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uemlwKFsnYScsICdiJ10sIFsxLCAyXSwgW3RydWUsIGZhbHNlXSk7XG4gICAgICogLy8gPT4gW1snYScsIDEsIHRydWVdLCBbJ2InLCAyLCBmYWxzZV1dXG4gICAgICovXG4gICAgdmFyIHppcCA9IGJhc2VSZXN0KHVuemlwKTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZnJvbVBhaXJzYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIHR3byBhcnJheXMsXG4gICAgICogb25lIG9mIHByb3BlcnR5IGlkZW50aWZpZXJzIGFuZCBvbmUgb2YgY29ycmVzcG9uZGluZyB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC40LjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbcHJvcHM9W11dIFRoZSBwcm9wZXJ0eSBpZGVudGlmaWVycy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbdmFsdWVzPVtdXSBUaGUgcHJvcGVydHkgdmFsdWVzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uemlwT2JqZWN0KFsnYScsICdiJ10sIFsxLCAyXSk7XG4gICAgICogLy8gPT4geyAnYSc6IDEsICdiJzogMiB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gemlwT2JqZWN0KHByb3BzLCB2YWx1ZXMpIHtcbiAgICAgIHJldHVybiBiYXNlWmlwT2JqZWN0KHByb3BzIHx8IFtdLCB2YWx1ZXMgfHwgW10sIGFzc2lnblZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnppcE9iamVjdGAgZXhjZXB0IHRoYXQgaXQgc3VwcG9ydHMgcHJvcGVydHkgcGF0aHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbcHJvcHM9W11dIFRoZSBwcm9wZXJ0eSBpZGVudGlmaWVycy5cbiAgICAgKiBAcGFyYW0ge0FycmF5fSBbdmFsdWVzPVtdXSBUaGUgcHJvcGVydHkgdmFsdWVzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uemlwT2JqZWN0RGVlcChbJ2EuYlswXS5jJywgJ2EuYlsxXS5kJ10sIFsxLCAyXSk7XG4gICAgICogLy8gPT4geyAnYSc6IHsgJ2InOiBbeyAnYyc6IDEgfSwgeyAnZCc6IDIgfV0gfSB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gemlwT2JqZWN0RGVlcChwcm9wcywgdmFsdWVzKSB7XG4gICAgICByZXR1cm4gYmFzZVppcE9iamVjdChwcm9wcyB8fCBbXSwgdmFsdWVzIHx8IFtdLCBiYXNlU2V0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnppcGAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgIHRvIHNwZWNpZnlcbiAgICAgKiBob3cgZ3JvdXBlZCB2YWx1ZXMgc2hvdWxkIGJlIGNvbWJpbmVkLiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIHRoZVxuICAgICAqIGVsZW1lbnRzIG9mIGVhY2ggZ3JvdXA6ICguLi5ncm91cCkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy44LjBcbiAgICAgKiBAY2F0ZWdvcnkgQXJyYXlcbiAgICAgKiBAcGFyYW0gey4uLkFycmF5fSBbYXJyYXlzXSBUaGUgYXJyYXlzIHRvIHByb2Nlc3MuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiB0byBjb21iaW5lXG4gICAgICogIGdyb3VwZWQgdmFsdWVzLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGdyb3VwZWQgZWxlbWVudHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uemlwV2l0aChbMSwgMl0sIFsxMCwgMjBdLCBbMTAwLCAyMDBdLCBmdW5jdGlvbihhLCBiLCBjKSB7XG4gICAgICogICByZXR1cm4gYSArIGIgKyBjO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IFsxMTEsIDIyMl1cbiAgICAgKi9cbiAgICB2YXIgemlwV2l0aCA9IGJhc2VSZXN0KGZ1bmN0aW9uKGFycmF5cykge1xuICAgICAgdmFyIGxlbmd0aCA9IGFycmF5cy5sZW5ndGgsXG4gICAgICAgICAgaXRlcmF0ZWUgPSBsZW5ndGggPiAxID8gYXJyYXlzW2xlbmd0aCAtIDFdIDogdW5kZWZpbmVkO1xuXG4gICAgICBpdGVyYXRlZSA9IHR5cGVvZiBpdGVyYXRlZSA9PSAnZnVuY3Rpb24nID8gKGFycmF5cy5wb3AoKSwgaXRlcmF0ZWUpIDogdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIHVuemlwV2l0aChhcnJheXMsIGl0ZXJhdGVlKTtcbiAgICB9KTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBgbG9kYXNoYCB3cmFwcGVyIGluc3RhbmNlIHRoYXQgd3JhcHMgYHZhbHVlYCB3aXRoIGV4cGxpY2l0IG1ldGhvZFxuICAgICAqIGNoYWluIHNlcXVlbmNlcyBlbmFibGVkLiBUaGUgcmVzdWx0IG9mIHN1Y2ggc2VxdWVuY2VzIG11c3QgYmUgdW53cmFwcGVkXG4gICAgICogd2l0aCBgXyN2YWx1ZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMS4zLjBcbiAgICAgKiBAY2F0ZWdvcnkgU2VxXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gd3JhcC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgYGxvZGFzaGAgd3JhcHBlciBpbnN0YW5jZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAgJ2FnZSc6IDM2IH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICAnYWdlJzogNDAgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAncGViYmxlcycsICdhZ2UnOiAxIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogdmFyIHlvdW5nZXN0ID0gX1xuICAgICAqICAgLmNoYWluKHVzZXJzKVxuICAgICAqICAgLnNvcnRCeSgnYWdlJylcbiAgICAgKiAgIC5tYXAoZnVuY3Rpb24obykge1xuICAgICAqICAgICByZXR1cm4gby51c2VyICsgJyBpcyAnICsgby5hZ2U7XG4gICAgICogICB9KVxuICAgICAqICAgLmhlYWQoKVxuICAgICAqICAgLnZhbHVlKCk7XG4gICAgICogLy8gPT4gJ3BlYmJsZXMgaXMgMSdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjaGFpbih2YWx1ZSkge1xuICAgICAgdmFyIHJlc3VsdCA9IGxvZGFzaCh2YWx1ZSk7XG4gICAgICByZXN1bHQuX19jaGFpbl9fID0gdHJ1ZTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaW52b2tlcyBgaW50ZXJjZXB0b3JgIGFuZCByZXR1cm5zIGB2YWx1ZWAuIFRoZSBpbnRlcmNlcHRvclxuICAgICAqIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ7ICh2YWx1ZSkuIFRoZSBwdXJwb3NlIG9mIHRoaXMgbWV0aG9kIGlzIHRvXG4gICAgICogXCJ0YXAgaW50b1wiIGEgbWV0aG9kIGNoYWluIHNlcXVlbmNlIGluIG9yZGVyIHRvIG1vZGlmeSBpbnRlcm1lZGlhdGUgcmVzdWx0cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBTZXFcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBwcm92aWRlIHRvIGBpbnRlcmNlcHRvcmAuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gaW50ZXJjZXB0b3IgVGhlIGZ1bmN0aW9uIHRvIGludm9rZS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyBgdmFsdWVgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfKFsxLCAyLCAzXSlcbiAgICAgKiAgLnRhcChmdW5jdGlvbihhcnJheSkge1xuICAgICAqICAgIC8vIE11dGF0ZSBpbnB1dCBhcnJheS5cbiAgICAgKiAgICBhcnJheS5wb3AoKTtcbiAgICAgKiAgfSlcbiAgICAgKiAgLnJldmVyc2UoKVxuICAgICAqICAudmFsdWUoKTtcbiAgICAgKiAvLyA9PiBbMiwgMV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0YXAodmFsdWUsIGludGVyY2VwdG9yKSB7XG4gICAgICBpbnRlcmNlcHRvcih2YWx1ZSk7XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy50YXBgIGV4Y2VwdCB0aGF0IGl0IHJldHVybnMgdGhlIHJlc3VsdCBvZiBgaW50ZXJjZXB0b3JgLlxuICAgICAqIFRoZSBwdXJwb3NlIG9mIHRoaXMgbWV0aG9kIGlzIHRvIFwicGFzcyB0aHJ1XCIgdmFsdWVzIHJlcGxhY2luZyBpbnRlcm1lZGlhdGVcbiAgICAgKiByZXN1bHRzIGluIGEgbWV0aG9kIGNoYWluIHNlcXVlbmNlLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IFNlcVxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHByb3ZpZGUgdG8gYGludGVyY2VwdG9yYC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBpbnRlcmNlcHRvciBUaGUgZnVuY3Rpb24gdG8gaW52b2tlLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSByZXN1bHQgb2YgYGludGVyY2VwdG9yYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXygnICBhYmMgICcpXG4gICAgICogIC5jaGFpbigpXG4gICAgICogIC50cmltKClcbiAgICAgKiAgLnRocnUoZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgKiAgICByZXR1cm4gW3ZhbHVlXTtcbiAgICAgKiAgfSlcbiAgICAgKiAgLnZhbHVlKCk7XG4gICAgICogLy8gPT4gWydhYmMnXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRocnUodmFsdWUsIGludGVyY2VwdG9yKSB7XG4gICAgICByZXR1cm4gaW50ZXJjZXB0b3IodmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIHRoZSB3cmFwcGVyIHZlcnNpb24gb2YgYF8uYXRgLlxuICAgICAqXG4gICAgICogQG5hbWUgYXRcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAxLjAuMFxuICAgICAqIEBjYXRlZ29yeSBTZXFcbiAgICAgKiBAcGFyYW0gey4uLihzdHJpbmd8c3RyaW5nW10pfSBbcGF0aHNdIFRoZSBwcm9wZXJ0eSBwYXRocyB0byBwaWNrLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBgbG9kYXNoYCB3cmFwcGVyIGluc3RhbmNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IFt7ICdiJzogeyAnYyc6IDMgfSB9LCA0XSB9O1xuICAgICAqXG4gICAgICogXyhvYmplY3QpLmF0KFsnYVswXS5iLmMnLCAnYVsxXSddKS52YWx1ZSgpO1xuICAgICAqIC8vID0+IFszLCA0XVxuICAgICAqL1xuICAgIHZhciB3cmFwcGVyQXQgPSBmbGF0UmVzdChmdW5jdGlvbihwYXRocykge1xuICAgICAgdmFyIGxlbmd0aCA9IHBhdGhzLmxlbmd0aCxcbiAgICAgICAgICBzdGFydCA9IGxlbmd0aCA/IHBhdGhzWzBdIDogMCxcbiAgICAgICAgICB2YWx1ZSA9IHRoaXMuX193cmFwcGVkX18sXG4gICAgICAgICAgaW50ZXJjZXB0b3IgPSBmdW5jdGlvbihvYmplY3QpIHsgcmV0dXJuIGJhc2VBdChvYmplY3QsIHBhdGhzKTsgfTtcblxuICAgICAgaWYgKGxlbmd0aCA+IDEgfHwgdGhpcy5fX2FjdGlvbnNfXy5sZW5ndGggfHxcbiAgICAgICAgICAhKHZhbHVlIGluc3RhbmNlb2YgTGF6eVdyYXBwZXIpIHx8ICFpc0luZGV4KHN0YXJ0KSkge1xuICAgICAgICByZXR1cm4gdGhpcy50aHJ1KGludGVyY2VwdG9yKTtcbiAgICAgIH1cbiAgICAgIHZhbHVlID0gdmFsdWUuc2xpY2Uoc3RhcnQsICtzdGFydCArIChsZW5ndGggPyAxIDogMCkpO1xuICAgICAgdmFsdWUuX19hY3Rpb25zX18ucHVzaCh7XG4gICAgICAgICdmdW5jJzogdGhydSxcbiAgICAgICAgJ2FyZ3MnOiBbaW50ZXJjZXB0b3JdLFxuICAgICAgICAndGhpc0FyZyc6IHVuZGVmaW5lZFxuICAgICAgfSk7XG4gICAgICByZXR1cm4gbmV3IExvZGFzaFdyYXBwZXIodmFsdWUsIHRoaXMuX19jaGFpbl9fKS50aHJ1KGZ1bmN0aW9uKGFycmF5KSB7XG4gICAgICAgIGlmIChsZW5ndGggJiYgIWFycmF5Lmxlbmd0aCkge1xuICAgICAgICAgIGFycmF5LnB1c2godW5kZWZpbmVkKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYXJyYXk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBgbG9kYXNoYCB3cmFwcGVyIGluc3RhbmNlIHdpdGggZXhwbGljaXQgbWV0aG9kIGNoYWluIHNlcXVlbmNlcyBlbmFibGVkLlxuICAgICAqXG4gICAgICogQG5hbWUgY2hhaW5cbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBTZXFcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgYGxvZGFzaGAgd3JhcHBlciBpbnN0YW5jZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAnYWdlJzogMzYgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FnZSc6IDQwIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogLy8gQSBzZXF1ZW5jZSB3aXRob3V0IGV4cGxpY2l0IGNoYWluaW5nLlxuICAgICAqIF8odXNlcnMpLmhlYWQoKTtcbiAgICAgKiAvLyA9PiB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNiB9XG4gICAgICpcbiAgICAgKiAvLyBBIHNlcXVlbmNlIHdpdGggZXhwbGljaXQgY2hhaW5pbmcuXG4gICAgICogXyh1c2VycylcbiAgICAgKiAgIC5jaGFpbigpXG4gICAgICogICAuaGVhZCgpXG4gICAgICogICAucGljaygndXNlcicpXG4gICAgICogICAudmFsdWUoKTtcbiAgICAgKiAvLyA9PiB7ICd1c2VyJzogJ2Jhcm5leScgfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdyYXBwZXJDaGFpbigpIHtcbiAgICAgIHJldHVybiBjaGFpbih0aGlzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFeGVjdXRlcyB0aGUgY2hhaW4gc2VxdWVuY2UgYW5kIHJldHVybnMgdGhlIHdyYXBwZWQgcmVzdWx0LlxuICAgICAqXG4gICAgICogQG5hbWUgY29tbWl0XG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4yLjBcbiAgICAgKiBAY2F0ZWdvcnkgU2VxXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IGBsb2Rhc2hgIHdyYXBwZXIgaW5zdGFuY2UuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFsxLCAyXTtcbiAgICAgKiB2YXIgd3JhcHBlZCA9IF8oYXJyYXkpLnB1c2goMyk7XG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheSk7XG4gICAgICogLy8gPT4gWzEsIDJdXG4gICAgICpcbiAgICAgKiB3cmFwcGVkID0gd3JhcHBlZC5jb21taXQoKTtcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICpcbiAgICAgKiB3cmFwcGVkLmxhc3QoKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICovXG4gICAgZnVuY3Rpb24gd3JhcHBlckNvbW1pdCgpIHtcbiAgICAgIHJldHVybiBuZXcgTG9kYXNoV3JhcHBlcih0aGlzLnZhbHVlKCksIHRoaXMuX19jaGFpbl9fKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBuZXh0IHZhbHVlIG9uIGEgd3JhcHBlZCBvYmplY3QgZm9sbG93aW5nIHRoZVxuICAgICAqIFtpdGVyYXRvciBwcm90b2NvbF0oaHR0cHM6Ly9tZG4uaW8vaXRlcmF0aW9uX3Byb3RvY29scyNpdGVyYXRvcikuXG4gICAgICpcbiAgICAgKiBAbmFtZSBuZXh0XG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU2VxXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV4dCBpdGVyYXRvciB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHdyYXBwZWQgPSBfKFsxLCAyXSk7XG4gICAgICpcbiAgICAgKiB3cmFwcGVkLm5leHQoKTtcbiAgICAgKiAvLyA9PiB7ICdkb25lJzogZmFsc2UsICd2YWx1ZSc6IDEgfVxuICAgICAqXG4gICAgICogd3JhcHBlZC5uZXh0KCk7XG4gICAgICogLy8gPT4geyAnZG9uZSc6IGZhbHNlLCAndmFsdWUnOiAyIH1cbiAgICAgKlxuICAgICAqIHdyYXBwZWQubmV4dCgpO1xuICAgICAqIC8vID0+IHsgJ2RvbmUnOiB0cnVlLCAndmFsdWUnOiB1bmRlZmluZWQgfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdyYXBwZXJOZXh0KCkge1xuICAgICAgaWYgKHRoaXMuX192YWx1ZXNfXyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMuX192YWx1ZXNfXyA9IHRvQXJyYXkodGhpcy52YWx1ZSgpKTtcbiAgICAgIH1cbiAgICAgIHZhciBkb25lID0gdGhpcy5fX2luZGV4X18gPj0gdGhpcy5fX3ZhbHVlc19fLmxlbmd0aCxcbiAgICAgICAgICB2YWx1ZSA9IGRvbmUgPyB1bmRlZmluZWQgOiB0aGlzLl9fdmFsdWVzX19bdGhpcy5fX2luZGV4X18rK107XG5cbiAgICAgIHJldHVybiB7ICdkb25lJzogZG9uZSwgJ3ZhbHVlJzogdmFsdWUgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFbmFibGVzIHRoZSB3cmFwcGVyIHRvIGJlIGl0ZXJhYmxlLlxuICAgICAqXG4gICAgICogQG5hbWUgU3ltYm9sLml0ZXJhdG9yXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU2VxXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgd3JhcHBlciBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB3cmFwcGVkID0gXyhbMSwgMl0pO1xuICAgICAqXG4gICAgICogd3JhcHBlZFtTeW1ib2wuaXRlcmF0b3JdKCkgPT09IHdyYXBwZWQ7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogQXJyYXkuZnJvbSh3cmFwcGVkKTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB3cmFwcGVyVG9JdGVyYXRvcigpIHtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBjbG9uZSBvZiB0aGUgY2hhaW4gc2VxdWVuY2UgcGxhbnRpbmcgYHZhbHVlYCBhcyB0aGUgd3JhcHBlZCB2YWx1ZS5cbiAgICAgKlxuICAgICAqIEBuYW1lIHBsYW50XG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4yLjBcbiAgICAgKiBAY2F0ZWdvcnkgU2VxXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcGxhbnQuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IGBsb2Rhc2hgIHdyYXBwZXIgaW5zdGFuY2UuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIHNxdWFyZShuKSB7XG4gICAgICogICByZXR1cm4gbiAqIG47XG4gICAgICogfVxuICAgICAqXG4gICAgICogdmFyIHdyYXBwZWQgPSBfKFsxLCAyXSkubWFwKHNxdWFyZSk7XG4gICAgICogdmFyIG90aGVyID0gd3JhcHBlZC5wbGFudChbMywgNF0pO1xuICAgICAqXG4gICAgICogb3RoZXIudmFsdWUoKTtcbiAgICAgKiAvLyA9PiBbOSwgMTZdXG4gICAgICpcbiAgICAgKiB3cmFwcGVkLnZhbHVlKCk7XG4gICAgICogLy8gPT4gWzEsIDRdXG4gICAgICovXG4gICAgZnVuY3Rpb24gd3JhcHBlclBsYW50KHZhbHVlKSB7XG4gICAgICB2YXIgcmVzdWx0LFxuICAgICAgICAgIHBhcmVudCA9IHRoaXM7XG5cbiAgICAgIHdoaWxlIChwYXJlbnQgaW5zdGFuY2VvZiBiYXNlTG9kYXNoKSB7XG4gICAgICAgIHZhciBjbG9uZSA9IHdyYXBwZXJDbG9uZShwYXJlbnQpO1xuICAgICAgICBjbG9uZS5fX2luZGV4X18gPSAwO1xuICAgICAgICBjbG9uZS5fX3ZhbHVlc19fID0gdW5kZWZpbmVkO1xuICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgcHJldmlvdXMuX193cmFwcGVkX18gPSBjbG9uZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXN1bHQgPSBjbG9uZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcHJldmlvdXMgPSBjbG9uZTtcbiAgICAgICAgcGFyZW50ID0gcGFyZW50Ll9fd3JhcHBlZF9fO1xuICAgICAgfVxuICAgICAgcHJldmlvdXMuX193cmFwcGVkX18gPSB2YWx1ZTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgdGhlIHdyYXBwZXIgdmVyc2lvbiBvZiBgXy5yZXZlcnNlYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBtdXRhdGVzIHRoZSB3cmFwcGVkIGFycmF5LlxuICAgICAqXG4gICAgICogQG5hbWUgcmV2ZXJzZVxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IFNlcVxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBgbG9kYXNoYCB3cmFwcGVyIGluc3RhbmNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbMSwgMiwgM107XG4gICAgICpcbiAgICAgKiBfKGFycmF5KS5yZXZlcnNlKCkudmFsdWUoKVxuICAgICAqIC8vID0+IFszLCAyLCAxXVxuICAgICAqXG4gICAgICogY29uc29sZS5sb2coYXJyYXkpO1xuICAgICAqIC8vID0+IFszLCAyLCAxXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdyYXBwZXJSZXZlcnNlKCkge1xuICAgICAgdmFyIHZhbHVlID0gdGhpcy5fX3dyYXBwZWRfXztcbiAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIExhenlXcmFwcGVyKSB7XG4gICAgICAgIHZhciB3cmFwcGVkID0gdmFsdWU7XG4gICAgICAgIGlmICh0aGlzLl9fYWN0aW9uc19fLmxlbmd0aCkge1xuICAgICAgICAgIHdyYXBwZWQgPSBuZXcgTGF6eVdyYXBwZXIodGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgd3JhcHBlZCA9IHdyYXBwZWQucmV2ZXJzZSgpO1xuICAgICAgICB3cmFwcGVkLl9fYWN0aW9uc19fLnB1c2goe1xuICAgICAgICAgICdmdW5jJzogdGhydSxcbiAgICAgICAgICAnYXJncyc6IFtyZXZlcnNlXSxcbiAgICAgICAgICAndGhpc0FyZyc6IHVuZGVmaW5lZFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIG5ldyBMb2Rhc2hXcmFwcGVyKHdyYXBwZWQsIHRoaXMuX19jaGFpbl9fKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLnRocnUocmV2ZXJzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXhlY3V0ZXMgdGhlIGNoYWluIHNlcXVlbmNlIHRvIHJlc29sdmUgdGhlIHVud3JhcHBlZCB2YWx1ZS5cbiAgICAgKlxuICAgICAqIEBuYW1lIHZhbHVlXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAYWxpYXMgdG9KU09OLCB2YWx1ZU9mXG4gICAgICogQGNhdGVnb3J5IFNlcVxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSByZXNvbHZlZCB1bndyYXBwZWQgdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8oWzEsIDIsIDNdKS52YWx1ZSgpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdyYXBwZXJWYWx1ZSgpIHtcbiAgICAgIHJldHVybiBiYXNlV3JhcHBlclZhbHVlKHRoaXMuX193cmFwcGVkX18sIHRoaXMuX19hY3Rpb25zX18pO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gb2JqZWN0IGNvbXBvc2VkIG9mIGtleXMgZ2VuZXJhdGVkIGZyb20gdGhlIHJlc3VsdHMgb2YgcnVubmluZ1xuICAgICAqIGVhY2ggZWxlbWVudCBvZiBgY29sbGVjdGlvbmAgdGhydSBgaXRlcmF0ZWVgLiBUaGUgY29ycmVzcG9uZGluZyB2YWx1ZSBvZlxuICAgICAqIGVhY2gga2V5IGlzIHRoZSBudW1iZXIgb2YgdGltZXMgdGhlIGtleSB3YXMgcmV0dXJuZWQgYnkgYGl0ZXJhdGVlYC4gVGhlXG4gICAgICogaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjUuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgaXRlcmF0ZWUgdG8gdHJhbnNmb3JtIGtleXMuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY29tcG9zZWQgYWdncmVnYXRlIG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5jb3VudEJ5KFs2LjEsIDQuMiwgNi4zXSwgTWF0aC5mbG9vcik7XG4gICAgICogLy8gPT4geyAnNCc6IDEsICc2JzogMiB9XG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmNvdW50QnkoWydvbmUnLCAndHdvJywgJ3RocmVlJ10sICdsZW5ndGgnKTtcbiAgICAgKiAvLyA9PiB7ICczJzogMiwgJzUnOiAxIH1cbiAgICAgKi9cbiAgICB2YXIgY291bnRCeSA9IGNyZWF0ZUFnZ3JlZ2F0b3IoZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChyZXN1bHQsIGtleSkpIHtcbiAgICAgICAgKytyZXN1bHRba2V5XTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJhc2VBc3NpZ25WYWx1ZShyZXN1bHQsIGtleSwgMSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHByZWRpY2F0ZWAgcmV0dXJucyB0cnV0aHkgZm9yICoqYWxsKiogZWxlbWVudHMgb2YgYGNvbGxlY3Rpb25gLlxuICAgICAqIEl0ZXJhdGlvbiBpcyBzdG9wcGVkIG9uY2UgYHByZWRpY2F0ZWAgcmV0dXJucyBmYWxzZXkuIFRoZSBwcmVkaWNhdGUgaXNcbiAgICAgKiBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzOiAodmFsdWUsIGluZGV4fGtleSwgY29sbGVjdGlvbikuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgcmV0dXJucyBgdHJ1ZWAgZm9yXG4gICAgICogW2VtcHR5IGNvbGxlY3Rpb25zXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9FbXB0eV9zZXQpIGJlY2F1c2VcbiAgICAgKiBbZXZlcnl0aGluZyBpcyB0cnVlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9WYWN1b3VzX3RydXRoKSBvZlxuICAgICAqIGVsZW1lbnRzIG9mIGVtcHR5IGNvbGxlY3Rpb25zLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFsbCBlbGVtZW50cyBwYXNzIHRoZSBwcmVkaWNhdGUgY2hlY2ssXG4gICAgICogIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5ldmVyeShbdHJ1ZSwgMSwgbnVsbCwgJ3llcyddLCBCb29sZWFuKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAnYWdlJzogMzYsICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWdlJzogNDAsICdhY3RpdmUnOiBmYWxzZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzYCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5ldmVyeSh1c2VycywgeyAndXNlcic6ICdiYXJuZXknLCAnYWN0aXZlJzogZmFsc2UgfSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmV2ZXJ5KHVzZXJzLCBbJ2FjdGl2ZScsIGZhbHNlXSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5ldmVyeSh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gZXZlcnkoY29sbGVjdGlvbiwgcHJlZGljYXRlLCBndWFyZCkge1xuICAgICAgdmFyIGZ1bmMgPSBpc0FycmF5KGNvbGxlY3Rpb24pID8gYXJyYXlFdmVyeSA6IGJhc2VFdmVyeTtcbiAgICAgIGlmIChndWFyZCAmJiBpc0l0ZXJhdGVlQ2FsbChjb2xsZWN0aW9uLCBwcmVkaWNhdGUsIGd1YXJkKSkge1xuICAgICAgICBwcmVkaWNhdGUgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJdGVyYXRlcyBvdmVyIGVsZW1lbnRzIG9mIGBjb2xsZWN0aW9uYCwgcmV0dXJuaW5nIGFuIGFycmF5IG9mIGFsbCBlbGVtZW50c1xuICAgICAqIGBwcmVkaWNhdGVgIHJldHVybnMgdHJ1dGh5IGZvci4gVGhlIHByZWRpY2F0ZSBpcyBpbnZva2VkIHdpdGggdGhyZWVcbiAgICAgKiBhcmd1bWVudHM6ICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBVbmxpa2UgYF8ucmVtb3ZlYCwgdGhpcyBtZXRob2QgcmV0dXJucyBhIG5ldyBhcnJheS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmaWx0ZXJlZCBhcnJheS5cbiAgICAgKiBAc2VlIF8ucmVqZWN0XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2LCAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWdlJzogNDAsICdhY3RpdmUnOiBmYWxzZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8uZmlsdGVyKHVzZXJzLCBmdW5jdGlvbihvKSB7IHJldHVybiAhby5hY3RpdmU7IH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnZnJlZCddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc2AgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmlsdGVyKHVzZXJzLCB7ICdhZ2UnOiAzNiwgJ2FjdGl2ZSc6IHRydWUgfSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydiYXJuZXknXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmlsdGVyKHVzZXJzLCBbJ2FjdGl2ZScsIGZhbHNlXSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydmcmVkJ11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmlsdGVyKHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydiYXJuZXknXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZpbHRlcihjb2xsZWN0aW9uLCBwcmVkaWNhdGUpIHtcbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5RmlsdGVyIDogYmFzZUZpbHRlcjtcbiAgICAgIHJldHVybiBmdW5jKGNvbGxlY3Rpb24sIGdldEl0ZXJhdGVlKHByZWRpY2F0ZSwgMykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEl0ZXJhdGVzIG92ZXIgZWxlbWVudHMgb2YgYGNvbGxlY3Rpb25gLCByZXR1cm5pbmcgdGhlIGZpcnN0IGVsZW1lbnRcbiAgICAgKiBgcHJlZGljYXRlYCByZXR1cm5zIHRydXRoeSBmb3IuIFRoZSBwcmVkaWNhdGUgaXMgaW52b2tlZCB3aXRoIHRocmVlXG4gICAgICogYXJndW1lbnRzOiAodmFsdWUsIGluZGV4fGtleSwgY29sbGVjdGlvbikuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZnJvbUluZGV4PTBdIFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgbWF0Y2hlZCBlbGVtZW50LCBlbHNlIGB1bmRlZmluZWRgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICAnYWdlJzogMzYsICdhY3RpdmUnOiB0cnVlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICAnYWdlJzogNDAsICdhY3RpdmUnOiBmYWxzZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdwZWJibGVzJywgJ2FnZSc6IDEsICAnYWN0aXZlJzogdHJ1ZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8uZmluZCh1c2VycywgZnVuY3Rpb24obykgeyByZXR1cm4gby5hZ2UgPCA0MDsgfSk7XG4gICAgICogLy8gPT4gb2JqZWN0IGZvciAnYmFybmV5J1xuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbmQodXNlcnMsIHsgJ2FnZSc6IDEsICdhY3RpdmUnOiB0cnVlIH0pO1xuICAgICAqIC8vID0+IG9iamVjdCBmb3IgJ3BlYmJsZXMnXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kKHVzZXJzLCBbJ2FjdGl2ZScsIGZhbHNlXSk7XG4gICAgICogLy8gPT4gb2JqZWN0IGZvciAnZnJlZCdcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmluZCh1c2VycywgJ2FjdGl2ZScpO1xuICAgICAqIC8vID0+IG9iamVjdCBmb3IgJ2Jhcm5leSdcbiAgICAgKi9cbiAgICB2YXIgZmluZCA9IGNyZWF0ZUZpbmQoZmluZEluZGV4KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZmluZGAgZXhjZXB0IHRoYXQgaXQgaXRlcmF0ZXMgb3ZlciBlbGVtZW50cyBvZlxuICAgICAqIGBjb2xsZWN0aW9uYCBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMi4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZnJvbUluZGV4PWNvbGxlY3Rpb24ubGVuZ3RoLTFdIFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgbWF0Y2hlZCBlbGVtZW50LCBlbHNlIGB1bmRlZmluZWRgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmZpbmRMYXN0KFsxLCAyLCAzLCA0XSwgZnVuY3Rpb24obikge1xuICAgICAqICAgcmV0dXJuIG4gJSAyID09IDE7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gM1xuICAgICAqL1xuICAgIHZhciBmaW5kTGFzdCA9IGNyZWF0ZUZpbmQoZmluZExhc3RJbmRleCk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZmxhdHRlbmVkIGFycmF5IG9mIHZhbHVlcyBieSBydW5uaW5nIGVhY2ggZWxlbWVudCBpbiBgY29sbGVjdGlvbmBcbiAgICAgKiB0aHJ1IGBpdGVyYXRlZWAgYW5kIGZsYXR0ZW5pbmcgdGhlIG1hcHBlZCByZXN1bHRzLiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZFxuICAgICAqIHdpdGggdGhyZWUgYXJndW1lbnRzOiAodmFsdWUsIGluZGV4fGtleSwgY29sbGVjdGlvbikuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmbGF0dGVuZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGR1cGxpY2F0ZShuKSB7XG4gICAgICogICByZXR1cm4gW24sIG5dO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIF8uZmxhdE1hcChbMSwgMl0sIGR1cGxpY2F0ZSk7XG4gICAgICogLy8gPT4gWzEsIDEsIDIsIDJdXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmxhdE1hcChjb2xsZWN0aW9uLCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIGJhc2VGbGF0dGVuKG1hcChjb2xsZWN0aW9uLCBpdGVyYXRlZSksIDEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZmxhdE1hcGAgZXhjZXB0IHRoYXQgaXQgcmVjdXJzaXZlbHkgZmxhdHRlbnMgdGhlXG4gICAgICogbWFwcGVkIHJlc3VsdHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC43LjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmbGF0dGVuZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGR1cGxpY2F0ZShuKSB7XG4gICAgICogICByZXR1cm4gW1tbbiwgbl1dXTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBfLmZsYXRNYXBEZWVwKFsxLCAyXSwgZHVwbGljYXRlKTtcbiAgICAgKiAvLyA9PiBbMSwgMSwgMiwgMl1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmbGF0TWFwRGVlcChjb2xsZWN0aW9uLCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIGJhc2VGbGF0dGVuKG1hcChjb2xsZWN0aW9uLCBpdGVyYXRlZSksIElORklOSVRZKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZsYXRNYXBgIGV4Y2VwdCB0aGF0IGl0IHJlY3Vyc2l2ZWx5IGZsYXR0ZW5zIHRoZVxuICAgICAqIG1hcHBlZCByZXN1bHRzIHVwIHRvIGBkZXB0aGAgdGltZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC43LjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2RlcHRoPTFdIFRoZSBtYXhpbXVtIHJlY3Vyc2lvbiBkZXB0aC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmbGF0dGVuZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGR1cGxpY2F0ZShuKSB7XG4gICAgICogICByZXR1cm4gW1tbbiwgbl1dXTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBfLmZsYXRNYXBEZXB0aChbMSwgMl0sIGR1cGxpY2F0ZSwgMik7XG4gICAgICogLy8gPT4gW1sxLCAxXSwgWzIsIDJdXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZsYXRNYXBEZXB0aChjb2xsZWN0aW9uLCBpdGVyYXRlZSwgZGVwdGgpIHtcbiAgICAgIGRlcHRoID0gZGVwdGggPT09IHVuZGVmaW5lZCA/IDEgOiB0b0ludGVnZXIoZGVwdGgpO1xuICAgICAgcmV0dXJuIGJhc2VGbGF0dGVuKG1hcChjb2xsZWN0aW9uLCBpdGVyYXRlZSksIGRlcHRoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJdGVyYXRlcyBvdmVyIGVsZW1lbnRzIG9mIGBjb2xsZWN0aW9uYCBhbmQgaW52b2tlcyBgaXRlcmF0ZWVgIGZvciBlYWNoIGVsZW1lbnQuXG4gICAgICogVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKiBJdGVyYXRlZSBmdW5jdGlvbnMgbWF5IGV4aXQgaXRlcmF0aW9uIGVhcmx5IGJ5IGV4cGxpY2l0bHkgcmV0dXJuaW5nIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogQXMgd2l0aCBvdGhlciBcIkNvbGxlY3Rpb25zXCIgbWV0aG9kcywgb2JqZWN0cyB3aXRoIGEgXCJsZW5ndGhcIlxuICAgICAqIHByb3BlcnR5IGFyZSBpdGVyYXRlZCBsaWtlIGFycmF5cy4gVG8gYXZvaWQgdGhpcyBiZWhhdmlvciB1c2UgYF8uZm9ySW5gXG4gICAgICogb3IgYF8uZm9yT3duYCBmb3Igb2JqZWN0IGl0ZXJhdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBhbGlhcyBlYWNoXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fE9iamVjdH0gUmV0dXJucyBgY29sbGVjdGlvbmAuXG4gICAgICogQHNlZSBfLmZvckVhY2hSaWdodFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmZvckVhY2goWzEsIDJdLCBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAqICAgY29uc29sZS5sb2codmFsdWUpO1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+IExvZ3MgYDFgIHRoZW4gYDJgLlxuICAgICAqXG4gICAgICogXy5mb3JFYWNoKHsgJ2EnOiAxLCAnYic6IDIgfSwgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAqICAgY29uc29sZS5sb2coa2V5KTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBMb2dzICdhJyB0aGVuICdiJyAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmb3JFYWNoKGNvbGxlY3Rpb24sIGl0ZXJhdGVlKSB7XG4gICAgICB2YXIgZnVuYyA9IGlzQXJyYXkoY29sbGVjdGlvbikgPyBhcnJheUVhY2ggOiBiYXNlRWFjaDtcbiAgICAgIHJldHVybiBmdW5jKGNvbGxlY3Rpb24sIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAzKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5mb3JFYWNoYCBleGNlcHQgdGhhdCBpdCBpdGVyYXRlcyBvdmVyIGVsZW1lbnRzIG9mXG4gICAgICogYGNvbGxlY3Rpb25gIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAyLjAuMFxuICAgICAqIEBhbGlhcyBlYWNoUmlnaHRcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl8T2JqZWN0fSBSZXR1cm5zIGBjb2xsZWN0aW9uYC5cbiAgICAgKiBAc2VlIF8uZm9yRWFjaFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmZvckVhY2hSaWdodChbMSwgMl0sIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICogICBjb25zb2xlLmxvZyh2YWx1ZSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gTG9ncyBgMmAgdGhlbiBgMWAuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZm9yRWFjaFJpZ2h0KGNvbGxlY3Rpb24sIGl0ZXJhdGVlKSB7XG4gICAgICB2YXIgZnVuYyA9IGlzQXJyYXkoY29sbGVjdGlvbikgPyBhcnJheUVhY2hSaWdodCA6IGJhc2VFYWNoUmlnaHQ7XG4gICAgICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gb2JqZWN0IGNvbXBvc2VkIG9mIGtleXMgZ2VuZXJhdGVkIGZyb20gdGhlIHJlc3VsdHMgb2YgcnVubmluZ1xuICAgICAqIGVhY2ggZWxlbWVudCBvZiBgY29sbGVjdGlvbmAgdGhydSBgaXRlcmF0ZWVgLiBUaGUgb3JkZXIgb2YgZ3JvdXBlZCB2YWx1ZXNcbiAgICAgKiBpcyBkZXRlcm1pbmVkIGJ5IHRoZSBvcmRlciB0aGV5IG9jY3VyIGluIGBjb2xsZWN0aW9uYC4gVGhlIGNvcnJlc3BvbmRpbmdcbiAgICAgKiB2YWx1ZSBvZiBlYWNoIGtleSBpcyBhbiBhcnJheSBvZiBlbGVtZW50cyByZXNwb25zaWJsZSBmb3IgZ2VuZXJhdGluZyB0aGVcbiAgICAgKiBrZXkuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSB0byB0cmFuc2Zvcm0ga2V5cy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjb21wb3NlZCBhZ2dyZWdhdGUgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmdyb3VwQnkoWzYuMSwgNC4yLCA2LjNdLCBNYXRoLmZsb29yKTtcbiAgICAgKiAvLyA9PiB7ICc0JzogWzQuMl0sICc2JzogWzYuMSwgNi4zXSB9XG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmdyb3VwQnkoWydvbmUnLCAndHdvJywgJ3RocmVlJ10sICdsZW5ndGgnKTtcbiAgICAgKiAvLyA9PiB7ICczJzogWydvbmUnLCAndHdvJ10sICc1JzogWyd0aHJlZSddIH1cbiAgICAgKi9cbiAgICB2YXIgZ3JvdXBCeSA9IGNyZWF0ZUFnZ3JlZ2F0b3IoZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbChyZXN1bHQsIGtleSkpIHtcbiAgICAgICAgcmVzdWx0W2tleV0ucHVzaCh2YWx1ZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBiYXNlQXNzaWduVmFsdWUocmVzdWx0LCBrZXksIFt2YWx1ZV0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgaW4gYGNvbGxlY3Rpb25gLiBJZiBgY29sbGVjdGlvbmAgaXMgYSBzdHJpbmcsIGl0J3NcbiAgICAgKiBjaGVja2VkIGZvciBhIHN1YnN0cmluZyBvZiBgdmFsdWVgLCBvdGhlcndpc2VcbiAgICAgKiBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICAgICAqIGlzIHVzZWQgZm9yIGVxdWFsaXR5IGNvbXBhcmlzb25zLiBJZiBgZnJvbUluZGV4YCBpcyBuZWdhdGl2ZSwgaXQncyB1c2VkIGFzXG4gICAgICogdGhlIG9mZnNldCBmcm9tIHRoZSBlbmQgb2YgYGNvbGxlY3Rpb25gLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbZnJvbUluZGV4PTBdIFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYW4gaXRlcmF0ZWUgZm9yIG1ldGhvZHMgbGlrZSBgXy5yZWR1Y2VgLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGZvdW5kLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaW5jbHVkZXMoWzEsIDIsIDNdLCAxKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmluY2x1ZGVzKFsxLCAyLCAzXSwgMSwgMik7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaW5jbHVkZXMoeyAnYSc6IDEsICdiJzogMiB9LCAxKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmluY2x1ZGVzKCdhYmNkJywgJ2JjJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluY2x1ZGVzKGNvbGxlY3Rpb24sIHZhbHVlLCBmcm9tSW5kZXgsIGd1YXJkKSB7XG4gICAgICBjb2xsZWN0aW9uID0gaXNBcnJheUxpa2UoY29sbGVjdGlvbikgPyBjb2xsZWN0aW9uIDogdmFsdWVzKGNvbGxlY3Rpb24pO1xuICAgICAgZnJvbUluZGV4ID0gKGZyb21JbmRleCAmJiAhZ3VhcmQpID8gdG9JbnRlZ2VyKGZyb21JbmRleCkgOiAwO1xuXG4gICAgICB2YXIgbGVuZ3RoID0gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgICBpZiAoZnJvbUluZGV4IDwgMCkge1xuICAgICAgICBmcm9tSW5kZXggPSBuYXRpdmVNYXgobGVuZ3RoICsgZnJvbUluZGV4LCAwKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpc1N0cmluZyhjb2xsZWN0aW9uKVxuICAgICAgICA/IChmcm9tSW5kZXggPD0gbGVuZ3RoICYmIGNvbGxlY3Rpb24uaW5kZXhPZih2YWx1ZSwgZnJvbUluZGV4KSA+IC0xKVxuICAgICAgICA6ICghIWxlbmd0aCAmJiBiYXNlSW5kZXhPZihjb2xsZWN0aW9uLCB2YWx1ZSwgZnJvbUluZGV4KSA+IC0xKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnZva2VzIHRoZSBtZXRob2QgYXQgYHBhdGhgIG9mIGVhY2ggZWxlbWVudCBpbiBgY29sbGVjdGlvbmAsIHJldHVybmluZ1xuICAgICAqIGFuIGFycmF5IG9mIHRoZSByZXN1bHRzIG9mIGVhY2ggaW52b2tlZCBtZXRob2QuIEFueSBhZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgICAqIGFyZSBwcm92aWRlZCB0byBlYWNoIGludm9rZWQgbWV0aG9kLiBJZiBgcGF0aGAgaXMgYSBmdW5jdGlvbiwgaXQncyBpbnZva2VkXG4gICAgICogZm9yLCBhbmQgYHRoaXNgIGJvdW5kIHRvLCBlYWNoIGVsZW1lbnQgaW4gYGNvbGxlY3Rpb25gLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtBcnJheXxGdW5jdGlvbnxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIG1ldGhvZCB0byBpbnZva2Ugb3JcbiAgICAgKiAgdGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0gey4uLip9IFthcmdzXSBUaGUgYXJndW1lbnRzIHRvIGludm9rZSBlYWNoIG1ldGhvZCB3aXRoLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcmVzdWx0cy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pbnZva2VNYXAoW1s1LCAxLCA3XSwgWzMsIDIsIDFdXSwgJ3NvcnQnKTtcbiAgICAgKiAvLyA9PiBbWzEsIDUsIDddLCBbMSwgMiwgM11dXG4gICAgICpcbiAgICAgKiBfLmludm9rZU1hcChbMTIzLCA0NTZdLCBTdHJpbmcucHJvdG90eXBlLnNwbGl0LCAnJyk7XG4gICAgICogLy8gPT4gW1snMScsICcyJywgJzMnXSwgWyc0JywgJzUnLCAnNiddXVxuICAgICAqL1xuICAgIHZhciBpbnZva2VNYXAgPSBiYXNlUmVzdChmdW5jdGlvbihjb2xsZWN0aW9uLCBwYXRoLCBhcmdzKSB7XG4gICAgICB2YXIgaW5kZXggPSAtMSxcbiAgICAgICAgICBpc0Z1bmMgPSB0eXBlb2YgcGF0aCA9PSAnZnVuY3Rpb24nLFxuICAgICAgICAgIHJlc3VsdCA9IGlzQXJyYXlMaWtlKGNvbGxlY3Rpb24pID8gQXJyYXkoY29sbGVjdGlvbi5sZW5ndGgpIDogW107XG5cbiAgICAgIGJhc2VFYWNoKGNvbGxlY3Rpb24sIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIHJlc3VsdFsrK2luZGV4XSA9IGlzRnVuYyA/IGFwcGx5KHBhdGgsIHZhbHVlLCBhcmdzKSA6IGJhc2VJbnZva2UodmFsdWUsIHBhdGgsIGFyZ3MpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBvYmplY3QgY29tcG9zZWQgb2Yga2V5cyBnZW5lcmF0ZWQgZnJvbSB0aGUgcmVzdWx0cyBvZiBydW5uaW5nXG4gICAgICogZWFjaCBlbGVtZW50IG9mIGBjb2xsZWN0aW9uYCB0aHJ1IGBpdGVyYXRlZWAuIFRoZSBjb3JyZXNwb25kaW5nIHZhbHVlIG9mXG4gICAgICogZWFjaCBrZXkgaXMgdGhlIGxhc3QgZWxlbWVudCByZXNwb25zaWJsZSBmb3IgZ2VuZXJhdGluZyB0aGUga2V5LiBUaGVcbiAgICAgKiBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSB0byB0cmFuc2Zvcm0ga2V5cy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjb21wb3NlZCBhZ2dyZWdhdGUgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbXG4gICAgICogICB7ICdkaXInOiAnbGVmdCcsICdjb2RlJzogOTcgfSxcbiAgICAgKiAgIHsgJ2Rpcic6ICdyaWdodCcsICdjb2RlJzogMTAwIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5rZXlCeShhcnJheSwgZnVuY3Rpb24obykge1xuICAgICAqICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoby5jb2RlKTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiB7ICdhJzogeyAnZGlyJzogJ2xlZnQnLCAnY29kZSc6IDk3IH0sICdkJzogeyAnZGlyJzogJ3JpZ2h0JywgJ2NvZGUnOiAxMDAgfSB9XG4gICAgICpcbiAgICAgKiBfLmtleUJ5KGFycmF5LCAnZGlyJyk7XG4gICAgICogLy8gPT4geyAnbGVmdCc6IHsgJ2Rpcic6ICdsZWZ0JywgJ2NvZGUnOiA5NyB9LCAncmlnaHQnOiB7ICdkaXInOiAncmlnaHQnLCAnY29kZSc6IDEwMCB9IH1cbiAgICAgKi9cbiAgICB2YXIga2V5QnkgPSBjcmVhdGVBZ2dyZWdhdG9yKGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgYmFzZUFzc2lnblZhbHVlKHJlc3VsdCwga2V5LCB2YWx1ZSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIHZhbHVlcyBieSBydW5uaW5nIGVhY2ggZWxlbWVudCBpbiBgY29sbGVjdGlvbmAgdGhydVxuICAgICAqIGBpdGVyYXRlZWAuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzOlxuICAgICAqICh2YWx1ZSwgaW5kZXh8a2V5LCBjb2xsZWN0aW9uKS5cbiAgICAgKlxuICAgICAqIE1hbnkgbG9kYXNoIG1ldGhvZHMgYXJlIGd1YXJkZWQgdG8gd29yayBhcyBpdGVyYXRlZXMgZm9yIG1ldGhvZHMgbGlrZVxuICAgICAqIGBfLmV2ZXJ5YCwgYF8uZmlsdGVyYCwgYF8ubWFwYCwgYF8ubWFwVmFsdWVzYCwgYF8ucmVqZWN0YCwgYW5kIGBfLnNvbWVgLlxuICAgICAqXG4gICAgICogVGhlIGd1YXJkZWQgbWV0aG9kcyBhcmU6XG4gICAgICogYGFyeWAsIGBjaHVua2AsIGBjdXJyeWAsIGBjdXJyeVJpZ2h0YCwgYGRyb3BgLCBgZHJvcFJpZ2h0YCwgYGV2ZXJ5YCxcbiAgICAgKiBgZmlsbGAsIGBpbnZlcnRgLCBgcGFyc2VJbnRgLCBgcmFuZG9tYCwgYHJhbmdlYCwgYHJhbmdlUmlnaHRgLCBgcmVwZWF0YCxcbiAgICAgKiBgc2FtcGxlU2l6ZWAsIGBzbGljZWAsIGBzb21lYCwgYHNvcnRCeWAsIGBzcGxpdGAsIGB0YWtlYCwgYHRha2VSaWdodGAsXG4gICAgICogYHRlbXBsYXRlYCwgYHRyaW1gLCBgdHJpbUVuZGAsIGB0cmltU3RhcnRgLCBhbmQgYHdvcmRzYFxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgbWFwcGVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBzcXVhcmUobikge1xuICAgICAqICAgcmV0dXJuIG4gKiBuO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIF8ubWFwKFs0LCA4XSwgc3F1YXJlKTtcbiAgICAgKiAvLyA9PiBbMTYsIDY0XVxuICAgICAqXG4gICAgICogXy5tYXAoeyAnYSc6IDQsICdiJzogOCB9LCBzcXVhcmUpO1xuICAgICAqIC8vID0+IFsxNiwgNjRdIChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLm1hcCh1c2VycywgJ3VzZXInKTtcbiAgICAgKiAvLyA9PiBbJ2Jhcm5leScsICdmcmVkJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYXAoY29sbGVjdGlvbiwgaXRlcmF0ZWUpIHtcbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5TWFwIDogYmFzZU1hcDtcbiAgICAgIHJldHVybiBmdW5jKGNvbGxlY3Rpb24sIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAzKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5zb3J0QnlgIGV4Y2VwdCB0aGF0IGl0IGFsbG93cyBzcGVjaWZ5aW5nIHRoZSBzb3J0XG4gICAgICogb3JkZXJzIG9mIHRoZSBpdGVyYXRlZXMgdG8gc29ydCBieS4gSWYgYG9yZGVyc2AgaXMgdW5zcGVjaWZpZWQsIGFsbCB2YWx1ZXNcbiAgICAgKiBhcmUgc29ydGVkIGluIGFzY2VuZGluZyBvcmRlci4gT3RoZXJ3aXNlLCBzcGVjaWZ5IGFuIG9yZGVyIG9mIFwiZGVzY1wiIGZvclxuICAgICAqIGRlc2NlbmRpbmcgb3IgXCJhc2NcIiBmb3IgYXNjZW5kaW5nIHNvcnQgb3JkZXIgb2YgY29ycmVzcG9uZGluZyB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0FycmF5W118RnVuY3Rpb25bXXxPYmplY3RbXXxzdHJpbmdbXX0gW2l0ZXJhdGVlcz1bXy5pZGVudGl0eV1dXG4gICAgICogIFRoZSBpdGVyYXRlZXMgdG8gc29ydCBieS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbb3JkZXJzXSBUaGUgc29ydCBvcmRlcnMgb2YgYGl0ZXJhdGVlc2AuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ucmVkdWNlYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBzb3J0ZWQgYXJyYXkuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FnZSc6IDQ4IH0sXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNCB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWdlJzogNDAgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2IH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogLy8gU29ydCBieSBgdXNlcmAgaW4gYXNjZW5kaW5nIG9yZGVyIGFuZCBieSBgYWdlYCBpbiBkZXNjZW5kaW5nIG9yZGVyLlxuICAgICAqIF8ub3JkZXJCeSh1c2VycywgWyd1c2VyJywgJ2FnZSddLCBbJ2FzYycsICdkZXNjJ10pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFtbJ2Jhcm5leScsIDM2XSwgWydiYXJuZXknLCAzNF0sIFsnZnJlZCcsIDQ4XSwgWydmcmVkJywgNDBdXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG9yZGVyQnkoY29sbGVjdGlvbiwgaXRlcmF0ZWVzLCBvcmRlcnMsIGd1YXJkKSB7XG4gICAgICBpZiAoY29sbGVjdGlvbiA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIGlmICghaXNBcnJheShpdGVyYXRlZXMpKSB7XG4gICAgICAgIGl0ZXJhdGVlcyA9IGl0ZXJhdGVlcyA9PSBudWxsID8gW10gOiBbaXRlcmF0ZWVzXTtcbiAgICAgIH1cbiAgICAgIG9yZGVycyA9IGd1YXJkID8gdW5kZWZpbmVkIDogb3JkZXJzO1xuICAgICAgaWYgKCFpc0FycmF5KG9yZGVycykpIHtcbiAgICAgICAgb3JkZXJzID0gb3JkZXJzID09IG51bGwgPyBbXSA6IFtvcmRlcnNdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VPcmRlckJ5KGNvbGxlY3Rpb24sIGl0ZXJhdGVlcywgb3JkZXJzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIGVsZW1lbnRzIHNwbGl0IGludG8gdHdvIGdyb3VwcywgdGhlIGZpcnN0IG9mIHdoaWNoXG4gICAgICogY29udGFpbnMgZWxlbWVudHMgYHByZWRpY2F0ZWAgcmV0dXJucyB0cnV0aHkgZm9yLCB0aGUgc2Vjb25kIG9mIHdoaWNoXG4gICAgICogY29udGFpbnMgZWxlbWVudHMgYHByZWRpY2F0ZWAgcmV0dXJucyBmYWxzZXkgZm9yLiBUaGUgcHJlZGljYXRlIGlzXG4gICAgICogaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIGdyb3VwZWQgZWxlbWVudHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgICdhZ2UnOiAzNiwgJ2FjdGl2ZSc6IGZhbHNlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICAnYWdlJzogNDAsICdhY3RpdmUnOiB0cnVlIH0sXG4gICAgICogICB7ICd1c2VyJzogJ3BlYmJsZXMnLCAnYWdlJzogMSwgICdhY3RpdmUnOiBmYWxzZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8ucGFydGl0aW9uKHVzZXJzLCBmdW5jdGlvbihvKSB7IHJldHVybiBvLmFjdGl2ZTsgfSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgW1snZnJlZCddLCBbJ2Jhcm5leScsICdwZWJibGVzJ11dXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc2AgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8ucGFydGl0aW9uKHVzZXJzLCB7ICdhZ2UnOiAxLCAnYWN0aXZlJzogZmFsc2UgfSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgW1sncGViYmxlcyddLCBbJ2Jhcm5leScsICdmcmVkJ11dXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc1Byb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5wYXJ0aXRpb24odXNlcnMsIFsnYWN0aXZlJywgZmFsc2VdKTtcbiAgICAgKiAvLyA9PiBvYmplY3RzIGZvciBbWydiYXJuZXknLCAncGViYmxlcyddLCBbJ2ZyZWQnXV1cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8ucGFydGl0aW9uKHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgW1snZnJlZCddLCBbJ2Jhcm5leScsICdwZWJibGVzJ11dXG4gICAgICovXG4gICAgdmFyIHBhcnRpdGlvbiA9IGNyZWF0ZUFnZ3JlZ2F0b3IoZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgICByZXN1bHRba2V5ID8gMCA6IDFdLnB1c2godmFsdWUpO1xuICAgIH0sIGZ1bmN0aW9uKCkgeyByZXR1cm4gW1tdLCBbXV07IH0pO1xuXG4gICAgLyoqXG4gICAgICogUmVkdWNlcyBgY29sbGVjdGlvbmAgdG8gYSB2YWx1ZSB3aGljaCBpcyB0aGUgYWNjdW11bGF0ZWQgcmVzdWx0IG9mIHJ1bm5pbmdcbiAgICAgKiBlYWNoIGVsZW1lbnQgaW4gYGNvbGxlY3Rpb25gIHRocnUgYGl0ZXJhdGVlYCwgd2hlcmUgZWFjaCBzdWNjZXNzaXZlXG4gICAgICogaW52b2NhdGlvbiBpcyBzdXBwbGllZCB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBwcmV2aW91cy4gSWYgYGFjY3VtdWxhdG9yYFxuICAgICAqIGlzIG5vdCBnaXZlbiwgdGhlIGZpcnN0IGVsZW1lbnQgb2YgYGNvbGxlY3Rpb25gIGlzIHVzZWQgYXMgdGhlIGluaXRpYWxcbiAgICAgKiB2YWx1ZS4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBmb3VyIGFyZ3VtZW50czpcbiAgICAgKiAoYWNjdW11bGF0b3IsIHZhbHVlLCBpbmRleHxrZXksIGNvbGxlY3Rpb24pLlxuICAgICAqXG4gICAgICogTWFueSBsb2Rhc2ggbWV0aG9kcyBhcmUgZ3VhcmRlZCB0byB3b3JrIGFzIGl0ZXJhdGVlcyBmb3IgbWV0aG9kcyBsaWtlXG4gICAgICogYF8ucmVkdWNlYCwgYF8ucmVkdWNlUmlnaHRgLCBhbmQgYF8udHJhbnNmb3JtYC5cbiAgICAgKlxuICAgICAqIFRoZSBndWFyZGVkIG1ldGhvZHMgYXJlOlxuICAgICAqIGBhc3NpZ25gLCBgZGVmYXVsdHNgLCBgZGVmYXVsdHNEZWVwYCwgYGluY2x1ZGVzYCwgYG1lcmdlYCwgYG9yZGVyQnlgLFxuICAgICAqIGFuZCBgc29ydEJ5YFxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbYWNjdW11bGF0b3JdIFRoZSBpbml0aWFsIHZhbHVlLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBhY2N1bXVsYXRlZCB2YWx1ZS5cbiAgICAgKiBAc2VlIF8ucmVkdWNlUmlnaHRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5yZWR1Y2UoWzEsIDJdLCBmdW5jdGlvbihzdW0sIG4pIHtcbiAgICAgKiAgIHJldHVybiBzdW0gKyBuO1xuICAgICAqIH0sIDApO1xuICAgICAqIC8vID0+IDNcbiAgICAgKlxuICAgICAqIF8ucmVkdWNlKHsgJ2EnOiAxLCAnYic6IDIsICdjJzogMSB9LCBmdW5jdGlvbihyZXN1bHQsIHZhbHVlLCBrZXkpIHtcbiAgICAgKiAgIChyZXN1bHRbdmFsdWVdIHx8IChyZXN1bHRbdmFsdWVdID0gW10pKS5wdXNoKGtleSk7XG4gICAgICogICByZXR1cm4gcmVzdWx0O1xuICAgICAqIH0sIHt9KTtcbiAgICAgKiAvLyA9PiB7ICcxJzogWydhJywgJ2MnXSwgJzInOiBbJ2InXSB9IChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gICAgICovXG4gICAgZnVuY3Rpb24gcmVkdWNlKGNvbGxlY3Rpb24sIGl0ZXJhdGVlLCBhY2N1bXVsYXRvcikge1xuICAgICAgdmFyIGZ1bmMgPSBpc0FycmF5KGNvbGxlY3Rpb24pID8gYXJyYXlSZWR1Y2UgOiBiYXNlUmVkdWNlLFxuICAgICAgICAgIGluaXRBY2N1bSA9IGFyZ3VtZW50cy5sZW5ndGggPCAzO1xuXG4gICAgICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgNCksIGFjY3VtdWxhdG9yLCBpbml0QWNjdW0sIGJhc2VFYWNoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnJlZHVjZWAgZXhjZXB0IHRoYXQgaXQgaXRlcmF0ZXMgb3ZlciBlbGVtZW50cyBvZlxuICAgICAqIGBjb2xsZWN0aW9uYCBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgQ29sbGVjdGlvblxuICAgICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcGFyYW0geyp9IFthY2N1bXVsYXRvcl0gVGhlIGluaXRpYWwgdmFsdWUuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGFjY3VtdWxhdGVkIHZhbHVlLlxuICAgICAqIEBzZWUgXy5yZWR1Y2VcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFycmF5ID0gW1swLCAxXSwgWzIsIDNdLCBbNCwgNV1dO1xuICAgICAqXG4gICAgICogXy5yZWR1Y2VSaWdodChhcnJheSwgZnVuY3Rpb24oZmxhdHRlbmVkLCBvdGhlcikge1xuICAgICAqICAgcmV0dXJuIGZsYXR0ZW5lZC5jb25jYXQob3RoZXIpO1xuICAgICAqIH0sIFtdKTtcbiAgICAgKiAvLyA9PiBbNCwgNSwgMiwgMywgMCwgMV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZWR1Y2VSaWdodChjb2xsZWN0aW9uLCBpdGVyYXRlZSwgYWNjdW11bGF0b3IpIHtcbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5UmVkdWNlUmlnaHQgOiBiYXNlUmVkdWNlLFxuICAgICAgICAgIGluaXRBY2N1bSA9IGFyZ3VtZW50cy5sZW5ndGggPCAzO1xuXG4gICAgICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgNCksIGFjY3VtdWxhdG9yLCBpbml0QWNjdW0sIGJhc2VFYWNoUmlnaHQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBvcHBvc2l0ZSBvZiBgXy5maWx0ZXJgOyB0aGlzIG1ldGhvZCByZXR1cm5zIHRoZSBlbGVtZW50cyBvZiBgY29sbGVjdGlvbmBcbiAgICAgKiB0aGF0IGBwcmVkaWNhdGVgIGRvZXMgKipub3QqKiByZXR1cm4gdHJ1dGh5IGZvci5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmaWx0ZXJlZCBhcnJheS5cbiAgICAgKiBAc2VlIF8uZmlsdGVyXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IFtcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2LCAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FnZSc6IDQwLCAnYWN0aXZlJzogdHJ1ZSB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8ucmVqZWN0KHVzZXJzLCBmdW5jdGlvbihvKSB7IHJldHVybiAhby5hY3RpdmU7IH0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFsnZnJlZCddXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc2AgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8ucmVqZWN0KHVzZXJzLCB7ICdhZ2UnOiA0MCwgJ2FjdGl2ZSc6IHRydWUgfSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydiYXJuZXknXVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8ucmVqZWN0KHVzZXJzLCBbJ2FjdGl2ZScsIGZhbHNlXSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydmcmVkJ11cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5wcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8ucmVqZWN0KHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgWydiYXJuZXknXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJlamVjdChjb2xsZWN0aW9uLCBwcmVkaWNhdGUpIHtcbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5RmlsdGVyIDogYmFzZUZpbHRlcjtcbiAgICAgIHJldHVybiBmdW5jKGNvbGxlY3Rpb24sIG5lZ2F0ZShnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBhIHJhbmRvbSBlbGVtZW50IGZyb20gYGNvbGxlY3Rpb25gLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDIuMC4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBzYW1wbGUuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJhbmRvbSBlbGVtZW50LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNhbXBsZShbMSwgMiwgMywgNF0pO1xuICAgICAqIC8vID0+IDJcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzYW1wbGUoY29sbGVjdGlvbikge1xuICAgICAgdmFyIGZ1bmMgPSBpc0FycmF5KGNvbGxlY3Rpb24pID8gYXJyYXlTYW1wbGUgOiBiYXNlU2FtcGxlO1xuICAgICAgcmV0dXJuIGZ1bmMoY29sbGVjdGlvbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBgbmAgcmFuZG9tIGVsZW1lbnRzIGF0IHVuaXF1ZSBrZXlzIGZyb20gYGNvbGxlY3Rpb25gIHVwIHRvIHRoZVxuICAgICAqIHNpemUgb2YgYGNvbGxlY3Rpb25gLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBzYW1wbGUuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtuPTFdIFRoZSBudW1iZXIgb2YgZWxlbWVudHMgdG8gc2FtcGxlLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSByYW5kb20gZWxlbWVudHMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc2FtcGxlU2l6ZShbMSwgMiwgM10sIDIpO1xuICAgICAqIC8vID0+IFszLCAxXVxuICAgICAqXG4gICAgICogXy5zYW1wbGVTaXplKFsxLCAyLCAzXSwgNCk7XG4gICAgICogLy8gPT4gWzIsIDMsIDFdXG4gICAgICovXG4gICAgZnVuY3Rpb24gc2FtcGxlU2l6ZShjb2xsZWN0aW9uLCBuLCBndWFyZCkge1xuICAgICAgaWYgKChndWFyZCA/IGlzSXRlcmF0ZWVDYWxsKGNvbGxlY3Rpb24sIG4sIGd1YXJkKSA6IG4gPT09IHVuZGVmaW5lZCkpIHtcbiAgICAgICAgbiA9IDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuID0gdG9JbnRlZ2VyKG4pO1xuICAgICAgfVxuICAgICAgdmFyIGZ1bmMgPSBpc0FycmF5KGNvbGxlY3Rpb24pID8gYXJyYXlTYW1wbGVTaXplIDogYmFzZVNhbXBsZVNpemU7XG4gICAgICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBuKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIHNodWZmbGVkIHZhbHVlcywgdXNpbmcgYSB2ZXJzaW9uIG9mIHRoZVxuICAgICAqIFtGaXNoZXItWWF0ZXMgc2h1ZmZsZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRmlzaGVyLVlhdGVzX3NodWZmbGUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBzaHVmZmxlLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IHNodWZmbGVkIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNodWZmbGUoWzEsIDIsIDMsIDRdKTtcbiAgICAgKiAvLyA9PiBbNCwgMSwgMywgMl1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzaHVmZmxlKGNvbGxlY3Rpb24pIHtcbiAgICAgIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5U2h1ZmZsZSA6IGJhc2VTaHVmZmxlO1xuICAgICAgcmV0dXJuIGZ1bmMoY29sbGVjdGlvbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgc2l6ZSBvZiBgY29sbGVjdGlvbmAgYnkgcmV0dXJuaW5nIGl0cyBsZW5ndGggZm9yIGFycmF5LWxpa2VcbiAgICAgKiB2YWx1ZXMgb3IgdGhlIG51bWJlciBvZiBvd24gZW51bWVyYWJsZSBzdHJpbmcga2V5ZWQgcHJvcGVydGllcyBmb3Igb2JqZWN0cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGluc3BlY3QuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgY29sbGVjdGlvbiBzaXplLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnNpemUoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICpcbiAgICAgKiBfLnNpemUoeyAnYSc6IDEsICdiJzogMiB9KTtcbiAgICAgKiAvLyA9PiAyXG4gICAgICpcbiAgICAgKiBfLnNpemUoJ3BlYmJsZXMnKTtcbiAgICAgKiAvLyA9PiA3XG4gICAgICovXG4gICAgZnVuY3Rpb24gc2l6ZShjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoY29sbGVjdGlvbiA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfVxuICAgICAgaWYgKGlzQXJyYXlMaWtlKGNvbGxlY3Rpb24pKSB7XG4gICAgICAgIHJldHVybiBpc1N0cmluZyhjb2xsZWN0aW9uKSA/IHN0cmluZ1NpemUoY29sbGVjdGlvbikgOiBjb2xsZWN0aW9uLmxlbmd0aDtcbiAgICAgIH1cbiAgICAgIHZhciB0YWcgPSBnZXRUYWcoY29sbGVjdGlvbik7XG4gICAgICBpZiAodGFnID09IG1hcFRhZyB8fCB0YWcgPT0gc2V0VGFnKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uLnNpemU7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZUtleXMoY29sbGVjdGlvbikubGVuZ3RoO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgcHJlZGljYXRlYCByZXR1cm5zIHRydXRoeSBmb3IgKiphbnkqKiBlbGVtZW50IG9mIGBjb2xsZWN0aW9uYC5cbiAgICAgKiBJdGVyYXRpb24gaXMgc3RvcHBlZCBvbmNlIGBwcmVkaWNhdGVgIHJldHVybnMgdHJ1dGh5LiBUaGUgcHJlZGljYXRlIGlzXG4gICAgICogaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleHxrZXksIGNvbGxlY3Rpb24pLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFueSBlbGVtZW50IHBhc3NlcyB0aGUgcHJlZGljYXRlIGNoZWNrLFxuICAgICAqICBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc29tZShbbnVsbCwgMCwgJ3llcycsIGZhbHNlXSwgQm9vbGVhbik7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAnYWN0aXZlJzogdHJ1ZSB9LFxuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWN0aXZlJzogZmFsc2UgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc2AgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uc29tZSh1c2VycywgeyAndXNlcic6ICdiYXJuZXknLCAnYWN0aXZlJzogZmFsc2UgfSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnNvbWUodXNlcnMsIFsnYWN0aXZlJywgZmFsc2VdKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLnNvbWUodXNlcnMsICdhY3RpdmUnKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gc29tZShjb2xsZWN0aW9uLCBwcmVkaWNhdGUsIGd1YXJkKSB7XG4gICAgICB2YXIgZnVuYyA9IGlzQXJyYXkoY29sbGVjdGlvbikgPyBhcnJheVNvbWUgOiBiYXNlU29tZTtcbiAgICAgIGlmIChndWFyZCAmJiBpc0l0ZXJhdGVlQ2FsbChjb2xsZWN0aW9uLCBwcmVkaWNhdGUsIGd1YXJkKSkge1xuICAgICAgICBwcmVkaWNhdGUgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIGVsZW1lbnRzLCBzb3J0ZWQgaW4gYXNjZW5kaW5nIG9yZGVyIGJ5IHRoZSByZXN1bHRzIG9mXG4gICAgICogcnVubmluZyBlYWNoIGVsZW1lbnQgaW4gYSBjb2xsZWN0aW9uIHRocnUgZWFjaCBpdGVyYXRlZS4gVGhpcyBtZXRob2RcbiAgICAgKiBwZXJmb3JtcyBhIHN0YWJsZSBzb3J0LCB0aGF0IGlzLCBpdCBwcmVzZXJ2ZXMgdGhlIG9yaWdpbmFsIHNvcnQgb3JkZXIgb2ZcbiAgICAgKiBlcXVhbCBlbGVtZW50cy4gVGhlIGl0ZXJhdGVlcyBhcmUgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7Li4uKEZ1bmN0aW9ufEZ1bmN0aW9uW10pfSBbaXRlcmF0ZWVzPVtfLmlkZW50aXR5XV1cbiAgICAgKiAgVGhlIGl0ZXJhdGVlcyB0byBzb3J0IGJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IHNvcnRlZCBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHVzZXJzID0gW1xuICAgICAqICAgeyAndXNlcic6ICdmcmVkJywgICAnYWdlJzogNDggfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnYmFybmV5JywgJ2FnZSc6IDM2IH0sXG4gICAgICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICdhZ2UnOiA0MCB9LFxuICAgICAqICAgeyAndXNlcic6ICdiYXJuZXknLCAnYWdlJzogMzQgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLnNvcnRCeSh1c2VycywgW2Z1bmN0aW9uKG8pIHsgcmV0dXJuIG8udXNlcjsgfV0pO1xuICAgICAqIC8vID0+IG9iamVjdHMgZm9yIFtbJ2Jhcm5leScsIDM2XSwgWydiYXJuZXknLCAzNF0sIFsnZnJlZCcsIDQ4XSwgWydmcmVkJywgNDBdXVxuICAgICAqXG4gICAgICogXy5zb3J0QnkodXNlcnMsIFsndXNlcicsICdhZ2UnXSk7XG4gICAgICogLy8gPT4gb2JqZWN0cyBmb3IgW1snYmFybmV5JywgMzRdLCBbJ2Jhcm5leScsIDM2XSwgWydmcmVkJywgNDBdLCBbJ2ZyZWQnLCA0OF1dXG4gICAgICovXG4gICAgdmFyIHNvcnRCeSA9IGJhc2VSZXN0KGZ1bmN0aW9uKGNvbGxlY3Rpb24sIGl0ZXJhdGVlcykge1xuICAgICAgaWYgKGNvbGxlY3Rpb24gPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICB2YXIgbGVuZ3RoID0gaXRlcmF0ZWVzLmxlbmd0aDtcbiAgICAgIGlmIChsZW5ndGggPiAxICYmIGlzSXRlcmF0ZWVDYWxsKGNvbGxlY3Rpb24sIGl0ZXJhdGVlc1swXSwgaXRlcmF0ZWVzWzFdKSkge1xuICAgICAgICBpdGVyYXRlZXMgPSBbXTtcbiAgICAgIH0gZWxzZSBpZiAobGVuZ3RoID4gMiAmJiBpc0l0ZXJhdGVlQ2FsbChpdGVyYXRlZXNbMF0sIGl0ZXJhdGVlc1sxXSwgaXRlcmF0ZWVzWzJdKSkge1xuICAgICAgICBpdGVyYXRlZXMgPSBbaXRlcmF0ZWVzWzBdXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlT3JkZXJCeShjb2xsZWN0aW9uLCBiYXNlRmxhdHRlbihpdGVyYXRlZXMsIDEpLCBbXSk7XG4gICAgfSk7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSB0aW1lc3RhbXAgb2YgdGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdGhhdCBoYXZlIGVsYXBzZWQgc2luY2VcbiAgICAgKiB0aGUgVW5peCBlcG9jaCAoMSBKYW51YXJ5IDE5NzAgMDA6MDA6MDAgVVRDKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAyLjQuMFxuICAgICAqIEBjYXRlZ29yeSBEYXRlXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgdGltZXN0YW1wLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRlZmVyKGZ1bmN0aW9uKHN0YW1wKSB7XG4gICAgICogICBjb25zb2xlLmxvZyhfLm5vdygpIC0gc3RhbXApO1xuICAgICAqIH0sIF8ubm93KCkpO1xuICAgICAqIC8vID0+IExvZ3MgdGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgaXQgdG9vayBmb3IgdGhlIGRlZmVycmVkIGludm9jYXRpb24uXG4gICAgICovXG4gICAgdmFyIG5vdyA9IGN0eE5vdyB8fCBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiByb290LkRhdGUubm93KCk7XG4gICAgfTtcblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIFRoZSBvcHBvc2l0ZSBvZiBgXy5iZWZvcmVgOyB0aGlzIG1ldGhvZCBjcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzXG4gICAgICogYGZ1bmNgIG9uY2UgaXQncyBjYWxsZWQgYG5gIG9yIG1vcmUgdGltZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbiBUaGUgbnVtYmVyIG9mIGNhbGxzIGJlZm9yZSBgZnVuY2AgaXMgaW52b2tlZC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byByZXN0cmljdC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyByZXN0cmljdGVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgc2F2ZXMgPSBbJ3Byb2ZpbGUnLCAnc2V0dGluZ3MnXTtcbiAgICAgKlxuICAgICAqIHZhciBkb25lID0gXy5hZnRlcihzYXZlcy5sZW5ndGgsIGZ1bmN0aW9uKCkge1xuICAgICAqICAgY29uc29sZS5sb2coJ2RvbmUgc2F2aW5nIScpO1xuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogXy5mb3JFYWNoKHNhdmVzLCBmdW5jdGlvbih0eXBlKSB7XG4gICAgICogICBhc3luY1NhdmUoeyAndHlwZSc6IHR5cGUsICdjb21wbGV0ZSc6IGRvbmUgfSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gTG9ncyAnZG9uZSBzYXZpbmchJyBhZnRlciB0aGUgdHdvIGFzeW5jIHNhdmVzIGhhdmUgY29tcGxldGVkLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFmdGVyKG4sIGZ1bmMpIHtcbiAgICAgIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgIH1cbiAgICAgIG4gPSB0b0ludGVnZXIobik7XG4gICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICgtLW4gPCAxKSB7XG4gICAgICAgICAgcmV0dXJuIGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIGBmdW5jYCwgd2l0aCB1cCB0byBgbmAgYXJndW1lbnRzLFxuICAgICAqIGlnbm9yaW5nIGFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGNhcCBhcmd1bWVudHMgZm9yLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbj1mdW5jLmxlbmd0aF0gVGhlIGFyaXR5IGNhcC5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYW4gaXRlcmF0ZWUgZm9yIG1ldGhvZHMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGNhcHBlZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5tYXAoWyc2JywgJzgnLCAnMTAnXSwgXy5hcnkocGFyc2VJbnQsIDEpKTtcbiAgICAgKiAvLyA9PiBbNiwgOCwgMTBdXG4gICAgICovXG4gICAgZnVuY3Rpb24gYXJ5KGZ1bmMsIG4sIGd1YXJkKSB7XG4gICAgICBuID0gZ3VhcmQgPyB1bmRlZmluZWQgOiBuO1xuICAgICAgbiA9IChmdW5jICYmIG4gPT0gbnVsbCkgPyBmdW5jLmxlbmd0aCA6IG47XG4gICAgICByZXR1cm4gY3JlYXRlV3JhcChmdW5jLCBXUkFQX0FSWV9GTEFHLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIG4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgYGZ1bmNgLCB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBhbmQgYXJndW1lbnRzXG4gICAgICogb2YgdGhlIGNyZWF0ZWQgZnVuY3Rpb24sIHdoaWxlIGl0J3MgY2FsbGVkIGxlc3MgdGhhbiBgbmAgdGltZXMuIFN1YnNlcXVlbnRcbiAgICAgKiBjYWxscyB0byB0aGUgY3JlYXRlZCBmdW5jdGlvbiByZXR1cm4gdGhlIHJlc3VsdCBvZiB0aGUgbGFzdCBgZnVuY2AgaW52b2NhdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBuIFRoZSBudW1iZXIgb2YgY2FsbHMgYXQgd2hpY2ggYGZ1bmNgIGlzIG5vIGxvbmdlciBpbnZva2VkLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHJlc3RyaWN0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHJlc3RyaWN0ZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGpRdWVyeShlbGVtZW50KS5vbignY2xpY2snLCBfLmJlZm9yZSg1LCBhZGRDb250YWN0VG9MaXN0KSk7XG4gICAgICogLy8gPT4gQWxsb3dzIGFkZGluZyB1cCB0byA0IGNvbnRhY3RzIHRvIHRoZSBsaXN0LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGJlZm9yZShuLCBmdW5jKSB7XG4gICAgICB2YXIgcmVzdWx0O1xuICAgICAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgfVxuICAgICAgbiA9IHRvSW50ZWdlcihuKTtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKC0tbiA+IDApIHtcbiAgICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG4gPD0gMSkge1xuICAgICAgICAgIGZ1bmMgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBgZnVuY2Agd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgb2YgYHRoaXNBcmdgXG4gICAgICogYW5kIGBwYXJ0aWFsc2AgcHJlcGVuZGVkIHRvIHRoZSBhcmd1bWVudHMgaXQgcmVjZWl2ZXMuXG4gICAgICpcbiAgICAgKiBUaGUgYF8uYmluZC5wbGFjZWhvbGRlcmAgdmFsdWUsIHdoaWNoIGRlZmF1bHRzIHRvIGBfYCBpbiBtb25vbGl0aGljIGJ1aWxkcyxcbiAgICAgKiBtYXkgYmUgdXNlZCBhcyBhIHBsYWNlaG9sZGVyIGZvciBwYXJ0aWFsbHkgYXBwbGllZCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVW5saWtlIG5hdGl2ZSBgRnVuY3Rpb24jYmluZGAsIHRoaXMgbWV0aG9kIGRvZXNuJ3Qgc2V0IHRoZSBcImxlbmd0aFwiXG4gICAgICogcHJvcGVydHkgb2YgYm91bmQgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gYmluZC5cbiAgICAgKiBAcGFyYW0geyp9IHRoaXNBcmcgVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBmdW5jYC5cbiAgICAgKiBAcGFyYW0gey4uLip9IFtwYXJ0aWFsc10gVGhlIGFyZ3VtZW50cyB0byBiZSBwYXJ0aWFsbHkgYXBwbGllZC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBib3VuZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gZ3JlZXQoZ3JlZXRpbmcsIHB1bmN0dWF0aW9uKSB7XG4gICAgICogICByZXR1cm4gZ3JlZXRpbmcgKyAnICcgKyB0aGlzLnVzZXIgKyBwdW5jdHVhdGlvbjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAndXNlcic6ICdmcmVkJyB9O1xuICAgICAqXG4gICAgICogdmFyIGJvdW5kID0gXy5iaW5kKGdyZWV0LCBvYmplY3QsICdoaScpO1xuICAgICAqIGJvdW5kKCchJyk7XG4gICAgICogLy8gPT4gJ2hpIGZyZWQhJ1xuICAgICAqXG4gICAgICogLy8gQm91bmQgd2l0aCBwbGFjZWhvbGRlcnMuXG4gICAgICogdmFyIGJvdW5kID0gXy5iaW5kKGdyZWV0LCBvYmplY3QsIF8sICchJyk7XG4gICAgICogYm91bmQoJ2hpJyk7XG4gICAgICogLy8gPT4gJ2hpIGZyZWQhJ1xuICAgICAqL1xuICAgIHZhciBiaW5kID0gYmFzZVJlc3QoZnVuY3Rpb24oZnVuYywgdGhpc0FyZywgcGFydGlhbHMpIHtcbiAgICAgIHZhciBiaXRtYXNrID0gV1JBUF9CSU5EX0ZMQUc7XG4gICAgICBpZiAocGFydGlhbHMubGVuZ3RoKSB7XG4gICAgICAgIHZhciBob2xkZXJzID0gcmVwbGFjZUhvbGRlcnMocGFydGlhbHMsIGdldEhvbGRlcihiaW5kKSk7XG4gICAgICAgIGJpdG1hc2sgfD0gV1JBUF9QQVJUSUFMX0ZMQUc7XG4gICAgICB9XG4gICAgICByZXR1cm4gY3JlYXRlV3JhcChmdW5jLCBiaXRtYXNrLCB0aGlzQXJnLCBwYXJ0aWFscywgaG9sZGVycyk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIHRoZSBtZXRob2QgYXQgYG9iamVjdFtrZXldYCB3aXRoIGBwYXJ0aWFsc2BcbiAgICAgKiBwcmVwZW5kZWQgdG8gdGhlIGFyZ3VtZW50cyBpdCByZWNlaXZlcy5cbiAgICAgKlxuICAgICAqIFRoaXMgbWV0aG9kIGRpZmZlcnMgZnJvbSBgXy5iaW5kYCBieSBhbGxvd2luZyBib3VuZCBmdW5jdGlvbnMgdG8gcmVmZXJlbmNlXG4gICAgICogbWV0aG9kcyB0aGF0IG1heSBiZSByZWRlZmluZWQgb3IgZG9uJ3QgeWV0IGV4aXN0LiBTZWVcbiAgICAgKiBbUGV0ZXIgTWljaGF1eCdzIGFydGljbGVdKGh0dHA6Ly9wZXRlci5taWNoYXV4LmNhL2FydGljbGVzL2xhenktZnVuY3Rpb24tZGVmaW5pdGlvbi1wYXR0ZXJuKVxuICAgICAqIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICpcbiAgICAgKiBUaGUgYF8uYmluZEtleS5wbGFjZWhvbGRlcmAgdmFsdWUsIHdoaWNoIGRlZmF1bHRzIHRvIGBfYCBpbiBtb25vbGl0aGljXG4gICAgICogYnVpbGRzLCBtYXkgYmUgdXNlZCBhcyBhIHBsYWNlaG9sZGVyIGZvciBwYXJ0aWFsbHkgYXBwbGllZCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xMC4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGludm9rZSB0aGUgbWV0aG9kIG9uLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgbWV0aG9kLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW3BhcnRpYWxzXSBUaGUgYXJndW1lbnRzIHRvIGJlIHBhcnRpYWxseSBhcHBsaWVkLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGJvdW5kIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0ge1xuICAgICAqICAgJ3VzZXInOiAnZnJlZCcsXG4gICAgICogICAnZ3JlZXQnOiBmdW5jdGlvbihncmVldGluZywgcHVuY3R1YXRpb24pIHtcbiAgICAgKiAgICAgcmV0dXJuIGdyZWV0aW5nICsgJyAnICsgdGhpcy51c2VyICsgcHVuY3R1YXRpb247XG4gICAgICogICB9XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIHZhciBib3VuZCA9IF8uYmluZEtleShvYmplY3QsICdncmVldCcsICdoaScpO1xuICAgICAqIGJvdW5kKCchJyk7XG4gICAgICogLy8gPT4gJ2hpIGZyZWQhJ1xuICAgICAqXG4gICAgICogb2JqZWN0LmdyZWV0ID0gZnVuY3Rpb24oZ3JlZXRpbmcsIHB1bmN0dWF0aW9uKSB7XG4gICAgICogICByZXR1cm4gZ3JlZXRpbmcgKyAneWEgJyArIHRoaXMudXNlciArIHB1bmN0dWF0aW9uO1xuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBib3VuZCgnIScpO1xuICAgICAqIC8vID0+ICdoaXlhIGZyZWQhJ1xuICAgICAqXG4gICAgICogLy8gQm91bmQgd2l0aCBwbGFjZWhvbGRlcnMuXG4gICAgICogdmFyIGJvdW5kID0gXy5iaW5kS2V5KG9iamVjdCwgJ2dyZWV0JywgXywgJyEnKTtcbiAgICAgKiBib3VuZCgnaGknKTtcbiAgICAgKiAvLyA9PiAnaGl5YSBmcmVkISdcbiAgICAgKi9cbiAgICB2YXIgYmluZEtleSA9IGJhc2VSZXN0KGZ1bmN0aW9uKG9iamVjdCwga2V5LCBwYXJ0aWFscykge1xuICAgICAgdmFyIGJpdG1hc2sgPSBXUkFQX0JJTkRfRkxBRyB8IFdSQVBfQklORF9LRVlfRkxBRztcbiAgICAgIGlmIChwYXJ0aWFscy5sZW5ndGgpIHtcbiAgICAgICAgdmFyIGhvbGRlcnMgPSByZXBsYWNlSG9sZGVycyhwYXJ0aWFscywgZ2V0SG9sZGVyKGJpbmRLZXkpKTtcbiAgICAgICAgYml0bWFzayB8PSBXUkFQX1BBUlRJQUxfRkxBRztcbiAgICAgIH1cbiAgICAgIHJldHVybiBjcmVhdGVXcmFwKGtleSwgYml0bWFzaywgb2JqZWN0LCBwYXJ0aWFscywgaG9sZGVycyk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBhY2NlcHRzIGFyZ3VtZW50cyBvZiBgZnVuY2AgYW5kIGVpdGhlciBpbnZva2VzXG4gICAgICogYGZ1bmNgIHJldHVybmluZyBpdHMgcmVzdWx0LCBpZiBhdCBsZWFzdCBgYXJpdHlgIG51bWJlciBvZiBhcmd1bWVudHMgaGF2ZVxuICAgICAqIGJlZW4gcHJvdmlkZWQsIG9yIHJldHVybnMgYSBmdW5jdGlvbiB0aGF0IGFjY2VwdHMgdGhlIHJlbWFpbmluZyBgZnVuY2BcbiAgICAgKiBhcmd1bWVudHMsIGFuZCBzbyBvbi4gVGhlIGFyaXR5IG9mIGBmdW5jYCBtYXkgYmUgc3BlY2lmaWVkIGlmIGBmdW5jLmxlbmd0aGBcbiAgICAgKiBpcyBub3Qgc3VmZmljaWVudC5cbiAgICAgKlxuICAgICAqIFRoZSBgXy5jdXJyeS5wbGFjZWhvbGRlcmAgdmFsdWUsIHdoaWNoIGRlZmF1bHRzIHRvIGBfYCBpbiBtb25vbGl0aGljIGJ1aWxkcyxcbiAgICAgKiBtYXkgYmUgdXNlZCBhcyBhIHBsYWNlaG9sZGVyIGZvciBwcm92aWRlZCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgZG9lc24ndCBzZXQgdGhlIFwibGVuZ3RoXCIgcHJvcGVydHkgb2YgY3VycmllZCBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMi4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjdXJyeS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2FyaXR5PWZ1bmMubGVuZ3RoXSBUaGUgYXJpdHkgb2YgYGZ1bmNgLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgY3VycmllZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGFiYyA9IGZ1bmN0aW9uKGEsIGIsIGMpIHtcbiAgICAgKiAgIHJldHVybiBbYSwgYiwgY107XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIHZhciBjdXJyaWVkID0gXy5jdXJyeShhYmMpO1xuICAgICAqXG4gICAgICogY3VycmllZCgxKSgyKSgzKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKlxuICAgICAqIGN1cnJpZWQoMSwgMikoMyk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICpcbiAgICAgKiBjdXJyaWVkKDEsIDIsIDMpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqXG4gICAgICogLy8gQ3VycmllZCB3aXRoIHBsYWNlaG9sZGVycy5cbiAgICAgKiBjdXJyaWVkKDEpKF8sIDMpKDIpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGN1cnJ5KGZ1bmMsIGFyaXR5LCBndWFyZCkge1xuICAgICAgYXJpdHkgPSBndWFyZCA/IHVuZGVmaW5lZCA6IGFyaXR5O1xuICAgICAgdmFyIHJlc3VsdCA9IGNyZWF0ZVdyYXAoZnVuYywgV1JBUF9DVVJSWV9GTEFHLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgYXJpdHkpO1xuICAgICAgcmVzdWx0LnBsYWNlaG9sZGVyID0gY3VycnkucGxhY2Vob2xkZXI7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uY3VycnlgIGV4Y2VwdCB0aGF0IGFyZ3VtZW50cyBhcmUgYXBwbGllZCB0byBgZnVuY2BcbiAgICAgKiBpbiB0aGUgbWFubmVyIG9mIGBfLnBhcnRpYWxSaWdodGAgaW5zdGVhZCBvZiBgXy5wYXJ0aWFsYC5cbiAgICAgKlxuICAgICAqIFRoZSBgXy5jdXJyeVJpZ2h0LnBsYWNlaG9sZGVyYCB2YWx1ZSwgd2hpY2ggZGVmYXVsdHMgdG8gYF9gIGluIG1vbm9saXRoaWNcbiAgICAgKiBidWlsZHMsIG1heSBiZSB1c2VkIGFzIGEgcGxhY2Vob2xkZXIgZm9yIHByb3ZpZGVkIGFyZ3VtZW50cy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBkb2Vzbid0IHNldCB0aGUgXCJsZW5ndGhcIiBwcm9wZXJ0eSBvZiBjdXJyaWVkIGZ1bmN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGN1cnJ5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJpdHk9ZnVuYy5sZW5ndGhdIFRoZSBhcml0eSBvZiBgZnVuY2AuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBjdXJyaWVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYWJjID0gZnVuY3Rpb24oYSwgYiwgYykge1xuICAgICAqICAgcmV0dXJuIFthLCBiLCBjXTtcbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogdmFyIGN1cnJpZWQgPSBfLmN1cnJ5UmlnaHQoYWJjKTtcbiAgICAgKlxuICAgICAqIGN1cnJpZWQoMykoMikoMSk7XG4gICAgICogLy8gPT4gWzEsIDIsIDNdXG4gICAgICpcbiAgICAgKiBjdXJyaWVkKDIsIDMpKDEpO1xuICAgICAqIC8vID0+IFsxLCAyLCAzXVxuICAgICAqXG4gICAgICogY3VycmllZCgxLCAyLCAzKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKlxuICAgICAqIC8vIEN1cnJpZWQgd2l0aCBwbGFjZWhvbGRlcnMuXG4gICAgICogY3VycmllZCgzKSgxLCBfKSgyKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjdXJyeVJpZ2h0KGZ1bmMsIGFyaXR5LCBndWFyZCkge1xuICAgICAgYXJpdHkgPSBndWFyZCA/IHVuZGVmaW5lZCA6IGFyaXR5O1xuICAgICAgdmFyIHJlc3VsdCA9IGNyZWF0ZVdyYXAoZnVuYywgV1JBUF9DVVJSWV9SSUdIVF9GTEFHLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgYXJpdHkpO1xuICAgICAgcmVzdWx0LnBsYWNlaG9sZGVyID0gY3VycnlSaWdodC5wbGFjZWhvbGRlcjtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGRlYm91bmNlZCBmdW5jdGlvbiB0aGF0IGRlbGF5cyBpbnZva2luZyBgZnVuY2AgdW50aWwgYWZ0ZXIgYHdhaXRgXG4gICAgICogbWlsbGlzZWNvbmRzIGhhdmUgZWxhcHNlZCBzaW5jZSB0aGUgbGFzdCB0aW1lIHRoZSBkZWJvdW5jZWQgZnVuY3Rpb24gd2FzXG4gICAgICogaW52b2tlZC4gVGhlIGRlYm91bmNlZCBmdW5jdGlvbiBjb21lcyB3aXRoIGEgYGNhbmNlbGAgbWV0aG9kIHRvIGNhbmNlbFxuICAgICAqIGRlbGF5ZWQgYGZ1bmNgIGludm9jYXRpb25zIGFuZCBhIGBmbHVzaGAgbWV0aG9kIHRvIGltbWVkaWF0ZWx5IGludm9rZSB0aGVtLlxuICAgICAqIFByb3ZpZGUgYG9wdGlvbnNgIHRvIGluZGljYXRlIHdoZXRoZXIgYGZ1bmNgIHNob3VsZCBiZSBpbnZva2VkIG9uIHRoZVxuICAgICAqIGxlYWRpbmcgYW5kL29yIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIGB3YWl0YCB0aW1lb3V0LiBUaGUgYGZ1bmNgIGlzIGludm9rZWRcbiAgICAgKiB3aXRoIHRoZSBsYXN0IGFyZ3VtZW50cyBwcm92aWRlZCB0byB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uLiBTdWJzZXF1ZW50XG4gICAgICogY2FsbHMgdG8gdGhlIGRlYm91bmNlZCBmdW5jdGlvbiByZXR1cm4gdGhlIHJlc3VsdCBvZiB0aGUgbGFzdCBgZnVuY2BcbiAgICAgKiBpbnZvY2F0aW9uLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIElmIGBsZWFkaW5nYCBhbmQgYHRyYWlsaW5nYCBvcHRpb25zIGFyZSBgdHJ1ZWAsIGBmdW5jYCBpc1xuICAgICAqIGludm9rZWQgb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQgb25seSBpZiB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uXG4gICAgICogaXMgaW52b2tlZCBtb3JlIHRoYW4gb25jZSBkdXJpbmcgdGhlIGB3YWl0YCB0aW1lb3V0LlxuICAgICAqXG4gICAgICogSWYgYHdhaXRgIGlzIGAwYCBhbmQgYGxlYWRpbmdgIGlzIGBmYWxzZWAsIGBmdW5jYCBpbnZvY2F0aW9uIGlzIGRlZmVycmVkXG4gICAgICogdW50aWwgdG8gdGhlIG5leHQgdGljaywgc2ltaWxhciB0byBgc2V0VGltZW91dGAgd2l0aCBhIHRpbWVvdXQgb2YgYDBgLlxuICAgICAqXG4gICAgICogU2VlIFtEYXZpZCBDb3JiYWNobydzIGFydGljbGVdKGh0dHBzOi8vY3NzLXRyaWNrcy5jb20vZGVib3VuY2luZy10aHJvdHRsaW5nLWV4cGxhaW5lZC1leGFtcGxlcy8pXG4gICAgICogZm9yIGRldGFpbHMgb3ZlciB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBgXy5kZWJvdW5jZWAgYW5kIGBfLnRocm90dGxlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRlYm91bmNlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbd2FpdD0wXSBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byBkZWxheS5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIFRoZSBvcHRpb25zIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmxlYWRpbmc9ZmFsc2VdXG4gICAgICogIFNwZWNpZnkgaW52b2tpbmcgb24gdGhlIGxlYWRpbmcgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW29wdGlvbnMubWF4V2FpdF1cbiAgICAgKiAgVGhlIG1heGltdW0gdGltZSBgZnVuY2AgaXMgYWxsb3dlZCB0byBiZSBkZWxheWVkIGJlZm9yZSBpdCdzIGludm9rZWQuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy50cmFpbGluZz10cnVlXVxuICAgICAqICBTcGVjaWZ5IGludm9raW5nIG9uIHRoZSB0cmFpbGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGRlYm91bmNlZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogLy8gQXZvaWQgY29zdGx5IGNhbGN1bGF0aW9ucyB3aGlsZSB0aGUgd2luZG93IHNpemUgaXMgaW4gZmx1eC5cbiAgICAgKiBqUXVlcnkod2luZG93KS5vbigncmVzaXplJywgXy5kZWJvdW5jZShjYWxjdWxhdGVMYXlvdXQsIDE1MCkpO1xuICAgICAqXG4gICAgICogLy8gSW52b2tlIGBzZW5kTWFpbGAgd2hlbiBjbGlja2VkLCBkZWJvdW5jaW5nIHN1YnNlcXVlbnQgY2FsbHMuXG4gICAgICogalF1ZXJ5KGVsZW1lbnQpLm9uKCdjbGljaycsIF8uZGVib3VuY2Uoc2VuZE1haWwsIDMwMCwge1xuICAgICAqICAgJ2xlYWRpbmcnOiB0cnVlLFxuICAgICAqICAgJ3RyYWlsaW5nJzogZmFsc2VcbiAgICAgKiB9KSk7XG4gICAgICpcbiAgICAgKiAvLyBFbnN1cmUgYGJhdGNoTG9nYCBpcyBpbnZva2VkIG9uY2UgYWZ0ZXIgMSBzZWNvbmQgb2YgZGVib3VuY2VkIGNhbGxzLlxuICAgICAqIHZhciBkZWJvdW5jZWQgPSBfLmRlYm91bmNlKGJhdGNoTG9nLCAyNTAsIHsgJ21heFdhaXQnOiAxMDAwIH0pO1xuICAgICAqIHZhciBzb3VyY2UgPSBuZXcgRXZlbnRTb3VyY2UoJy9zdHJlYW0nKTtcbiAgICAgKiBqUXVlcnkoc291cmNlKS5vbignbWVzc2FnZScsIGRlYm91bmNlZCk7XG4gICAgICpcbiAgICAgKiAvLyBDYW5jZWwgdGhlIHRyYWlsaW5nIGRlYm91bmNlZCBpbnZvY2F0aW9uLlxuICAgICAqIGpRdWVyeSh3aW5kb3cpLm9uKCdwb3BzdGF0ZScsIGRlYm91bmNlZC5jYW5jZWwpO1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGRlYm91bmNlKGZ1bmMsIHdhaXQsIG9wdGlvbnMpIHtcbiAgICAgIHZhciBsYXN0QXJncyxcbiAgICAgICAgICBsYXN0VGhpcyxcbiAgICAgICAgICBtYXhXYWl0LFxuICAgICAgICAgIHJlc3VsdCxcbiAgICAgICAgICB0aW1lcklkLFxuICAgICAgICAgIGxhc3RDYWxsVGltZSxcbiAgICAgICAgICBsYXN0SW52b2tlVGltZSA9IDAsXG4gICAgICAgICAgbGVhZGluZyA9IGZhbHNlLFxuICAgICAgICAgIG1heGluZyA9IGZhbHNlLFxuICAgICAgICAgIHRyYWlsaW5nID0gdHJ1ZTtcblxuICAgICAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgfVxuICAgICAgd2FpdCA9IHRvTnVtYmVyKHdhaXQpIHx8IDA7XG4gICAgICBpZiAoaXNPYmplY3Qob3B0aW9ucykpIHtcbiAgICAgICAgbGVhZGluZyA9ICEhb3B0aW9ucy5sZWFkaW5nO1xuICAgICAgICBtYXhpbmcgPSAnbWF4V2FpdCcgaW4gb3B0aW9ucztcbiAgICAgICAgbWF4V2FpdCA9IG1heGluZyA/IG5hdGl2ZU1heCh0b051bWJlcihvcHRpb25zLm1heFdhaXQpIHx8IDAsIHdhaXQpIDogbWF4V2FpdDtcbiAgICAgICAgdHJhaWxpbmcgPSAndHJhaWxpbmcnIGluIG9wdGlvbnMgPyAhIW9wdGlvbnMudHJhaWxpbmcgOiB0cmFpbGluZztcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gaW52b2tlRnVuYyh0aW1lKSB7XG4gICAgICAgIHZhciBhcmdzID0gbGFzdEFyZ3MsXG4gICAgICAgICAgICB0aGlzQXJnID0gbGFzdFRoaXM7XG5cbiAgICAgICAgbGFzdEFyZ3MgPSBsYXN0VGhpcyA9IHVuZGVmaW5lZDtcbiAgICAgICAgbGFzdEludm9rZVRpbWUgPSB0aW1lO1xuICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KHRoaXNBcmcsIGFyZ3MpO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBsZWFkaW5nRWRnZSh0aW1lKSB7XG4gICAgICAgIC8vIFJlc2V0IGFueSBgbWF4V2FpdGAgdGltZXIuXG4gICAgICAgIGxhc3RJbnZva2VUaW1lID0gdGltZTtcbiAgICAgICAgLy8gU3RhcnQgdGhlIHRpbWVyIGZvciB0aGUgdHJhaWxpbmcgZWRnZS5cbiAgICAgICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCB3YWl0KTtcbiAgICAgICAgLy8gSW52b2tlIHRoZSBsZWFkaW5nIGVkZ2UuXG4gICAgICAgIHJldHVybiBsZWFkaW5nID8gaW52b2tlRnVuYyh0aW1lKSA6IHJlc3VsdDtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gcmVtYWluaW5nV2FpdCh0aW1lKSB7XG4gICAgICAgIHZhciB0aW1lU2luY2VMYXN0Q2FsbCA9IHRpbWUgLSBsYXN0Q2FsbFRpbWUsXG4gICAgICAgICAgICB0aW1lU2luY2VMYXN0SW52b2tlID0gdGltZSAtIGxhc3RJbnZva2VUaW1lLFxuICAgICAgICAgICAgcmVzdWx0ID0gd2FpdCAtIHRpbWVTaW5jZUxhc3RDYWxsO1xuXG4gICAgICAgIHJldHVybiBtYXhpbmcgPyBuYXRpdmVNaW4ocmVzdWx0LCBtYXhXYWl0IC0gdGltZVNpbmNlTGFzdEludm9rZSkgOiByZXN1bHQ7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIHNob3VsZEludm9rZSh0aW1lKSB7XG4gICAgICAgIHZhciB0aW1lU2luY2VMYXN0Q2FsbCA9IHRpbWUgLSBsYXN0Q2FsbFRpbWUsXG4gICAgICAgICAgICB0aW1lU2luY2VMYXN0SW52b2tlID0gdGltZSAtIGxhc3RJbnZva2VUaW1lO1xuXG4gICAgICAgIC8vIEVpdGhlciB0aGlzIGlzIHRoZSBmaXJzdCBjYWxsLCBhY3Rpdml0eSBoYXMgc3RvcHBlZCBhbmQgd2UncmUgYXQgdGhlXG4gICAgICAgIC8vIHRyYWlsaW5nIGVkZ2UsIHRoZSBzeXN0ZW0gdGltZSBoYXMgZ29uZSBiYWNrd2FyZHMgYW5kIHdlJ3JlIHRyZWF0aW5nXG4gICAgICAgIC8vIGl0IGFzIHRoZSB0cmFpbGluZyBlZGdlLCBvciB3ZSd2ZSBoaXQgdGhlIGBtYXhXYWl0YCBsaW1pdC5cbiAgICAgICAgcmV0dXJuIChsYXN0Q2FsbFRpbWUgPT09IHVuZGVmaW5lZCB8fCAodGltZVNpbmNlTGFzdENhbGwgPj0gd2FpdCkgfHxcbiAgICAgICAgICAodGltZVNpbmNlTGFzdENhbGwgPCAwKSB8fCAobWF4aW5nICYmIHRpbWVTaW5jZUxhc3RJbnZva2UgPj0gbWF4V2FpdCkpO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiB0aW1lckV4cGlyZWQoKSB7XG4gICAgICAgIHZhciB0aW1lID0gbm93KCk7XG4gICAgICAgIGlmIChzaG91bGRJbnZva2UodGltZSkpIHtcbiAgICAgICAgICByZXR1cm4gdHJhaWxpbmdFZGdlKHRpbWUpO1xuICAgICAgICB9XG4gICAgICAgIC8vIFJlc3RhcnQgdGhlIHRpbWVyLlxuICAgICAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHJlbWFpbmluZ1dhaXQodGltZSkpO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiB0cmFpbGluZ0VkZ2UodGltZSkge1xuICAgICAgICB0aW1lcklkID0gdW5kZWZpbmVkO1xuXG4gICAgICAgIC8vIE9ubHkgaW52b2tlIGlmIHdlIGhhdmUgYGxhc3RBcmdzYCB3aGljaCBtZWFucyBgZnVuY2AgaGFzIGJlZW5cbiAgICAgICAgLy8gZGVib3VuY2VkIGF0IGxlYXN0IG9uY2UuXG4gICAgICAgIGlmICh0cmFpbGluZyAmJiBsYXN0QXJncykge1xuICAgICAgICAgIHJldHVybiBpbnZva2VGdW5jKHRpbWUpO1xuICAgICAgICB9XG4gICAgICAgIGxhc3RBcmdzID0gbGFzdFRoaXMgPSB1bmRlZmluZWQ7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGNhbmNlbCgpIHtcbiAgICAgICAgaWYgKHRpbWVySWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lcklkKTtcbiAgICAgICAgfVxuICAgICAgICBsYXN0SW52b2tlVGltZSA9IDA7XG4gICAgICAgIGxhc3RBcmdzID0gbGFzdENhbGxUaW1lID0gbGFzdFRoaXMgPSB0aW1lcklkID0gdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBmbHVzaCgpIHtcbiAgICAgICAgcmV0dXJuIHRpbWVySWQgPT09IHVuZGVmaW5lZCA/IHJlc3VsdCA6IHRyYWlsaW5nRWRnZShub3coKSk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGRlYm91bmNlZCgpIHtcbiAgICAgICAgdmFyIHRpbWUgPSBub3coKSxcbiAgICAgICAgICAgIGlzSW52b2tpbmcgPSBzaG91bGRJbnZva2UodGltZSk7XG5cbiAgICAgICAgbGFzdEFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgIGxhc3RUaGlzID0gdGhpcztcbiAgICAgICAgbGFzdENhbGxUaW1lID0gdGltZTtcblxuICAgICAgICBpZiAoaXNJbnZva2luZykge1xuICAgICAgICAgIGlmICh0aW1lcklkID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBsZWFkaW5nRWRnZShsYXN0Q2FsbFRpbWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAobWF4aW5nKSB7XG4gICAgICAgICAgICAvLyBIYW5kbGUgaW52b2NhdGlvbnMgaW4gYSB0aWdodCBsb29wLlxuICAgICAgICAgICAgdGltZXJJZCA9IHNldFRpbWVvdXQodGltZXJFeHBpcmVkLCB3YWl0KTtcbiAgICAgICAgICAgIHJldHVybiBpbnZva2VGdW5jKGxhc3RDYWxsVGltZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0aW1lcklkID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHdhaXQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgICBkZWJvdW5jZWQuY2FuY2VsID0gY2FuY2VsO1xuICAgICAgZGVib3VuY2VkLmZsdXNoID0gZmx1c2g7XG4gICAgICByZXR1cm4gZGVib3VuY2VkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERlZmVycyBpbnZva2luZyB0aGUgYGZ1bmNgIHVudGlsIHRoZSBjdXJyZW50IGNhbGwgc3RhY2sgaGFzIGNsZWFyZWQuIEFueVxuICAgICAqIGFkZGl0aW9uYWwgYXJndW1lbnRzIGFyZSBwcm92aWRlZCB0byBgZnVuY2Agd2hlbiBpdCdzIGludm9rZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBkZWZlci5cbiAgICAgKiBAcGFyYW0gey4uLip9IFthcmdzXSBUaGUgYXJndW1lbnRzIHRvIGludm9rZSBgZnVuY2Agd2l0aC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSB0aW1lciBpZC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5kZWZlcihmdW5jdGlvbih0ZXh0KSB7XG4gICAgICogICBjb25zb2xlLmxvZyh0ZXh0KTtcbiAgICAgKiB9LCAnZGVmZXJyZWQnKTtcbiAgICAgKiAvLyA9PiBMb2dzICdkZWZlcnJlZCcgYWZ0ZXIgb25lIG1pbGxpc2Vjb25kLlxuICAgICAqL1xuICAgIHZhciBkZWZlciA9IGJhc2VSZXN0KGZ1bmN0aW9uKGZ1bmMsIGFyZ3MpIHtcbiAgICAgIHJldHVybiBiYXNlRGVsYXkoZnVuYywgMSwgYXJncyk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBJbnZva2VzIGBmdW5jYCBhZnRlciBgd2FpdGAgbWlsbGlzZWNvbmRzLiBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgYXJlXG4gICAgICogcHJvdmlkZWQgdG8gYGZ1bmNgIHdoZW4gaXQncyBpbnZva2VkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gZGVsYXkuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHdhaXQgVGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gZGVsYXkgaW52b2NhdGlvbi5cbiAgICAgKiBAcGFyYW0gey4uLip9IFthcmdzXSBUaGUgYXJndW1lbnRzIHRvIGludm9rZSBgZnVuY2Agd2l0aC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSB0aW1lciBpZC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5kZWxheShmdW5jdGlvbih0ZXh0KSB7XG4gICAgICogICBjb25zb2xlLmxvZyh0ZXh0KTtcbiAgICAgKiB9LCAxMDAwLCAnbGF0ZXInKTtcbiAgICAgKiAvLyA9PiBMb2dzICdsYXRlcicgYWZ0ZXIgb25lIHNlY29uZC5cbiAgICAgKi9cbiAgICB2YXIgZGVsYXkgPSBiYXNlUmVzdChmdW5jdGlvbihmdW5jLCB3YWl0LCBhcmdzKSB7XG4gICAgICByZXR1cm4gYmFzZURlbGF5KGZ1bmMsIHRvTnVtYmVyKHdhaXQpIHx8IDAsIGFyZ3MpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBgZnVuY2Agd2l0aCBhcmd1bWVudHMgcmV2ZXJzZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBmbGlwIGFyZ3VtZW50cyBmb3IuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZmxpcHBlZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGZsaXBwZWQgPSBfLmZsaXAoZnVuY3Rpb24oKSB7XG4gICAgICogICByZXR1cm4gXy50b0FycmF5KGFyZ3VtZW50cyk7XG4gICAgICogfSk7XG4gICAgICpcbiAgICAgKiBmbGlwcGVkKCdhJywgJ2InLCAnYycsICdkJyk7XG4gICAgICogLy8gPT4gWydkJywgJ2MnLCAnYicsICdhJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmbGlwKGZ1bmMpIHtcbiAgICAgIHJldHVybiBjcmVhdGVXcmFwKGZ1bmMsIFdSQVBfRkxJUF9GTEFHKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBtZW1vaXplcyB0aGUgcmVzdWx0IG9mIGBmdW5jYC4gSWYgYHJlc29sdmVyYCBpc1xuICAgICAqIHByb3ZpZGVkLCBpdCBkZXRlcm1pbmVzIHRoZSBjYWNoZSBrZXkgZm9yIHN0b3JpbmcgdGhlIHJlc3VsdCBiYXNlZCBvbiB0aGVcbiAgICAgKiBhcmd1bWVudHMgcHJvdmlkZWQgdG8gdGhlIG1lbW9pemVkIGZ1bmN0aW9uLiBCeSBkZWZhdWx0LCB0aGUgZmlyc3QgYXJndW1lbnRcbiAgICAgKiBwcm92aWRlZCB0byB0aGUgbWVtb2l6ZWQgZnVuY3Rpb24gaXMgdXNlZCBhcyB0aGUgbWFwIGNhY2hlIGtleS4gVGhlIGBmdW5jYFxuICAgICAqIGlzIGludm9rZWQgd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgb2YgdGhlIG1lbW9pemVkIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoZSBjYWNoZSBpcyBleHBvc2VkIGFzIHRoZSBgY2FjaGVgIHByb3BlcnR5IG9uIHRoZSBtZW1vaXplZFxuICAgICAqIGZ1bmN0aW9uLiBJdHMgY3JlYXRpb24gbWF5IGJlIGN1c3RvbWl6ZWQgYnkgcmVwbGFjaW5nIHRoZSBgXy5tZW1vaXplLkNhY2hlYFxuICAgICAqIGNvbnN0cnVjdG9yIHdpdGggb25lIHdob3NlIGluc3RhbmNlcyBpbXBsZW1lbnQgdGhlXG4gICAgICogW2BNYXBgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1wcm9wZXJ0aWVzLW9mLXRoZS1tYXAtcHJvdG90eXBlLW9iamVjdClcbiAgICAgKiBtZXRob2QgaW50ZXJmYWNlIG9mIGBjbGVhcmAsIGBkZWxldGVgLCBgZ2V0YCwgYGhhc2AsIGFuZCBgc2V0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGhhdmUgaXRzIG91dHB1dCBtZW1vaXplZC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcmVzb2x2ZXJdIFRoZSBmdW5jdGlvbiB0byByZXNvbHZlIHRoZSBjYWNoZSBrZXkuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgbWVtb2l6ZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogMSwgJ2InOiAyIH07XG4gICAgICogdmFyIG90aGVyID0geyAnYyc6IDMsICdkJzogNCB9O1xuICAgICAqXG4gICAgICogdmFyIHZhbHVlcyA9IF8ubWVtb2l6ZShfLnZhbHVlcyk7XG4gICAgICogdmFsdWVzKG9iamVjdCk7XG4gICAgICogLy8gPT4gWzEsIDJdXG4gICAgICpcbiAgICAgKiB2YWx1ZXMob3RoZXIpO1xuICAgICAqIC8vID0+IFszLCA0XVxuICAgICAqXG4gICAgICogb2JqZWN0LmEgPSAyO1xuICAgICAqIHZhbHVlcyhvYmplY3QpO1xuICAgICAqIC8vID0+IFsxLCAyXVxuICAgICAqXG4gICAgICogLy8gTW9kaWZ5IHRoZSByZXN1bHQgY2FjaGUuXG4gICAgICogdmFsdWVzLmNhY2hlLnNldChvYmplY3QsIFsnYScsICdiJ10pO1xuICAgICAqIHZhbHVlcyhvYmplY3QpO1xuICAgICAqIC8vID0+IFsnYScsICdiJ11cbiAgICAgKlxuICAgICAqIC8vIFJlcGxhY2UgYF8ubWVtb2l6ZS5DYWNoZWAuXG4gICAgICogXy5tZW1vaXplLkNhY2hlID0gV2Vha01hcDtcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtZW1vaXplKGZ1bmMsIHJlc29sdmVyKSB7XG4gICAgICBpZiAodHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJyB8fCAocmVzb2x2ZXIgIT0gbnVsbCAmJiB0eXBlb2YgcmVzb2x2ZXIgIT0gJ2Z1bmN0aW9uJykpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgfVxuICAgICAgdmFyIG1lbW9pemVkID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzLFxuICAgICAgICAgICAga2V5ID0gcmVzb2x2ZXIgPyByZXNvbHZlci5hcHBseSh0aGlzLCBhcmdzKSA6IGFyZ3NbMF0sXG4gICAgICAgICAgICBjYWNoZSA9IG1lbW9pemVkLmNhY2hlO1xuXG4gICAgICAgIGlmIChjYWNoZS5oYXMoa2V5KSkge1xuICAgICAgICAgIHJldHVybiBjYWNoZS5nZXQoa2V5KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmVzdWx0ID0gZnVuYy5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgbWVtb2l6ZWQuY2FjaGUgPSBjYWNoZS5zZXQoa2V5LCByZXN1bHQpIHx8IGNhY2hlO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfTtcbiAgICAgIG1lbW9pemVkLmNhY2hlID0gbmV3IChtZW1vaXplLkNhY2hlIHx8IE1hcENhY2hlKTtcbiAgICAgIHJldHVybiBtZW1vaXplZDtcbiAgICB9XG5cbiAgICAvLyBFeHBvc2UgYE1hcENhY2hlYC5cbiAgICBtZW1vaXplLkNhY2hlID0gTWFwQ2FjaGU7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBuZWdhdGVzIHRoZSByZXN1bHQgb2YgdGhlIHByZWRpY2F0ZSBgZnVuY2AuIFRoZVxuICAgICAqIGBmdW5jYCBwcmVkaWNhdGUgaXMgaW52b2tlZCB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBhbmQgYXJndW1lbnRzIG9mIHRoZVxuICAgICAqIGNyZWF0ZWQgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIHByZWRpY2F0ZSB0byBuZWdhdGUuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgbmVnYXRlZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gaXNFdmVuKG4pIHtcbiAgICAgKiAgIHJldHVybiBuICUgMiA9PSAwO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIF8uZmlsdGVyKFsxLCAyLCAzLCA0LCA1LCA2XSwgXy5uZWdhdGUoaXNFdmVuKSk7XG4gICAgICogLy8gPT4gWzEsIDMsIDVdXG4gICAgICovXG4gICAgZnVuY3Rpb24gbmVnYXRlKHByZWRpY2F0ZSkge1xuICAgICAgaWYgKHR5cGVvZiBwcmVkaWNhdGUgIT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgICBzd2l0Y2ggKGFyZ3MubGVuZ3RoKSB7XG4gICAgICAgICAgY2FzZSAwOiByZXR1cm4gIXByZWRpY2F0ZS5jYWxsKHRoaXMpO1xuICAgICAgICAgIGNhc2UgMTogcmV0dXJuICFwcmVkaWNhdGUuY2FsbCh0aGlzLCBhcmdzWzBdKTtcbiAgICAgICAgICBjYXNlIDI6IHJldHVybiAhcHJlZGljYXRlLmNhbGwodGhpcywgYXJnc1swXSwgYXJnc1sxXSk7XG4gICAgICAgICAgY2FzZSAzOiByZXR1cm4gIXByZWRpY2F0ZS5jYWxsKHRoaXMsIGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAhcHJlZGljYXRlLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpcyByZXN0cmljdGVkIHRvIGludm9raW5nIGBmdW5jYCBvbmNlLiBSZXBlYXQgY2FsbHNcbiAgICAgKiB0byB0aGUgZnVuY3Rpb24gcmV0dXJuIHRoZSB2YWx1ZSBvZiB0aGUgZmlyc3QgaW52b2NhdGlvbi4gVGhlIGBmdW5jYCBpc1xuICAgICAqIGludm9rZWQgd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgYW5kIGFyZ3VtZW50cyBvZiB0aGUgY3JlYXRlZCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHJlc3RyaWN0LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHJlc3RyaWN0ZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBpbml0aWFsaXplID0gXy5vbmNlKGNyZWF0ZUFwcGxpY2F0aW9uKTtcbiAgICAgKiBpbml0aWFsaXplKCk7XG4gICAgICogaW5pdGlhbGl6ZSgpO1xuICAgICAqIC8vID0+IGBjcmVhdGVBcHBsaWNhdGlvbmAgaXMgaW52b2tlZCBvbmNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gb25jZShmdW5jKSB7XG4gICAgICByZXR1cm4gYmVmb3JlKDIsIGZ1bmMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgYGZ1bmNgIHdpdGggaXRzIGFyZ3VtZW50cyB0cmFuc2Zvcm1lZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHdyYXAuXG4gICAgICogQHBhcmFtIHsuLi4oRnVuY3Rpb258RnVuY3Rpb25bXSl9IFt0cmFuc2Zvcm1zPVtfLmlkZW50aXR5XV1cbiAgICAgKiAgVGhlIGFyZ3VtZW50IHRyYW5zZm9ybXMuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGRvdWJsZWQobikge1xuICAgICAqICAgcmV0dXJuIG4gKiAyO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIHNxdWFyZShuKSB7XG4gICAgICogICByZXR1cm4gbiAqIG47XG4gICAgICogfVxuICAgICAqXG4gICAgICogdmFyIGZ1bmMgPSBfLm92ZXJBcmdzKGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgKiAgIHJldHVybiBbeCwgeV07XG4gICAgICogfSwgW3NxdWFyZSwgZG91YmxlZF0pO1xuICAgICAqXG4gICAgICogZnVuYyg5LCAzKTtcbiAgICAgKiAvLyA9PiBbODEsIDZdXG4gICAgICpcbiAgICAgKiBmdW5jKDEwLCA1KTtcbiAgICAgKiAvLyA9PiBbMTAwLCAxMF1cbiAgICAgKi9cbiAgICB2YXIgb3ZlckFyZ3MgPSBjYXN0UmVzdChmdW5jdGlvbihmdW5jLCB0cmFuc2Zvcm1zKSB7XG4gICAgICB0cmFuc2Zvcm1zID0gKHRyYW5zZm9ybXMubGVuZ3RoID09IDEgJiYgaXNBcnJheSh0cmFuc2Zvcm1zWzBdKSlcbiAgICAgICAgPyBhcnJheU1hcCh0cmFuc2Zvcm1zWzBdLCBiYXNlVW5hcnkoZ2V0SXRlcmF0ZWUoKSkpXG4gICAgICAgIDogYXJyYXlNYXAoYmFzZUZsYXR0ZW4odHJhbnNmb3JtcywgMSksIGJhc2VVbmFyeShnZXRJdGVyYXRlZSgpKSk7XG5cbiAgICAgIHZhciBmdW5jc0xlbmd0aCA9IHRyYW5zZm9ybXMubGVuZ3RoO1xuICAgICAgcmV0dXJuIGJhc2VSZXN0KGZ1bmN0aW9uKGFyZ3MpIHtcbiAgICAgICAgdmFyIGluZGV4ID0gLTEsXG4gICAgICAgICAgICBsZW5ndGggPSBuYXRpdmVNaW4oYXJncy5sZW5ndGgsIGZ1bmNzTGVuZ3RoKTtcblxuICAgICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICAgIGFyZ3NbaW5kZXhdID0gdHJhbnNmb3Jtc1tpbmRleF0uY2FsbCh0aGlzLCBhcmdzW2luZGV4XSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFwcGx5KGZ1bmMsIHRoaXMsIGFyZ3MpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIGBmdW5jYCB3aXRoIGBwYXJ0aWFsc2AgcHJlcGVuZGVkIHRvIHRoZVxuICAgICAqIGFyZ3VtZW50cyBpdCByZWNlaXZlcy4gVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5iaW5kYCBleGNlcHQgaXQgZG9lcyAqKm5vdCoqXG4gICAgICogYWx0ZXIgdGhlIGB0aGlzYCBiaW5kaW5nLlxuICAgICAqXG4gICAgICogVGhlIGBfLnBhcnRpYWwucGxhY2Vob2xkZXJgIHZhbHVlLCB3aGljaCBkZWZhdWx0cyB0byBgX2AgaW4gbW9ub2xpdGhpY1xuICAgICAqIGJ1aWxkcywgbWF5IGJlIHVzZWQgYXMgYSBwbGFjZWhvbGRlciBmb3IgcGFydGlhbGx5IGFwcGxpZWQgYXJndW1lbnRzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGRvZXNuJ3Qgc2V0IHRoZSBcImxlbmd0aFwiIHByb3BlcnR5IG9mIHBhcnRpYWxseVxuICAgICAqIGFwcGxpZWQgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMi4wXG4gICAgICogQGNhdGVnb3J5IEZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcGFydGlhbGx5IGFwcGx5IGFyZ3VtZW50cyB0by5cbiAgICAgKiBAcGFyYW0gey4uLip9IFtwYXJ0aWFsc10gVGhlIGFyZ3VtZW50cyB0byBiZSBwYXJ0aWFsbHkgYXBwbGllZC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBwYXJ0aWFsbHkgYXBwbGllZCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gZ3JlZXQoZ3JlZXRpbmcsIG5hbWUpIHtcbiAgICAgKiAgIHJldHVybiBncmVldGluZyArICcgJyArIG5hbWU7XG4gICAgICogfVxuICAgICAqXG4gICAgICogdmFyIHNheUhlbGxvVG8gPSBfLnBhcnRpYWwoZ3JlZXQsICdoZWxsbycpO1xuICAgICAqIHNheUhlbGxvVG8oJ2ZyZWQnKTtcbiAgICAgKiAvLyA9PiAnaGVsbG8gZnJlZCdcbiAgICAgKlxuICAgICAqIC8vIFBhcnRpYWxseSBhcHBsaWVkIHdpdGggcGxhY2Vob2xkZXJzLlxuICAgICAqIHZhciBncmVldEZyZWQgPSBfLnBhcnRpYWwoZ3JlZXQsIF8sICdmcmVkJyk7XG4gICAgICogZ3JlZXRGcmVkKCdoaScpO1xuICAgICAqIC8vID0+ICdoaSBmcmVkJ1xuICAgICAqL1xuICAgIHZhciBwYXJ0aWFsID0gYmFzZVJlc3QoZnVuY3Rpb24oZnVuYywgcGFydGlhbHMpIHtcbiAgICAgIHZhciBob2xkZXJzID0gcmVwbGFjZUhvbGRlcnMocGFydGlhbHMsIGdldEhvbGRlcihwYXJ0aWFsKSk7XG4gICAgICByZXR1cm4gY3JlYXRlV3JhcChmdW5jLCBXUkFQX1BBUlRJQUxfRkxBRywgdW5kZWZpbmVkLCBwYXJ0aWFscywgaG9sZGVycyk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnBhcnRpYWxgIGV4Y2VwdCB0aGF0IHBhcnRpYWxseSBhcHBsaWVkIGFyZ3VtZW50c1xuICAgICAqIGFyZSBhcHBlbmRlZCB0byB0aGUgYXJndW1lbnRzIGl0IHJlY2VpdmVzLlxuICAgICAqXG4gICAgICogVGhlIGBfLnBhcnRpYWxSaWdodC5wbGFjZWhvbGRlcmAgdmFsdWUsIHdoaWNoIGRlZmF1bHRzIHRvIGBfYCBpbiBtb25vbGl0aGljXG4gICAgICogYnVpbGRzLCBtYXkgYmUgdXNlZCBhcyBhIHBsYWNlaG9sZGVyIGZvciBwYXJ0aWFsbHkgYXBwbGllZCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgZG9lc24ndCBzZXQgdGhlIFwibGVuZ3RoXCIgcHJvcGVydHkgb2YgcGFydGlhbGx5XG4gICAgICogYXBwbGllZCBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMS4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBwYXJ0aWFsbHkgYXBwbHkgYXJndW1lbnRzIHRvLlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW3BhcnRpYWxzXSBUaGUgYXJndW1lbnRzIHRvIGJlIHBhcnRpYWxseSBhcHBsaWVkLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHBhcnRpYWxseSBhcHBsaWVkIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBncmVldChncmVldGluZywgbmFtZSkge1xuICAgICAqICAgcmV0dXJuIGdyZWV0aW5nICsgJyAnICsgbmFtZTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgZ3JlZXRGcmVkID0gXy5wYXJ0aWFsUmlnaHQoZ3JlZXQsICdmcmVkJyk7XG4gICAgICogZ3JlZXRGcmVkKCdoaScpO1xuICAgICAqIC8vID0+ICdoaSBmcmVkJ1xuICAgICAqXG4gICAgICogLy8gUGFydGlhbGx5IGFwcGxpZWQgd2l0aCBwbGFjZWhvbGRlcnMuXG4gICAgICogdmFyIHNheUhlbGxvVG8gPSBfLnBhcnRpYWxSaWdodChncmVldCwgJ2hlbGxvJywgXyk7XG4gICAgICogc2F5SGVsbG9UbygnZnJlZCcpO1xuICAgICAqIC8vID0+ICdoZWxsbyBmcmVkJ1xuICAgICAqL1xuICAgIHZhciBwYXJ0aWFsUmlnaHQgPSBiYXNlUmVzdChmdW5jdGlvbihmdW5jLCBwYXJ0aWFscykge1xuICAgICAgdmFyIGhvbGRlcnMgPSByZXBsYWNlSG9sZGVycyhwYXJ0aWFscywgZ2V0SG9sZGVyKHBhcnRpYWxSaWdodCkpO1xuICAgICAgcmV0dXJuIGNyZWF0ZVdyYXAoZnVuYywgV1JBUF9QQVJUSUFMX1JJR0hUX0ZMQUcsIHVuZGVmaW5lZCwgcGFydGlhbHMsIGhvbGRlcnMpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBgZnVuY2Agd2l0aCBhcmd1bWVudHMgYXJyYW5nZWQgYWNjb3JkaW5nXG4gICAgICogdG8gdGhlIHNwZWNpZmllZCBgaW5kZXhlc2Agd2hlcmUgdGhlIGFyZ3VtZW50IHZhbHVlIGF0IHRoZSBmaXJzdCBpbmRleCBpc1xuICAgICAqIHByb3ZpZGVkIGFzIHRoZSBmaXJzdCBhcmd1bWVudCwgdGhlIGFyZ3VtZW50IHZhbHVlIGF0IHRoZSBzZWNvbmQgaW5kZXggaXNcbiAgICAgKiBwcm92aWRlZCBhcyB0aGUgc2Vjb25kIGFyZ3VtZW50LCBhbmQgc28gb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byByZWFycmFuZ2UgYXJndW1lbnRzIGZvci5cbiAgICAgKiBAcGFyYW0gey4uLihudW1iZXJ8bnVtYmVyW10pfSBpbmRleGVzIFRoZSBhcnJhbmdlZCBhcmd1bWVudCBpbmRleGVzLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgcmVhcmdlZCA9IF8ucmVhcmcoZnVuY3Rpb24oYSwgYiwgYykge1xuICAgICAqICAgcmV0dXJuIFthLCBiLCBjXTtcbiAgICAgKiB9LCBbMiwgMCwgMV0pO1xuICAgICAqXG4gICAgICogcmVhcmdlZCgnYicsICdjJywgJ2EnKVxuICAgICAqIC8vID0+IFsnYScsICdiJywgJ2MnXVxuICAgICAqL1xuICAgIHZhciByZWFyZyA9IGZsYXRSZXN0KGZ1bmN0aW9uKGZ1bmMsIGluZGV4ZXMpIHtcbiAgICAgIHJldHVybiBjcmVhdGVXcmFwKGZ1bmMsIFdSQVBfUkVBUkdfRkxBRywgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgaW5kZXhlcyk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIGBmdW5jYCB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBvZiB0aGVcbiAgICAgKiBjcmVhdGVkIGZ1bmN0aW9uIGFuZCBhcmd1bWVudHMgZnJvbSBgc3RhcnRgIGFuZCBiZXlvbmQgcHJvdmlkZWQgYXNcbiAgICAgKiBhbiBhcnJheS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBiYXNlZCBvbiB0aGVcbiAgICAgKiBbcmVzdCBwYXJhbWV0ZXJdKGh0dHBzOi8vbWRuLmlvL3Jlc3RfcGFyYW1ldGVycykuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBhcHBseSBhIHJlc3QgcGFyYW1ldGVyIHRvLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbc3RhcnQ9ZnVuYy5sZW5ndGgtMV0gVGhlIHN0YXJ0IHBvc2l0aW9uIG9mIHRoZSByZXN0IHBhcmFtZXRlci5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHNheSA9IF8ucmVzdChmdW5jdGlvbih3aGF0LCBuYW1lcykge1xuICAgICAqICAgcmV0dXJuIHdoYXQgKyAnICcgKyBfLmluaXRpYWwobmFtZXMpLmpvaW4oJywgJykgK1xuICAgICAqICAgICAoXy5zaXplKG5hbWVzKSA+IDEgPyAnLCAmICcgOiAnJykgKyBfLmxhc3QobmFtZXMpO1xuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogc2F5KCdoZWxsbycsICdmcmVkJywgJ2Jhcm5leScsICdwZWJibGVzJyk7XG4gICAgICogLy8gPT4gJ2hlbGxvIGZyZWQsIGJhcm5leSwgJiBwZWJibGVzJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJlc3QoZnVuYywgc3RhcnQpIHtcbiAgICAgIGlmICh0eXBlb2YgZnVuYyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgICAgIH1cbiAgICAgIHN0YXJ0ID0gc3RhcnQgPT09IHVuZGVmaW5lZCA/IHN0YXJ0IDogdG9JbnRlZ2VyKHN0YXJ0KTtcbiAgICAgIHJldHVybiBiYXNlUmVzdChmdW5jLCBzdGFydCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBgZnVuY2Agd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgb2YgdGhlXG4gICAgICogY3JlYXRlIGZ1bmN0aW9uIGFuZCBhbiBhcnJheSBvZiBhcmd1bWVudHMgbXVjaCBsaWtlXG4gICAgICogW2BGdW5jdGlvbiNhcHBseWBdKGh0dHA6Ly93d3cuZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1mdW5jdGlvbi5wcm90b3R5cGUuYXBwbHkpLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGlzIGJhc2VkIG9uIHRoZVxuICAgICAqIFtzcHJlYWQgb3BlcmF0b3JdKGh0dHBzOi8vbWRuLmlvL3NwcmVhZF9vcGVyYXRvcikuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4yLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBzcHJlYWQgYXJndW1lbnRzIG92ZXIuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGFydD0wXSBUaGUgc3RhcnQgcG9zaXRpb24gb2YgdGhlIHNwcmVhZC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHNheSA9IF8uc3ByZWFkKGZ1bmN0aW9uKHdobywgd2hhdCkge1xuICAgICAqICAgcmV0dXJuIHdobyArICcgc2F5cyAnICsgd2hhdDtcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIHNheShbJ2ZyZWQnLCAnaGVsbG8nXSk7XG4gICAgICogLy8gPT4gJ2ZyZWQgc2F5cyBoZWxsbydcbiAgICAgKlxuICAgICAqIHZhciBudW1iZXJzID0gUHJvbWlzZS5hbGwoW1xuICAgICAqICAgUHJvbWlzZS5yZXNvbHZlKDQwKSxcbiAgICAgKiAgIFByb21pc2UucmVzb2x2ZSgzNilcbiAgICAgKiBdKTtcbiAgICAgKlxuICAgICAqIG51bWJlcnMudGhlbihfLnNwcmVhZChmdW5jdGlvbih4LCB5KSB7XG4gICAgICogICByZXR1cm4geCArIHk7XG4gICAgICogfSkpO1xuICAgICAqIC8vID0+IGEgUHJvbWlzZSBvZiA3NlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNwcmVhZChmdW5jLCBzdGFydCkge1xuICAgICAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihGVU5DX0VSUk9SX1RFWFQpO1xuICAgICAgfVxuICAgICAgc3RhcnQgPSBzdGFydCA9PSBudWxsID8gMCA6IG5hdGl2ZU1heCh0b0ludGVnZXIoc3RhcnQpLCAwKTtcbiAgICAgIHJldHVybiBiYXNlUmVzdChmdW5jdGlvbihhcmdzKSB7XG4gICAgICAgIHZhciBhcnJheSA9IGFyZ3Nbc3RhcnRdLFxuICAgICAgICAgICAgb3RoZXJBcmdzID0gY2FzdFNsaWNlKGFyZ3MsIDAsIHN0YXJ0KTtcblxuICAgICAgICBpZiAoYXJyYXkpIHtcbiAgICAgICAgICBhcnJheVB1c2gob3RoZXJBcmdzLCBhcnJheSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFwcGx5KGZ1bmMsIHRoaXMsIG90aGVyQXJncyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgdGhyb3R0bGVkIGZ1bmN0aW9uIHRoYXQgb25seSBpbnZva2VzIGBmdW5jYCBhdCBtb3N0IG9uY2UgcGVyXG4gICAgICogZXZlcnkgYHdhaXRgIG1pbGxpc2Vjb25kcy4gVGhlIHRocm90dGxlZCBmdW5jdGlvbiBjb21lcyB3aXRoIGEgYGNhbmNlbGBcbiAgICAgKiBtZXRob2QgdG8gY2FuY2VsIGRlbGF5ZWQgYGZ1bmNgIGludm9jYXRpb25zIGFuZCBhIGBmbHVzaGAgbWV0aG9kIHRvXG4gICAgICogaW1tZWRpYXRlbHkgaW52b2tlIHRoZW0uIFByb3ZpZGUgYG9wdGlvbnNgIHRvIGluZGljYXRlIHdoZXRoZXIgYGZ1bmNgXG4gICAgICogc2hvdWxkIGJlIGludm9rZWQgb24gdGhlIGxlYWRpbmcgYW5kL29yIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIGB3YWl0YFxuICAgICAqIHRpbWVvdXQuIFRoZSBgZnVuY2AgaXMgaW52b2tlZCB3aXRoIHRoZSBsYXN0IGFyZ3VtZW50cyBwcm92aWRlZCB0byB0aGVcbiAgICAgKiB0aHJvdHRsZWQgZnVuY3Rpb24uIFN1YnNlcXVlbnQgY2FsbHMgdG8gdGhlIHRocm90dGxlZCBmdW5jdGlvbiByZXR1cm4gdGhlXG4gICAgICogcmVzdWx0IG9mIHRoZSBsYXN0IGBmdW5jYCBpbnZvY2F0aW9uLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIElmIGBsZWFkaW5nYCBhbmQgYHRyYWlsaW5nYCBvcHRpb25zIGFyZSBgdHJ1ZWAsIGBmdW5jYCBpc1xuICAgICAqIGludm9rZWQgb24gdGhlIHRyYWlsaW5nIGVkZ2Ugb2YgdGhlIHRpbWVvdXQgb25seSBpZiB0aGUgdGhyb3R0bGVkIGZ1bmN0aW9uXG4gICAgICogaXMgaW52b2tlZCBtb3JlIHRoYW4gb25jZSBkdXJpbmcgdGhlIGB3YWl0YCB0aW1lb3V0LlxuICAgICAqXG4gICAgICogSWYgYHdhaXRgIGlzIGAwYCBhbmQgYGxlYWRpbmdgIGlzIGBmYWxzZWAsIGBmdW5jYCBpbnZvY2F0aW9uIGlzIGRlZmVycmVkXG4gICAgICogdW50aWwgdG8gdGhlIG5leHQgdGljaywgc2ltaWxhciB0byBgc2V0VGltZW91dGAgd2l0aCBhIHRpbWVvdXQgb2YgYDBgLlxuICAgICAqXG4gICAgICogU2VlIFtEYXZpZCBDb3JiYWNobydzIGFydGljbGVdKGh0dHBzOi8vY3NzLXRyaWNrcy5jb20vZGVib3VuY2luZy10aHJvdHRsaW5nLWV4cGxhaW5lZC1leGFtcGxlcy8pXG4gICAgICogZm9yIGRldGFpbHMgb3ZlciB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBgXy50aHJvdHRsZWAgYW5kIGBfLmRlYm91bmNlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHRocm90dGxlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbd2FpdD0wXSBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byB0aHJvdHRsZSBpbnZvY2F0aW9ucyB0by5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIFRoZSBvcHRpb25zIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmxlYWRpbmc9dHJ1ZV1cbiAgICAgKiAgU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgbGVhZGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0LlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMudHJhaWxpbmc9dHJ1ZV1cbiAgICAgKiAgU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgdHJhaWxpbmcgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyB0aHJvdHRsZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIC8vIEF2b2lkIGV4Y2Vzc2l2ZWx5IHVwZGF0aW5nIHRoZSBwb3NpdGlvbiB3aGlsZSBzY3JvbGxpbmcuXG4gICAgICogalF1ZXJ5KHdpbmRvdykub24oJ3Njcm9sbCcsIF8udGhyb3R0bGUodXBkYXRlUG9zaXRpb24sIDEwMCkpO1xuICAgICAqXG4gICAgICogLy8gSW52b2tlIGByZW5ld1Rva2VuYCB3aGVuIHRoZSBjbGljayBldmVudCBpcyBmaXJlZCwgYnV0IG5vdCBtb3JlIHRoYW4gb25jZSBldmVyeSA1IG1pbnV0ZXMuXG4gICAgICogdmFyIHRocm90dGxlZCA9IF8udGhyb3R0bGUocmVuZXdUb2tlbiwgMzAwMDAwLCB7ICd0cmFpbGluZyc6IGZhbHNlIH0pO1xuICAgICAqIGpRdWVyeShlbGVtZW50KS5vbignY2xpY2snLCB0aHJvdHRsZWQpO1xuICAgICAqXG4gICAgICogLy8gQ2FuY2VsIHRoZSB0cmFpbGluZyB0aHJvdHRsZWQgaW52b2NhdGlvbi5cbiAgICAgKiBqUXVlcnkod2luZG93KS5vbigncG9wc3RhdGUnLCB0aHJvdHRsZWQuY2FuY2VsKTtcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0aHJvdHRsZShmdW5jLCB3YWl0LCBvcHRpb25zKSB7XG4gICAgICB2YXIgbGVhZGluZyA9IHRydWUsXG4gICAgICAgICAgdHJhaWxpbmcgPSB0cnVlO1xuXG4gICAgICBpZiAodHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gICAgICB9XG4gICAgICBpZiAoaXNPYmplY3Qob3B0aW9ucykpIHtcbiAgICAgICAgbGVhZGluZyA9ICdsZWFkaW5nJyBpbiBvcHRpb25zID8gISFvcHRpb25zLmxlYWRpbmcgOiBsZWFkaW5nO1xuICAgICAgICB0cmFpbGluZyA9ICd0cmFpbGluZycgaW4gb3B0aW9ucyA/ICEhb3B0aW9ucy50cmFpbGluZyA6IHRyYWlsaW5nO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGRlYm91bmNlKGZ1bmMsIHdhaXQsIHtcbiAgICAgICAgJ2xlYWRpbmcnOiBsZWFkaW5nLFxuICAgICAgICAnbWF4V2FpdCc6IHdhaXQsXG4gICAgICAgICd0cmFpbGluZyc6IHRyYWlsaW5nXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBhY2NlcHRzIHVwIHRvIG9uZSBhcmd1bWVudCwgaWdub3JpbmcgYW55XG4gICAgICogYWRkaXRpb25hbCBhcmd1bWVudHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjYXAgYXJndW1lbnRzIGZvci5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBjYXBwZWQgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubWFwKFsnNicsICc4JywgJzEwJ10sIF8udW5hcnkocGFyc2VJbnQpKTtcbiAgICAgKiAvLyA9PiBbNiwgOCwgMTBdXG4gICAgICovXG4gICAgZnVuY3Rpb24gdW5hcnkoZnVuYykge1xuICAgICAgcmV0dXJuIGFyeShmdW5jLCAxKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBwcm92aWRlcyBgdmFsdWVgIHRvIGB3cmFwcGVyYCBhcyBpdHMgZmlyc3RcbiAgICAgKiBhcmd1bWVudC4gQW55IGFkZGl0aW9uYWwgYXJndW1lbnRzIHByb3ZpZGVkIHRvIHRoZSBmdW5jdGlvbiBhcmUgYXBwZW5kZWRcbiAgICAgKiB0byB0aG9zZSBwcm92aWRlZCB0byB0aGUgYHdyYXBwZXJgLiBUaGUgd3JhcHBlciBpcyBpbnZva2VkIHdpdGggdGhlIGB0aGlzYFxuICAgICAqIGJpbmRpbmcgb2YgdGhlIGNyZWF0ZWQgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byB3cmFwLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFt3cmFwcGVyPWlkZW50aXR5XSBUaGUgd3JhcHBlciBmdW5jdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHAgPSBfLndyYXAoXy5lc2NhcGUsIGZ1bmN0aW9uKGZ1bmMsIHRleHQpIHtcbiAgICAgKiAgIHJldHVybiAnPHA+JyArIGZ1bmModGV4dCkgKyAnPC9wPic7XG4gICAgICogfSk7XG4gICAgICpcbiAgICAgKiBwKCdmcmVkLCBiYXJuZXksICYgcGViYmxlcycpO1xuICAgICAqIC8vID0+ICc8cD5mcmVkLCBiYXJuZXksICZhbXA7IHBlYmJsZXM8L3A+J1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdyYXAodmFsdWUsIHdyYXBwZXIpIHtcbiAgICAgIHJldHVybiBwYXJ0aWFsKGNhc3RGdW5jdGlvbih3cmFwcGVyKSwgdmFsdWUpO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIENhc3RzIGB2YWx1ZWAgYXMgYW4gYXJyYXkgaWYgaXQncyBub3Qgb25lLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuNC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBpbnNwZWN0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgY2FzdCBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5jYXN0QXJyYXkoMSk7XG4gICAgICogLy8gPT4gWzFdXG4gICAgICpcbiAgICAgKiBfLmNhc3RBcnJheSh7ICdhJzogMSB9KTtcbiAgICAgKiAvLyA9PiBbeyAnYSc6IDEgfV1cbiAgICAgKlxuICAgICAqIF8uY2FzdEFycmF5KCdhYmMnKTtcbiAgICAgKiAvLyA9PiBbJ2FiYyddXG4gICAgICpcbiAgICAgKiBfLmNhc3RBcnJheShudWxsKTtcbiAgICAgKiAvLyA9PiBbbnVsbF1cbiAgICAgKlxuICAgICAqIF8uY2FzdEFycmF5KHVuZGVmaW5lZCk7XG4gICAgICogLy8gPT4gW3VuZGVmaW5lZF1cbiAgICAgKlxuICAgICAqIF8uY2FzdEFycmF5KCk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFsxLCAyLCAzXTtcbiAgICAgKiBjb25zb2xlLmxvZyhfLmNhc3RBcnJheShhcnJheSkgPT09IGFycmF5KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2FzdEFycmF5KCkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIHZhciB2YWx1ZSA9IGFyZ3VtZW50c1swXTtcbiAgICAgIHJldHVybiBpc0FycmF5KHZhbHVlKSA/IHZhbHVlIDogW3ZhbHVlXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc2hhbGxvdyBjbG9uZSBvZiBgdmFsdWVgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGlzIGxvb3NlbHkgYmFzZWQgb24gdGhlXG4gICAgICogW3N0cnVjdHVyZWQgY2xvbmUgYWxnb3JpdGhtXShodHRwczovL21kbi5pby9TdHJ1Y3R1cmVkX2Nsb25lX2FsZ29yaXRobSlcbiAgICAgKiBhbmQgc3VwcG9ydHMgY2xvbmluZyBhcnJheXMsIGFycmF5IGJ1ZmZlcnMsIGJvb2xlYW5zLCBkYXRlIG9iamVjdHMsIG1hcHMsXG4gICAgICogbnVtYmVycywgYE9iamVjdGAgb2JqZWN0cywgcmVnZXhlcywgc2V0cywgc3RyaW5ncywgc3ltYm9scywgYW5kIHR5cGVkXG4gICAgICogYXJyYXlzLiBUaGUgb3duIGVudW1lcmFibGUgcHJvcGVydGllcyBvZiBgYXJndW1lbnRzYCBvYmplY3RzIGFyZSBjbG9uZWRcbiAgICAgKiBhcyBwbGFpbiBvYmplY3RzLiBBbiBlbXB0eSBvYmplY3QgaXMgcmV0dXJuZWQgZm9yIHVuY2xvbmVhYmxlIHZhbHVlcyBzdWNoXG4gICAgICogYXMgZXJyb3Igb2JqZWN0cywgZnVuY3Rpb25zLCBET00gbm9kZXMsIGFuZCBXZWFrTWFwcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2xvbmUuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGNsb25lZCB2YWx1ZS5cbiAgICAgKiBAc2VlIF8uY2xvbmVEZWVwXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW3sgJ2EnOiAxIH0sIHsgJ2InOiAyIH1dO1xuICAgICAqXG4gICAgICogdmFyIHNoYWxsb3cgPSBfLmNsb25lKG9iamVjdHMpO1xuICAgICAqIGNvbnNvbGUubG9nKHNoYWxsb3dbMF0gPT09IG9iamVjdHNbMF0pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjbG9uZSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGJhc2VDbG9uZSh2YWx1ZSwgQ0xPTkVfU1lNQk9MU19GTEFHKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmNsb25lYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBjdXN0b21pemVyYCB3aGljaFxuICAgICAqIGlzIGludm9rZWQgdG8gcHJvZHVjZSB0aGUgY2xvbmVkIHZhbHVlLiBJZiBgY3VzdG9taXplcmAgcmV0dXJucyBgdW5kZWZpbmVkYCxcbiAgICAgKiBjbG9uaW5nIGlzIGhhbmRsZWQgYnkgdGhlIG1ldGhvZCBpbnN0ZWFkLiBUaGUgYGN1c3RvbWl6ZXJgIGlzIGludm9rZWQgd2l0aFxuICAgICAqIHVwIHRvIGZvdXIgYXJndW1lbnRzOyAodmFsdWUgWywgaW5kZXh8a2V5LCBvYmplY3QsIHN0YWNrXSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNsb25lLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNsb25pbmcuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGNsb25lZCB2YWx1ZS5cbiAgICAgKiBAc2VlIF8uY2xvbmVEZWVwV2l0aFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBjdXN0b21pemVyKHZhbHVlKSB7XG4gICAgICogICBpZiAoXy5pc0VsZW1lbnQodmFsdWUpKSB7XG4gICAgICogICAgIHJldHVybiB2YWx1ZS5jbG9uZU5vZGUoZmFsc2UpO1xuICAgICAqICAgfVxuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHZhciBlbCA9IF8uY2xvbmVXaXRoKGRvY3VtZW50LmJvZHksIGN1c3RvbWl6ZXIpO1xuICAgICAqXG4gICAgICogY29uc29sZS5sb2coZWwgPT09IGRvY3VtZW50LmJvZHkpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICogY29uc29sZS5sb2coZWwubm9kZU5hbWUpO1xuICAgICAqIC8vID0+ICdCT0RZJ1xuICAgICAqIGNvbnNvbGUubG9nKGVsLmNoaWxkTm9kZXMubGVuZ3RoKTtcbiAgICAgKiAvLyA9PiAwXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2xvbmVXaXRoKHZhbHVlLCBjdXN0b21pemVyKSB7XG4gICAgICBjdXN0b21pemVyID0gdHlwZW9mIGN1c3RvbWl6ZXIgPT0gJ2Z1bmN0aW9uJyA/IGN1c3RvbWl6ZXIgOiB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4gYmFzZUNsb25lKHZhbHVlLCBDTE9ORV9TWU1CT0xTX0ZMQUcsIGN1c3RvbWl6ZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uY2xvbmVgIGV4Y2VwdCB0aGF0IGl0IHJlY3Vyc2l2ZWx5IGNsb25lcyBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDEuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byByZWN1cnNpdmVseSBjbG9uZS5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZGVlcCBjbG9uZWQgdmFsdWUuXG4gICAgICogQHNlZSBfLmNsb25lXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW3sgJ2EnOiAxIH0sIHsgJ2InOiAyIH1dO1xuICAgICAqXG4gICAgICogdmFyIGRlZXAgPSBfLmNsb25lRGVlcChvYmplY3RzKTtcbiAgICAgKiBjb25zb2xlLmxvZyhkZWVwWzBdID09PSBvYmplY3RzWzBdKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsb25lRGVlcCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGJhc2VDbG9uZSh2YWx1ZSwgQ0xPTkVfREVFUF9GTEFHIHwgQ0xPTkVfU1lNQk9MU19GTEFHKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmNsb25lV2l0aGAgZXhjZXB0IHRoYXQgaXQgcmVjdXJzaXZlbHkgY2xvbmVzIGB2YWx1ZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHJlY3Vyc2l2ZWx5IGNsb25lLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNsb25pbmcuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGRlZXAgY2xvbmVkIHZhbHVlLlxuICAgICAqIEBzZWUgXy5jbG9uZVdpdGhcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gY3VzdG9taXplcih2YWx1ZSkge1xuICAgICAqICAgaWYgKF8uaXNFbGVtZW50KHZhbHVlKSkge1xuICAgICAqICAgICByZXR1cm4gdmFsdWUuY2xvbmVOb2RlKHRydWUpO1xuICAgICAqICAgfVxuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHZhciBlbCA9IF8uY2xvbmVEZWVwV2l0aChkb2N1bWVudC5ib2R5LCBjdXN0b21pemVyKTtcbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKGVsID09PSBkb2N1bWVudC5ib2R5KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqIGNvbnNvbGUubG9nKGVsLm5vZGVOYW1lKTtcbiAgICAgKiAvLyA9PiAnQk9EWSdcbiAgICAgKiBjb25zb2xlLmxvZyhlbC5jaGlsZE5vZGVzLmxlbmd0aCk7XG4gICAgICogLy8gPT4gMjBcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjbG9uZURlZXBXaXRoKHZhbHVlLCBjdXN0b21pemVyKSB7XG4gICAgICBjdXN0b21pemVyID0gdHlwZW9mIGN1c3RvbWl6ZXIgPT0gJ2Z1bmN0aW9uJyA/IGN1c3RvbWl6ZXIgOiB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4gYmFzZUNsb25lKHZhbHVlLCBDTE9ORV9ERUVQX0ZMQUcgfCBDTE9ORV9TWU1CT0xTX0ZMQUcsIGN1c3RvbWl6ZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgb2JqZWN0YCBjb25mb3JtcyB0byBgc291cmNlYCBieSBpbnZva2luZyB0aGUgcHJlZGljYXRlXG4gICAgICogcHJvcGVydGllcyBvZiBgc291cmNlYCB3aXRoIHRoZSBjb3JyZXNwb25kaW5nIHByb3BlcnR5IHZhbHVlcyBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBlcXVpdmFsZW50IHRvIGBfLmNvbmZvcm1zYCB3aGVuIGBzb3VyY2VgIGlzXG4gICAgICogcGFydGlhbGx5IGFwcGxpZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4xNC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBvYmplY3Qgb2YgcHJvcGVydHkgcHJlZGljYXRlcyB0byBjb25mb3JtIHRvLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgb2JqZWN0YCBjb25mb3JtcywgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IDEsICdiJzogMiB9O1xuICAgICAqXG4gICAgICogXy5jb25mb3Jtc1RvKG9iamVjdCwgeyAnYic6IGZ1bmN0aW9uKG4pIHsgcmV0dXJuIG4gPiAxOyB9IH0pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uY29uZm9ybXNUbyhvYmplY3QsIHsgJ2InOiBmdW5jdGlvbihuKSB7IHJldHVybiBuID4gMjsgfSB9KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNvbmZvcm1zVG8ob2JqZWN0LCBzb3VyY2UpIHtcbiAgICAgIHJldHVybiBzb3VyY2UgPT0gbnVsbCB8fCBiYXNlQ29uZm9ybXNUbyhvYmplY3QsIHNvdXJjZSwga2V5cyhzb3VyY2UpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQZXJmb3JtcyBhXG4gICAgICogW2BTYW1lVmFsdWVaZXJvYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtc2FtZXZhbHVlemVybylcbiAgICAgKiBjb21wYXJpc29uIGJldHdlZW4gdHdvIHZhbHVlcyB0byBkZXRlcm1pbmUgaWYgdGhleSBhcmUgZXF1aXZhbGVudC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0geyp9IG90aGVyIFRoZSBvdGhlciB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgdmFsdWVzIGFyZSBlcXVpdmFsZW50LCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogMSB9O1xuICAgICAqIHZhciBvdGhlciA9IHsgJ2EnOiAxIH07XG4gICAgICpcbiAgICAgKiBfLmVxKG9iamVjdCwgb2JqZWN0KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmVxKG9iamVjdCwgb3RoZXIpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmVxKCdhJywgJ2EnKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmVxKCdhJywgT2JqZWN0KCdhJykpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmVxKE5hTiwgTmFOKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gZXEodmFsdWUsIG90aGVyKSB7XG4gICAgICByZXR1cm4gdmFsdWUgPT09IG90aGVyIHx8ICh2YWx1ZSAhPT0gdmFsdWUgJiYgb3RoZXIgIT09IG90aGVyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBncmVhdGVyIHRoYW4gYG90aGVyYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjkuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0geyp9IG90aGVyIFRoZSBvdGhlciB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGdyZWF0ZXIgdGhhbiBgb3RoZXJgLFxuICAgICAqICBlbHNlIGBmYWxzZWAuXG4gICAgICogQHNlZSBfLmx0XG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZ3QoMywgMSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5ndCgzLCAzKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5ndCgxLCAzKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBndCA9IGNyZWF0ZVJlbGF0aW9uYWxPcGVyYXRpb24oYmFzZUd0KTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byBgb3RoZXJgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuOS4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7Kn0gb3RoZXIgVGhlIG90aGVyIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvXG4gICAgICogIGBvdGhlcmAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAc2VlIF8ubHRlXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZ3RlKDMsIDEpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uZ3RlKDMsIDMpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uZ3RlKDEsIDMpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGd0ZSA9IGNyZWF0ZVJlbGF0aW9uYWxPcGVyYXRpb24oZnVuY3Rpb24odmFsdWUsIG90aGVyKSB7XG4gICAgICByZXR1cm4gdmFsdWUgPj0gb3RoZXI7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBsaWtlbHkgYW4gYGFyZ3VtZW50c2Agb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhbiBgYXJndW1lbnRzYCBvYmplY3QsXG4gICAgICogIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0FyZ3VtZW50cyhmdW5jdGlvbigpIHsgcmV0dXJuIGFyZ3VtZW50czsgfSgpKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzQXJndW1lbnRzKFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICB2YXIgaXNBcmd1bWVudHMgPSBiYXNlSXNBcmd1bWVudHMoZnVuY3Rpb24oKSB7IHJldHVybiBhcmd1bWVudHM7IH0oKSkgPyBiYXNlSXNBcmd1bWVudHMgOiBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgaGFzT3duUHJvcGVydHkuY2FsbCh2YWx1ZSwgJ2NhbGxlZScpICYmXG4gICAgICAgICFwcm9wZXJ0eUlzRW51bWVyYWJsZS5jYWxsKHZhbHVlLCAnY2FsbGVlJyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYW4gYEFycmF5YCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFuIGFycmF5LCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheShbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheShkb2N1bWVudC5ib2R5LmNoaWxkcmVuKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5KCdhYmMnKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5KF8ubm9vcCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICB2YXIgaXNBcnJheSA9IEFycmF5LmlzQXJyYXk7XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGFuIGBBcnJheUJ1ZmZlcmAgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMy4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhbiBhcnJheSBidWZmZXIsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5QnVmZmVyKG5ldyBBcnJheUJ1ZmZlcigyKSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5QnVmZmVyKG5ldyBBcnJheSgyKSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICB2YXIgaXNBcnJheUJ1ZmZlciA9IG5vZGVJc0FycmF5QnVmZmVyID8gYmFzZVVuYXJ5KG5vZGVJc0FycmF5QnVmZmVyKSA6IGJhc2VJc0FycmF5QnVmZmVyO1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYXJyYXktbGlrZS4gQSB2YWx1ZSBpcyBjb25zaWRlcmVkIGFycmF5LWxpa2UgaWYgaXQnc1xuICAgICAqIG5vdCBhIGZ1bmN0aW9uIGFuZCBoYXMgYSBgdmFsdWUubGVuZ3RoYCB0aGF0J3MgYW4gaW50ZWdlciBncmVhdGVyIHRoYW4gb3JcbiAgICAgKiBlcXVhbCB0byBgMGAgYW5kIGxlc3MgdGhhbiBvciBlcXVhbCB0byBgTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVJgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhcnJheS1saWtlLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheUxpa2UoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXlMaWtlKGRvY3VtZW50LmJvZHkuY2hpbGRyZW4pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheUxpa2UoJ2FiYycpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNBcnJheUxpa2UoXy5ub29wKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzQXJyYXlMaWtlKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdmFsdWUgIT0gbnVsbCAmJiBpc0xlbmd0aCh2YWx1ZS5sZW5ndGgpICYmICFpc0Z1bmN0aW9uKHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmlzQXJyYXlMaWtlYCBleGNlcHQgdGhhdCBpdCBhbHNvIGNoZWNrcyBpZiBgdmFsdWVgXG4gICAgICogaXMgYW4gb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhbiBhcnJheS1saWtlIG9iamVjdCxcbiAgICAgKiAgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXlMaWtlT2JqZWN0KFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5TGlrZU9iamVjdChkb2N1bWVudC5ib2R5LmNoaWxkcmVuKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzQXJyYXlMaWtlT2JqZWN0KCdhYmMnKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc0FycmF5TGlrZU9iamVjdChfLm5vb3ApO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNBcnJheUxpa2VPYmplY3QodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmIGlzQXJyYXlMaWtlKHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYm9vbGVhbiBwcmltaXRpdmUgb3Igb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIGJvb2xlYW4sIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0Jvb2xlYW4oZmFsc2UpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNCb29sZWFuKG51bGwpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNCb29sZWFuKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdmFsdWUgPT09IHRydWUgfHwgdmFsdWUgPT09IGZhbHNlIHx8XG4gICAgICAgIChpc09iamVjdExpa2UodmFsdWUpICYmIGJhc2VHZXRUYWcodmFsdWUpID09IGJvb2xUYWcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgYnVmZmVyLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMy4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIGJ1ZmZlciwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzQnVmZmVyKG5ldyBCdWZmZXIoMikpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNCdWZmZXIobmV3IFVpbnQ4QXJyYXkoMikpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGlzQnVmZmVyID0gbmF0aXZlSXNCdWZmZXIgfHwgc3R1YkZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBEYXRlYCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgZGF0ZSBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0RhdGUobmV3IERhdGUpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNEYXRlKCdNb24gQXByaWwgMjMgMjAxMicpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgdmFyIGlzRGF0ZSA9IG5vZGVJc0RhdGUgPyBiYXNlVW5hcnkobm9kZUlzRGF0ZSkgOiBiYXNlSXNEYXRlO1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgbGlrZWx5IGEgRE9NIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgRE9NIGVsZW1lbnQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0VsZW1lbnQoZG9jdW1lbnQuYm9keSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0VsZW1lbnQoJzxib2R5PicpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNFbGVtZW50KHZhbHVlKSB7XG4gICAgICByZXR1cm4gaXNPYmplY3RMaWtlKHZhbHVlKSAmJiB2YWx1ZS5ub2RlVHlwZSA9PT0gMSAmJiAhaXNQbGFpbk9iamVjdCh2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYW4gZW1wdHkgb2JqZWN0LCBjb2xsZWN0aW9uLCBtYXAsIG9yIHNldC5cbiAgICAgKlxuICAgICAqIE9iamVjdHMgYXJlIGNvbnNpZGVyZWQgZW1wdHkgaWYgdGhleSBoYXZlIG5vIG93biBlbnVtZXJhYmxlIHN0cmluZyBrZXllZFxuICAgICAqIHByb3BlcnRpZXMuXG4gICAgICpcbiAgICAgKiBBcnJheS1saWtlIHZhbHVlcyBzdWNoIGFzIGBhcmd1bWVudHNgIG9iamVjdHMsIGFycmF5cywgYnVmZmVycywgc3RyaW5ncywgb3JcbiAgICAgKiBqUXVlcnktbGlrZSBjb2xsZWN0aW9ucyBhcmUgY29uc2lkZXJlZCBlbXB0eSBpZiB0aGV5IGhhdmUgYSBgbGVuZ3RoYCBvZiBgMGAuXG4gICAgICogU2ltaWxhcmx5LCBtYXBzIGFuZCBzZXRzIGFyZSBjb25zaWRlcmVkIGVtcHR5IGlmIHRoZXkgaGF2ZSBhIGBzaXplYCBvZiBgMGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGVtcHR5LCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNFbXB0eShudWxsKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzRW1wdHkodHJ1ZSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc0VtcHR5KDEpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNFbXB0eShbMSwgMiwgM10pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzRW1wdHkoeyAnYSc6IDEgfSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0VtcHR5KHZhbHVlKSB7XG4gICAgICBpZiAodmFsdWUgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGlmIChpc0FycmF5TGlrZSh2YWx1ZSkgJiZcbiAgICAgICAgICAoaXNBcnJheSh2YWx1ZSkgfHwgdHlwZW9mIHZhbHVlID09ICdzdHJpbmcnIHx8IHR5cGVvZiB2YWx1ZS5zcGxpY2UgPT0gJ2Z1bmN0aW9uJyB8fFxuICAgICAgICAgICAgaXNCdWZmZXIodmFsdWUpIHx8IGlzVHlwZWRBcnJheSh2YWx1ZSkgfHwgaXNBcmd1bWVudHModmFsdWUpKSkge1xuICAgICAgICByZXR1cm4gIXZhbHVlLmxlbmd0aDtcbiAgICAgIH1cbiAgICAgIHZhciB0YWcgPSBnZXRUYWcodmFsdWUpO1xuICAgICAgaWYgKHRhZyA9PSBtYXBUYWcgfHwgdGFnID09IHNldFRhZykge1xuICAgICAgICByZXR1cm4gIXZhbHVlLnNpemU7XG4gICAgICB9XG4gICAgICBpZiAoaXNQcm90b3R5cGUodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiAhYmFzZUtleXModmFsdWUpLmxlbmd0aDtcbiAgICAgIH1cbiAgICAgIGZvciAodmFyIGtleSBpbiB2YWx1ZSkge1xuICAgICAgICBpZiAoaGFzT3duUHJvcGVydHkuY2FsbCh2YWx1ZSwga2V5KSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGVyZm9ybXMgYSBkZWVwIGNvbXBhcmlzb24gYmV0d2VlbiB0d28gdmFsdWVzIHRvIGRldGVybWluZSBpZiB0aGV5IGFyZVxuICAgICAqIGVxdWl2YWxlbnQuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2Qgc3VwcG9ydHMgY29tcGFyaW5nIGFycmF5cywgYXJyYXkgYnVmZmVycywgYm9vbGVhbnMsXG4gICAgICogZGF0ZSBvYmplY3RzLCBlcnJvciBvYmplY3RzLCBtYXBzLCBudW1iZXJzLCBgT2JqZWN0YCBvYmplY3RzLCByZWdleGVzLFxuICAgICAqIHNldHMsIHN0cmluZ3MsIHN5bWJvbHMsIGFuZCB0eXBlZCBhcnJheXMuIGBPYmplY3RgIG9iamVjdHMgYXJlIGNvbXBhcmVkXG4gICAgICogYnkgdGhlaXIgb3duLCBub3QgaW5oZXJpdGVkLCBlbnVtZXJhYmxlIHByb3BlcnRpZXMuIEZ1bmN0aW9ucyBhbmQgRE9NXG4gICAgICogbm9kZXMgYXJlIGNvbXBhcmVkIGJ5IHN0cmljdCBlcXVhbGl0eSwgaS5lLiBgPT09YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0geyp9IG90aGVyIFRoZSBvdGhlciB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgdmFsdWVzIGFyZSBlcXVpdmFsZW50LCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogMSB9O1xuICAgICAqIHZhciBvdGhlciA9IHsgJ2EnOiAxIH07XG4gICAgICpcbiAgICAgKiBfLmlzRXF1YWwob2JqZWN0LCBvdGhlcik7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogb2JqZWN0ID09PSBvdGhlcjtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzRXF1YWwodmFsdWUsIG90aGVyKSB7XG4gICAgICByZXR1cm4gYmFzZUlzRXF1YWwodmFsdWUsIG90aGVyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmlzRXF1YWxgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGN1c3RvbWl6ZXJgIHdoaWNoXG4gICAgICogaXMgaW52b2tlZCB0byBjb21wYXJlIHZhbHVlcy4gSWYgYGN1c3RvbWl6ZXJgIHJldHVybnMgYHVuZGVmaW5lZGAsIGNvbXBhcmlzb25zXG4gICAgICogYXJlIGhhbmRsZWQgYnkgdGhlIG1ldGhvZCBpbnN0ZWFkLiBUaGUgYGN1c3RvbWl6ZXJgIGlzIGludm9rZWQgd2l0aCB1cCB0b1xuICAgICAqIHNpeCBhcmd1bWVudHM6IChvYmpWYWx1ZSwgb3RoVmFsdWUgWywgaW5kZXh8a2V5LCBvYmplY3QsIG90aGVyLCBzdGFja10pLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEBwYXJhbSB7Kn0gb3RoZXIgVGhlIG90aGVyIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY29tcGFyaXNvbnMuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSB2YWx1ZXMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gaXNHcmVldGluZyh2YWx1ZSkge1xuICAgICAqICAgcmV0dXJuIC9eaCg/Oml8ZWxsbykkLy50ZXN0KHZhbHVlKTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBjdXN0b21pemVyKG9ialZhbHVlLCBvdGhWYWx1ZSkge1xuICAgICAqICAgaWYgKGlzR3JlZXRpbmcob2JqVmFsdWUpICYmIGlzR3JlZXRpbmcob3RoVmFsdWUpKSB7XG4gICAgICogICAgIHJldHVybiB0cnVlO1xuICAgICAqICAgfVxuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHZhciBhcnJheSA9IFsnaGVsbG8nLCAnZ29vZGJ5ZSddO1xuICAgICAqIHZhciBvdGhlciA9IFsnaGknLCAnZ29vZGJ5ZSddO1xuICAgICAqXG4gICAgICogXy5pc0VxdWFsV2l0aChhcnJheSwgb3RoZXIsIGN1c3RvbWl6ZXIpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0VxdWFsV2l0aCh2YWx1ZSwgb3RoZXIsIGN1c3RvbWl6ZXIpIHtcbiAgICAgIGN1c3RvbWl6ZXIgPSB0eXBlb2YgY3VzdG9taXplciA9PSAnZnVuY3Rpb24nID8gY3VzdG9taXplciA6IHVuZGVmaW5lZDtcbiAgICAgIHZhciByZXN1bHQgPSBjdXN0b21pemVyID8gY3VzdG9taXplcih2YWx1ZSwgb3RoZXIpIDogdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIHJlc3VsdCA9PT0gdW5kZWZpbmVkID8gYmFzZUlzRXF1YWwodmFsdWUsIG90aGVyLCB1bmRlZmluZWQsIGN1c3RvbWl6ZXIpIDogISFyZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYW4gYEVycm9yYCwgYEV2YWxFcnJvcmAsIGBSYW5nZUVycm9yYCwgYFJlZmVyZW5jZUVycm9yYCxcbiAgICAgKiBgU3ludGF4RXJyb3JgLCBgVHlwZUVycm9yYCwgb3IgYFVSSUVycm9yYCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFuIGVycm9yIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzRXJyb3IobmV3IEVycm9yKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzRXJyb3IoRXJyb3IpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNFcnJvcih2YWx1ZSkge1xuICAgICAgaWYgKCFpc09iamVjdExpa2UodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHZhciB0YWcgPSBiYXNlR2V0VGFnKHZhbHVlKTtcbiAgICAgIHJldHVybiB0YWcgPT0gZXJyb3JUYWcgfHwgdGFnID09IGRvbUV4Y1RhZyB8fFxuICAgICAgICAodHlwZW9mIHZhbHVlLm1lc3NhZ2UgPT0gJ3N0cmluZycgJiYgdHlwZW9mIHZhbHVlLm5hbWUgPT0gJ3N0cmluZycgJiYgIWlzUGxhaW5PYmplY3QodmFsdWUpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIGZpbml0ZSBwcmltaXRpdmUgbnVtYmVyLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGlzIGJhc2VkIG9uXG4gICAgICogW2BOdW1iZXIuaXNGaW5pdGVgXShodHRwczovL21kbi5pby9OdW1iZXIvaXNGaW5pdGUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIGZpbml0ZSBudW1iZXIsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc0Zpbml0ZSgzKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzRmluaXRlKE51bWJlci5NSU5fVkFMVUUpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNGaW5pdGUoSW5maW5pdHkpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzRmluaXRlKCczJyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0Zpbml0ZSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSAnbnVtYmVyJyAmJiBuYXRpdmVJc0Zpbml0ZSh2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBGdW5jdGlvbmAgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIGZ1bmN0aW9uLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNGdW5jdGlvbihfKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzRnVuY3Rpb24oL2FiYy8pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNGdW5jdGlvbih2YWx1ZSkge1xuICAgICAgaWYgKCFpc09iamVjdCh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgLy8gVGhlIHVzZSBvZiBgT2JqZWN0I3RvU3RyaW5nYCBhdm9pZHMgaXNzdWVzIHdpdGggdGhlIGB0eXBlb2ZgIG9wZXJhdG9yXG4gICAgICAvLyBpbiBTYWZhcmkgOSB3aGljaCByZXR1cm5zICdvYmplY3QnIGZvciB0eXBlZCBhcnJheXMgYW5kIG90aGVyIGNvbnN0cnVjdG9ycy5cbiAgICAgIHZhciB0YWcgPSBiYXNlR2V0VGFnKHZhbHVlKTtcbiAgICAgIHJldHVybiB0YWcgPT0gZnVuY1RhZyB8fCB0YWcgPT0gZ2VuVGFnIHx8IHRhZyA9PSBhc3luY1RhZyB8fCB0YWcgPT0gcHJveHlUYWc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYW4gaW50ZWdlci5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBiYXNlZCBvblxuICAgICAqIFtgTnVtYmVyLmlzSW50ZWdlcmBdKGh0dHBzOi8vbWRuLmlvL051bWJlci9pc0ludGVnZXIpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhbiBpbnRlZ2VyLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNJbnRlZ2VyKDMpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNJbnRlZ2VyKE51bWJlci5NSU5fVkFMVUUpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzSW50ZWdlcihJbmZpbml0eSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNJbnRlZ2VyKCczJyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0ludGVnZXIodmFsdWUpIHtcbiAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gJ251bWJlcicgJiYgdmFsdWUgPT0gdG9JbnRlZ2VyKHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIHZhbGlkIGFycmF5LWxpa2UgbGVuZ3RoLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGlzIGxvb3NlbHkgYmFzZWQgb25cbiAgICAgKiBbYFRvTGVuZ3RoYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtdG9sZW5ndGgpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHZhbGlkIGxlbmd0aCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzTGVuZ3RoKDMpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNMZW5ndGgoTnVtYmVyLk1JTl9WQUxVRSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNMZW5ndGgoSW5maW5pdHkpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzTGVuZ3RoKCczJyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0xlbmd0aCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSAnbnVtYmVyJyAmJlxuICAgICAgICB2YWx1ZSA+IC0xICYmIHZhbHVlICUgMSA9PSAwICYmIHZhbHVlIDw9IE1BWF9TQUZFX0lOVEVHRVI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgdGhlXG4gICAgICogW2xhbmd1YWdlIHR5cGVdKGh0dHA6Ly93d3cuZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1lY21hc2NyaXB0LWxhbmd1YWdlLXR5cGVzKVxuICAgICAqIG9mIGBPYmplY3RgLiAoZS5nLiBhcnJheXMsIGZ1bmN0aW9ucywgb2JqZWN0cywgcmVnZXhlcywgYG5ldyBOdW1iZXIoMClgLCBhbmQgYG5ldyBTdHJpbmcoJycpYClcbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYW4gb2JqZWN0LCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNPYmplY3Qoe30pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNPYmplY3QoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzT2JqZWN0KF8ubm9vcCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc09iamVjdChudWxsKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzT2JqZWN0KHZhbHVlKSB7XG4gICAgICB2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZTtcbiAgICAgIHJldHVybiB2YWx1ZSAhPSBudWxsICYmICh0eXBlID09ICdvYmplY3QnIHx8IHR5cGUgPT0gJ2Z1bmN0aW9uJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgb2JqZWN0LWxpa2UuIEEgdmFsdWUgaXMgb2JqZWN0LWxpa2UgaWYgaXQncyBub3QgYG51bGxgXG4gICAgICogYW5kIGhhcyBhIGB0eXBlb2ZgIHJlc3VsdCBvZiBcIm9iamVjdFwiLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBvYmplY3QtbGlrZSwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzT2JqZWN0TGlrZSh7fSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc09iamVjdExpa2UoWzEsIDIsIDNdKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzT2JqZWN0TGlrZShfLm5vb3ApO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzT2JqZWN0TGlrZShudWxsKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzT2JqZWN0TGlrZSh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlICE9IG51bGwgJiYgdHlwZW9mIHZhbHVlID09ICdvYmplY3QnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgTWFwYCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4zLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgbWFwLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNNYXAobmV3IE1hcCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc01hcChuZXcgV2Vha01hcCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICB2YXIgaXNNYXAgPSBub2RlSXNNYXAgPyBiYXNlVW5hcnkobm9kZUlzTWFwKSA6IGJhc2VJc01hcDtcblxuICAgIC8qKlxuICAgICAqIFBlcmZvcm1zIGEgcGFydGlhbCBkZWVwIGNvbXBhcmlzb24gYmV0d2VlbiBgb2JqZWN0YCBhbmQgYHNvdXJjZWAgdG9cbiAgICAgKiBkZXRlcm1pbmUgaWYgYG9iamVjdGAgY29udGFpbnMgZXF1aXZhbGVudCBwcm9wZXJ0eSB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgZXF1aXZhbGVudCB0byBgXy5tYXRjaGVzYCB3aGVuIGBzb3VyY2VgIGlzXG4gICAgICogcGFydGlhbGx5IGFwcGxpZWQuXG4gICAgICpcbiAgICAgKiBQYXJ0aWFsIGNvbXBhcmlzb25zIHdpbGwgbWF0Y2ggZW1wdHkgYXJyYXkgYW5kIGVtcHR5IG9iamVjdCBgc291cmNlYFxuICAgICAqIHZhbHVlcyBhZ2FpbnN0IGFueSBhcnJheSBvciBvYmplY3QgdmFsdWUsIHJlc3BlY3RpdmVseS4gU2VlIGBfLmlzRXF1YWxgXG4gICAgICogZm9yIGEgbGlzdCBvZiBzdXBwb3J0ZWQgdmFsdWUgY29tcGFyaXNvbnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCBvZiBwcm9wZXJ0eSB2YWx1ZXMgdG8gbWF0Y2guXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGBvYmplY3RgIGlzIGEgbWF0Y2gsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiAxLCAnYic6IDIgfTtcbiAgICAgKlxuICAgICAqIF8uaXNNYXRjaChvYmplY3QsIHsgJ2InOiAyIH0pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNNYXRjaChvYmplY3QsIHsgJ2InOiAxIH0pO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNNYXRjaChvYmplY3QsIHNvdXJjZSkge1xuICAgICAgcmV0dXJuIG9iamVjdCA9PT0gc291cmNlIHx8IGJhc2VJc01hdGNoKG9iamVjdCwgc291cmNlLCBnZXRNYXRjaERhdGEoc291cmNlKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5pc01hdGNoYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBjdXN0b21pemVyYCB3aGljaFxuICAgICAqIGlzIGludm9rZWQgdG8gY29tcGFyZSB2YWx1ZXMuIElmIGBjdXN0b21pemVyYCByZXR1cm5zIGB1bmRlZmluZWRgLCBjb21wYXJpc29uc1xuICAgICAqIGFyZSBoYW5kbGVkIGJ5IHRoZSBtZXRob2QgaW5zdGVhZC4gVGhlIGBjdXN0b21pemVyYCBpcyBpbnZva2VkIHdpdGggZml2ZVxuICAgICAqIGFyZ3VtZW50czogKG9ialZhbHVlLCBzcmNWYWx1ZSwgaW5kZXh8a2V5LCBvYmplY3QsIHNvdXJjZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCBvZiBwcm9wZXJ0eSB2YWx1ZXMgdG8gbWF0Y2guXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY29tcGFyaXNvbnMuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGBvYmplY3RgIGlzIGEgbWF0Y2gsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gaXNHcmVldGluZyh2YWx1ZSkge1xuICAgICAqICAgcmV0dXJuIC9eaCg/Oml8ZWxsbykkLy50ZXN0KHZhbHVlKTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBjdXN0b21pemVyKG9ialZhbHVlLCBzcmNWYWx1ZSkge1xuICAgICAqICAgaWYgKGlzR3JlZXRpbmcob2JqVmFsdWUpICYmIGlzR3JlZXRpbmcoc3JjVmFsdWUpKSB7XG4gICAgICogICAgIHJldHVybiB0cnVlO1xuICAgICAqICAgfVxuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdncmVldGluZyc6ICdoZWxsbycgfTtcbiAgICAgKiB2YXIgc291cmNlID0geyAnZ3JlZXRpbmcnOiAnaGknIH07XG4gICAgICpcbiAgICAgKiBfLmlzTWF0Y2hXaXRoKG9iamVjdCwgc291cmNlLCBjdXN0b21pemVyKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNNYXRjaFdpdGgob2JqZWN0LCBzb3VyY2UsIGN1c3RvbWl6ZXIpIHtcbiAgICAgIGN1c3RvbWl6ZXIgPSB0eXBlb2YgY3VzdG9taXplciA9PSAnZnVuY3Rpb24nID8gY3VzdG9taXplciA6IHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiBiYXNlSXNNYXRjaChvYmplY3QsIHNvdXJjZSwgZ2V0TWF0Y2hEYXRhKHNvdXJjZSksIGN1c3RvbWl6ZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGBOYU5gLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGlzIGJhc2VkIG9uXG4gICAgICogW2BOdW1iZXIuaXNOYU5gXShodHRwczovL21kbi5pby9OdW1iZXIvaXNOYU4pIGFuZCBpcyBub3QgdGhlIHNhbWUgYXNcbiAgICAgKiBnbG9iYWwgW2Bpc05hTmBdKGh0dHBzOi8vbWRuLmlvL2lzTmFOKSB3aGljaCByZXR1cm5zIGB0cnVlYCBmb3JcbiAgICAgKiBgdW5kZWZpbmVkYCBhbmQgb3RoZXIgbm9uLW51bWJlciB2YWx1ZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGBOYU5gLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNOYU4oTmFOKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzTmFOKG5ldyBOdW1iZXIoTmFOKSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogaXNOYU4odW5kZWZpbmVkKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzTmFOKHVuZGVmaW5lZCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc05hTih2YWx1ZSkge1xuICAgICAgLy8gQW4gYE5hTmAgcHJpbWl0aXZlIGlzIHRoZSBvbmx5IHZhbHVlIHRoYXQgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi5cbiAgICAgIC8vIFBlcmZvcm0gdGhlIGB0b1N0cmluZ1RhZ2AgY2hlY2sgZmlyc3QgdG8gYXZvaWQgZXJyb3JzIHdpdGggc29tZVxuICAgICAgLy8gQWN0aXZlWCBvYmplY3RzIGluIElFLlxuICAgICAgcmV0dXJuIGlzTnVtYmVyKHZhbHVlKSAmJiB2YWx1ZSAhPSArdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYSBwcmlzdGluZSBuYXRpdmUgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgY2FuJ3QgcmVsaWFibHkgZGV0ZWN0IG5hdGl2ZSBmdW5jdGlvbnMgaW4gdGhlIHByZXNlbmNlXG4gICAgICogb2YgdGhlIGNvcmUtanMgcGFja2FnZSBiZWNhdXNlIGNvcmUtanMgY2lyY3VtdmVudHMgdGhpcyBraW5kIG9mIGRldGVjdGlvbi5cbiAgICAgKiBEZXNwaXRlIG11bHRpcGxlIHJlcXVlc3RzLCB0aGUgY29yZS1qcyBtYWludGFpbmVyIGhhcyBtYWRlIGl0IGNsZWFyOiBhbnlcbiAgICAgKiBhdHRlbXB0IHRvIGZpeCB0aGUgZGV0ZWN0aW9uIHdpbGwgYmUgb2JzdHJ1Y3RlZC4gQXMgYSByZXN1bHQsIHdlJ3JlIGxlZnRcbiAgICAgKiB3aXRoIGxpdHRsZSBjaG9pY2UgYnV0IHRvIHRocm93IGFuIGVycm9yLiBVbmZvcnR1bmF0ZWx5LCB0aGlzIGFsc28gYWZmZWN0c1xuICAgICAqIHBhY2thZ2VzLCBsaWtlIFtiYWJlbC1wb2x5ZmlsbF0oaHR0cHM6Ly93d3cubnBtanMuY29tL3BhY2thZ2UvYmFiZWwtcG9seWZpbGwpLFxuICAgICAqIHdoaWNoIHJlbHkgb24gY29yZS1qcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBuYXRpdmUgZnVuY3Rpb24sXG4gICAgICogIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc05hdGl2ZShBcnJheS5wcm90b3R5cGUucHVzaCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc05hdGl2ZShfKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTmF0aXZlKHZhbHVlKSB7XG4gICAgICBpZiAoaXNNYXNrYWJsZSh2YWx1ZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKENPUkVfRVJST1JfVEVYVCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYmFzZUlzTmF0aXZlKHZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBgbnVsbGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGBudWxsYCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzTnVsbChudWxsKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzTnVsbCh2b2lkIDApO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNOdWxsKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdmFsdWUgPT09IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYG51bGxgIG9yIGB1bmRlZmluZWRgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBudWxsaXNoLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNOaWwobnVsbCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc05pbCh2b2lkIDApO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNOaWwoTmFOKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTmlsKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdmFsdWUgPT0gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYE51bWJlcmAgcHJpbWl0aXZlIG9yIG9iamVjdC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUbyBleGNsdWRlIGBJbmZpbml0eWAsIGAtSW5maW5pdHlgLCBhbmQgYE5hTmAsIHdoaWNoIGFyZVxuICAgICAqIGNsYXNzaWZpZWQgYXMgbnVtYmVycywgdXNlIHRoZSBgXy5pc0Zpbml0ZWAgbWV0aG9kLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIG51bWJlciwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzTnVtYmVyKDMpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNOdW1iZXIoTnVtYmVyLk1JTl9WQUxVRSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc051bWJlcihJbmZpbml0eSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc051bWJlcignMycpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNOdW1iZXIodmFsdWUpIHtcbiAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gJ251bWJlcicgfHxcbiAgICAgICAgKGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgYmFzZUdldFRhZyh2YWx1ZSkgPT0gbnVtYmVyVGFnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIHBsYWluIG9iamVjdCwgdGhhdCBpcywgYW4gb2JqZWN0IGNyZWF0ZWQgYnkgdGhlXG4gICAgICogYE9iamVjdGAgY29uc3RydWN0b3Igb3Igb25lIHdpdGggYSBgW1tQcm90b3R5cGVdXWAgb2YgYG51bGxgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuOC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHBsYWluIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIF8uaXNQbGFpbk9iamVjdChuZXcgRm9vKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pc1BsYWluT2JqZWN0KFsxLCAyLCAzXSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaXNQbGFpbk9iamVjdCh7ICd4JzogMCwgJ3knOiAwIH0pO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNQbGFpbk9iamVjdChPYmplY3QuY3JlYXRlKG51bGwpKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNQbGFpbk9iamVjdCh2YWx1ZSkge1xuICAgICAgaWYgKCFpc09iamVjdExpa2UodmFsdWUpIHx8IGJhc2VHZXRUYWcodmFsdWUpICE9IG9iamVjdFRhZykge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICB2YXIgcHJvdG8gPSBnZXRQcm90b3R5cGUodmFsdWUpO1xuICAgICAgaWYgKHByb3RvID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgICAgdmFyIEN0b3IgPSBoYXNPd25Qcm9wZXJ0eS5jYWxsKHByb3RvLCAnY29uc3RydWN0b3InKSAmJiBwcm90by5jb25zdHJ1Y3RvcjtcbiAgICAgIHJldHVybiB0eXBlb2YgQ3RvciA9PSAnZnVuY3Rpb24nICYmIEN0b3IgaW5zdGFuY2VvZiBDdG9yICYmXG4gICAgICAgIGZ1bmNUb1N0cmluZy5jYWxsKEN0b3IpID09IG9iamVjdEN0b3JTdHJpbmc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBSZWdFeHBgIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSByZWdleHAsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc1JlZ0V4cCgvYWJjLyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc1JlZ0V4cCgnL2FiYy8nKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBpc1JlZ0V4cCA9IG5vZGVJc1JlZ0V4cCA/IGJhc2VVbmFyeShub2RlSXNSZWdFeHApIDogYmFzZUlzUmVnRXhwO1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYSBzYWZlIGludGVnZXIuIEFuIGludGVnZXIgaXMgc2FmZSBpZiBpdCdzIGFuIElFRUUtNzU0XG4gICAgICogZG91YmxlIHByZWNpc2lvbiBudW1iZXIgd2hpY2ggaXNuJ3QgdGhlIHJlc3VsdCBvZiBhIHJvdW5kZWQgdW5zYWZlIGludGVnZXIuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgYmFzZWQgb25cbiAgICAgKiBbYE51bWJlci5pc1NhZmVJbnRlZ2VyYF0oaHR0cHM6Ly9tZG4uaW8vTnVtYmVyL2lzU2FmZUludGVnZXIpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHNhZmUgaW50ZWdlciwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzU2FmZUludGVnZXIoMyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc1NhZmVJbnRlZ2VyKE51bWJlci5NSU5fVkFMVUUpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzU2FmZUludGVnZXIoSW5maW5pdHkpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBfLmlzU2FmZUludGVnZXIoJzMnKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzU2FmZUludGVnZXIodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc0ludGVnZXIodmFsdWUpICYmIHZhbHVlID49IC1NQVhfU0FGRV9JTlRFR0VSICYmIHZhbHVlIDw9IE1BWF9TQUZFX0lOVEVHRVI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBTZXRgIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjMuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBzZXQsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc1NldChuZXcgU2V0KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmlzU2V0KG5ldyBXZWFrU2V0KTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBpc1NldCA9IG5vZGVJc1NldCA/IGJhc2VVbmFyeShub2RlSXNTZXQpIDogYmFzZUlzU2V0O1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBTdHJpbmdgIHByaW1pdGl2ZSBvciBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgc3RyaW5nLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uaXNTdHJpbmcoJ2FiYycpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNTdHJpbmcoMSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc1N0cmluZyh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJyB8fFxuICAgICAgICAoIWlzQXJyYXkodmFsdWUpICYmIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgYmFzZUdldFRhZyh2YWx1ZSkgPT0gc3RyaW5nVGFnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYFN5bWJvbGAgcHJpbWl0aXZlIG9yIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBzeW1ib2wsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc1N5bWJvbChTeW1ib2wuaXRlcmF0b3IpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNTeW1ib2woJ2FiYycpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNTeW1ib2wodmFsdWUpIHtcbiAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gJ3N5bWJvbCcgfHxcbiAgICAgICAgKGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgYmFzZUdldFRhZyh2YWx1ZSkgPT0gc3ltYm9sVGFnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgdHlwZWQgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgdHlwZWQgYXJyYXksIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pc1R5cGVkQXJyYXkobmV3IFVpbnQ4QXJyYXkpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaXNUeXBlZEFycmF5KFtdKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBpc1R5cGVkQXJyYXkgPSBub2RlSXNUeXBlZEFycmF5ID8gYmFzZVVuYXJ5KG5vZGVJc1R5cGVkQXJyYXkpIDogYmFzZUlzVHlwZWRBcnJheTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGB1bmRlZmluZWRgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBgdW5kZWZpbmVkYCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzVW5kZWZpbmVkKHZvaWQgMCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc1VuZGVmaW5lZChudWxsKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzVW5kZWZpbmVkKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdmFsdWUgPT09IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYFdlYWtNYXBgIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjMuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSB3ZWFrIG1hcCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzV2Vha01hcChuZXcgV2Vha01hcCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc1dlYWtNYXAobmV3IE1hcCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc1dlYWtNYXAodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmIGdldFRhZyh2YWx1ZSkgPT0gd2Vha01hcFRhZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYFdlYWtTZXRgIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjMuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSB3ZWFrIHNldCwgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmlzV2Vha1NldChuZXcgV2Vha1NldCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pc1dlYWtTZXQobmV3IFNldCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc1dlYWtTZXQodmFsdWUpIHtcbiAgICAgIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmIGJhc2VHZXRUYWcodmFsdWUpID09IHdlYWtTZXRUYWc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgbGVzcyB0aGFuIGBvdGhlcmAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy45LjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbXBhcmUuXG4gICAgICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBsZXNzIHRoYW4gYG90aGVyYCxcbiAgICAgKiAgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBzZWUgXy5ndFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmx0KDEsIDMpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8ubHQoMywgMyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8ubHQoMywgMSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICB2YXIgbHQgPSBjcmVhdGVSZWxhdGlvbmFsT3BlcmF0aW9uKGJhc2VMdCk7XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gYG90aGVyYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjkuMFxuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAgICAgKiBAcGFyYW0geyp9IG90aGVyIFRoZSBvdGhlciB2YWx1ZSB0byBjb21wYXJlLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGxlc3MgdGhhbiBvciBlcXVhbCB0b1xuICAgICAqICBgb3RoZXJgLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQHNlZSBfLmd0ZVxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmx0ZSgxLCAzKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmx0ZSgzLCAzKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmx0ZSgzLCAxKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIHZhciBsdGUgPSBjcmVhdGVSZWxhdGlvbmFsT3BlcmF0aW9uKGZ1bmN0aW9uKHZhbHVlLCBvdGhlcikge1xuICAgICAgcmV0dXJuIHZhbHVlIDw9IG90aGVyO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHZhbHVlYCB0byBhbiBhcnJheS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBMYW5nXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBhcnJheS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50b0FycmF5KHsgJ2EnOiAxLCAnYic6IDIgfSk7XG4gICAgICogLy8gPT4gWzEsIDJdXG4gICAgICpcbiAgICAgKiBfLnRvQXJyYXkoJ2FiYycpO1xuICAgICAqIC8vID0+IFsnYScsICdiJywgJ2MnXVxuICAgICAqXG4gICAgICogXy50b0FycmF5KDEpO1xuICAgICAqIC8vID0+IFtdXG4gICAgICpcbiAgICAgKiBfLnRvQXJyYXkobnVsbCk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b0FycmF5KHZhbHVlKSB7XG4gICAgICBpZiAoIXZhbHVlKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIGlmIChpc0FycmF5TGlrZSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIGlzU3RyaW5nKHZhbHVlKSA/IHN0cmluZ1RvQXJyYXkodmFsdWUpIDogY29weUFycmF5KHZhbHVlKTtcbiAgICAgIH1cbiAgICAgIGlmIChzeW1JdGVyYXRvciAmJiB2YWx1ZVtzeW1JdGVyYXRvcl0pIHtcbiAgICAgICAgcmV0dXJuIGl0ZXJhdG9yVG9BcnJheSh2YWx1ZVtzeW1JdGVyYXRvcl0oKSk7XG4gICAgICB9XG4gICAgICB2YXIgdGFnID0gZ2V0VGFnKHZhbHVlKSxcbiAgICAgICAgICBmdW5jID0gdGFnID09IG1hcFRhZyA/IG1hcFRvQXJyYXkgOiAodGFnID09IHNldFRhZyA/IHNldFRvQXJyYXkgOiB2YWx1ZXMpO1xuXG4gICAgICByZXR1cm4gZnVuYyh2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHZhbHVlYCB0byBhIGZpbml0ZSBudW1iZXIuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4xMi4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBudW1iZXIuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udG9GaW5pdGUoMy4yKTtcbiAgICAgKiAvLyA9PiAzLjJcbiAgICAgKlxuICAgICAqIF8udG9GaW5pdGUoTnVtYmVyLk1JTl9WQUxVRSk7XG4gICAgICogLy8gPT4gNWUtMzI0XG4gICAgICpcbiAgICAgKiBfLnRvRmluaXRlKEluZmluaXR5KTtcbiAgICAgKiAvLyA9PiAxLjc5NzY5MzEzNDg2MjMxNTdlKzMwOFxuICAgICAqXG4gICAgICogXy50b0Zpbml0ZSgnMy4yJyk7XG4gICAgICogLy8gPT4gMy4yXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9GaW5pdGUodmFsdWUpIHtcbiAgICAgIGlmICghdmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlID09PSAwID8gdmFsdWUgOiAwO1xuICAgICAgfVxuICAgICAgdmFsdWUgPSB0b051bWJlcih2YWx1ZSk7XG4gICAgICBpZiAodmFsdWUgPT09IElORklOSVRZIHx8IHZhbHVlID09PSAtSU5GSU5JVFkpIHtcbiAgICAgICAgdmFyIHNpZ24gPSAodmFsdWUgPCAwID8gLTEgOiAxKTtcbiAgICAgICAgcmV0dXJuIHNpZ24gKiBNQVhfSU5URUdFUjtcbiAgICAgIH1cbiAgICAgIHJldHVybiB2YWx1ZSA9PT0gdmFsdWUgPyB2YWx1ZSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHZhbHVlYCB0byBhbiBpbnRlZ2VyLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGlzIGxvb3NlbHkgYmFzZWQgb25cbiAgICAgKiBbYFRvSW50ZWdlcmBdKGh0dHA6Ly93d3cuZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy10b2ludGVnZXIpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBpbnRlZ2VyLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRvSW50ZWdlcigzLjIpO1xuICAgICAqIC8vID0+IDNcbiAgICAgKlxuICAgICAqIF8udG9JbnRlZ2VyKE51bWJlci5NSU5fVkFMVUUpO1xuICAgICAqIC8vID0+IDBcbiAgICAgKlxuICAgICAqIF8udG9JbnRlZ2VyKEluZmluaXR5KTtcbiAgICAgKiAvLyA9PiAxLjc5NzY5MzEzNDg2MjMxNTdlKzMwOFxuICAgICAqXG4gICAgICogXy50b0ludGVnZXIoJzMuMicpO1xuICAgICAqIC8vID0+IDNcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b0ludGVnZXIodmFsdWUpIHtcbiAgICAgIHZhciByZXN1bHQgPSB0b0Zpbml0ZSh2YWx1ZSksXG4gICAgICAgICAgcmVtYWluZGVyID0gcmVzdWx0ICUgMTtcblxuICAgICAgcmV0dXJuIHJlc3VsdCA9PT0gcmVzdWx0ID8gKHJlbWFpbmRlciA/IHJlc3VsdCAtIHJlbWFpbmRlciA6IHJlc3VsdCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGB2YWx1ZWAgdG8gYW4gaW50ZWdlciBzdWl0YWJsZSBmb3IgdXNlIGFzIHRoZSBsZW5ndGggb2YgYW5cbiAgICAgKiBhcnJheS1saWtlIG9iamVjdC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBiYXNlZCBvblxuICAgICAqIFtgVG9MZW5ndGhgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy10b2xlbmd0aCkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgY29udmVydGVkIGludGVnZXIuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udG9MZW5ndGgoMy4yKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICpcbiAgICAgKiBfLnRvTGVuZ3RoKE51bWJlci5NSU5fVkFMVUUpO1xuICAgICAqIC8vID0+IDBcbiAgICAgKlxuICAgICAqIF8udG9MZW5ndGgoSW5maW5pdHkpO1xuICAgICAqIC8vID0+IDQyOTQ5NjcyOTVcbiAgICAgKlxuICAgICAqIF8udG9MZW5ndGgoJzMuMicpO1xuICAgICAqIC8vID0+IDNcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b0xlbmd0aCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlID8gYmFzZUNsYW1wKHRvSW50ZWdlcih2YWx1ZSksIDAsIE1BWF9BUlJBWV9MRU5HVEgpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGEgbnVtYmVyLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IExhbmdcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBwcm9jZXNzLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIG51bWJlci5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50b051bWJlcigzLjIpO1xuICAgICAqIC8vID0+IDMuMlxuICAgICAqXG4gICAgICogXy50b051bWJlcihOdW1iZXIuTUlOX1ZBTFVFKTtcbiAgICAgKiAvLyA9PiA1ZS0zMjRcbiAgICAgKlxuICAgICAqIF8udG9OdW1iZXIoSW5maW5pdHkpO1xuICAgICAqIC8vID0+IEluZmluaXR5XG4gICAgICpcbiAgICAgKiBfLnRvTnVtYmVyKCczLjInKTtcbiAgICAgKiAvLyA9PiAzLjJcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b051bWJlcih2YWx1ZSkge1xuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PSAnbnVtYmVyJykge1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICB9XG4gICAgICBpZiAoaXNTeW1ib2wodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiBOQU47XG4gICAgICB9XG4gICAgICBpZiAoaXNPYmplY3QodmFsdWUpKSB7XG4gICAgICAgIHZhciBvdGhlciA9IHR5cGVvZiB2YWx1ZS52YWx1ZU9mID09ICdmdW5jdGlvbicgPyB2YWx1ZS52YWx1ZU9mKCkgOiB2YWx1ZTtcbiAgICAgICAgdmFsdWUgPSBpc09iamVjdChvdGhlcikgPyAob3RoZXIgKyAnJykgOiBvdGhlcjtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlID09PSAwID8gdmFsdWUgOiArdmFsdWU7XG4gICAgICB9XG4gICAgICB2YWx1ZSA9IHZhbHVlLnJlcGxhY2UocmVUcmltLCAnJyk7XG4gICAgICB2YXIgaXNCaW5hcnkgPSByZUlzQmluYXJ5LnRlc3QodmFsdWUpO1xuICAgICAgcmV0dXJuIChpc0JpbmFyeSB8fCByZUlzT2N0YWwudGVzdCh2YWx1ZSkpXG4gICAgICAgID8gZnJlZVBhcnNlSW50KHZhbHVlLnNsaWNlKDIpLCBpc0JpbmFyeSA/IDIgOiA4KVxuICAgICAgICA6IChyZUlzQmFkSGV4LnRlc3QodmFsdWUpID8gTkFOIDogK3ZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGEgcGxhaW4gb2JqZWN0IGZsYXR0ZW5pbmcgaW5oZXJpdGVkIGVudW1lcmFibGUgc3RyaW5nXG4gICAgICoga2V5ZWQgcHJvcGVydGllcyBvZiBgdmFsdWVgIHRvIG93biBwcm9wZXJ0aWVzIG9mIHRoZSBwbGFpbiBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY29udmVydGVkIHBsYWluIG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy5hc3NpZ24oeyAnYSc6IDEgfSwgbmV3IEZvbyk7XG4gICAgICogLy8gPT4geyAnYSc6IDEsICdiJzogMiB9XG4gICAgICpcbiAgICAgKiBfLmFzc2lnbih7ICdhJzogMSB9LCBfLnRvUGxhaW5PYmplY3QobmV3IEZvbykpO1xuICAgICAqIC8vID0+IHsgJ2EnOiAxLCAnYic6IDIsICdjJzogMyB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9QbGFpbk9iamVjdCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIGNvcHlPYmplY3QodmFsdWUsIGtleXNJbih2YWx1ZSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGB2YWx1ZWAgdG8gYSBzYWZlIGludGVnZXIuIEEgc2FmZSBpbnRlZ2VyIGNhbiBiZSBjb21wYXJlZCBhbmRcbiAgICAgKiByZXByZXNlbnRlZCBjb3JyZWN0bHkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgY29udmVydGVkIGludGVnZXIuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udG9TYWZlSW50ZWdlcigzLjIpO1xuICAgICAqIC8vID0+IDNcbiAgICAgKlxuICAgICAqIF8udG9TYWZlSW50ZWdlcihOdW1iZXIuTUlOX1ZBTFVFKTtcbiAgICAgKiAvLyA9PiAwXG4gICAgICpcbiAgICAgKiBfLnRvU2FmZUludGVnZXIoSW5maW5pdHkpO1xuICAgICAqIC8vID0+IDkwMDcxOTkyNTQ3NDA5OTFcbiAgICAgKlxuICAgICAqIF8udG9TYWZlSW50ZWdlcignMy4yJyk7XG4gICAgICogLy8gPT4gM1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRvU2FmZUludGVnZXIodmFsdWUpIHtcbiAgICAgIHJldHVybiB2YWx1ZVxuICAgICAgICA/IGJhc2VDbGFtcCh0b0ludGVnZXIodmFsdWUpLCAtTUFYX1NBRkVfSU5URUdFUiwgTUFYX1NBRkVfSU5URUdFUilcbiAgICAgICAgOiAodmFsdWUgPT09IDAgPyB2YWx1ZSA6IDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGB2YWx1ZWAgdG8gYSBzdHJpbmcuIEFuIGVtcHR5IHN0cmluZyBpcyByZXR1cm5lZCBmb3IgYG51bGxgXG4gICAgICogYW5kIGB1bmRlZmluZWRgIHZhbHVlcy4gVGhlIHNpZ24gb2YgYC0wYCBpcyBwcmVzZXJ2ZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTGFuZ1xuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgY29udmVydGVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50b1N0cmluZyhudWxsKTtcbiAgICAgKiAvLyA9PiAnJ1xuICAgICAqXG4gICAgICogXy50b1N0cmluZygtMCk7XG4gICAgICogLy8gPT4gJy0wJ1xuICAgICAqXG4gICAgICogXy50b1N0cmluZyhbMSwgMiwgM10pO1xuICAgICAqIC8vID0+ICcxLDIsMydcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b1N0cmluZyh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlID09IG51bGwgPyAnJyA6IGJhc2VUb1N0cmluZyh2YWx1ZSk7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQXNzaWducyBvd24gZW51bWVyYWJsZSBzdHJpbmcga2V5ZWQgcHJvcGVydGllcyBvZiBzb3VyY2Ugb2JqZWN0cyB0byB0aGVcbiAgICAgKiBkZXN0aW5hdGlvbiBvYmplY3QuIFNvdXJjZSBvYmplY3RzIGFyZSBhcHBsaWVkIGZyb20gbGVmdCB0byByaWdodC5cbiAgICAgKiBTdWJzZXF1ZW50IHNvdXJjZXMgb3ZlcndyaXRlIHByb3BlcnR5IGFzc2lnbm1lbnRzIG9mIHByZXZpb3VzIHNvdXJjZXMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgb2JqZWN0YCBhbmQgaXMgbG9vc2VseSBiYXNlZCBvblxuICAgICAqIFtgT2JqZWN0LmFzc2lnbmBdKGh0dHBzOi8vbWRuLmlvL09iamVjdC9hc3NpZ24pLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuMTAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHsuLi5PYmplY3R9IFtzb3VyY2VzXSBUaGUgc291cmNlIG9iamVjdHMuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAc2VlIF8uYXNzaWduSW5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBCYXIoKSB7XG4gICAgICogICB0aGlzLmMgPSAzO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYiA9IDI7XG4gICAgICogQmFyLnByb3RvdHlwZS5kID0gNDtcbiAgICAgKlxuICAgICAqIF8uYXNzaWduKHsgJ2EnOiAwIH0sIG5ldyBGb28sIG5ldyBCYXIpO1xuICAgICAqIC8vID0+IHsgJ2EnOiAxLCAnYyc6IDMgfVxuICAgICAqL1xuICAgIHZhciBhc3NpZ24gPSBjcmVhdGVBc3NpZ25lcihmdW5jdGlvbihvYmplY3QsIHNvdXJjZSkge1xuICAgICAgaWYgKGlzUHJvdG90eXBlKHNvdXJjZSkgfHwgaXNBcnJheUxpa2Uoc291cmNlKSkge1xuICAgICAgICBjb3B5T2JqZWN0KHNvdXJjZSwga2V5cyhzb3VyY2UpLCBvYmplY3QpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBmb3IgKHZhciBrZXkgaW4gc291cmNlKSB7XG4gICAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKHNvdXJjZSwga2V5KSkge1xuICAgICAgICAgIGFzc2lnblZhbHVlKG9iamVjdCwga2V5LCBzb3VyY2Vba2V5XSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uYXNzaWduYCBleGNlcHQgdGhhdCBpdCBpdGVyYXRlcyBvdmVyIG93biBhbmRcbiAgICAgKiBpbmhlcml0ZWQgc291cmNlIHByb3BlcnRpZXMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBhbGlhcyBleHRlbmRcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7Li4uT2JqZWN0fSBbc291cmNlc10gVGhlIHNvdXJjZSBvYmplY3RzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQHNlZSBfLmFzc2lnblxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEJhcigpIHtcbiAgICAgKiAgIHRoaXMuYyA9IDM7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5iID0gMjtcbiAgICAgKiBCYXIucHJvdG90eXBlLmQgPSA0O1xuICAgICAqXG4gICAgICogXy5hc3NpZ25Jbih7ICdhJzogMCB9LCBuZXcgRm9vLCBuZXcgQmFyKTtcbiAgICAgKiAvLyA9PiB7ICdhJzogMSwgJ2InOiAyLCAnYyc6IDMsICdkJzogNCB9XG4gICAgICovXG4gICAgdmFyIGFzc2lnbkluID0gY3JlYXRlQXNzaWduZXIoZnVuY3Rpb24ob2JqZWN0LCBzb3VyY2UpIHtcbiAgICAgIGNvcHlPYmplY3Qoc291cmNlLCBrZXlzSW4oc291cmNlKSwgb2JqZWN0KTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uYXNzaWduSW5gIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGN1c3RvbWl6ZXJgXG4gICAgICogd2hpY2ggaXMgaW52b2tlZCB0byBwcm9kdWNlIHRoZSBhc3NpZ25lZCB2YWx1ZXMuIElmIGBjdXN0b21pemVyYCByZXR1cm5zXG4gICAgICogYHVuZGVmaW5lZGAsIGFzc2lnbm1lbnQgaXMgaGFuZGxlZCBieSB0aGUgbWV0aG9kIGluc3RlYWQuIFRoZSBgY3VzdG9taXplcmBcbiAgICAgKiBpcyBpbnZva2VkIHdpdGggZml2ZSBhcmd1bWVudHM6IChvYmpWYWx1ZSwgc3JjVmFsdWUsIGtleSwgb2JqZWN0LCBzb3VyY2UpLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAYWxpYXMgZXh0ZW5kV2l0aFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHsuLi5PYmplY3R9IHNvdXJjZXMgVGhlIHNvdXJjZSBvYmplY3RzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGFzc2lnbmVkIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBzZWUgXy5hc3NpZ25XaXRoXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIGN1c3RvbWl6ZXIob2JqVmFsdWUsIHNyY1ZhbHVlKSB7XG4gICAgICogICByZXR1cm4gXy5pc1VuZGVmaW5lZChvYmpWYWx1ZSkgPyBzcmNWYWx1ZSA6IG9ialZhbHVlO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHZhciBkZWZhdWx0cyA9IF8ucGFydGlhbFJpZ2h0KF8uYXNzaWduSW5XaXRoLCBjdXN0b21pemVyKTtcbiAgICAgKlxuICAgICAqIGRlZmF1bHRzKHsgJ2EnOiAxIH0sIHsgJ2InOiAyIH0sIHsgJ2EnOiAzIH0pO1xuICAgICAqIC8vID0+IHsgJ2EnOiAxLCAnYic6IDIgfVxuICAgICAqL1xuICAgIHZhciBhc3NpZ25JbldpdGggPSBjcmVhdGVBc3NpZ25lcihmdW5jdGlvbihvYmplY3QsIHNvdXJjZSwgc3JjSW5kZXgsIGN1c3RvbWl6ZXIpIHtcbiAgICAgIGNvcHlPYmplY3Qoc291cmNlLCBrZXlzSW4oc291cmNlKSwgb2JqZWN0LCBjdXN0b21pemVyKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uYXNzaWduYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBjdXN0b21pemVyYFxuICAgICAqIHdoaWNoIGlzIGludm9rZWQgdG8gcHJvZHVjZSB0aGUgYXNzaWduZWQgdmFsdWVzLiBJZiBgY3VzdG9taXplcmAgcmV0dXJuc1xuICAgICAqIGB1bmRlZmluZWRgLCBhc3NpZ25tZW50IGlzIGhhbmRsZWQgYnkgdGhlIG1ldGhvZCBpbnN0ZWFkLiBUaGUgYGN1c3RvbWl6ZXJgXG4gICAgICogaXMgaW52b2tlZCB3aXRoIGZpdmUgYXJndW1lbnRzOiAob2JqVmFsdWUsIHNyY1ZhbHVlLCBrZXksIG9iamVjdCwgc291cmNlKS5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBtdXRhdGVzIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0gey4uLk9iamVjdH0gc291cmNlcyBUaGUgc291cmNlIG9iamVjdHMuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgYXNzaWduZWQgdmFsdWVzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQHNlZSBfLmFzc2lnbkluV2l0aFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBjdXN0b21pemVyKG9ialZhbHVlLCBzcmNWYWx1ZSkge1xuICAgICAqICAgcmV0dXJuIF8uaXNVbmRlZmluZWQob2JqVmFsdWUpID8gc3JjVmFsdWUgOiBvYmpWYWx1ZTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiB2YXIgZGVmYXVsdHMgPSBfLnBhcnRpYWxSaWdodChfLmFzc2lnbldpdGgsIGN1c3RvbWl6ZXIpO1xuICAgICAqXG4gICAgICogZGVmYXVsdHMoeyAnYSc6IDEgfSwgeyAnYic6IDIgfSwgeyAnYSc6IDMgfSk7XG4gICAgICogLy8gPT4geyAnYSc6IDEsICdiJzogMiB9XG4gICAgICovXG4gICAgdmFyIGFzc2lnbldpdGggPSBjcmVhdGVBc3NpZ25lcihmdW5jdGlvbihvYmplY3QsIHNvdXJjZSwgc3JjSW5kZXgsIGN1c3RvbWl6ZXIpIHtcbiAgICAgIGNvcHlPYmplY3Qoc291cmNlLCBrZXlzKHNvdXJjZSksIG9iamVjdCwgY3VzdG9taXplcik7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIHZhbHVlcyBjb3JyZXNwb25kaW5nIHRvIGBwYXRoc2Agb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMS4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0gey4uLihzdHJpbmd8c3RyaW5nW10pfSBbcGF0aHNdIFRoZSBwcm9wZXJ0eSBwYXRocyB0byBwaWNrLlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgcGlja2VkIHZhbHVlcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiBbeyAnYic6IHsgJ2MnOiAzIH0gfSwgNF0gfTtcbiAgICAgKlxuICAgICAqIF8uYXQob2JqZWN0LCBbJ2FbMF0uYi5jJywgJ2FbMV0nXSk7XG4gICAgICogLy8gPT4gWzMsIDRdXG4gICAgICovXG4gICAgdmFyIGF0ID0gZmxhdFJlc3QoYmFzZUF0KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gb2JqZWN0IHRoYXQgaW5oZXJpdHMgZnJvbSB0aGUgYHByb3RvdHlwZWAgb2JqZWN0LiBJZiBhXG4gICAgICogYHByb3BlcnRpZXNgIG9iamVjdCBpcyBnaXZlbiwgaXRzIG93biBlbnVtZXJhYmxlIHN0cmluZyBrZXllZCBwcm9wZXJ0aWVzXG4gICAgICogYXJlIGFzc2lnbmVkIHRvIHRoZSBjcmVhdGVkIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAyLjMuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcHJvdG90eXBlIFRoZSBvYmplY3QgdG8gaW5oZXJpdCBmcm9tLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbcHJvcGVydGllc10gVGhlIHByb3BlcnRpZXMgdG8gYXNzaWduIHRvIHRoZSBvYmplY3QuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gU2hhcGUoKSB7XG4gICAgICogICB0aGlzLnggPSAwO1xuICAgICAqICAgdGhpcy55ID0gMDtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBDaXJjbGUoKSB7XG4gICAgICogICBTaGFwZS5jYWxsKHRoaXMpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIENpcmNsZS5wcm90b3R5cGUgPSBfLmNyZWF0ZShTaGFwZS5wcm90b3R5cGUsIHtcbiAgICAgKiAgICdjb25zdHJ1Y3Rvcic6IENpcmNsZVxuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogdmFyIGNpcmNsZSA9IG5ldyBDaXJjbGU7XG4gICAgICogY2lyY2xlIGluc3RhbmNlb2YgQ2lyY2xlO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIGNpcmNsZSBpbnN0YW5jZW9mIFNoYXBlO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGUocHJvdG90eXBlLCBwcm9wZXJ0aWVzKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gYmFzZUNyZWF0ZShwcm90b3R5cGUpO1xuICAgICAgcmV0dXJuIHByb3BlcnRpZXMgPT0gbnVsbCA/IHJlc3VsdCA6IGJhc2VBc3NpZ24ocmVzdWx0LCBwcm9wZXJ0aWVzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBc3NpZ25zIG93biBhbmQgaW5oZXJpdGVkIGVudW1lcmFibGUgc3RyaW5nIGtleWVkIHByb3BlcnRpZXMgb2Ygc291cmNlXG4gICAgICogb2JqZWN0cyB0byB0aGUgZGVzdGluYXRpb24gb2JqZWN0IGZvciBhbGwgZGVzdGluYXRpb24gcHJvcGVydGllcyB0aGF0XG4gICAgICogcmVzb2x2ZSB0byBgdW5kZWZpbmVkYC4gU291cmNlIG9iamVjdHMgYXJlIGFwcGxpZWQgZnJvbSBsZWZ0IHRvIHJpZ2h0LlxuICAgICAqIE9uY2UgYSBwcm9wZXJ0eSBpcyBzZXQsIGFkZGl0aW9uYWwgdmFsdWVzIG9mIHRoZSBzYW1lIHByb3BlcnR5IGFyZSBpZ25vcmVkLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7Li4uT2JqZWN0fSBbc291cmNlc10gVGhlIHNvdXJjZSBvYmplY3RzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQHNlZSBfLmRlZmF1bHRzRGVlcFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRlZmF1bHRzKHsgJ2EnOiAxIH0sIHsgJ2InOiAyIH0sIHsgJ2EnOiAzIH0pO1xuICAgICAqIC8vID0+IHsgJ2EnOiAxLCAnYic6IDIgfVxuICAgICAqL1xuICAgIHZhciBkZWZhdWx0cyA9IGJhc2VSZXN0KGZ1bmN0aW9uKGFyZ3MpIHtcbiAgICAgIGFyZ3MucHVzaCh1bmRlZmluZWQsIGN1c3RvbURlZmF1bHRzQXNzaWduSW4pO1xuICAgICAgcmV0dXJuIGFwcGx5KGFzc2lnbkluV2l0aCwgdW5kZWZpbmVkLCBhcmdzKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZGVmYXVsdHNgIGV4Y2VwdCB0aGF0IGl0IHJlY3Vyc2l2ZWx5IGFzc2lnbnNcbiAgICAgKiBkZWZhdWx0IHByb3BlcnRpZXMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjEwLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7Li4uT2JqZWN0fSBbc291cmNlc10gVGhlIHNvdXJjZSBvYmplY3RzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQHNlZSBfLmRlZmF1bHRzXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZGVmYXVsdHNEZWVwKHsgJ2EnOiB7ICdiJzogMiB9IH0sIHsgJ2EnOiB7ICdiJzogMSwgJ2MnOiAzIH0gfSk7XG4gICAgICogLy8gPT4geyAnYSc6IHsgJ2InOiAyLCAnYyc6IDMgfSB9XG4gICAgICovXG4gICAgdmFyIGRlZmF1bHRzRGVlcCA9IGJhc2VSZXN0KGZ1bmN0aW9uKGFyZ3MpIHtcbiAgICAgIGFyZ3MucHVzaCh1bmRlZmluZWQsIGN1c3RvbURlZmF1bHRzTWVyZ2UpO1xuICAgICAgcmV0dXJuIGFwcGx5KG1lcmdlV2l0aCwgdW5kZWZpbmVkLCBhcmdzKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZmluZGAgZXhjZXB0IHRoYXQgaXQgcmV0dXJucyB0aGUga2V5IG9mIHRoZSBmaXJzdFxuICAgICAqIGVsZW1lbnQgYHByZWRpY2F0ZWAgcmV0dXJucyB0cnV0aHkgZm9yIGluc3RlYWQgb2YgdGhlIGVsZW1lbnQgaXRzZWxmLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDEuMS4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfHVuZGVmaW5lZH0gUmV0dXJucyB0aGUga2V5IG9mIHRoZSBtYXRjaGVkIGVsZW1lbnQsXG4gICAgICogIGVsc2UgYHVuZGVmaW5lZGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IHtcbiAgICAgKiAgICdiYXJuZXknOiAgeyAnYWdlJzogMzYsICdhY3RpdmUnOiB0cnVlIH0sXG4gICAgICogICAnZnJlZCc6ICAgIHsgJ2FnZSc6IDQwLCAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgICdwZWJibGVzJzogeyAnYWdlJzogMSwgICdhY3RpdmUnOiB0cnVlIH1cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogXy5maW5kS2V5KHVzZXJzLCBmdW5jdGlvbihvKSB7IHJldHVybiBvLmFnZSA8IDQwOyB9KTtcbiAgICAgKiAvLyA9PiAnYmFybmV5JyAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbmRLZXkodXNlcnMsIHsgJ2FnZSc6IDEsICdhY3RpdmUnOiB0cnVlIH0pO1xuICAgICAqIC8vID0+ICdwZWJibGVzJ1xuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmluZEtleSh1c2VycywgWydhY3RpdmUnLCBmYWxzZV0pO1xuICAgICAqIC8vID0+ICdmcmVkJ1xuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5maW5kS2V5KHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gJ2Jhcm5leSdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmaW5kS2V5KG9iamVjdCwgcHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gYmFzZUZpbmRLZXkob2JqZWN0LCBnZXRJdGVyYXRlZShwcmVkaWNhdGUsIDMpLCBiYXNlRm9yT3duKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZpbmRLZXlgIGV4Y2VwdCB0aGF0IGl0IGl0ZXJhdGVzIG92ZXIgZWxlbWVudHMgb2ZcbiAgICAgKiBhIGNvbGxlY3Rpb24gaW4gdGhlIG9wcG9zaXRlIG9yZGVyLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDIuMC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtwcmVkaWNhdGU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfHVuZGVmaW5lZH0gUmV0dXJucyB0aGUga2V5IG9mIHRoZSBtYXRjaGVkIGVsZW1lbnQsXG4gICAgICogIGVsc2UgYHVuZGVmaW5lZGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IHtcbiAgICAgKiAgICdiYXJuZXknOiAgeyAnYWdlJzogMzYsICdhY3RpdmUnOiB0cnVlIH0sXG4gICAgICogICAnZnJlZCc6ICAgIHsgJ2FnZSc6IDQwLCAnYWN0aXZlJzogZmFsc2UgfSxcbiAgICAgKiAgICdwZWJibGVzJzogeyAnYWdlJzogMSwgICdhY3RpdmUnOiB0cnVlIH1cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogXy5maW5kTGFzdEtleSh1c2VycywgZnVuY3Rpb24obykgeyByZXR1cm4gby5hZ2UgPCA0MDsgfSk7XG4gICAgICogLy8gPT4gcmV0dXJucyAncGViYmxlcycgYXNzdW1pbmcgYF8uZmluZEtleWAgcmV0dXJucyAnYmFybmV5J1xuICAgICAqXG4gICAgICogLy8gVGhlIGBfLm1hdGNoZXNgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbmRMYXN0S2V5KHVzZXJzLCB7ICdhZ2UnOiAzNiwgJ2FjdGl2ZSc6IHRydWUgfSk7XG4gICAgICogLy8gPT4gJ2Jhcm5leSdcbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbmRMYXN0S2V5KHVzZXJzLCBbJ2FjdGl2ZScsIGZhbHNlXSk7XG4gICAgICogLy8gPT4gJ2ZyZWQnXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbmRMYXN0S2V5KHVzZXJzLCAnYWN0aXZlJyk7XG4gICAgICogLy8gPT4gJ3BlYmJsZXMnXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmluZExhc3RLZXkob2JqZWN0LCBwcmVkaWNhdGUpIHtcbiAgICAgIHJldHVybiBiYXNlRmluZEtleShvYmplY3QsIGdldEl0ZXJhdGVlKHByZWRpY2F0ZSwgMyksIGJhc2VGb3JPd25SaWdodCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSXRlcmF0ZXMgb3ZlciBvd24gYW5kIGluaGVyaXRlZCBlbnVtZXJhYmxlIHN0cmluZyBrZXllZCBwcm9wZXJ0aWVzIG9mIGFuXG4gICAgICogb2JqZWN0IGFuZCBpbnZva2VzIGBpdGVyYXRlZWAgZm9yIGVhY2ggcHJvcGVydHkuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkXG4gICAgICogd2l0aCB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwga2V5LCBvYmplY3QpLiBJdGVyYXRlZSBmdW5jdGlvbnMgbWF5IGV4aXRcbiAgICAgKiBpdGVyYXRpb24gZWFybHkgYnkgZXhwbGljaXRseSByZXR1cm5pbmcgYGZhbHNlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjMuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQHNlZSBfLmZvckluUmlnaHRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiAgIHRoaXMuYiA9IDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAgICAgKlxuICAgICAqIF8uZm9ySW4obmV3IEZvbywgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAqICAgY29uc29sZS5sb2coa2V5KTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBMb2dzICdhJywgJ2InLCB0aGVuICdjJyAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmb3JJbihvYmplY3QsIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGxcbiAgICAgICAgPyBvYmplY3RcbiAgICAgICAgOiBiYXNlRm9yKG9iamVjdCwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDMpLCBrZXlzSW4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uZm9ySW5gIGV4Y2VwdCB0aGF0IGl0IGl0ZXJhdGVzIG92ZXIgcHJvcGVydGllcyBvZlxuICAgICAqIGBvYmplY3RgIGluIHRoZSBvcHBvc2l0ZSBvcmRlci5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAyLjAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQHNlZSBfLmZvckluXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYSA9IDE7XG4gICAgICogICB0aGlzLmIgPSAyO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYyA9IDM7XG4gICAgICpcbiAgICAgKiBfLmZvckluUmlnaHQobmV3IEZvbywgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAqICAgY29uc29sZS5sb2coa2V5KTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBMb2dzICdjJywgJ2InLCB0aGVuICdhJyBhc3N1bWluZyBgXy5mb3JJbmAgbG9ncyAnYScsICdiJywgdGhlbiAnYycuXG4gICAgICovXG4gICAgZnVuY3Rpb24gZm9ySW5SaWdodChvYmplY3QsIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGxcbiAgICAgICAgPyBvYmplY3RcbiAgICAgICAgOiBiYXNlRm9yUmlnaHQob2JqZWN0LCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMyksIGtleXNJbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSXRlcmF0ZXMgb3ZlciBvd24gZW51bWVyYWJsZSBzdHJpbmcga2V5ZWQgcHJvcGVydGllcyBvZiBhbiBvYmplY3QgYW5kXG4gICAgICogaW52b2tlcyBgaXRlcmF0ZWVgIGZvciBlYWNoIHByb3BlcnR5LiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIHRocmVlXG4gICAgICogYXJndW1lbnRzOiAodmFsdWUsIGtleSwgb2JqZWN0KS4gSXRlcmF0ZWUgZnVuY3Rpb25zIG1heSBleGl0IGl0ZXJhdGlvblxuICAgICAqIGVhcmx5IGJ5IGV4cGxpY2l0bHkgcmV0dXJuaW5nIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC4zLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBzZWUgXy5mb3JPd25SaWdodFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy5mb3JPd24obmV3IEZvbywgZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAqICAgY29uc29sZS5sb2coa2V5KTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiBMb2dzICdhJyB0aGVuICdiJyAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmb3JPd24ob2JqZWN0LCBpdGVyYXRlZSkge1xuICAgICAgcmV0dXJuIG9iamVjdCAmJiBiYXNlRm9yT3duKG9iamVjdCwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDMpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmZvck93bmAgZXhjZXB0IHRoYXQgaXQgaXRlcmF0ZXMgb3ZlciBwcm9wZXJ0aWVzIG9mXG4gICAgICogYG9iamVjdGAgaW4gdGhlIG9wcG9zaXRlIG9yZGVyLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDIuMC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAc2VlIF8uZm9yT3duXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYSA9IDE7XG4gICAgICogICB0aGlzLmIgPSAyO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYyA9IDM7XG4gICAgICpcbiAgICAgKiBfLmZvck93blJpZ2h0KG5ldyBGb28sIGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKGtleSk7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4gTG9ncyAnYicgdGhlbiAnYScgYXNzdW1pbmcgYF8uZm9yT3duYCBsb2dzICdhJyB0aGVuICdiJy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmb3JPd25SaWdodChvYmplY3QsIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ICYmIGJhc2VGb3JPd25SaWdodChvYmplY3QsIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAzKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBmdW5jdGlvbiBwcm9wZXJ0eSBuYW1lcyBmcm9tIG93biBlbnVtZXJhYmxlIHByb3BlcnRpZXNcbiAgICAgKiBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW5zcGVjdC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGZ1bmN0aW9uIG5hbWVzLlxuICAgICAqIEBzZWUgXy5mdW5jdGlvbnNJblxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSBfLmNvbnN0YW50KCdhJyk7XG4gICAgICogICB0aGlzLmIgPSBfLmNvbnN0YW50KCdiJyk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gXy5jb25zdGFudCgnYycpO1xuICAgICAqXG4gICAgICogXy5mdW5jdGlvbnMobmV3IEZvbyk7XG4gICAgICogLy8gPT4gWydhJywgJ2InXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZ1bmN0aW9ucyhvYmplY3QpIHtcbiAgICAgIHJldHVybiBvYmplY3QgPT0gbnVsbCA/IFtdIDogYmFzZUZ1bmN0aW9ucyhvYmplY3QsIGtleXMob2JqZWN0KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBmdW5jdGlvbiBwcm9wZXJ0eSBuYW1lcyBmcm9tIG93biBhbmQgaW5oZXJpdGVkXG4gICAgICogZW51bWVyYWJsZSBwcm9wZXJ0aWVzIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpbnNwZWN0LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgZnVuY3Rpb24gbmFtZXMuXG4gICAgICogQHNlZSBfLmZ1bmN0aW9uc1xuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSBfLmNvbnN0YW50KCdhJyk7XG4gICAgICogICB0aGlzLmIgPSBfLmNvbnN0YW50KCdiJyk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gXy5jb25zdGFudCgnYycpO1xuICAgICAqXG4gICAgICogXy5mdW5jdGlvbnNJbihuZXcgRm9vKTtcbiAgICAgKiAvLyA9PiBbJ2EnLCAnYicsICdjJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmdW5jdGlvbnNJbihvYmplY3QpIHtcbiAgICAgIHJldHVybiBvYmplY3QgPT0gbnVsbCA/IFtdIDogYmFzZUZ1bmN0aW9ucyhvYmplY3QsIGtleXNJbihvYmplY3QpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSB2YWx1ZSBhdCBgcGF0aGAgb2YgYG9iamVjdGAuIElmIHRoZSByZXNvbHZlZCB2YWx1ZSBpc1xuICAgICAqIGB1bmRlZmluZWRgLCB0aGUgYGRlZmF1bHRWYWx1ZWAgaXMgcmV0dXJuZWQgaW4gaXRzIHBsYWNlLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuNy4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICAgICAqIEBwYXJhbSB7Kn0gW2RlZmF1bHRWYWx1ZV0gVGhlIHZhbHVlIHJldHVybmVkIGZvciBgdW5kZWZpbmVkYCByZXNvbHZlZCB2YWx1ZXMuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJlc29sdmVkIHZhbHVlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IFt7ICdiJzogeyAnYyc6IDMgfSB9XSB9O1xuICAgICAqXG4gICAgICogXy5nZXQob2JqZWN0LCAnYVswXS5iLmMnKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICpcbiAgICAgKiBfLmdldChvYmplY3QsIFsnYScsICcwJywgJ2InLCAnYyddKTtcbiAgICAgKiAvLyA9PiAzXG4gICAgICpcbiAgICAgKiBfLmdldChvYmplY3QsICdhLmIuYycsICdkZWZhdWx0Jyk7XG4gICAgICogLy8gPT4gJ2RlZmF1bHQnXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0KG9iamVjdCwgcGF0aCwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICB2YXIgcmVzdWx0ID0gb2JqZWN0ID09IG51bGwgPyB1bmRlZmluZWQgOiBiYXNlR2V0KG9iamVjdCwgcGF0aCk7XG4gICAgICByZXR1cm4gcmVzdWx0ID09PSB1bmRlZmluZWQgPyBkZWZhdWx0VmFsdWUgOiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGBwYXRoYCBpcyBhIGRpcmVjdCBwcm9wZXJ0eSBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGBwYXRoYCBleGlzdHMsIGVsc2UgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiB7ICdiJzogMiB9IH07XG4gICAgICogdmFyIG90aGVyID0gXy5jcmVhdGUoeyAnYSc6IF8uY3JlYXRlKHsgJ2InOiAyIH0pIH0pO1xuICAgICAqXG4gICAgICogXy5oYXMob2JqZWN0LCAnYScpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaGFzKG9iamVjdCwgJ2EuYicpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaGFzKG9iamVjdCwgWydhJywgJ2InXSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5oYXMob3RoZXIsICdhJyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBoYXMob2JqZWN0LCBwYXRoKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ICE9IG51bGwgJiYgaGFzUGF0aChvYmplY3QsIHBhdGgsIGJhc2VIYXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgcGF0aGAgaXMgYSBkaXJlY3Qgb3IgaW5oZXJpdGVkIHByb3BlcnR5IG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHBhdGhgIGV4aXN0cywgZWxzZSBgZmFsc2VgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0gXy5jcmVhdGUoeyAnYSc6IF8uY3JlYXRlKHsgJ2InOiAyIH0pIH0pO1xuICAgICAqXG4gICAgICogXy5oYXNJbihvYmplY3QsICdhJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5oYXNJbihvYmplY3QsICdhLmInKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmhhc0luKG9iamVjdCwgWydhJywgJ2InXSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5oYXNJbihvYmplY3QsICdiJyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBoYXNJbihvYmplY3QsIHBhdGgpIHtcbiAgICAgIHJldHVybiBvYmplY3QgIT0gbnVsbCAmJiBoYXNQYXRoKG9iamVjdCwgcGF0aCwgYmFzZUhhc0luKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIG9iamVjdCBjb21wb3NlZCBvZiB0aGUgaW52ZXJ0ZWQga2V5cyBhbmQgdmFsdWVzIG9mIGBvYmplY3RgLlxuICAgICAqIElmIGBvYmplY3RgIGNvbnRhaW5zIGR1cGxpY2F0ZSB2YWx1ZXMsIHN1YnNlcXVlbnQgdmFsdWVzIG92ZXJ3cml0ZVxuICAgICAqIHByb3BlcnR5IGFzc2lnbm1lbnRzIG9mIHByZXZpb3VzIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjcuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaW52ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBpbnZlcnRlZCBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogMSwgJ2InOiAyLCAnYyc6IDEgfTtcbiAgICAgKlxuICAgICAqIF8uaW52ZXJ0KG9iamVjdCk7XG4gICAgICogLy8gPT4geyAnMSc6ICdjJywgJzInOiAnYicgfVxuICAgICAqL1xuICAgIHZhciBpbnZlcnQgPSBjcmVhdGVJbnZlcnRlcihmdW5jdGlvbihyZXN1bHQsIHZhbHVlLCBrZXkpIHtcbiAgICAgIHJlc3VsdFt2YWx1ZV0gPSBrZXk7XG4gICAgfSwgY29uc3RhbnQoaWRlbnRpdHkpKTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uaW52ZXJ0YCBleGNlcHQgdGhhdCB0aGUgaW52ZXJ0ZWQgb2JqZWN0IGlzIGdlbmVyYXRlZFxuICAgICAqIGZyb20gdGhlIHJlc3VsdHMgb2YgcnVubmluZyBlYWNoIGVsZW1lbnQgb2YgYG9iamVjdGAgdGhydSBgaXRlcmF0ZWVgLiBUaGVcbiAgICAgKiBjb3JyZXNwb25kaW5nIGludmVydGVkIHZhbHVlIG9mIGVhY2ggaW52ZXJ0ZWQga2V5IGlzIGFuIGFycmF5IG9mIGtleXNcbiAgICAgKiByZXNwb25zaWJsZSBmb3IgZ2VuZXJhdGluZyB0aGUgaW52ZXJ0ZWQgdmFsdWUuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkXG4gICAgICogd2l0aCBvbmUgYXJndW1lbnQ6ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4xLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGludmVydC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IGludmVydGVkIG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiAxLCAnYic6IDIsICdjJzogMSB9O1xuICAgICAqXG4gICAgICogXy5pbnZlcnRCeShvYmplY3QpO1xuICAgICAqIC8vID0+IHsgJzEnOiBbJ2EnLCAnYyddLCAnMic6IFsnYiddIH1cbiAgICAgKlxuICAgICAqIF8uaW52ZXJ0Qnkob2JqZWN0LCBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAqICAgcmV0dXJuICdncm91cCcgKyB2YWx1ZTtcbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiB7ICdncm91cDEnOiBbJ2EnLCAnYyddLCAnZ3JvdXAyJzogWydiJ10gfVxuICAgICAqL1xuICAgIHZhciBpbnZlcnRCeSA9IGNyZWF0ZUludmVydGVyKGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwocmVzdWx0LCB2YWx1ZSkpIHtcbiAgICAgICAgcmVzdWx0W3ZhbHVlXS5wdXNoKGtleSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXN1bHRbdmFsdWVdID0gW2tleV07XG4gICAgICB9XG4gICAgfSwgZ2V0SXRlcmF0ZWUpO1xuXG4gICAgLyoqXG4gICAgICogSW52b2tlcyB0aGUgbWV0aG9kIGF0IGBwYXRoYCBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIG1ldGhvZCB0byBpbnZva2UuXG4gICAgICogQHBhcmFtIHsuLi4qfSBbYXJnc10gVGhlIGFyZ3VtZW50cyB0byBpbnZva2UgdGhlIG1ldGhvZCB3aXRoLlxuICAgICAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSByZXN1bHQgb2YgdGhlIGludm9rZWQgbWV0aG9kLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IFt7ICdiJzogeyAnYyc6IFsxLCAyLCAzLCA0XSB9IH1dIH07XG4gICAgICpcbiAgICAgKiBfLmludm9rZShvYmplY3QsICdhWzBdLmIuYy5zbGljZScsIDEsIDMpO1xuICAgICAqIC8vID0+IFsyLCAzXVxuICAgICAqL1xuICAgIHZhciBpbnZva2UgPSBiYXNlUmVzdChiYXNlSW52b2tlKTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdGhlIG93biBlbnVtZXJhYmxlIHByb3BlcnR5IG5hbWVzIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIE5vbi1vYmplY3QgdmFsdWVzIGFyZSBjb2VyY2VkIHRvIG9iamVjdHMuIFNlZSB0aGVcbiAgICAgKiBbRVMgc3BlY10oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtb2JqZWN0LmtleXMpXG4gICAgICogZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiAgIHRoaXMuYiA9IDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAgICAgKlxuICAgICAqIF8ua2V5cyhuZXcgRm9vKTtcbiAgICAgKiAvLyA9PiBbJ2EnLCAnYiddIChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gICAgICpcbiAgICAgKiBfLmtleXMoJ2hpJyk7XG4gICAgICogLy8gPT4gWycwJywgJzEnXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGtleXMob2JqZWN0KSB7XG4gICAgICByZXR1cm4gaXNBcnJheUxpa2Uob2JqZWN0KSA/IGFycmF5TGlrZUtleXMob2JqZWN0KSA6IGJhc2VLZXlzKG9iamVjdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgb3duIGFuZCBpbmhlcml0ZWQgZW51bWVyYWJsZSBwcm9wZXJ0eSBuYW1lcyBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBOb24tb2JqZWN0IHZhbHVlcyBhcmUgY29lcmNlZCB0byBvYmplY3RzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy5rZXlzSW4obmV3IEZvbyk7XG4gICAgICogLy8gPT4gWydhJywgJ2InLCAnYyddIChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gICAgICovXG4gICAgZnVuY3Rpb24ga2V5c0luKG9iamVjdCkge1xuICAgICAgcmV0dXJuIGlzQXJyYXlMaWtlKG9iamVjdCkgPyBhcnJheUxpa2VLZXlzKG9iamVjdCwgdHJ1ZSkgOiBiYXNlS2V5c0luKG9iamVjdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIG9wcG9zaXRlIG9mIGBfLm1hcFZhbHVlc2A7IHRoaXMgbWV0aG9kIGNyZWF0ZXMgYW4gb2JqZWN0IHdpdGggdGhlXG4gICAgICogc2FtZSB2YWx1ZXMgYXMgYG9iamVjdGAgYW5kIGtleXMgZ2VuZXJhdGVkIGJ5IHJ1bm5pbmcgZWFjaCBvd24gZW51bWVyYWJsZVxuICAgICAqIHN0cmluZyBrZXllZCBwcm9wZXJ0eSBvZiBgb2JqZWN0YCB0aHJ1IGBpdGVyYXRlZWAuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkXG4gICAgICogd2l0aCB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwga2V5LCBvYmplY3QpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuOC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG1hcHBlZCBvYmplY3QuXG4gICAgICogQHNlZSBfLm1hcFZhbHVlc1xuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLm1hcEtleXMoeyAnYSc6IDEsICdiJzogMiB9LCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG4gICAgICogICByZXR1cm4ga2V5ICsgdmFsdWU7XG4gICAgICogfSk7XG4gICAgICogLy8gPT4geyAnYTEnOiAxLCAnYjInOiAyIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYXBLZXlzKG9iamVjdCwgaXRlcmF0ZWUpIHtcbiAgICAgIHZhciByZXN1bHQgPSB7fTtcbiAgICAgIGl0ZXJhdGVlID0gZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDMpO1xuXG4gICAgICBiYXNlRm9yT3duKG9iamVjdCwgZnVuY3Rpb24odmFsdWUsIGtleSwgb2JqZWN0KSB7XG4gICAgICAgIGJhc2VBc3NpZ25WYWx1ZShyZXN1bHQsIGl0ZXJhdGVlKHZhbHVlLCBrZXksIG9iamVjdCksIHZhbHVlKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIG9iamVjdCB3aXRoIHRoZSBzYW1lIGtleXMgYXMgYG9iamVjdGAgYW5kIHZhbHVlcyBnZW5lcmF0ZWRcbiAgICAgKiBieSBydW5uaW5nIGVhY2ggb3duIGVudW1lcmFibGUgc3RyaW5nIGtleWVkIHByb3BlcnR5IG9mIGBvYmplY3RgIHRocnVcbiAgICAgKiBgaXRlcmF0ZWVgLiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIHRocmVlIGFyZ3VtZW50czpcbiAgICAgKiAodmFsdWUsIGtleSwgb2JqZWN0KS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAyLjQuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIG5ldyBtYXBwZWQgb2JqZWN0LlxuICAgICAqIEBzZWUgXy5tYXBLZXlzXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciB1c2VycyA9IHtcbiAgICAgKiAgICdmcmVkJzogICAgeyAndXNlcic6ICdmcmVkJywgICAgJ2FnZSc6IDQwIH0sXG4gICAgICogICAncGViYmxlcyc6IHsgJ3VzZXInOiAncGViYmxlcycsICdhZ2UnOiAxIH1cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogXy5tYXBWYWx1ZXModXNlcnMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuIG8uYWdlOyB9KTtcbiAgICAgKiAvLyA9PiB7ICdmcmVkJzogNDAsICdwZWJibGVzJzogMSB9IChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLm1hcFZhbHVlcyh1c2VycywgJ2FnZScpO1xuICAgICAqIC8vID0+IHsgJ2ZyZWQnOiA0MCwgJ3BlYmJsZXMnOiAxIH0gKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZClcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYXBWYWx1ZXMob2JqZWN0LCBpdGVyYXRlZSkge1xuICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgaXRlcmF0ZWUgPSBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMyk7XG5cbiAgICAgIGJhc2VGb3JPd24ob2JqZWN0LCBmdW5jdGlvbih2YWx1ZSwga2V5LCBvYmplY3QpIHtcbiAgICAgICAgYmFzZUFzc2lnblZhbHVlKHJlc3VsdCwga2V5LCBpdGVyYXRlZSh2YWx1ZSwga2V5LCBvYmplY3QpKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmFzc2lnbmAgZXhjZXB0IHRoYXQgaXQgcmVjdXJzaXZlbHkgbWVyZ2VzIG93biBhbmRcbiAgICAgKiBpbmhlcml0ZWQgZW51bWVyYWJsZSBzdHJpbmcga2V5ZWQgcHJvcGVydGllcyBvZiBzb3VyY2Ugb2JqZWN0cyBpbnRvIHRoZVxuICAgICAqIGRlc3RpbmF0aW9uIG9iamVjdC4gU291cmNlIHByb3BlcnRpZXMgdGhhdCByZXNvbHZlIHRvIGB1bmRlZmluZWRgIGFyZVxuICAgICAqIHNraXBwZWQgaWYgYSBkZXN0aW5hdGlvbiB2YWx1ZSBleGlzdHMuIEFycmF5IGFuZCBwbGFpbiBvYmplY3QgcHJvcGVydGllc1xuICAgICAqIGFyZSBtZXJnZWQgcmVjdXJzaXZlbHkuIE90aGVyIG9iamVjdHMgYW5kIHZhbHVlIHR5cGVzIGFyZSBvdmVycmlkZGVuIGJ5XG4gICAgICogYXNzaWdubWVudC4gU291cmNlIG9iamVjdHMgYXJlIGFwcGxpZWQgZnJvbSBsZWZ0IHRvIHJpZ2h0LiBTdWJzZXF1ZW50XG4gICAgICogc291cmNlcyBvdmVyd3JpdGUgcHJvcGVydHkgYXNzaWdubWVudHMgb2YgcHJldmlvdXMgc291cmNlcy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBtdXRhdGVzIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDAuNS4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0gey4uLk9iamVjdH0gW3NvdXJjZXNdIFRoZSBzb3VyY2Ugb2JqZWN0cy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0ge1xuICAgICAqICAgJ2EnOiBbeyAnYic6IDIgfSwgeyAnZCc6IDQgfV1cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogdmFyIG90aGVyID0ge1xuICAgICAqICAgJ2EnOiBbeyAnYyc6IDMgfSwgeyAnZSc6IDUgfV1cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogXy5tZXJnZShvYmplY3QsIG90aGVyKTtcbiAgICAgKiAvLyA9PiB7ICdhJzogW3sgJ2InOiAyLCAnYyc6IDMgfSwgeyAnZCc6IDQsICdlJzogNSB9XSB9XG4gICAgICovXG4gICAgdmFyIG1lcmdlID0gY3JlYXRlQXNzaWduZXIoZnVuY3Rpb24ob2JqZWN0LCBzb3VyY2UsIHNyY0luZGV4KSB7XG4gICAgICBiYXNlTWVyZ2Uob2JqZWN0LCBzb3VyY2UsIHNyY0luZGV4KTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8ubWVyZ2VgIGV4Y2VwdCB0aGF0IGl0IGFjY2VwdHMgYGN1c3RvbWl6ZXJgIHdoaWNoXG4gICAgICogaXMgaW52b2tlZCB0byBwcm9kdWNlIHRoZSBtZXJnZWQgdmFsdWVzIG9mIHRoZSBkZXN0aW5hdGlvbiBhbmQgc291cmNlXG4gICAgICogcHJvcGVydGllcy4gSWYgYGN1c3RvbWl6ZXJgIHJldHVybnMgYHVuZGVmaW5lZGAsIG1lcmdpbmcgaXMgaGFuZGxlZCBieSB0aGVcbiAgICAgKiBtZXRob2QgaW5zdGVhZC4gVGhlIGBjdXN0b21pemVyYCBpcyBpbnZva2VkIHdpdGggc2l4IGFyZ3VtZW50czpcbiAgICAgKiAob2JqVmFsdWUsIHNyY1ZhbHVlLCBrZXksIG9iamVjdCwgc291cmNlLCBzdGFjaykuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gICAgICogQHBhcmFtIHsuLi5PYmplY3R9IHNvdXJjZXMgVGhlIHNvdXJjZSBvYmplY3RzLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGN1c3RvbWl6ZXIgVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBhc3NpZ25lZCB2YWx1ZXMuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gY3VzdG9taXplcihvYmpWYWx1ZSwgc3JjVmFsdWUpIHtcbiAgICAgKiAgIGlmIChfLmlzQXJyYXkob2JqVmFsdWUpKSB7XG4gICAgICogICAgIHJldHVybiBvYmpWYWx1ZS5jb25jYXQoc3JjVmFsdWUpO1xuICAgICAqICAgfVxuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogWzFdLCAnYic6IFsyXSB9O1xuICAgICAqIHZhciBvdGhlciA9IHsgJ2EnOiBbM10sICdiJzogWzRdIH07XG4gICAgICpcbiAgICAgKiBfLm1lcmdlV2l0aChvYmplY3QsIG90aGVyLCBjdXN0b21pemVyKTtcbiAgICAgKiAvLyA9PiB7ICdhJzogWzEsIDNdLCAnYic6IFsyLCA0XSB9XG4gICAgICovXG4gICAgdmFyIG1lcmdlV2l0aCA9IGNyZWF0ZUFzc2lnbmVyKGZ1bmN0aW9uKG9iamVjdCwgc291cmNlLCBzcmNJbmRleCwgY3VzdG9taXplcikge1xuICAgICAgYmFzZU1lcmdlKG9iamVjdCwgc291cmNlLCBzcmNJbmRleCwgY3VzdG9taXplcik7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb3Bwb3NpdGUgb2YgYF8ucGlja2A7IHRoaXMgbWV0aG9kIGNyZWF0ZXMgYW4gb2JqZWN0IGNvbXBvc2VkIG9mIHRoZVxuICAgICAqIG93biBhbmQgaW5oZXJpdGVkIGVudW1lcmFibGUgcHJvcGVydHkgcGF0aHMgb2YgYG9iamVjdGAgdGhhdCBhcmUgbm90IG9taXR0ZWQuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgY29uc2lkZXJhYmx5IHNsb3dlciB0aGFuIGBfLnBpY2tgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIHNvdXJjZSBvYmplY3QuXG4gICAgICogQHBhcmFtIHsuLi4oc3RyaW5nfHN0cmluZ1tdKX0gW3BhdGhzXSBUaGUgcHJvcGVydHkgcGF0aHMgdG8gb21pdC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IDEsICdiJzogJzInLCAnYyc6IDMgfTtcbiAgICAgKlxuICAgICAqIF8ub21pdChvYmplY3QsIFsnYScsICdjJ10pO1xuICAgICAqIC8vID0+IHsgJ2InOiAnMicgfVxuICAgICAqL1xuICAgIHZhciBvbWl0ID0gZmxhdFJlc3QoZnVuY3Rpb24ob2JqZWN0LCBwYXRocykge1xuICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgaWYgKG9iamVjdCA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgICB2YXIgaXNEZWVwID0gZmFsc2U7XG4gICAgICBwYXRocyA9IGFycmF5TWFwKHBhdGhzLCBmdW5jdGlvbihwYXRoKSB7XG4gICAgICAgIHBhdGggPSBjYXN0UGF0aChwYXRoLCBvYmplY3QpO1xuICAgICAgICBpc0RlZXAgfHwgKGlzRGVlcCA9IHBhdGgubGVuZ3RoID4gMSk7XG4gICAgICAgIHJldHVybiBwYXRoO1xuICAgICAgfSk7XG4gICAgICBjb3B5T2JqZWN0KG9iamVjdCwgZ2V0QWxsS2V5c0luKG9iamVjdCksIHJlc3VsdCk7XG4gICAgICBpZiAoaXNEZWVwKSB7XG4gICAgICAgIHJlc3VsdCA9IGJhc2VDbG9uZShyZXN1bHQsIENMT05FX0RFRVBfRkxBRyB8IENMT05FX0ZMQVRfRkxBRyB8IENMT05FX1NZTUJPTFNfRkxBRywgY3VzdG9tT21pdENsb25lKTtcbiAgICAgIH1cbiAgICAgIHZhciBsZW5ndGggPSBwYXRocy5sZW5ndGg7XG4gICAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgICAgYmFzZVVuc2V0KHJlc3VsdCwgcGF0aHNbbGVuZ3RoXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG9wcG9zaXRlIG9mIGBfLnBpY2tCeWA7IHRoaXMgbWV0aG9kIGNyZWF0ZXMgYW4gb2JqZWN0IGNvbXBvc2VkIG9mXG4gICAgICogdGhlIG93biBhbmQgaW5oZXJpdGVkIGVudW1lcmFibGUgc3RyaW5nIGtleWVkIHByb3BlcnRpZXMgb2YgYG9iamVjdGAgdGhhdFxuICAgICAqIGBwcmVkaWNhdGVgIGRvZXNuJ3QgcmV0dXJuIHRydXRoeSBmb3IuIFRoZSBwcmVkaWNhdGUgaXMgaW52b2tlZCB3aXRoIHR3b1xuICAgICAqIGFyZ3VtZW50czogKHZhbHVlLCBrZXkpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIHNvdXJjZSBvYmplY3QuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW3ByZWRpY2F0ZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgcHJvcGVydHkuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG9iamVjdC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiAxLCAnYic6ICcyJywgJ2MnOiAzIH07XG4gICAgICpcbiAgICAgKiBfLm9taXRCeShvYmplY3QsIF8uaXNOdW1iZXIpO1xuICAgICAqIC8vID0+IHsgJ2InOiAnMicgfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG9taXRCeShvYmplY3QsIHByZWRpY2F0ZSkge1xuICAgICAgcmV0dXJuIHBpY2tCeShvYmplY3QsIG5lZ2F0ZShnZXRJdGVyYXRlZShwcmVkaWNhdGUpKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBvYmplY3QgY29tcG9zZWQgb2YgdGhlIHBpY2tlZCBgb2JqZWN0YCBwcm9wZXJ0aWVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIHNvdXJjZSBvYmplY3QuXG4gICAgICogQHBhcmFtIHsuLi4oc3RyaW5nfHN0cmluZ1tdKX0gW3BhdGhzXSBUaGUgcHJvcGVydHkgcGF0aHMgdG8gcGljay5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IDEsICdiJzogJzInLCAnYyc6IDMgfTtcbiAgICAgKlxuICAgICAqIF8ucGljayhvYmplY3QsIFsnYScsICdjJ10pO1xuICAgICAqIC8vID0+IHsgJ2EnOiAxLCAnYyc6IDMgfVxuICAgICAqL1xuICAgIHZhciBwaWNrID0gZmxhdFJlc3QoZnVuY3Rpb24ob2JqZWN0LCBwYXRocykge1xuICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsID8ge30gOiBiYXNlUGljayhvYmplY3QsIHBhdGhzKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gb2JqZWN0IGNvbXBvc2VkIG9mIHRoZSBgb2JqZWN0YCBwcm9wZXJ0aWVzIGBwcmVkaWNhdGVgIHJldHVybnNcbiAgICAgKiB0cnV0aHkgZm9yLiBUaGUgcHJlZGljYXRlIGlzIGludm9rZWQgd2l0aCB0d28gYXJndW1lbnRzOiAodmFsdWUsIGtleSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgc291cmNlIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBwcm9wZXJ0eS5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IDEsICdiJzogJzInLCAnYyc6IDMgfTtcbiAgICAgKlxuICAgICAqIF8ucGlja0J5KG9iamVjdCwgXy5pc051bWJlcik7XG4gICAgICogLy8gPT4geyAnYSc6IDEsICdjJzogMyB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gcGlja0J5KG9iamVjdCwgcHJlZGljYXRlKSB7XG4gICAgICBpZiAob2JqZWN0ID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgfVxuICAgICAgdmFyIHByb3BzID0gYXJyYXlNYXAoZ2V0QWxsS2V5c0luKG9iamVjdCksIGZ1bmN0aW9uKHByb3ApIHtcbiAgICAgICAgcmV0dXJuIFtwcm9wXTtcbiAgICAgIH0pO1xuICAgICAgcHJlZGljYXRlID0gZ2V0SXRlcmF0ZWUocHJlZGljYXRlKTtcbiAgICAgIHJldHVybiBiYXNlUGlja0J5KG9iamVjdCwgcHJvcHMsIGZ1bmN0aW9uKHZhbHVlLCBwYXRoKSB7XG4gICAgICAgIHJldHVybiBwcmVkaWNhdGUodmFsdWUsIHBhdGhbMF0pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5nZXRgIGV4Y2VwdCB0aGF0IGlmIHRoZSByZXNvbHZlZCB2YWx1ZSBpcyBhXG4gICAgICogZnVuY3Rpb24gaXQncyBpbnZva2VkIHdpdGggdGhlIGB0aGlzYCBiaW5kaW5nIG9mIGl0cyBwYXJlbnQgb2JqZWN0IGFuZFxuICAgICAqIGl0cyByZXN1bHQgaXMgcmV0dXJuZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byByZXNvbHZlLlxuICAgICAqIEBwYXJhbSB7Kn0gW2RlZmF1bHRWYWx1ZV0gVGhlIHZhbHVlIHJldHVybmVkIGZvciBgdW5kZWZpbmVkYCByZXNvbHZlZCB2YWx1ZXMuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJlc29sdmVkIHZhbHVlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IFt7ICdiJzogeyAnYzEnOiAzLCAnYzInOiBfLmNvbnN0YW50KDQpIH0gfV0gfTtcbiAgICAgKlxuICAgICAqIF8ucmVzdWx0KG9iamVjdCwgJ2FbMF0uYi5jMScpO1xuICAgICAqIC8vID0+IDNcbiAgICAgKlxuICAgICAqIF8ucmVzdWx0KG9iamVjdCwgJ2FbMF0uYi5jMicpO1xuICAgICAqIC8vID0+IDRcbiAgICAgKlxuICAgICAqIF8ucmVzdWx0KG9iamVjdCwgJ2FbMF0uYi5jMycsICdkZWZhdWx0Jyk7XG4gICAgICogLy8gPT4gJ2RlZmF1bHQnXG4gICAgICpcbiAgICAgKiBfLnJlc3VsdChvYmplY3QsICdhWzBdLmIuYzMnLCBfLmNvbnN0YW50KCdkZWZhdWx0JykpO1xuICAgICAqIC8vID0+ICdkZWZhdWx0J1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJlc3VsdChvYmplY3QsIHBhdGgsIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgcGF0aCA9IGNhc3RQYXRoKHBhdGgsIG9iamVjdCk7XG5cbiAgICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICAgIGxlbmd0aCA9IHBhdGgubGVuZ3RoO1xuXG4gICAgICAvLyBFbnN1cmUgdGhlIGxvb3AgaXMgZW50ZXJlZCB3aGVuIHBhdGggaXMgZW1wdHkuXG4gICAgICBpZiAoIWxlbmd0aCkge1xuICAgICAgICBsZW5ndGggPSAxO1xuICAgICAgICBvYmplY3QgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgICB2YXIgdmFsdWUgPSBvYmplY3QgPT0gbnVsbCA/IHVuZGVmaW5lZCA6IG9iamVjdFt0b0tleShwYXRoW2luZGV4XSldO1xuICAgICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGluZGV4ID0gbGVuZ3RoO1xuICAgICAgICAgIHZhbHVlID0gZGVmYXVsdFZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIG9iamVjdCA9IGlzRnVuY3Rpb24odmFsdWUpID8gdmFsdWUuY2FsbChvYmplY3QpIDogdmFsdWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gb2JqZWN0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHZhbHVlIGF0IGBwYXRoYCBvZiBgb2JqZWN0YC4gSWYgYSBwb3J0aW9uIG9mIGBwYXRoYCBkb2Vzbid0IGV4aXN0LFxuICAgICAqIGl0J3MgY3JlYXRlZC4gQXJyYXlzIGFyZSBjcmVhdGVkIGZvciBtaXNzaW5nIGluZGV4IHByb3BlcnRpZXMgd2hpbGUgb2JqZWN0c1xuICAgICAqIGFyZSBjcmVhdGVkIGZvciBhbGwgb3RoZXIgbWlzc2luZyBwcm9wZXJ0aWVzLiBVc2UgYF8uc2V0V2l0aGAgdG8gY3VzdG9taXplXG4gICAgICogYHBhdGhgIGNyZWF0aW9uLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy43LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgcHJvcGVydHkgdG8gc2V0LlxuICAgICAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNldC5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0geyAnYSc6IFt7ICdiJzogeyAnYyc6IDMgfSB9XSB9O1xuICAgICAqXG4gICAgICogXy5zZXQob2JqZWN0LCAnYVswXS5iLmMnLCA0KTtcbiAgICAgKiBjb25zb2xlLmxvZyhvYmplY3QuYVswXS5iLmMpO1xuICAgICAqIC8vID0+IDRcbiAgICAgKlxuICAgICAqIF8uc2V0KG9iamVjdCwgWyd4JywgJzAnLCAneScsICd6J10sIDUpO1xuICAgICAqIGNvbnNvbGUubG9nKG9iamVjdC54WzBdLnkueik7XG4gICAgICogLy8gPT4gNVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNldChvYmplY3QsIHBhdGgsIHZhbHVlKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyBvYmplY3QgOiBiYXNlU2V0KG9iamVjdCwgcGF0aCwgdmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uc2V0YCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBjdXN0b21pemVyYCB3aGljaCBpc1xuICAgICAqIGludm9rZWQgdG8gcHJvZHVjZSB0aGUgb2JqZWN0cyBvZiBgcGF0aGAuICBJZiBgY3VzdG9taXplcmAgcmV0dXJucyBgdW5kZWZpbmVkYFxuICAgICAqIHBhdGggY3JlYXRpb24gaXMgaGFuZGxlZCBieSB0aGUgbWV0aG9kIGluc3RlYWQuIFRoZSBgY3VzdG9taXplcmAgaXMgaW52b2tlZFxuICAgICAqIHdpdGggdGhyZWUgYXJndW1lbnRzOiAobnNWYWx1ZSwga2V5LCBuc09iamVjdCkuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgbXV0YXRlcyBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gbW9kaWZ5LlxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBzZXQuXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGFzc2lnbmVkIHZhbHVlcy5cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0ID0ge307XG4gICAgICpcbiAgICAgKiBfLnNldFdpdGgob2JqZWN0LCAnWzBdWzFdJywgJ2EnLCBPYmplY3QpO1xuICAgICAqIC8vID0+IHsgJzAnOiB7ICcxJzogJ2EnIH0gfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNldFdpdGgob2JqZWN0LCBwYXRoLCB2YWx1ZSwgY3VzdG9taXplcikge1xuICAgICAgY3VzdG9taXplciA9IHR5cGVvZiBjdXN0b21pemVyID09ICdmdW5jdGlvbicgPyBjdXN0b21pemVyIDogdW5kZWZpbmVkO1xuICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsID8gb2JqZWN0IDogYmFzZVNldChvYmplY3QsIHBhdGgsIHZhbHVlLCBjdXN0b21pemVyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGFycmF5IG9mIG93biBlbnVtZXJhYmxlIHN0cmluZyBrZXllZC12YWx1ZSBwYWlycyBmb3IgYG9iamVjdGBcbiAgICAgKiB3aGljaCBjYW4gYmUgY29uc3VtZWQgYnkgYF8uZnJvbVBhaXJzYC4gSWYgYG9iamVjdGAgaXMgYSBtYXAgb3Igc2V0LCBpdHNcbiAgICAgKiBlbnRyaWVzIGFyZSByZXR1cm5lZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBhbGlhcyBlbnRyaWVzXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGtleS12YWx1ZSBwYWlycy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiAgIHRoaXMuYiA9IDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAgICAgKlxuICAgICAqIF8udG9QYWlycyhuZXcgRm9vKTtcbiAgICAgKiAvLyA9PiBbWydhJywgMV0sIFsnYicsIDJdXSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqL1xuICAgIHZhciB0b1BhaXJzID0gY3JlYXRlVG9QYWlycyhrZXlzKTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2Ygb3duIGFuZCBpbmhlcml0ZWQgZW51bWVyYWJsZSBzdHJpbmcga2V5ZWQtdmFsdWUgcGFpcnNcbiAgICAgKiBmb3IgYG9iamVjdGAgd2hpY2ggY2FuIGJlIGNvbnN1bWVkIGJ5IGBfLmZyb21QYWlyc2AuIElmIGBvYmplY3RgIGlzIGEgbWFwXG4gICAgICogb3Igc2V0LCBpdHMgZW50cmllcyBhcmUgcmV0dXJuZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAYWxpYXMgZW50cmllc0luXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGtleS12YWx1ZSBwYWlycy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogZnVuY3Rpb24gRm9vKCkge1xuICAgICAqICAgdGhpcy5hID0gMTtcbiAgICAgKiAgIHRoaXMuYiA9IDI7XG4gICAgICogfVxuICAgICAqXG4gICAgICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAgICAgKlxuICAgICAqIF8udG9QYWlyc0luKG5ldyBGb28pO1xuICAgICAqIC8vID0+IFtbJ2EnLCAxXSwgWydiJywgMl0sIFsnYycsIDNdXSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICAgICAqL1xuICAgIHZhciB0b1BhaXJzSW4gPSBjcmVhdGVUb1BhaXJzKGtleXNJbik7XG5cbiAgICAvKipcbiAgICAgKiBBbiBhbHRlcm5hdGl2ZSB0byBgXy5yZWR1Y2VgOyB0aGlzIG1ldGhvZCB0cmFuc2Zvcm1zIGBvYmplY3RgIHRvIGEgbmV3XG4gICAgICogYGFjY3VtdWxhdG9yYCBvYmplY3Qgd2hpY2ggaXMgdGhlIHJlc3VsdCBvZiBydW5uaW5nIGVhY2ggb2YgaXRzIG93blxuICAgICAqIGVudW1lcmFibGUgc3RyaW5nIGtleWVkIHByb3BlcnRpZXMgdGhydSBgaXRlcmF0ZWVgLCB3aXRoIGVhY2ggaW52b2NhdGlvblxuICAgICAqIHBvdGVudGlhbGx5IG11dGF0aW5nIHRoZSBgYWNjdW11bGF0b3JgIG9iamVjdC4gSWYgYGFjY3VtdWxhdG9yYCBpcyBub3RcbiAgICAgKiBwcm92aWRlZCwgYSBuZXcgb2JqZWN0IHdpdGggdGhlIHNhbWUgYFtbUHJvdG90eXBlXV1gIHdpbGwgYmUgdXNlZC4gVGhlXG4gICAgICogaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIGZvdXIgYXJndW1lbnRzOiAoYWNjdW11bGF0b3IsIHZhbHVlLCBrZXksIG9iamVjdCkuXG4gICAgICogSXRlcmF0ZWUgZnVuY3Rpb25zIG1heSBleGl0IGl0ZXJhdGlvbiBlYXJseSBieSBleHBsaWNpdGx5IHJldHVybmluZyBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDEuMy4wXG4gICAgICogQGNhdGVnb3J5IE9iamVjdFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHBhcmFtIHsqfSBbYWNjdW11bGF0b3JdIFRoZSBjdXN0b20gYWNjdW11bGF0b3IgdmFsdWUuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGFjY3VtdWxhdGVkIHZhbHVlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRyYW5zZm9ybShbMiwgMywgNF0sIGZ1bmN0aW9uKHJlc3VsdCwgbikge1xuICAgICAqICAgcmVzdWx0LnB1c2gobiAqPSBuKTtcbiAgICAgKiAgIHJldHVybiBuICUgMiA9PSAwO1xuICAgICAqIH0sIFtdKTtcbiAgICAgKiAvLyA9PiBbNCwgOV1cbiAgICAgKlxuICAgICAqIF8udHJhbnNmb3JtKHsgJ2EnOiAxLCAnYic6IDIsICdjJzogMSB9LCBmdW5jdGlvbihyZXN1bHQsIHZhbHVlLCBrZXkpIHtcbiAgICAgKiAgIChyZXN1bHRbdmFsdWVdIHx8IChyZXN1bHRbdmFsdWVdID0gW10pKS5wdXNoKGtleSk7XG4gICAgICogfSwge30pO1xuICAgICAqIC8vID0+IHsgJzEnOiBbJ2EnLCAnYyddLCAnMic6IFsnYiddIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0cmFuc2Zvcm0ob2JqZWN0LCBpdGVyYXRlZSwgYWNjdW11bGF0b3IpIHtcbiAgICAgIHZhciBpc0FyciA9IGlzQXJyYXkob2JqZWN0KSxcbiAgICAgICAgICBpc0Fyckxpa2UgPSBpc0FyciB8fCBpc0J1ZmZlcihvYmplY3QpIHx8IGlzVHlwZWRBcnJheShvYmplY3QpO1xuXG4gICAgICBpdGVyYXRlZSA9IGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCA0KTtcbiAgICAgIGlmIChhY2N1bXVsYXRvciA9PSBudWxsKSB7XG4gICAgICAgIHZhciBDdG9yID0gb2JqZWN0ICYmIG9iamVjdC5jb25zdHJ1Y3RvcjtcbiAgICAgICAgaWYgKGlzQXJyTGlrZSkge1xuICAgICAgICAgIGFjY3VtdWxhdG9yID0gaXNBcnIgPyBuZXcgQ3RvciA6IFtdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGlzT2JqZWN0KG9iamVjdCkpIHtcbiAgICAgICAgICBhY2N1bXVsYXRvciA9IGlzRnVuY3Rpb24oQ3RvcikgPyBiYXNlQ3JlYXRlKGdldFByb3RvdHlwZShvYmplY3QpKSA6IHt9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGFjY3VtdWxhdG9yID0ge307XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIChpc0Fyckxpa2UgPyBhcnJheUVhY2ggOiBiYXNlRm9yT3duKShvYmplY3QsIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgb2JqZWN0KSB7XG4gICAgICAgIHJldHVybiBpdGVyYXRlZShhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBvYmplY3QpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gYWNjdW11bGF0b3I7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgcHJvcGVydHkgYXQgYHBhdGhgIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgcHJvcGVydHkgdG8gdW5zZXQuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBwcm9wZXJ0eSBpcyBkZWxldGVkLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7ICdhJzogW3sgJ2InOiB7ICdjJzogNyB9IH1dIH07XG4gICAgICogXy51bnNldChvYmplY3QsICdhWzBdLmIuYycpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKG9iamVjdCk7XG4gICAgICogLy8gPT4geyAnYSc6IFt7ICdiJzoge30gfV0gfTtcbiAgICAgKlxuICAgICAqIF8udW5zZXQob2JqZWN0LCBbJ2EnLCAnMCcsICdiJywgJ2MnXSk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogY29uc29sZS5sb2cob2JqZWN0KTtcbiAgICAgKiAvLyA9PiB7ICdhJzogW3sgJ2InOiB7fSB9XSB9O1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVuc2V0KG9iamVjdCwgcGF0aCkge1xuICAgICAgcmV0dXJuIG9iamVjdCA9PSBudWxsID8gdHJ1ZSA6IGJhc2VVbnNldChvYmplY3QsIHBhdGgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGxpa2UgYF8uc2V0YCBleGNlcHQgdGhhdCBhY2NlcHRzIGB1cGRhdGVyYCB0byBwcm9kdWNlIHRoZVxuICAgICAqIHZhbHVlIHRvIHNldC4gVXNlIGBfLnVwZGF0ZVdpdGhgIHRvIGN1c3RvbWl6ZSBgcGF0aGAgY3JlYXRpb24uIFRoZSBgdXBkYXRlcmBcbiAgICAgKiBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC42LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgcHJvcGVydHkgdG8gc2V0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHVwZGF0ZXIgVGhlIGZ1bmN0aW9uIHRvIHByb2R1Y2UgdGhlIHVwZGF0ZWQgdmFsdWUuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiBbeyAnYic6IHsgJ2MnOiAzIH0gfV0gfTtcbiAgICAgKlxuICAgICAqIF8udXBkYXRlKG9iamVjdCwgJ2FbMF0uYi5jJywgZnVuY3Rpb24obikgeyByZXR1cm4gbiAqIG47IH0pO1xuICAgICAqIGNvbnNvbGUubG9nKG9iamVjdC5hWzBdLmIuYyk7XG4gICAgICogLy8gPT4gOVxuICAgICAqXG4gICAgICogXy51cGRhdGUob2JqZWN0LCAneFswXS55LnonLCBmdW5jdGlvbihuKSB7IHJldHVybiBuID8gbiArIDEgOiAwOyB9KTtcbiAgICAgKiBjb25zb2xlLmxvZyhvYmplY3QueFswXS55LnopO1xuICAgICAqIC8vID0+IDBcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1cGRhdGUob2JqZWN0LCBwYXRoLCB1cGRhdGVyKSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyBvYmplY3QgOiBiYXNlVXBkYXRlKG9iamVjdCwgcGF0aCwgY2FzdEZ1bmN0aW9uKHVwZGF0ZXIpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnVwZGF0ZWAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgY3VzdG9taXplcmAgd2hpY2ggaXNcbiAgICAgKiBpbnZva2VkIHRvIHByb2R1Y2UgdGhlIG9iamVjdHMgb2YgYHBhdGhgLiAgSWYgYGN1c3RvbWl6ZXJgIHJldHVybnMgYHVuZGVmaW5lZGBcbiAgICAgKiBwYXRoIGNyZWF0aW9uIGlzIGhhbmRsZWQgYnkgdGhlIG1ldGhvZCBpbnN0ZWFkLiBUaGUgYGN1c3RvbWl6ZXJgIGlzIGludm9rZWRcbiAgICAgKiB3aXRoIHRocmVlIGFyZ3VtZW50czogKG5zVmFsdWUsIGtleSwgbnNPYmplY3QpLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIG11dGF0ZXMgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC42LjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgcHJvcGVydHkgdG8gc2V0LlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHVwZGF0ZXIgVGhlIGZ1bmN0aW9uIHRvIHByb2R1Y2UgdGhlIHVwZGF0ZWQgdmFsdWUuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgYXNzaWduZWQgdmFsdWVzLlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3QgPSB7fTtcbiAgICAgKlxuICAgICAqIF8udXBkYXRlV2l0aChvYmplY3QsICdbMF1bMV0nLCBfLmNvbnN0YW50KCdhJyksIE9iamVjdCk7XG4gICAgICogLy8gPT4geyAnMCc6IHsgJzEnOiAnYScgfSB9XG4gICAgICovXG4gICAgZnVuY3Rpb24gdXBkYXRlV2l0aChvYmplY3QsIHBhdGgsIHVwZGF0ZXIsIGN1c3RvbWl6ZXIpIHtcbiAgICAgIGN1c3RvbWl6ZXIgPSB0eXBlb2YgY3VzdG9taXplciA9PSAnZnVuY3Rpb24nID8gY3VzdG9taXplciA6IHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiBvYmplY3QgPT0gbnVsbCA/IG9iamVjdCA6IGJhc2VVcGRhdGUob2JqZWN0LCBwYXRoLCBjYXN0RnVuY3Rpb24odXBkYXRlciksIGN1c3RvbWl6ZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdGhlIG93biBlbnVtZXJhYmxlIHN0cmluZyBrZXllZCBwcm9wZXJ0eSB2YWx1ZXMgb2YgYG9iamVjdGAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogTm9uLW9iamVjdCB2YWx1ZXMgYXJlIGNvZXJjZWQgdG8gb2JqZWN0cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBPYmplY3RcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSB2YWx1ZXMuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIEZvbygpIHtcbiAgICAgKiAgIHRoaXMuYSA9IDE7XG4gICAgICogICB0aGlzLmIgPSAyO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIEZvby5wcm90b3R5cGUuYyA9IDM7XG4gICAgICpcbiAgICAgKiBfLnZhbHVlcyhuZXcgRm9vKTtcbiAgICAgKiAvLyA9PiBbMSwgMl0gKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZClcbiAgICAgKlxuICAgICAqIF8udmFsdWVzKCdoaScpO1xuICAgICAqIC8vID0+IFsnaCcsICdpJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB2YWx1ZXMob2JqZWN0KSB7XG4gICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyBbXSA6IGJhc2VWYWx1ZXMob2JqZWN0LCBrZXlzKG9iamVjdCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdGhlIG93biBhbmQgaW5oZXJpdGVkIGVudW1lcmFibGUgc3RyaW5nIGtleWVkIHByb3BlcnR5XG4gICAgICogdmFsdWVzIG9mIGBvYmplY3RgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIE5vbi1vYmplY3QgdmFsdWVzIGFyZSBjb2VyY2VkIHRvIG9iamVjdHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgT2JqZWN0XG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgdmFsdWVzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBGb28oKSB7XG4gICAgICogICB0aGlzLmEgPSAxO1xuICAgICAqICAgdGhpcy5iID0gMjtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICAgICAqXG4gICAgICogXy52YWx1ZXNJbihuZXcgRm9vKTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgM10gKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZClcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB2YWx1ZXNJbihvYmplY3QpIHtcbiAgICAgIHJldHVybiBvYmplY3QgPT0gbnVsbCA/IFtdIDogYmFzZVZhbHVlcyhvYmplY3QsIGtleXNJbihvYmplY3QpKTtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDbGFtcHMgYG51bWJlcmAgd2l0aGluIHRoZSBpbmNsdXNpdmUgYGxvd2VyYCBhbmQgYHVwcGVyYCBib3VuZHMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgTnVtYmVyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG51bWJlciBUaGUgbnVtYmVyIHRvIGNsYW1wLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbG93ZXJdIFRoZSBsb3dlciBib3VuZC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdXBwZXIgVGhlIHVwcGVyIGJvdW5kLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGNsYW1wZWQgbnVtYmVyLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmNsYW1wKC0xMCwgLTUsIDUpO1xuICAgICAqIC8vID0+IC01XG4gICAgICpcbiAgICAgKiBfLmNsYW1wKDEwLCAtNSwgNSk7XG4gICAgICogLy8gPT4gNVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNsYW1wKG51bWJlciwgbG93ZXIsIHVwcGVyKSB7XG4gICAgICBpZiAodXBwZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB1cHBlciA9IGxvd2VyO1xuICAgICAgICBsb3dlciA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIGlmICh1cHBlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHVwcGVyID0gdG9OdW1iZXIodXBwZXIpO1xuICAgICAgICB1cHBlciA9IHVwcGVyID09PSB1cHBlciA/IHVwcGVyIDogMDtcbiAgICAgIH1cbiAgICAgIGlmIChsb3dlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGxvd2VyID0gdG9OdW1iZXIobG93ZXIpO1xuICAgICAgICBsb3dlciA9IGxvd2VyID09PSBsb3dlciA/IGxvd2VyIDogMDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlQ2xhbXAodG9OdW1iZXIobnVtYmVyKSwgbG93ZXIsIHVwcGVyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgYG5gIGlzIGJldHdlZW4gYHN0YXJ0YCBhbmQgdXAgdG8sIGJ1dCBub3QgaW5jbHVkaW5nLCBgZW5kYC4gSWZcbiAgICAgKiBgZW5kYCBpcyBub3Qgc3BlY2lmaWVkLCBpdCdzIHNldCB0byBgc3RhcnRgIHdpdGggYHN0YXJ0YCB0aGVuIHNldCB0byBgMGAuXG4gICAgICogSWYgYHN0YXJ0YCBpcyBncmVhdGVyIHRoYW4gYGVuZGAgdGhlIHBhcmFtcyBhcmUgc3dhcHBlZCB0byBzdXBwb3J0XG4gICAgICogbmVnYXRpdmUgcmFuZ2VzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMy4wXG4gICAgICogQGNhdGVnb3J5IE51bWJlclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBudW1iZXIgVGhlIG51bWJlciB0byBjaGVjay5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0YXJ0PTBdIFRoZSBzdGFydCBvZiB0aGUgcmFuZ2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGVuZCBUaGUgZW5kIG9mIHRoZSByYW5nZS5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYG51bWJlcmAgaXMgaW4gdGhlIHJhbmdlLCBlbHNlIGBmYWxzZWAuXG4gICAgICogQHNlZSBfLnJhbmdlLCBfLnJhbmdlUmlnaHRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5pblJhbmdlKDMsIDIsIDQpO1xuICAgICAqIC8vID0+IHRydWVcbiAgICAgKlxuICAgICAqIF8uaW5SYW5nZSg0LCA4KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLmluUmFuZ2UoNCwgMik7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaW5SYW5nZSgyLCAyKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5pblJhbmdlKDEuMiwgMik7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5pblJhbmdlKDUuMiwgNCk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uaW5SYW5nZSgtMywgLTIsIC02KTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gaW5SYW5nZShudW1iZXIsIHN0YXJ0LCBlbmQpIHtcbiAgICAgIHN0YXJ0ID0gdG9GaW5pdGUoc3RhcnQpO1xuICAgICAgaWYgKGVuZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGVuZCA9IHN0YXJ0O1xuICAgICAgICBzdGFydCA9IDA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBlbmQgPSB0b0Zpbml0ZShlbmQpO1xuICAgICAgfVxuICAgICAgbnVtYmVyID0gdG9OdW1iZXIobnVtYmVyKTtcbiAgICAgIHJldHVybiBiYXNlSW5SYW5nZShudW1iZXIsIHN0YXJ0LCBlbmQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFByb2R1Y2VzIGEgcmFuZG9tIG51bWJlciBiZXR3ZWVuIHRoZSBpbmNsdXNpdmUgYGxvd2VyYCBhbmQgYHVwcGVyYCBib3VuZHMuXG4gICAgICogSWYgb25seSBvbmUgYXJndW1lbnQgaXMgcHJvdmlkZWQgYSBudW1iZXIgYmV0d2VlbiBgMGAgYW5kIHRoZSBnaXZlbiBudW1iZXJcbiAgICAgKiBpcyByZXR1cm5lZC4gSWYgYGZsb2F0aW5nYCBpcyBgdHJ1ZWAsIG9yIGVpdGhlciBgbG93ZXJgIG9yIGB1cHBlcmAgYXJlXG4gICAgICogZmxvYXRzLCBhIGZsb2F0aW5nLXBvaW50IG51bWJlciBpcyByZXR1cm5lZCBpbnN0ZWFkIG9mIGFuIGludGVnZXIuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogSmF2YVNjcmlwdCBmb2xsb3dzIHRoZSBJRUVFLTc1NCBzdGFuZGFyZCBmb3IgcmVzb2x2aW5nXG4gICAgICogZmxvYXRpbmctcG9pbnQgdmFsdWVzIHdoaWNoIGNhbiBwcm9kdWNlIHVuZXhwZWN0ZWQgcmVzdWx0cy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAwLjcuMFxuICAgICAqIEBjYXRlZ29yeSBOdW1iZXJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xvd2VyPTBdIFRoZSBsb3dlciBib3VuZC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3VwcGVyPTFdIFRoZSB1cHBlciBib3VuZC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtmbG9hdGluZ10gU3BlY2lmeSByZXR1cm5pbmcgYSBmbG9hdGluZy1wb2ludCBudW1iZXIuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgcmFuZG9tIG51bWJlci5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5yYW5kb20oMCwgNSk7XG4gICAgICogLy8gPT4gYW4gaW50ZWdlciBiZXR3ZWVuIDAgYW5kIDVcbiAgICAgKlxuICAgICAqIF8ucmFuZG9tKDUpO1xuICAgICAqIC8vID0+IGFsc28gYW4gaW50ZWdlciBiZXR3ZWVuIDAgYW5kIDVcbiAgICAgKlxuICAgICAqIF8ucmFuZG9tKDUsIHRydWUpO1xuICAgICAqIC8vID0+IGEgZmxvYXRpbmctcG9pbnQgbnVtYmVyIGJldHdlZW4gMCBhbmQgNVxuICAgICAqXG4gICAgICogXy5yYW5kb20oMS4yLCA1LjIpO1xuICAgICAqIC8vID0+IGEgZmxvYXRpbmctcG9pbnQgbnVtYmVyIGJldHdlZW4gMS4yIGFuZCA1LjJcbiAgICAgKi9cbiAgICBmdW5jdGlvbiByYW5kb20obG93ZXIsIHVwcGVyLCBmbG9hdGluZykge1xuICAgICAgaWYgKGZsb2F0aW5nICYmIHR5cGVvZiBmbG9hdGluZyAhPSAnYm9vbGVhbicgJiYgaXNJdGVyYXRlZUNhbGwobG93ZXIsIHVwcGVyLCBmbG9hdGluZykpIHtcbiAgICAgICAgdXBwZXIgPSBmbG9hdGluZyA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIGlmIChmbG9hdGluZyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGlmICh0eXBlb2YgdXBwZXIgPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgZmxvYXRpbmcgPSB1cHBlcjtcbiAgICAgICAgICB1cHBlciA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0eXBlb2YgbG93ZXIgPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgZmxvYXRpbmcgPSBsb3dlcjtcbiAgICAgICAgICBsb3dlciA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGxvd2VyID09PSB1bmRlZmluZWQgJiYgdXBwZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBsb3dlciA9IDA7XG4gICAgICAgIHVwcGVyID0gMTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBsb3dlciA9IHRvRmluaXRlKGxvd2VyKTtcbiAgICAgICAgaWYgKHVwcGVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB1cHBlciA9IGxvd2VyO1xuICAgICAgICAgIGxvd2VyID0gMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB1cHBlciA9IHRvRmluaXRlKHVwcGVyKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGxvd2VyID4gdXBwZXIpIHtcbiAgICAgICAgdmFyIHRlbXAgPSBsb3dlcjtcbiAgICAgICAgbG93ZXIgPSB1cHBlcjtcbiAgICAgICAgdXBwZXIgPSB0ZW1wO1xuICAgICAgfVxuICAgICAgaWYgKGZsb2F0aW5nIHx8IGxvd2VyICUgMSB8fCB1cHBlciAlIDEpIHtcbiAgICAgICAgdmFyIHJhbmQgPSBuYXRpdmVSYW5kb20oKTtcbiAgICAgICAgcmV0dXJuIG5hdGl2ZU1pbihsb3dlciArIChyYW5kICogKHVwcGVyIC0gbG93ZXIgKyBmcmVlUGFyc2VGbG9hdCgnMWUtJyArICgocmFuZCArICcnKS5sZW5ndGggLSAxKSkpKSwgdXBwZXIpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJhc2VSYW5kb20obG93ZXIsIHVwcGVyKTtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgc3RyaW5nYCB0byBbY2FtZWwgY2FzZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ2FtZWxDYXNlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGNhbWVsIGNhc2VkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5jYW1lbENhc2UoJ0ZvbyBCYXInKTtcbiAgICAgKiAvLyA9PiAnZm9vQmFyJ1xuICAgICAqXG4gICAgICogXy5jYW1lbENhc2UoJy0tZm9vLWJhci0tJyk7XG4gICAgICogLy8gPT4gJ2Zvb0JhcidcbiAgICAgKlxuICAgICAqIF8uY2FtZWxDYXNlKCdfX0ZPT19CQVJfXycpO1xuICAgICAqIC8vID0+ICdmb29CYXInXG4gICAgICovXG4gICAgdmFyIGNhbWVsQ2FzZSA9IGNyZWF0ZUNvbXBvdW5kZXIoZnVuY3Rpb24ocmVzdWx0LCB3b3JkLCBpbmRleCkge1xuICAgICAgd29yZCA9IHdvcmQudG9Mb3dlckNhc2UoKTtcbiAgICAgIHJldHVybiByZXN1bHQgKyAoaW5kZXggPyBjYXBpdGFsaXplKHdvcmQpIDogd29yZCk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyB0aGUgZmlyc3QgY2hhcmFjdGVyIG9mIGBzdHJpbmdgIHRvIHVwcGVyIGNhc2UgYW5kIHRoZSByZW1haW5pbmdcbiAgICAgKiB0byBsb3dlciBjYXNlLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGNhcGl0YWxpemUuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgY2FwaXRhbGl6ZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmNhcGl0YWxpemUoJ0ZSRUQnKTtcbiAgICAgKiAvLyA9PiAnRnJlZCdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjYXBpdGFsaXplKHN0cmluZykge1xuICAgICAgcmV0dXJuIHVwcGVyRmlyc3QodG9TdHJpbmcoc3RyaW5nKS50b0xvd2VyQ2FzZSgpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZWJ1cnJzIGBzdHJpbmdgIGJ5IGNvbnZlcnRpbmdcbiAgICAgKiBbTGF0aW4tMSBTdXBwbGVtZW50XShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9MYXRpbi0xX1N1cHBsZW1lbnRfKFVuaWNvZGVfYmxvY2spI0NoYXJhY3Rlcl90YWJsZSlcbiAgICAgKiBhbmQgW0xhdGluIEV4dGVuZGVkLUFdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0xhdGluX0V4dGVuZGVkLUEpXG4gICAgICogbGV0dGVycyB0byBiYXNpYyBMYXRpbiBsZXR0ZXJzIGFuZCByZW1vdmluZ1xuICAgICAqIFtjb21iaW5pbmcgZGlhY3JpdGljYWwgbWFya3NdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NvbWJpbmluZ19EaWFjcml0aWNhbF9NYXJrcykuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gZGVidXJyLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGRlYnVycmVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5kZWJ1cnIoJ2TDqWrDoCB2dScpO1xuICAgICAqIC8vID0+ICdkZWphIHZ1J1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGRlYnVycihzdHJpbmcpIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICByZXR1cm4gc3RyaW5nICYmIHN0cmluZy5yZXBsYWNlKHJlTGF0aW4sIGRlYnVyckxldHRlcikucmVwbGFjZShyZUNvbWJvTWFyaywgJycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgc3RyaW5nYCBlbmRzIHdpdGggdGhlIGdpdmVuIHRhcmdldCBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gaW5zcGVjdC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3RhcmdldF0gVGhlIHN0cmluZyB0byBzZWFyY2ggZm9yLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbcG9zaXRpb249c3RyaW5nLmxlbmd0aF0gVGhlIHBvc2l0aW9uIHRvIHNlYXJjaCB1cCB0by5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHN0cmluZ2AgZW5kcyB3aXRoIGB0YXJnZXRgLFxuICAgICAqICBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZW5kc1dpdGgoJ2FiYycsICdjJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogXy5lbmRzV2l0aCgnYWJjJywgJ2InKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqXG4gICAgICogXy5lbmRzV2l0aCgnYWJjJywgJ2InLCAyKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gZW5kc1dpdGgoc3RyaW5nLCB0YXJnZXQsIHBvc2l0aW9uKSB7XG4gICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuICAgICAgdGFyZ2V0ID0gYmFzZVRvU3RyaW5nKHRhcmdldCk7XG5cbiAgICAgIHZhciBsZW5ndGggPSBzdHJpbmcubGVuZ3RoO1xuICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbiA9PT0gdW5kZWZpbmVkXG4gICAgICAgID8gbGVuZ3RoXG4gICAgICAgIDogYmFzZUNsYW1wKHRvSW50ZWdlcihwb3NpdGlvbiksIDAsIGxlbmd0aCk7XG5cbiAgICAgIHZhciBlbmQgPSBwb3NpdGlvbjtcbiAgICAgIHBvc2l0aW9uIC09IHRhcmdldC5sZW5ndGg7XG4gICAgICByZXR1cm4gcG9zaXRpb24gPj0gMCAmJiBzdHJpbmcuc2xpY2UocG9zaXRpb24sIGVuZCkgPT0gdGFyZ2V0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIHRoZSBjaGFyYWN0ZXJzIFwiJlwiLCBcIjxcIiwgXCI+XCIsICdcIicsIGFuZCBcIidcIiBpbiBgc3RyaW5nYCB0byB0aGVpclxuICAgICAqIGNvcnJlc3BvbmRpbmcgSFRNTCBlbnRpdGllcy5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBObyBvdGhlciBjaGFyYWN0ZXJzIGFyZSBlc2NhcGVkLiBUbyBlc2NhcGUgYWRkaXRpb25hbFxuICAgICAqIGNoYXJhY3RlcnMgdXNlIGEgdGhpcmQtcGFydHkgbGlicmFyeSBsaWtlIFtfaGVfXShodHRwczovL210aHMuYmUvaGUpLlxuICAgICAqXG4gICAgICogVGhvdWdoIHRoZSBcIj5cIiBjaGFyYWN0ZXIgaXMgZXNjYXBlZCBmb3Igc3ltbWV0cnksIGNoYXJhY3RlcnMgbGlrZVxuICAgICAqIFwiPlwiIGFuZCBcIi9cIiBkb24ndCBuZWVkIGVzY2FwaW5nIGluIEhUTUwgYW5kIGhhdmUgbm8gc3BlY2lhbCBtZWFuaW5nXG4gICAgICogdW5sZXNzIHRoZXkncmUgcGFydCBvZiBhIHRhZyBvciB1bnF1b3RlZCBhdHRyaWJ1dGUgdmFsdWUuIFNlZVxuICAgICAqIFtNYXRoaWFzIEJ5bmVucydzIGFydGljbGVdKGh0dHBzOi8vbWF0aGlhc2J5bmVucy5iZS9ub3Rlcy9hbWJpZ3VvdXMtYW1wZXJzYW5kcylcbiAgICAgKiAodW5kZXIgXCJzZW1pLXJlbGF0ZWQgZnVuIGZhY3RcIikgZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgKlxuICAgICAqIFdoZW4gd29ya2luZyB3aXRoIEhUTUwgeW91IHNob3VsZCBhbHdheXNcbiAgICAgKiBbcXVvdGUgYXR0cmlidXRlIHZhbHVlc10oaHR0cDovL3dvbmtvLmNvbS9wb3N0L2h0bWwtZXNjYXBpbmcpIHRvIHJlZHVjZVxuICAgICAqIFhTUyB2ZWN0b3JzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGVzY2FwZS5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBlc2NhcGVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5lc2NhcGUoJ2ZyZWQsIGJhcm5leSwgJiBwZWJibGVzJyk7XG4gICAgICogLy8gPT4gJ2ZyZWQsIGJhcm5leSwgJmFtcDsgcGViYmxlcydcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBlc2NhcGUoc3RyaW5nKSB7XG4gICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuICAgICAgcmV0dXJuIChzdHJpbmcgJiYgcmVIYXNVbmVzY2FwZWRIdG1sLnRlc3Qoc3RyaW5nKSlcbiAgICAgICAgPyBzdHJpbmcucmVwbGFjZShyZVVuZXNjYXBlZEh0bWwsIGVzY2FwZUh0bWxDaGFyKVxuICAgICAgICA6IHN0cmluZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFc2NhcGVzIHRoZSBgUmVnRXhwYCBzcGVjaWFsIGNoYXJhY3RlcnMgXCJeXCIsIFwiJFwiLCBcIlxcXCIsIFwiLlwiLCBcIipcIiwgXCIrXCIsXG4gICAgICogXCI/XCIsIFwiKFwiLCBcIilcIiwgXCJbXCIsIFwiXVwiLCBcIntcIiwgXCJ9XCIsIGFuZCBcInxcIiBpbiBgc3RyaW5nYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBlc2NhcGUuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgZXNjYXBlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uZXNjYXBlUmVnRXhwKCdbbG9kYXNoXShodHRwczovL2xvZGFzaC5jb20vKScpO1xuICAgICAqIC8vID0+ICdcXFtsb2Rhc2hcXF1cXChodHRwczovL2xvZGFzaFxcLmNvbS9cXCknXG4gICAgICovXG4gICAgZnVuY3Rpb24gZXNjYXBlUmVnRXhwKHN0cmluZykge1xuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIHJldHVybiAoc3RyaW5nICYmIHJlSGFzUmVnRXhwQ2hhci50ZXN0KHN0cmluZykpXG4gICAgICAgID8gc3RyaW5nLnJlcGxhY2UocmVSZWdFeHBDaGFyLCAnXFxcXCQmJylcbiAgICAgICAgOiBzdHJpbmc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHN0cmluZ2AgdG9cbiAgICAgKiBba2ViYWIgY2FzZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGV0dGVyX2Nhc2UjU3BlY2lhbF9jYXNlX3N0eWxlcykuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBrZWJhYiBjYXNlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ua2ViYWJDYXNlKCdGb28gQmFyJyk7XG4gICAgICogLy8gPT4gJ2Zvby1iYXInXG4gICAgICpcbiAgICAgKiBfLmtlYmFiQ2FzZSgnZm9vQmFyJyk7XG4gICAgICogLy8gPT4gJ2Zvby1iYXInXG4gICAgICpcbiAgICAgKiBfLmtlYmFiQ2FzZSgnX19GT09fQkFSX18nKTtcbiAgICAgKiAvLyA9PiAnZm9vLWJhcidcbiAgICAgKi9cbiAgICB2YXIga2ViYWJDYXNlID0gY3JlYXRlQ29tcG91bmRlcihmdW5jdGlvbihyZXN1bHQsIHdvcmQsIGluZGV4KSB7XG4gICAgICByZXR1cm4gcmVzdWx0ICsgKGluZGV4ID8gJy0nIDogJycpICsgd29yZC50b0xvd2VyQ2FzZSgpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHN0cmluZ2AsIGFzIHNwYWNlIHNlcGFyYXRlZCB3b3JkcywgdG8gbG93ZXIgY2FzZS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGxvd2VyIGNhc2VkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5sb3dlckNhc2UoJy0tRm9vLUJhci0tJyk7XG4gICAgICogLy8gPT4gJ2ZvbyBiYXInXG4gICAgICpcbiAgICAgKiBfLmxvd2VyQ2FzZSgnZm9vQmFyJyk7XG4gICAgICogLy8gPT4gJ2ZvbyBiYXInXG4gICAgICpcbiAgICAgKiBfLmxvd2VyQ2FzZSgnX19GT09fQkFSX18nKTtcbiAgICAgKiAvLyA9PiAnZm9vIGJhcidcbiAgICAgKi9cbiAgICB2YXIgbG93ZXJDYXNlID0gY3JlYXRlQ29tcG91bmRlcihmdW5jdGlvbihyZXN1bHQsIHdvcmQsIGluZGV4KSB7XG4gICAgICByZXR1cm4gcmVzdWx0ICsgKGluZGV4ID8gJyAnIDogJycpICsgd29yZC50b0xvd2VyQ2FzZSgpO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgdGhlIGZpcnN0IGNoYXJhY3RlciBvZiBgc3RyaW5nYCB0byBsb3dlciBjYXNlLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgY29udmVydGVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5sb3dlckZpcnN0KCdGcmVkJyk7XG4gICAgICogLy8gPT4gJ2ZyZWQnXG4gICAgICpcbiAgICAgKiBfLmxvd2VyRmlyc3QoJ0ZSRUQnKTtcbiAgICAgKiAvLyA9PiAnZlJFRCdcbiAgICAgKi9cbiAgICB2YXIgbG93ZXJGaXJzdCA9IGNyZWF0ZUNhc2VGaXJzdCgndG9Mb3dlckNhc2UnKTtcblxuICAgIC8qKlxuICAgICAqIFBhZHMgYHN0cmluZ2Agb24gdGhlIGxlZnQgYW5kIHJpZ2h0IHNpZGVzIGlmIGl0J3Mgc2hvcnRlciB0aGFuIGBsZW5ndGhgLlxuICAgICAqIFBhZGRpbmcgY2hhcmFjdGVycyBhcmUgdHJ1bmNhdGVkIGlmIHRoZXkgY2FuJ3QgYmUgZXZlbmx5IGRpdmlkZWQgYnkgYGxlbmd0aGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gcGFkLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbGVuZ3RoPTBdIFRoZSBwYWRkaW5nIGxlbmd0aC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW2NoYXJzPScgJ10gVGhlIHN0cmluZyB1c2VkIGFzIHBhZGRpbmcuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgcGFkZGVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5wYWQoJ2FiYycsIDgpO1xuICAgICAqIC8vID0+ICcgIGFiYyAgICdcbiAgICAgKlxuICAgICAqIF8ucGFkKCdhYmMnLCA4LCAnXy0nKTtcbiAgICAgKiAvLyA9PiAnXy1hYmNfLV8nXG4gICAgICpcbiAgICAgKiBfLnBhZCgnYWJjJywgMyk7XG4gICAgICogLy8gPT4gJ2FiYydcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwYWQoc3RyaW5nLCBsZW5ndGgsIGNoYXJzKSB7XG4gICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuICAgICAgbGVuZ3RoID0gdG9JbnRlZ2VyKGxlbmd0aCk7XG5cbiAgICAgIHZhciBzdHJMZW5ndGggPSBsZW5ndGggPyBzdHJpbmdTaXplKHN0cmluZykgOiAwO1xuICAgICAgaWYgKCFsZW5ndGggfHwgc3RyTGVuZ3RoID49IGxlbmd0aCkge1xuICAgICAgICByZXR1cm4gc3RyaW5nO1xuICAgICAgfVxuICAgICAgdmFyIG1pZCA9IChsZW5ndGggLSBzdHJMZW5ndGgpIC8gMjtcbiAgICAgIHJldHVybiAoXG4gICAgICAgIGNyZWF0ZVBhZGRpbmcobmF0aXZlRmxvb3IobWlkKSwgY2hhcnMpICtcbiAgICAgICAgc3RyaW5nICtcbiAgICAgICAgY3JlYXRlUGFkZGluZyhuYXRpdmVDZWlsKG1pZCksIGNoYXJzKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQYWRzIGBzdHJpbmdgIG9uIHRoZSByaWdodCBzaWRlIGlmIGl0J3Mgc2hvcnRlciB0aGFuIGBsZW5ndGhgLiBQYWRkaW5nXG4gICAgICogY2hhcmFjdGVycyBhcmUgdHJ1bmNhdGVkIGlmIHRoZXkgZXhjZWVkIGBsZW5ndGhgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIHBhZC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xlbmd0aD0wXSBUaGUgcGFkZGluZyBsZW5ndGguXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtjaGFycz0nICddIFRoZSBzdHJpbmcgdXNlZCBhcyBwYWRkaW5nLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHBhZGRlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ucGFkRW5kKCdhYmMnLCA2KTtcbiAgICAgKiAvLyA9PiAnYWJjICAgJ1xuICAgICAqXG4gICAgICogXy5wYWRFbmQoJ2FiYycsIDYsICdfLScpO1xuICAgICAqIC8vID0+ICdhYmNfLV8nXG4gICAgICpcbiAgICAgKiBfLnBhZEVuZCgnYWJjJywgMyk7XG4gICAgICogLy8gPT4gJ2FiYydcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwYWRFbmQoc3RyaW5nLCBsZW5ndGgsIGNoYXJzKSB7XG4gICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuICAgICAgbGVuZ3RoID0gdG9JbnRlZ2VyKGxlbmd0aCk7XG5cbiAgICAgIHZhciBzdHJMZW5ndGggPSBsZW5ndGggPyBzdHJpbmdTaXplKHN0cmluZykgOiAwO1xuICAgICAgcmV0dXJuIChsZW5ndGggJiYgc3RyTGVuZ3RoIDwgbGVuZ3RoKVxuICAgICAgICA/IChzdHJpbmcgKyBjcmVhdGVQYWRkaW5nKGxlbmd0aCAtIHN0ckxlbmd0aCwgY2hhcnMpKVxuICAgICAgICA6IHN0cmluZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQYWRzIGBzdHJpbmdgIG9uIHRoZSBsZWZ0IHNpZGUgaWYgaXQncyBzaG9ydGVyIHRoYW4gYGxlbmd0aGAuIFBhZGRpbmdcbiAgICAgKiBjaGFyYWN0ZXJzIGFyZSB0cnVuY2F0ZWQgaWYgdGhleSBleGNlZWQgYGxlbmd0aGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gcGFkLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbGVuZ3RoPTBdIFRoZSBwYWRkaW5nIGxlbmd0aC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW2NoYXJzPScgJ10gVGhlIHN0cmluZyB1c2VkIGFzIHBhZGRpbmcuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgcGFkZGVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5wYWRTdGFydCgnYWJjJywgNik7XG4gICAgICogLy8gPT4gJyAgIGFiYydcbiAgICAgKlxuICAgICAqIF8ucGFkU3RhcnQoJ2FiYycsIDYsICdfLScpO1xuICAgICAqIC8vID0+ICdfLV9hYmMnXG4gICAgICpcbiAgICAgKiBfLnBhZFN0YXJ0KCdhYmMnLCAzKTtcbiAgICAgKiAvLyA9PiAnYWJjJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHBhZFN0YXJ0KHN0cmluZywgbGVuZ3RoLCBjaGFycykge1xuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIGxlbmd0aCA9IHRvSW50ZWdlcihsZW5ndGgpO1xuXG4gICAgICB2YXIgc3RyTGVuZ3RoID0gbGVuZ3RoID8gc3RyaW5nU2l6ZShzdHJpbmcpIDogMDtcbiAgICAgIHJldHVybiAobGVuZ3RoICYmIHN0ckxlbmd0aCA8IGxlbmd0aClcbiAgICAgICAgPyAoY3JlYXRlUGFkZGluZyhsZW5ndGggLSBzdHJMZW5ndGgsIGNoYXJzKSArIHN0cmluZylcbiAgICAgICAgOiBzdHJpbmc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHN0cmluZ2AgdG8gYW4gaW50ZWdlciBvZiB0aGUgc3BlY2lmaWVkIHJhZGl4LiBJZiBgcmFkaXhgIGlzXG4gICAgICogYHVuZGVmaW5lZGAgb3IgYDBgLCBhIGByYWRpeGAgb2YgYDEwYCBpcyB1c2VkIHVubGVzcyBgdmFsdWVgIGlzIGFcbiAgICAgKiBoZXhhZGVjaW1hbCwgaW4gd2hpY2ggY2FzZSBhIGByYWRpeGAgb2YgYDE2YCBpcyB1c2VkLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGFsaWducyB3aXRoIHRoZVxuICAgICAqIFtFUzUgaW1wbGVtZW50YXRpb25dKGh0dHBzOi8vZXM1LmdpdGh1Yi5pby8jeDE1LjEuMi4yKSBvZiBgcGFyc2VJbnRgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDEuMS4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbcmFkaXg9MTBdIFRoZSByYWRpeCB0byBpbnRlcnByZXQgYHZhbHVlYCBieS5cbiAgICAgKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYW4gaXRlcmF0ZWUgZm9yIG1ldGhvZHMgbGlrZSBgXy5tYXBgLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBpbnRlZ2VyLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnBhcnNlSW50KCcwOCcpO1xuICAgICAqIC8vID0+IDhcbiAgICAgKlxuICAgICAqIF8ubWFwKFsnNicsICcwOCcsICcxMCddLCBfLnBhcnNlSW50KTtcbiAgICAgKiAvLyA9PiBbNiwgOCwgMTBdXG4gICAgICovXG4gICAgZnVuY3Rpb24gcGFyc2VJbnQoc3RyaW5nLCByYWRpeCwgZ3VhcmQpIHtcbiAgICAgIGlmIChndWFyZCB8fCByYWRpeCA9PSBudWxsKSB7XG4gICAgICAgIHJhZGl4ID0gMDtcbiAgICAgIH0gZWxzZSBpZiAocmFkaXgpIHtcbiAgICAgICAgcmFkaXggPSArcmFkaXg7XG4gICAgICB9XG4gICAgICByZXR1cm4gbmF0aXZlUGFyc2VJbnQodG9TdHJpbmcoc3RyaW5nKS5yZXBsYWNlKHJlVHJpbVN0YXJ0LCAnJyksIHJhZGl4IHx8IDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlcGVhdHMgdGhlIGdpdmVuIHN0cmluZyBgbmAgdGltZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gcmVwZWF0LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbj0xXSBUaGUgbnVtYmVyIG9mIHRpbWVzIHRvIHJlcGVhdCB0aGUgc3RyaW5nLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgcmVwZWF0ZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnJlcGVhdCgnKicsIDMpO1xuICAgICAqIC8vID0+ICcqKionXG4gICAgICpcbiAgICAgKiBfLnJlcGVhdCgnYWJjJywgMik7XG4gICAgICogLy8gPT4gJ2FiY2FiYydcbiAgICAgKlxuICAgICAqIF8ucmVwZWF0KCdhYmMnLCAwKTtcbiAgICAgKiAvLyA9PiAnJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHJlcGVhdChzdHJpbmcsIG4sIGd1YXJkKSB7XG4gICAgICBpZiAoKGd1YXJkID8gaXNJdGVyYXRlZUNhbGwoc3RyaW5nLCBuLCBndWFyZCkgOiBuID09PSB1bmRlZmluZWQpKSB7XG4gICAgICAgIG4gPSAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbiA9IHRvSW50ZWdlcihuKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiYXNlUmVwZWF0KHRvU3RyaW5nKHN0cmluZyksIG4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlcGxhY2VzIG1hdGNoZXMgZm9yIGBwYXR0ZXJuYCBpbiBgc3RyaW5nYCB3aXRoIGByZXBsYWNlbWVudGAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgYmFzZWQgb25cbiAgICAgKiBbYFN0cmluZyNyZXBsYWNlYF0oaHR0cHM6Ly9tZG4uaW8vU3RyaW5nL3JlcGxhY2UpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIG1vZGlmeS5cbiAgICAgKiBAcGFyYW0ge1JlZ0V4cHxzdHJpbmd9IHBhdHRlcm4gVGhlIHBhdHRlcm4gdG8gcmVwbGFjZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufHN0cmluZ30gcmVwbGFjZW1lbnQgVGhlIG1hdGNoIHJlcGxhY2VtZW50LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIG1vZGlmaWVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5yZXBsYWNlKCdIaSBGcmVkJywgJ0ZyZWQnLCAnQmFybmV5Jyk7XG4gICAgICogLy8gPT4gJ0hpIEJhcm5leSdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZXBsYWNlKCkge1xuICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHMsXG4gICAgICAgICAgc3RyaW5nID0gdG9TdHJpbmcoYXJnc1swXSk7XG5cbiAgICAgIHJldHVybiBhcmdzLmxlbmd0aCA8IDMgPyBzdHJpbmcgOiBzdHJpbmcucmVwbGFjZShhcmdzWzFdLCBhcmdzWzJdKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgc3RyaW5nYCB0b1xuICAgICAqIFtzbmFrZSBjYXNlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TbmFrZV9jYXNlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHNuYWtlIGNhc2VkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zbmFrZUNhc2UoJ0ZvbyBCYXInKTtcbiAgICAgKiAvLyA9PiAnZm9vX2JhcidcbiAgICAgKlxuICAgICAqIF8uc25ha2VDYXNlKCdmb29CYXInKTtcbiAgICAgKiAvLyA9PiAnZm9vX2JhcidcbiAgICAgKlxuICAgICAqIF8uc25ha2VDYXNlKCctLUZPTy1CQVItLScpO1xuICAgICAqIC8vID0+ICdmb29fYmFyJ1xuICAgICAqL1xuICAgIHZhciBzbmFrZUNhc2UgPSBjcmVhdGVDb21wb3VuZGVyKGZ1bmN0aW9uKHJlc3VsdCwgd29yZCwgaW5kZXgpIHtcbiAgICAgIHJldHVybiByZXN1bHQgKyAoaW5kZXggPyAnXycgOiAnJykgKyB3b3JkLnRvTG93ZXJDYXNlKCk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBTcGxpdHMgYHN0cmluZ2AgYnkgYHNlcGFyYXRvcmAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgYmFzZWQgb25cbiAgICAgKiBbYFN0cmluZyNzcGxpdGBdKGh0dHBzOi8vbWRuLmlvL1N0cmluZy9zcGxpdCkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gc3BsaXQuXG4gICAgICogQHBhcmFtIHtSZWdFeHB8c3RyaW5nfSBzZXBhcmF0b3IgVGhlIHNlcGFyYXRvciBwYXR0ZXJuIHRvIHNwbGl0IGJ5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbGltaXRdIFRoZSBsZW5ndGggdG8gdHJ1bmNhdGUgcmVzdWx0cyB0by5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHN0cmluZyBzZWdtZW50cy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zcGxpdCgnYS1iLWMnLCAnLScsIDIpO1xuICAgICAqIC8vID0+IFsnYScsICdiJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzcGxpdChzdHJpbmcsIHNlcGFyYXRvciwgbGltaXQpIHtcbiAgICAgIGlmIChsaW1pdCAmJiB0eXBlb2YgbGltaXQgIT0gJ251bWJlcicgJiYgaXNJdGVyYXRlZUNhbGwoc3RyaW5nLCBzZXBhcmF0b3IsIGxpbWl0KSkge1xuICAgICAgICBzZXBhcmF0b3IgPSBsaW1pdCA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIGxpbWl0ID0gbGltaXQgPT09IHVuZGVmaW5lZCA/IE1BWF9BUlJBWV9MRU5HVEggOiBsaW1pdCA+Pj4gMDtcbiAgICAgIGlmICghbGltaXQpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIGlmIChzdHJpbmcgJiYgKFxuICAgICAgICAgICAgdHlwZW9mIHNlcGFyYXRvciA9PSAnc3RyaW5nJyB8fFxuICAgICAgICAgICAgKHNlcGFyYXRvciAhPSBudWxsICYmICFpc1JlZ0V4cChzZXBhcmF0b3IpKVxuICAgICAgICAgICkpIHtcbiAgICAgICAgc2VwYXJhdG9yID0gYmFzZVRvU3RyaW5nKHNlcGFyYXRvcik7XG4gICAgICAgIGlmICghc2VwYXJhdG9yICYmIGhhc1VuaWNvZGUoc3RyaW5nKSkge1xuICAgICAgICAgIHJldHVybiBjYXN0U2xpY2Uoc3RyaW5nVG9BcnJheShzdHJpbmcpLCAwLCBsaW1pdCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBzdHJpbmcuc3BsaXQoc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHN0cmluZ2AgdG9cbiAgICAgKiBbc3RhcnQgY2FzZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGV0dGVyX2Nhc2UjU3R5bGlzdGljX29yX3NwZWNpYWxpc2VkX3VzYWdlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjEuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHN0YXJ0IGNhc2VkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zdGFydENhc2UoJy0tZm9vLWJhci0tJyk7XG4gICAgICogLy8gPT4gJ0ZvbyBCYXInXG4gICAgICpcbiAgICAgKiBfLnN0YXJ0Q2FzZSgnZm9vQmFyJyk7XG4gICAgICogLy8gPT4gJ0ZvbyBCYXInXG4gICAgICpcbiAgICAgKiBfLnN0YXJ0Q2FzZSgnX19GT09fQkFSX18nKTtcbiAgICAgKiAvLyA9PiAnRk9PIEJBUidcbiAgICAgKi9cbiAgICB2YXIgc3RhcnRDYXNlID0gY3JlYXRlQ29tcG91bmRlcihmdW5jdGlvbihyZXN1bHQsIHdvcmQsIGluZGV4KSB7XG4gICAgICByZXR1cm4gcmVzdWx0ICsgKGluZGV4ID8gJyAnIDogJycpICsgdXBwZXJGaXJzdCh3b3JkKTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBgc3RyaW5nYCBzdGFydHMgd2l0aCB0aGUgZ2l2ZW4gdGFyZ2V0IHN0cmluZy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHN0cmluZyB0byBpbnNwZWN0LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbdGFyZ2V0XSBUaGUgc3RyaW5nIHRvIHNlYXJjaCBmb3IuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtwb3NpdGlvbj0wXSBUaGUgcG9zaXRpb24gdG8gc2VhcmNoIGZyb20uXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGBzdHJpbmdgIHN0YXJ0cyB3aXRoIGB0YXJnZXRgLFxuICAgICAqICBlbHNlIGBmYWxzZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uc3RhcnRzV2l0aCgnYWJjJywgJ2EnKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBfLnN0YXJ0c1dpdGgoJ2FiYycsICdiJyk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKlxuICAgICAqIF8uc3RhcnRzV2l0aCgnYWJjJywgJ2InLCAxKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gc3RhcnRzV2l0aChzdHJpbmcsIHRhcmdldCwgcG9zaXRpb24pIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uID09IG51bGxcbiAgICAgICAgPyAwXG4gICAgICAgIDogYmFzZUNsYW1wKHRvSW50ZWdlcihwb3NpdGlvbiksIDAsIHN0cmluZy5sZW5ndGgpO1xuXG4gICAgICB0YXJnZXQgPSBiYXNlVG9TdHJpbmcodGFyZ2V0KTtcbiAgICAgIHJldHVybiBzdHJpbmcuc2xpY2UocG9zaXRpb24sIHBvc2l0aW9uICsgdGFyZ2V0Lmxlbmd0aCkgPT0gdGFyZ2V0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBjb21waWxlZCB0ZW1wbGF0ZSBmdW5jdGlvbiB0aGF0IGNhbiBpbnRlcnBvbGF0ZSBkYXRhIHByb3BlcnRpZXNcbiAgICAgKiBpbiBcImludGVycG9sYXRlXCIgZGVsaW1pdGVycywgSFRNTC1lc2NhcGUgaW50ZXJwb2xhdGVkIGRhdGEgcHJvcGVydGllcyBpblxuICAgICAqIFwiZXNjYXBlXCIgZGVsaW1pdGVycywgYW5kIGV4ZWN1dGUgSmF2YVNjcmlwdCBpbiBcImV2YWx1YXRlXCIgZGVsaW1pdGVycy4gRGF0YVxuICAgICAqIHByb3BlcnRpZXMgbWF5IGJlIGFjY2Vzc2VkIGFzIGZyZWUgdmFyaWFibGVzIGluIHRoZSB0ZW1wbGF0ZS4gSWYgYSBzZXR0aW5nXG4gICAgICogb2JqZWN0IGlzIGdpdmVuLCBpdCB0YWtlcyBwcmVjZWRlbmNlIG92ZXIgYF8udGVtcGxhdGVTZXR0aW5nc2AgdmFsdWVzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIEluIHRoZSBkZXZlbG9wbWVudCBidWlsZCBgXy50ZW1wbGF0ZWAgdXRpbGl6ZXNcbiAgICAgKiBbc291cmNlVVJMc10oaHR0cDovL3d3dy5odG1sNXJvY2tzLmNvbS9lbi90dXRvcmlhbHMvZGV2ZWxvcGVydG9vbHMvc291cmNlbWFwcy8jdG9jLXNvdXJjZXVybClcbiAgICAgKiBmb3IgZWFzaWVyIGRlYnVnZ2luZy5cbiAgICAgKlxuICAgICAqIEZvciBtb3JlIGluZm9ybWF0aW9uIG9uIHByZWNvbXBpbGluZyB0ZW1wbGF0ZXMgc2VlXG4gICAgICogW2xvZGFzaCdzIGN1c3RvbSBidWlsZHMgZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly9sb2Rhc2guY29tL2N1c3RvbS1idWlsZHMpLlxuICAgICAqXG4gICAgICogRm9yIG1vcmUgaW5mb3JtYXRpb24gb24gQ2hyb21lIGV4dGVuc2lvbiBzYW5kYm94ZXMgc2VlXG4gICAgICogW0Nocm9tZSdzIGV4dGVuc2lvbnMgZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly9kZXZlbG9wZXIuY2hyb21lLmNvbS9leHRlbnNpb25zL3NhbmRib3hpbmdFdmFsKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3N0cmluZz0nJ10gVGhlIHRlbXBsYXRlIHN0cmluZy5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIFRoZSBvcHRpb25zIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge1JlZ0V4cH0gW29wdGlvbnMuZXNjYXBlPV8udGVtcGxhdGVTZXR0aW5ncy5lc2NhcGVdXG4gICAgICogIFRoZSBIVE1MIFwiZXNjYXBlXCIgZGVsaW1pdGVyLlxuICAgICAqIEBwYXJhbSB7UmVnRXhwfSBbb3B0aW9ucy5ldmFsdWF0ZT1fLnRlbXBsYXRlU2V0dGluZ3MuZXZhbHVhdGVdXG4gICAgICogIFRoZSBcImV2YWx1YXRlXCIgZGVsaW1pdGVyLlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucy5pbXBvcnRzPV8udGVtcGxhdGVTZXR0aW5ncy5pbXBvcnRzXVxuICAgICAqICBBbiBvYmplY3QgdG8gaW1wb3J0IGludG8gdGhlIHRlbXBsYXRlIGFzIGZyZWUgdmFyaWFibGVzLlxuICAgICAqIEBwYXJhbSB7UmVnRXhwfSBbb3B0aW9ucy5pbnRlcnBvbGF0ZT1fLnRlbXBsYXRlU2V0dGluZ3MuaW50ZXJwb2xhdGVdXG4gICAgICogIFRoZSBcImludGVycG9sYXRlXCIgZGVsaW1pdGVyLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0aW9ucy5zb3VyY2VVUkw9J2xvZGFzaC50ZW1wbGF0ZVNvdXJjZXNbbl0nXVxuICAgICAqICBUaGUgc291cmNlVVJMIG9mIHRoZSBjb21waWxlZCB0ZW1wbGF0ZS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdGlvbnMudmFyaWFibGU9J29iaiddXG4gICAgICogIFRoZSBkYXRhIG9iamVjdCB2YXJpYWJsZSBuYW1lLlxuICAgICAqIEBwYXJhbS0ge09iamVjdH0gW2d1YXJkXSBFbmFibGVzIHVzZSBhcyBhbiBpdGVyYXRlZSBmb3IgbWV0aG9kcyBsaWtlIGBfLm1hcGAuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBjb21waWxlZCB0ZW1wbGF0ZSBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogLy8gVXNlIHRoZSBcImludGVycG9sYXRlXCIgZGVsaW1pdGVyIHRvIGNyZWF0ZSBhIGNvbXBpbGVkIHRlbXBsYXRlLlxuICAgICAqIHZhciBjb21waWxlZCA9IF8udGVtcGxhdGUoJ2hlbGxvIDwlPSB1c2VyICU+IScpO1xuICAgICAqIGNvbXBpbGVkKHsgJ3VzZXInOiAnZnJlZCcgfSk7XG4gICAgICogLy8gPT4gJ2hlbGxvIGZyZWQhJ1xuICAgICAqXG4gICAgICogLy8gVXNlIHRoZSBIVE1MIFwiZXNjYXBlXCIgZGVsaW1pdGVyIHRvIGVzY2FwZSBkYXRhIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgKiB2YXIgY29tcGlsZWQgPSBfLnRlbXBsYXRlKCc8Yj48JS0gdmFsdWUgJT48L2I+Jyk7XG4gICAgICogY29tcGlsZWQoeyAndmFsdWUnOiAnPHNjcmlwdD4nIH0pO1xuICAgICAqIC8vID0+ICc8Yj4mbHQ7c2NyaXB0Jmd0OzwvYj4nXG4gICAgICpcbiAgICAgKiAvLyBVc2UgdGhlIFwiZXZhbHVhdGVcIiBkZWxpbWl0ZXIgdG8gZXhlY3V0ZSBKYXZhU2NyaXB0IGFuZCBnZW5lcmF0ZSBIVE1MLlxuICAgICAqIHZhciBjb21waWxlZCA9IF8udGVtcGxhdGUoJzwlIF8uZm9yRWFjaCh1c2VycywgZnVuY3Rpb24odXNlcikgeyAlPjxsaT48JS0gdXNlciAlPjwvbGk+PCUgfSk7ICU+Jyk7XG4gICAgICogY29tcGlsZWQoeyAndXNlcnMnOiBbJ2ZyZWQnLCAnYmFybmV5J10gfSk7XG4gICAgICogLy8gPT4gJzxsaT5mcmVkPC9saT48bGk+YmFybmV5PC9saT4nXG4gICAgICpcbiAgICAgKiAvLyBVc2UgdGhlIGludGVybmFsIGBwcmludGAgZnVuY3Rpb24gaW4gXCJldmFsdWF0ZVwiIGRlbGltaXRlcnMuXG4gICAgICogdmFyIGNvbXBpbGVkID0gXy50ZW1wbGF0ZSgnPCUgcHJpbnQoXCJoZWxsbyBcIiArIHVzZXIpOyAlPiEnKTtcbiAgICAgKiBjb21waWxlZCh7ICd1c2VyJzogJ2Jhcm5leScgfSk7XG4gICAgICogLy8gPT4gJ2hlbGxvIGJhcm5leSEnXG4gICAgICpcbiAgICAgKiAvLyBVc2UgdGhlIEVTIHRlbXBsYXRlIGxpdGVyYWwgZGVsaW1pdGVyIGFzIGFuIFwiaW50ZXJwb2xhdGVcIiBkZWxpbWl0ZXIuXG4gICAgICogLy8gRGlzYWJsZSBzdXBwb3J0IGJ5IHJlcGxhY2luZyB0aGUgXCJpbnRlcnBvbGF0ZVwiIGRlbGltaXRlci5cbiAgICAgKiB2YXIgY29tcGlsZWQgPSBfLnRlbXBsYXRlKCdoZWxsbyAkeyB1c2VyIH0hJyk7XG4gICAgICogY29tcGlsZWQoeyAndXNlcic6ICdwZWJibGVzJyB9KTtcbiAgICAgKiAvLyA9PiAnaGVsbG8gcGViYmxlcyEnXG4gICAgICpcbiAgICAgKiAvLyBVc2UgYmFja3NsYXNoZXMgdG8gdHJlYXQgZGVsaW1pdGVycyBhcyBwbGFpbiB0ZXh0LlxuICAgICAqIHZhciBjb21waWxlZCA9IF8udGVtcGxhdGUoJzwlPSBcIlxcXFw8JS0gdmFsdWUgJVxcXFw+XCIgJT4nKTtcbiAgICAgKiBjb21waWxlZCh7ICd2YWx1ZSc6ICdpZ25vcmVkJyB9KTtcbiAgICAgKiAvLyA9PiAnPCUtIHZhbHVlICU+J1xuICAgICAqXG4gICAgICogLy8gVXNlIHRoZSBgaW1wb3J0c2Agb3B0aW9uIHRvIGltcG9ydCBgalF1ZXJ5YCBhcyBganFgLlxuICAgICAqIHZhciB0ZXh0ID0gJzwlIGpxLmVhY2godXNlcnMsIGZ1bmN0aW9uKHVzZXIpIHsgJT48bGk+PCUtIHVzZXIgJT48L2xpPjwlIH0pOyAlPic7XG4gICAgICogdmFyIGNvbXBpbGVkID0gXy50ZW1wbGF0ZSh0ZXh0LCB7ICdpbXBvcnRzJzogeyAnanEnOiBqUXVlcnkgfSB9KTtcbiAgICAgKiBjb21waWxlZCh7ICd1c2Vycyc6IFsnZnJlZCcsICdiYXJuZXknXSB9KTtcbiAgICAgKiAvLyA9PiAnPGxpPmZyZWQ8L2xpPjxsaT5iYXJuZXk8L2xpPidcbiAgICAgKlxuICAgICAqIC8vIFVzZSB0aGUgYHNvdXJjZVVSTGAgb3B0aW9uIHRvIHNwZWNpZnkgYSBjdXN0b20gc291cmNlVVJMIGZvciB0aGUgdGVtcGxhdGUuXG4gICAgICogdmFyIGNvbXBpbGVkID0gXy50ZW1wbGF0ZSgnaGVsbG8gPCU9IHVzZXIgJT4hJywgeyAnc291cmNlVVJMJzogJy9iYXNpYy9ncmVldGluZy5qc3QnIH0pO1xuICAgICAqIGNvbXBpbGVkKGRhdGEpO1xuICAgICAqIC8vID0+IEZpbmQgdGhlIHNvdXJjZSBvZiBcImdyZWV0aW5nLmpzdFwiIHVuZGVyIHRoZSBTb3VyY2VzIHRhYiBvciBSZXNvdXJjZXMgcGFuZWwgb2YgdGhlIHdlYiBpbnNwZWN0b3IuXG4gICAgICpcbiAgICAgKiAvLyBVc2UgdGhlIGB2YXJpYWJsZWAgb3B0aW9uIHRvIGVuc3VyZSBhIHdpdGgtc3RhdGVtZW50IGlzbid0IHVzZWQgaW4gdGhlIGNvbXBpbGVkIHRlbXBsYXRlLlxuICAgICAqIHZhciBjb21waWxlZCA9IF8udGVtcGxhdGUoJ2hpIDwlPSBkYXRhLnVzZXIgJT4hJywgeyAndmFyaWFibGUnOiAnZGF0YScgfSk7XG4gICAgICogY29tcGlsZWQuc291cmNlO1xuICAgICAqIC8vID0+IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgKiAvLyAgIHZhciBfX3QsIF9fcCA9ICcnO1xuICAgICAqIC8vICAgX19wICs9ICdoaSAnICsgKChfX3QgPSAoIGRhdGEudXNlciApKSA9PSBudWxsID8gJycgOiBfX3QpICsgJyEnO1xuICAgICAqIC8vICAgcmV0dXJuIF9fcDtcbiAgICAgKiAvLyB9XG4gICAgICpcbiAgICAgKiAvLyBVc2UgY3VzdG9tIHRlbXBsYXRlIGRlbGltaXRlcnMuXG4gICAgICogXy50ZW1wbGF0ZVNldHRpbmdzLmludGVycG9sYXRlID0gL3t7KFtcXHNcXFNdKz8pfX0vZztcbiAgICAgKiB2YXIgY29tcGlsZWQgPSBfLnRlbXBsYXRlKCdoZWxsbyB7eyB1c2VyIH19IScpO1xuICAgICAqIGNvbXBpbGVkKHsgJ3VzZXInOiAnbXVzdGFjaGUnIH0pO1xuICAgICAqIC8vID0+ICdoZWxsbyBtdXN0YWNoZSEnXG4gICAgICpcbiAgICAgKiAvLyBVc2UgdGhlIGBzb3VyY2VgIHByb3BlcnR5IHRvIGlubGluZSBjb21waWxlZCB0ZW1wbGF0ZXMgZm9yIG1lYW5pbmdmdWxcbiAgICAgKiAvLyBsaW5lIG51bWJlcnMgaW4gZXJyb3IgbWVzc2FnZXMgYW5kIHN0YWNrIHRyYWNlcy5cbiAgICAgKiBmcy53cml0ZUZpbGVTeW5jKHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCAnanN0LmpzJyksICdcXFxuICAgICAqICAgdmFyIEpTVCA9IHtcXFxuICAgICAqICAgICBcIm1haW5cIjogJyArIF8udGVtcGxhdGUobWFpblRleHQpLnNvdXJjZSArICdcXFxuICAgICAqICAgfTtcXFxuICAgICAqICcpO1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRlbXBsYXRlKHN0cmluZywgb3B0aW9ucywgZ3VhcmQpIHtcbiAgICAgIC8vIEJhc2VkIG9uIEpvaG4gUmVzaWcncyBgdG1wbGAgaW1wbGVtZW50YXRpb25cbiAgICAgIC8vIChodHRwOi8vZWpvaG4ub3JnL2Jsb2cvamF2YXNjcmlwdC1taWNyby10ZW1wbGF0aW5nLylcbiAgICAgIC8vIGFuZCBMYXVyYSBEb2t0b3JvdmEncyBkb1QuanMgKGh0dHBzOi8vZ2l0aHViLmNvbS9vbGFkby9kb1QpLlxuICAgICAgdmFyIHNldHRpbmdzID0gbG9kYXNoLnRlbXBsYXRlU2V0dGluZ3M7XG5cbiAgICAgIGlmIChndWFyZCAmJiBpc0l0ZXJhdGVlQ2FsbChzdHJpbmcsIG9wdGlvbnMsIGd1YXJkKSkge1xuICAgICAgICBvcHRpb25zID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIG9wdGlvbnMgPSBhc3NpZ25JbldpdGgoe30sIG9wdGlvbnMsIHNldHRpbmdzLCBjdXN0b21EZWZhdWx0c0Fzc2lnbkluKTtcblxuICAgICAgdmFyIGltcG9ydHMgPSBhc3NpZ25JbldpdGgoe30sIG9wdGlvbnMuaW1wb3J0cywgc2V0dGluZ3MuaW1wb3J0cywgY3VzdG9tRGVmYXVsdHNBc3NpZ25JbiksXG4gICAgICAgICAgaW1wb3J0c0tleXMgPSBrZXlzKGltcG9ydHMpLFxuICAgICAgICAgIGltcG9ydHNWYWx1ZXMgPSBiYXNlVmFsdWVzKGltcG9ydHMsIGltcG9ydHNLZXlzKTtcblxuICAgICAgdmFyIGlzRXNjYXBpbmcsXG4gICAgICAgICAgaXNFdmFsdWF0aW5nLFxuICAgICAgICAgIGluZGV4ID0gMCxcbiAgICAgICAgICBpbnRlcnBvbGF0ZSA9IG9wdGlvbnMuaW50ZXJwb2xhdGUgfHwgcmVOb01hdGNoLFxuICAgICAgICAgIHNvdXJjZSA9IFwiX19wICs9ICdcIjtcblxuICAgICAgLy8gQ29tcGlsZSB0aGUgcmVnZXhwIHRvIG1hdGNoIGVhY2ggZGVsaW1pdGVyLlxuICAgICAgdmFyIHJlRGVsaW1pdGVycyA9IFJlZ0V4cChcbiAgICAgICAgKG9wdGlvbnMuZXNjYXBlIHx8IHJlTm9NYXRjaCkuc291cmNlICsgJ3wnICtcbiAgICAgICAgaW50ZXJwb2xhdGUuc291cmNlICsgJ3wnICtcbiAgICAgICAgKGludGVycG9sYXRlID09PSByZUludGVycG9sYXRlID8gcmVFc1RlbXBsYXRlIDogcmVOb01hdGNoKS5zb3VyY2UgKyAnfCcgK1xuICAgICAgICAob3B0aW9ucy5ldmFsdWF0ZSB8fCByZU5vTWF0Y2gpLnNvdXJjZSArICd8JCdcbiAgICAgICwgJ2cnKTtcblxuICAgICAgLy8gVXNlIGEgc291cmNlVVJMIGZvciBlYXNpZXIgZGVidWdnaW5nLlxuICAgICAgdmFyIHNvdXJjZVVSTCA9ICcvLyMgc291cmNlVVJMPScgK1xuICAgICAgICAoJ3NvdXJjZVVSTCcgaW4gb3B0aW9uc1xuICAgICAgICAgID8gb3B0aW9ucy5zb3VyY2VVUkxcbiAgICAgICAgICA6ICgnbG9kYXNoLnRlbXBsYXRlU291cmNlc1snICsgKCsrdGVtcGxhdGVDb3VudGVyKSArICddJylcbiAgICAgICAgKSArICdcXG4nO1xuXG4gICAgICBzdHJpbmcucmVwbGFjZShyZURlbGltaXRlcnMsIGZ1bmN0aW9uKG1hdGNoLCBlc2NhcGVWYWx1ZSwgaW50ZXJwb2xhdGVWYWx1ZSwgZXNUZW1wbGF0ZVZhbHVlLCBldmFsdWF0ZVZhbHVlLCBvZmZzZXQpIHtcbiAgICAgICAgaW50ZXJwb2xhdGVWYWx1ZSB8fCAoaW50ZXJwb2xhdGVWYWx1ZSA9IGVzVGVtcGxhdGVWYWx1ZSk7XG5cbiAgICAgICAgLy8gRXNjYXBlIGNoYXJhY3RlcnMgdGhhdCBjYW4ndCBiZSBpbmNsdWRlZCBpbiBzdHJpbmcgbGl0ZXJhbHMuXG4gICAgICAgIHNvdXJjZSArPSBzdHJpbmcuc2xpY2UoaW5kZXgsIG9mZnNldCkucmVwbGFjZShyZVVuZXNjYXBlZFN0cmluZywgZXNjYXBlU3RyaW5nQ2hhcik7XG5cbiAgICAgICAgLy8gUmVwbGFjZSBkZWxpbWl0ZXJzIHdpdGggc25pcHBldHMuXG4gICAgICAgIGlmIChlc2NhcGVWYWx1ZSkge1xuICAgICAgICAgIGlzRXNjYXBpbmcgPSB0cnVlO1xuICAgICAgICAgIHNvdXJjZSArPSBcIicgK1xcbl9fZShcIiArIGVzY2FwZVZhbHVlICsgXCIpICtcXG4nXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGV2YWx1YXRlVmFsdWUpIHtcbiAgICAgICAgICBpc0V2YWx1YXRpbmcgPSB0cnVlO1xuICAgICAgICAgIHNvdXJjZSArPSBcIic7XFxuXCIgKyBldmFsdWF0ZVZhbHVlICsgXCI7XFxuX19wICs9ICdcIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaW50ZXJwb2xhdGVWYWx1ZSkge1xuICAgICAgICAgIHNvdXJjZSArPSBcIicgK1xcbigoX190ID0gKFwiICsgaW50ZXJwb2xhdGVWYWx1ZSArIFwiKSkgPT0gbnVsbCA/ICcnIDogX190KSArXFxuJ1wiO1xuICAgICAgICB9XG4gICAgICAgIGluZGV4ID0gb2Zmc2V0ICsgbWF0Y2gubGVuZ3RoO1xuXG4gICAgICAgIC8vIFRoZSBKUyBlbmdpbmUgZW1iZWRkZWQgaW4gQWRvYmUgcHJvZHVjdHMgbmVlZHMgYG1hdGNoYCByZXR1cm5lZCBpblxuICAgICAgICAvLyBvcmRlciB0byBwcm9kdWNlIHRoZSBjb3JyZWN0IGBvZmZzZXRgIHZhbHVlLlxuICAgICAgICByZXR1cm4gbWF0Y2g7XG4gICAgICB9KTtcblxuICAgICAgc291cmNlICs9IFwiJztcXG5cIjtcblxuICAgICAgLy8gSWYgYHZhcmlhYmxlYCBpcyBub3Qgc3BlY2lmaWVkIHdyYXAgYSB3aXRoLXN0YXRlbWVudCBhcm91bmQgdGhlIGdlbmVyYXRlZFxuICAgICAgLy8gY29kZSB0byBhZGQgdGhlIGRhdGEgb2JqZWN0IHRvIHRoZSB0b3Agb2YgdGhlIHNjb3BlIGNoYWluLlxuICAgICAgdmFyIHZhcmlhYmxlID0gb3B0aW9ucy52YXJpYWJsZTtcbiAgICAgIGlmICghdmFyaWFibGUpIHtcbiAgICAgICAgc291cmNlID0gJ3dpdGggKG9iaikge1xcbicgKyBzb3VyY2UgKyAnXFxufVxcbic7XG4gICAgICB9XG4gICAgICAvLyBDbGVhbnVwIGNvZGUgYnkgc3RyaXBwaW5nIGVtcHR5IHN0cmluZ3MuXG4gICAgICBzb3VyY2UgPSAoaXNFdmFsdWF0aW5nID8gc291cmNlLnJlcGxhY2UocmVFbXB0eVN0cmluZ0xlYWRpbmcsICcnKSA6IHNvdXJjZSlcbiAgICAgICAgLnJlcGxhY2UocmVFbXB0eVN0cmluZ01pZGRsZSwgJyQxJylcbiAgICAgICAgLnJlcGxhY2UocmVFbXB0eVN0cmluZ1RyYWlsaW5nLCAnJDE7Jyk7XG5cbiAgICAgIC8vIEZyYW1lIGNvZGUgYXMgdGhlIGZ1bmN0aW9uIGJvZHkuXG4gICAgICBzb3VyY2UgPSAnZnVuY3Rpb24oJyArICh2YXJpYWJsZSB8fCAnb2JqJykgKyAnKSB7XFxuJyArXG4gICAgICAgICh2YXJpYWJsZVxuICAgICAgICAgID8gJydcbiAgICAgICAgICA6ICdvYmogfHwgKG9iaiA9IHt9KTtcXG4nXG4gICAgICAgICkgK1xuICAgICAgICBcInZhciBfX3QsIF9fcCA9ICcnXCIgK1xuICAgICAgICAoaXNFc2NhcGluZ1xuICAgICAgICAgICA/ICcsIF9fZSA9IF8uZXNjYXBlJ1xuICAgICAgICAgICA6ICcnXG4gICAgICAgICkgK1xuICAgICAgICAoaXNFdmFsdWF0aW5nXG4gICAgICAgICAgPyAnLCBfX2ogPSBBcnJheS5wcm90b3R5cGUuam9pbjtcXG4nICtcbiAgICAgICAgICAgIFwiZnVuY3Rpb24gcHJpbnQoKSB7IF9fcCArPSBfX2ouY2FsbChhcmd1bWVudHMsICcnKSB9XFxuXCJcbiAgICAgICAgICA6ICc7XFxuJ1xuICAgICAgICApICtcbiAgICAgICAgc291cmNlICtcbiAgICAgICAgJ3JldHVybiBfX3BcXG59JztcblxuICAgICAgdmFyIHJlc3VsdCA9IGF0dGVtcHQoZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBGdW5jdGlvbihpbXBvcnRzS2V5cywgc291cmNlVVJMICsgJ3JldHVybiAnICsgc291cmNlKVxuICAgICAgICAgIC5hcHBseSh1bmRlZmluZWQsIGltcG9ydHNWYWx1ZXMpO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIFByb3ZpZGUgdGhlIGNvbXBpbGVkIGZ1bmN0aW9uJ3Mgc291cmNlIGJ5IGl0cyBgdG9TdHJpbmdgIG1ldGhvZCBvclxuICAgICAgLy8gdGhlIGBzb3VyY2VgIHByb3BlcnR5IGFzIGEgY29udmVuaWVuY2UgZm9yIGlubGluaW5nIGNvbXBpbGVkIHRlbXBsYXRlcy5cbiAgICAgIHJlc3VsdC5zb3VyY2UgPSBzb3VyY2U7XG4gICAgICBpZiAoaXNFcnJvcihyZXN1bHQpKSB7XG4gICAgICAgIHRocm93IHJlc3VsdDtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHN0cmluZ2AsIGFzIGEgd2hvbGUsIHRvIGxvd2VyIGNhc2UganVzdCBsaWtlXG4gICAgICogW1N0cmluZyN0b0xvd2VyQ2FzZV0oaHR0cHM6Ly9tZG4uaW8vdG9Mb3dlckNhc2UpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgbG93ZXIgY2FzZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRvTG93ZXIoJy0tRm9vLUJhci0tJyk7XG4gICAgICogLy8gPT4gJy0tZm9vLWJhci0tJ1xuICAgICAqXG4gICAgICogXy50b0xvd2VyKCdmb29CYXInKTtcbiAgICAgKiAvLyA9PiAnZm9vYmFyJ1xuICAgICAqXG4gICAgICogXy50b0xvd2VyKCdfX0ZPT19CQVJfXycpO1xuICAgICAqIC8vID0+ICdfX2Zvb19iYXJfXydcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b0xvd2VyKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdG9TdHJpbmcodmFsdWUpLnRvTG93ZXJDYXNlKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydHMgYHN0cmluZ2AsIGFzIGEgd2hvbGUsIHRvIHVwcGVyIGNhc2UganVzdCBsaWtlXG4gICAgICogW1N0cmluZyN0b1VwcGVyQ2FzZV0oaHR0cHM6Ly9tZG4uaW8vdG9VcHBlckNhc2UpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgdXBwZXIgY2FzZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRvVXBwZXIoJy0tZm9vLWJhci0tJyk7XG4gICAgICogLy8gPT4gJy0tRk9PLUJBUi0tJ1xuICAgICAqXG4gICAgICogXy50b1VwcGVyKCdmb29CYXInKTtcbiAgICAgKiAvLyA9PiAnRk9PQkFSJ1xuICAgICAqXG4gICAgICogXy50b1VwcGVyKCdfX2Zvb19iYXJfXycpO1xuICAgICAqIC8vID0+ICdfX0ZPT19CQVJfXydcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0b1VwcGVyKHZhbHVlKSB7XG4gICAgICByZXR1cm4gdG9TdHJpbmcodmFsdWUpLnRvVXBwZXJDYXNlKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBsZWFkaW5nIGFuZCB0cmFpbGluZyB3aGl0ZXNwYWNlIG9yIHNwZWNpZmllZCBjaGFyYWN0ZXJzIGZyb20gYHN0cmluZ2AuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gdHJpbS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW2NoYXJzPXdoaXRlc3BhY2VdIFRoZSBjaGFyYWN0ZXJzIHRvIHRyaW0uXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSB0cmltbWVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50cmltKCcgIGFiYyAgJyk7XG4gICAgICogLy8gPT4gJ2FiYydcbiAgICAgKlxuICAgICAqIF8udHJpbSgnLV8tYWJjLV8tJywgJ18tJyk7XG4gICAgICogLy8gPT4gJ2FiYydcbiAgICAgKlxuICAgICAqIF8ubWFwKFsnICBmb28gICcsICcgIGJhciAgJ10sIF8udHJpbSk7XG4gICAgICogLy8gPT4gWydmb28nLCAnYmFyJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0cmltKHN0cmluZywgY2hhcnMsIGd1YXJkKSB7XG4gICAgICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuICAgICAgaWYgKHN0cmluZyAmJiAoZ3VhcmQgfHwgY2hhcnMgPT09IHVuZGVmaW5lZCkpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKHJlVHJpbSwgJycpO1xuICAgICAgfVxuICAgICAgaWYgKCFzdHJpbmcgfHwgIShjaGFycyA9IGJhc2VUb1N0cmluZyhjaGFycykpKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmc7XG4gICAgICB9XG4gICAgICB2YXIgc3RyU3ltYm9scyA9IHN0cmluZ1RvQXJyYXkoc3RyaW5nKSxcbiAgICAgICAgICBjaHJTeW1ib2xzID0gc3RyaW5nVG9BcnJheShjaGFycyksXG4gICAgICAgICAgc3RhcnQgPSBjaGFyc1N0YXJ0SW5kZXgoc3RyU3ltYm9scywgY2hyU3ltYm9scyksXG4gICAgICAgICAgZW5kID0gY2hhcnNFbmRJbmRleChzdHJTeW1ib2xzLCBjaHJTeW1ib2xzKSArIDE7XG5cbiAgICAgIHJldHVybiBjYXN0U2xpY2Uoc3RyU3ltYm9scywgc3RhcnQsIGVuZCkuam9pbignJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0cmFpbGluZyB3aGl0ZXNwYWNlIG9yIHNwZWNpZmllZCBjaGFyYWN0ZXJzIGZyb20gYHN0cmluZ2AuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gdHJpbS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW2NoYXJzPXdoaXRlc3BhY2VdIFRoZSBjaGFyYWN0ZXJzIHRvIHRyaW0uXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSB0cmltbWVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50cmltRW5kKCcgIGFiYyAgJyk7XG4gICAgICogLy8gPT4gJyAgYWJjJ1xuICAgICAqXG4gICAgICogXy50cmltRW5kKCctXy1hYmMtXy0nLCAnXy0nKTtcbiAgICAgKiAvLyA9PiAnLV8tYWJjJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHRyaW1FbmQoc3RyaW5nLCBjaGFycywgZ3VhcmQpIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICBpZiAoc3RyaW5nICYmIChndWFyZCB8fCBjaGFycyA9PT0gdW5kZWZpbmVkKSkge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UocmVUcmltRW5kLCAnJyk7XG4gICAgICB9XG4gICAgICBpZiAoIXN0cmluZyB8fCAhKGNoYXJzID0gYmFzZVRvU3RyaW5nKGNoYXJzKSkpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZztcbiAgICAgIH1cbiAgICAgIHZhciBzdHJTeW1ib2xzID0gc3RyaW5nVG9BcnJheShzdHJpbmcpLFxuICAgICAgICAgIGVuZCA9IGNoYXJzRW5kSW5kZXgoc3RyU3ltYm9scywgc3RyaW5nVG9BcnJheShjaGFycykpICsgMTtcblxuICAgICAgcmV0dXJuIGNhc3RTbGljZShzdHJTeW1ib2xzLCAwLCBlbmQpLmpvaW4oJycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgbGVhZGluZyB3aGl0ZXNwYWNlIG9yIHNwZWNpZmllZCBjaGFyYWN0ZXJzIGZyb20gYHN0cmluZ2AuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gdHJpbS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW2NoYXJzPXdoaXRlc3BhY2VdIFRoZSBjaGFyYWN0ZXJzIHRvIHRyaW0uXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSB0cmltbWVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50cmltU3RhcnQoJyAgYWJjICAnKTtcbiAgICAgKiAvLyA9PiAnYWJjICAnXG4gICAgICpcbiAgICAgKiBfLnRyaW1TdGFydCgnLV8tYWJjLV8tJywgJ18tJyk7XG4gICAgICogLy8gPT4gJ2FiYy1fLSdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0cmltU3RhcnQoc3RyaW5nLCBjaGFycywgZ3VhcmQpIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICBpZiAoc3RyaW5nICYmIChndWFyZCB8fCBjaGFycyA9PT0gdW5kZWZpbmVkKSkge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UocmVUcmltU3RhcnQsICcnKTtcbiAgICAgIH1cbiAgICAgIGlmICghc3RyaW5nIHx8ICEoY2hhcnMgPSBiYXNlVG9TdHJpbmcoY2hhcnMpKSkge1xuICAgICAgICByZXR1cm4gc3RyaW5nO1xuICAgICAgfVxuICAgICAgdmFyIHN0clN5bWJvbHMgPSBzdHJpbmdUb0FycmF5KHN0cmluZyksXG4gICAgICAgICAgc3RhcnQgPSBjaGFyc1N0YXJ0SW5kZXgoc3RyU3ltYm9scywgc3RyaW5nVG9BcnJheShjaGFycykpO1xuXG4gICAgICByZXR1cm4gY2FzdFNsaWNlKHN0clN5bWJvbHMsIHN0YXJ0KS5qb2luKCcnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUcnVuY2F0ZXMgYHN0cmluZ2AgaWYgaXQncyBsb25nZXIgdGhhbiB0aGUgZ2l2ZW4gbWF4aW11bSBzdHJpbmcgbGVuZ3RoLlxuICAgICAqIFRoZSBsYXN0IGNoYXJhY3RlcnMgb2YgdGhlIHRydW5jYXRlZCBzdHJpbmcgYXJlIHJlcGxhY2VkIHdpdGggdGhlIG9taXNzaW9uXG4gICAgICogc3RyaW5nIHdoaWNoIGRlZmF1bHRzIHRvIFwiLi4uXCIuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gdHJ1bmNhdGUuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSBUaGUgb3B0aW9ucyBvYmplY3QuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLmxlbmd0aD0zMF0gVGhlIG1heGltdW0gc3RyaW5nIGxlbmd0aC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdGlvbnMub21pc3Npb249Jy4uLiddIFRoZSBzdHJpbmcgdG8gaW5kaWNhdGUgdGV4dCBpcyBvbWl0dGVkLlxuICAgICAqIEBwYXJhbSB7UmVnRXhwfHN0cmluZ30gW29wdGlvbnMuc2VwYXJhdG9yXSBUaGUgc2VwYXJhdG9yIHBhdHRlcm4gdG8gdHJ1bmNhdGUgdG8uXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgdHJ1bmNhdGVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50cnVuY2F0ZSgnaGktZGlkZGx5LWhvIHRoZXJlLCBuZWlnaGJvcmlubycpO1xuICAgICAqIC8vID0+ICdoaS1kaWRkbHktaG8gdGhlcmUsIG5laWdoYm8uLi4nXG4gICAgICpcbiAgICAgKiBfLnRydW5jYXRlKCdoaS1kaWRkbHktaG8gdGhlcmUsIG5laWdoYm9yaW5vJywge1xuICAgICAqICAgJ2xlbmd0aCc6IDI0LFxuICAgICAqICAgJ3NlcGFyYXRvcic6ICcgJ1xuICAgICAqIH0pO1xuICAgICAqIC8vID0+ICdoaS1kaWRkbHktaG8gdGhlcmUsLi4uJ1xuICAgICAqXG4gICAgICogXy50cnVuY2F0ZSgnaGktZGlkZGx5LWhvIHRoZXJlLCBuZWlnaGJvcmlubycsIHtcbiAgICAgKiAgICdsZW5ndGgnOiAyNCxcbiAgICAgKiAgICdzZXBhcmF0b3InOiAvLD8gKy9cbiAgICAgKiB9KTtcbiAgICAgKiAvLyA9PiAnaGktZGlkZGx5LWhvIHRoZXJlLi4uJ1xuICAgICAqXG4gICAgICogXy50cnVuY2F0ZSgnaGktZGlkZGx5LWhvIHRoZXJlLCBuZWlnaGJvcmlubycsIHtcbiAgICAgKiAgICdvbWlzc2lvbic6ICcgWy4uLl0nXG4gICAgICogfSk7XG4gICAgICogLy8gPT4gJ2hpLWRpZGRseS1obyB0aGVyZSwgbmVpZyBbLi4uXSdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0cnVuY2F0ZShzdHJpbmcsIG9wdGlvbnMpIHtcbiAgICAgIHZhciBsZW5ndGggPSBERUZBVUxUX1RSVU5DX0xFTkdUSCxcbiAgICAgICAgICBvbWlzc2lvbiA9IERFRkFVTFRfVFJVTkNfT01JU1NJT047XG5cbiAgICAgIGlmIChpc09iamVjdChvcHRpb25zKSkge1xuICAgICAgICB2YXIgc2VwYXJhdG9yID0gJ3NlcGFyYXRvcicgaW4gb3B0aW9ucyA/IG9wdGlvbnMuc2VwYXJhdG9yIDogc2VwYXJhdG9yO1xuICAgICAgICBsZW5ndGggPSAnbGVuZ3RoJyBpbiBvcHRpb25zID8gdG9JbnRlZ2VyKG9wdGlvbnMubGVuZ3RoKSA6IGxlbmd0aDtcbiAgICAgICAgb21pc3Npb24gPSAnb21pc3Npb24nIGluIG9wdGlvbnMgPyBiYXNlVG9TdHJpbmcob3B0aW9ucy5vbWlzc2lvbikgOiBvbWlzc2lvbjtcbiAgICAgIH1cbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG5cbiAgICAgIHZhciBzdHJMZW5ndGggPSBzdHJpbmcubGVuZ3RoO1xuICAgICAgaWYgKGhhc1VuaWNvZGUoc3RyaW5nKSkge1xuICAgICAgICB2YXIgc3RyU3ltYm9scyA9IHN0cmluZ1RvQXJyYXkoc3RyaW5nKTtcbiAgICAgICAgc3RyTGVuZ3RoID0gc3RyU3ltYm9scy5sZW5ndGg7XG4gICAgICB9XG4gICAgICBpZiAobGVuZ3RoID49IHN0ckxlbmd0aCkge1xuICAgICAgICByZXR1cm4gc3RyaW5nO1xuICAgICAgfVxuICAgICAgdmFyIGVuZCA9IGxlbmd0aCAtIHN0cmluZ1NpemUob21pc3Npb24pO1xuICAgICAgaWYgKGVuZCA8IDEpIHtcbiAgICAgICAgcmV0dXJuIG9taXNzaW9uO1xuICAgICAgfVxuICAgICAgdmFyIHJlc3VsdCA9IHN0clN5bWJvbHNcbiAgICAgICAgPyBjYXN0U2xpY2Uoc3RyU3ltYm9scywgMCwgZW5kKS5qb2luKCcnKVxuICAgICAgICA6IHN0cmluZy5zbGljZSgwLCBlbmQpO1xuXG4gICAgICBpZiAoc2VwYXJhdG9yID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCArIG9taXNzaW9uO1xuICAgICAgfVxuICAgICAgaWYgKHN0clN5bWJvbHMpIHtcbiAgICAgICAgZW5kICs9IChyZXN1bHQubGVuZ3RoIC0gZW5kKTtcbiAgICAgIH1cbiAgICAgIGlmIChpc1JlZ0V4cChzZXBhcmF0b3IpKSB7XG4gICAgICAgIGlmIChzdHJpbmcuc2xpY2UoZW5kKS5zZWFyY2goc2VwYXJhdG9yKSkge1xuICAgICAgICAgIHZhciBtYXRjaCxcbiAgICAgICAgICAgICAgc3Vic3RyaW5nID0gcmVzdWx0O1xuXG4gICAgICAgICAgaWYgKCFzZXBhcmF0b3IuZ2xvYmFsKSB7XG4gICAgICAgICAgICBzZXBhcmF0b3IgPSBSZWdFeHAoc2VwYXJhdG9yLnNvdXJjZSwgdG9TdHJpbmcocmVGbGFncy5leGVjKHNlcGFyYXRvcikpICsgJ2cnKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCA9IDA7XG4gICAgICAgICAgd2hpbGUgKChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN1YnN0cmluZykpKSB7XG4gICAgICAgICAgICB2YXIgbmV3RW5kID0gbWF0Y2guaW5kZXg7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5zbGljZSgwLCBuZXdFbmQgPT09IHVuZGVmaW5lZCA/IGVuZCA6IG5ld0VuZCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoc3RyaW5nLmluZGV4T2YoYmFzZVRvU3RyaW5nKHNlcGFyYXRvciksIGVuZCkgIT0gZW5kKSB7XG4gICAgICAgIHZhciBpbmRleCA9IHJlc3VsdC5sYXN0SW5kZXhPZihzZXBhcmF0b3IpO1xuICAgICAgICBpZiAoaW5kZXggPiAtMSkge1xuICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5zbGljZSgwLCBpbmRleCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQgKyBvbWlzc2lvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgaW52ZXJzZSBvZiBgXy5lc2NhcGVgOyB0aGlzIG1ldGhvZCBjb252ZXJ0cyB0aGUgSFRNTCBlbnRpdGllc1xuICAgICAqIGAmYW1wO2AsIGAmbHQ7YCwgYCZndDtgLCBgJnF1b3Q7YCwgYW5kIGAmIzM5O2AgaW4gYHN0cmluZ2AgdG9cbiAgICAgKiB0aGVpciBjb3JyZXNwb25kaW5nIGNoYXJhY3RlcnMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogTm8gb3RoZXIgSFRNTCBlbnRpdGllcyBhcmUgdW5lc2NhcGVkLiBUbyB1bmVzY2FwZSBhZGRpdGlvbmFsXG4gICAgICogSFRNTCBlbnRpdGllcyB1c2UgYSB0aGlyZC1wYXJ0eSBsaWJyYXJ5IGxpa2UgW19oZV9dKGh0dHBzOi8vbXRocy5iZS9oZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMC42LjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gdW5lc2NhcGUuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgdW5lc2NhcGVkIHN0cmluZy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy51bmVzY2FwZSgnZnJlZCwgYmFybmV5LCAmYW1wOyBwZWJibGVzJyk7XG4gICAgICogLy8gPT4gJ2ZyZWQsIGJhcm5leSwgJiBwZWJibGVzJ1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHVuZXNjYXBlKHN0cmluZykge1xuICAgICAgc3RyaW5nID0gdG9TdHJpbmcoc3RyaW5nKTtcbiAgICAgIHJldHVybiAoc3RyaW5nICYmIHJlSGFzRXNjYXBlZEh0bWwudGVzdChzdHJpbmcpKVxuICAgICAgICA/IHN0cmluZy5yZXBsYWNlKHJlRXNjYXBlZEh0bWwsIHVuZXNjYXBlSHRtbENoYXIpXG4gICAgICAgIDogc3RyaW5nO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnRzIGBzdHJpbmdgLCBhcyBzcGFjZSBzZXBhcmF0ZWQgd29yZHMsIHRvIHVwcGVyIGNhc2UuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSB1cHBlciBjYXNlZCBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udXBwZXJDYXNlKCctLWZvby1iYXInKTtcbiAgICAgKiAvLyA9PiAnRk9PIEJBUidcbiAgICAgKlxuICAgICAqIF8udXBwZXJDYXNlKCdmb29CYXInKTtcbiAgICAgKiAvLyA9PiAnRk9PIEJBUidcbiAgICAgKlxuICAgICAqIF8udXBwZXJDYXNlKCdfX2Zvb19iYXJfXycpO1xuICAgICAqIC8vID0+ICdGT08gQkFSJ1xuICAgICAqL1xuICAgIHZhciB1cHBlckNhc2UgPSBjcmVhdGVDb21wb3VuZGVyKGZ1bmN0aW9uKHJlc3VsdCwgd29yZCwgaW5kZXgpIHtcbiAgICAgIHJldHVybiByZXN1bHQgKyAoaW5kZXggPyAnICcgOiAnJykgKyB3b3JkLnRvVXBwZXJDYXNlKCk7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyB0aGUgZmlyc3QgY2hhcmFjdGVyIG9mIGBzdHJpbmdgIHRvIHVwcGVyIGNhc2UuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtzdHJpbmc9JyddIFRoZSBzdHJpbmcgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBjb252ZXJ0ZWQgc3RyaW5nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnVwcGVyRmlyc3QoJ2ZyZWQnKTtcbiAgICAgKiAvLyA9PiAnRnJlZCdcbiAgICAgKlxuICAgICAqIF8udXBwZXJGaXJzdCgnRlJFRCcpO1xuICAgICAqIC8vID0+ICdGUkVEJ1xuICAgICAqL1xuICAgIHZhciB1cHBlckZpcnN0ID0gY3JlYXRlQ2FzZUZpcnN0KCd0b1VwcGVyQ2FzZScpO1xuXG4gICAgLyoqXG4gICAgICogU3BsaXRzIGBzdHJpbmdgIGludG8gYW4gYXJyYXkgb2YgaXRzIHdvcmRzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IFN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbc3RyaW5nPScnXSBUaGUgc3RyaW5nIHRvIGluc3BlY3QuXG4gICAgICogQHBhcmFtIHtSZWdFeHB8c3RyaW5nfSBbcGF0dGVybl0gVGhlIHBhdHRlcm4gdG8gbWF0Y2ggd29yZHMuXG4gICAgICogQHBhcmFtLSB7T2JqZWN0fSBbZ3VhcmRdIEVuYWJsZXMgdXNlIGFzIGFuIGl0ZXJhdGVlIGZvciBtZXRob2RzIGxpa2UgYF8ubWFwYC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHdvcmRzIG9mIGBzdHJpbmdgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLndvcmRzKCdmcmVkLCBiYXJuZXksICYgcGViYmxlcycpO1xuICAgICAqIC8vID0+IFsnZnJlZCcsICdiYXJuZXknLCAncGViYmxlcyddXG4gICAgICpcbiAgICAgKiBfLndvcmRzKCdmcmVkLCBiYXJuZXksICYgcGViYmxlcycsIC9bXiwgXSsvZyk7XG4gICAgICogLy8gPT4gWydmcmVkJywgJ2Jhcm5leScsICcmJywgJ3BlYmJsZXMnXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHdvcmRzKHN0cmluZywgcGF0dGVybiwgZ3VhcmQpIHtcbiAgICAgIHN0cmluZyA9IHRvU3RyaW5nKHN0cmluZyk7XG4gICAgICBwYXR0ZXJuID0gZ3VhcmQgPyB1bmRlZmluZWQgOiBwYXR0ZXJuO1xuXG4gICAgICBpZiAocGF0dGVybiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBoYXNVbmljb2RlV29yZChzdHJpbmcpID8gdW5pY29kZVdvcmRzKHN0cmluZykgOiBhc2NpaVdvcmRzKHN0cmluZyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gc3RyaW5nLm1hdGNoKHBhdHRlcm4pIHx8IFtdO1xuICAgIH1cblxuICAgIC8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuICAgIC8qKlxuICAgICAqIEF0dGVtcHRzIHRvIGludm9rZSBgZnVuY2AsIHJldHVybmluZyBlaXRoZXIgdGhlIHJlc3VsdCBvciB0aGUgY2F1Z2h0IGVycm9yXG4gICAgICogb2JqZWN0LiBBbnkgYWRkaXRpb25hbCBhcmd1bWVudHMgYXJlIHByb3ZpZGVkIHRvIGBmdW5jYCB3aGVuIGl0J3MgaW52b2tlZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gYXR0ZW1wdC5cbiAgICAgKiBAcGFyYW0gey4uLip9IFthcmdzXSBUaGUgYXJndW1lbnRzIHRvIGludm9rZSBgZnVuY2Agd2l0aC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgYGZ1bmNgIHJlc3VsdCBvciBlcnJvciBvYmplY3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIC8vIEF2b2lkIHRocm93aW5nIGVycm9ycyBmb3IgaW52YWxpZCBzZWxlY3RvcnMuXG4gICAgICogdmFyIGVsZW1lbnRzID0gXy5hdHRlbXB0KGZ1bmN0aW9uKHNlbGVjdG9yKSB7XG4gICAgICogICByZXR1cm4gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3Rvcik7XG4gICAgICogfSwgJz5fPicpO1xuICAgICAqXG4gICAgICogaWYgKF8uaXNFcnJvcihlbGVtZW50cykpIHtcbiAgICAgKiAgIGVsZW1lbnRzID0gW107XG4gICAgICogfVxuICAgICAqL1xuICAgIHZhciBhdHRlbXB0ID0gYmFzZVJlc3QoZnVuY3Rpb24oZnVuYywgYXJncykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGFwcGx5KGZ1bmMsIHVuZGVmaW5lZCwgYXJncyk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiBpc0Vycm9yKGUpID8gZSA6IG5ldyBFcnJvcihlKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIEJpbmRzIG1ldGhvZHMgb2YgYW4gb2JqZWN0IHRvIHRoZSBvYmplY3QgaXRzZWxmLCBvdmVyd3JpdGluZyB0aGUgZXhpc3RpbmdcbiAgICAgKiBtZXRob2QuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgZG9lc24ndCBzZXQgdGhlIFwibGVuZ3RoXCIgcHJvcGVydHkgb2YgYm91bmQgZnVuY3Rpb25zLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gYmluZCBhbmQgYXNzaWduIHRoZSBib3VuZCBtZXRob2RzIHRvLlxuICAgICAqIEBwYXJhbSB7Li4uKHN0cmluZ3xzdHJpbmdbXSl9IG1ldGhvZE5hbWVzIFRoZSBvYmplY3QgbWV0aG9kIG5hbWVzIHRvIGJpbmQuXG4gICAgICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIHZpZXcgPSB7XG4gICAgICogICAnbGFiZWwnOiAnZG9jcycsXG4gICAgICogICAnY2xpY2snOiBmdW5jdGlvbigpIHtcbiAgICAgKiAgICAgY29uc29sZS5sb2coJ2NsaWNrZWQgJyArIHRoaXMubGFiZWwpO1xuICAgICAqICAgfVxuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBfLmJpbmRBbGwodmlldywgWydjbGljayddKTtcbiAgICAgKiBqUXVlcnkoZWxlbWVudCkub24oJ2NsaWNrJywgdmlldy5jbGljayk7XG4gICAgICogLy8gPT4gTG9ncyAnY2xpY2tlZCBkb2NzJyB3aGVuIGNsaWNrZWQuXG4gICAgICovXG4gICAgdmFyIGJpbmRBbGwgPSBmbGF0UmVzdChmdW5jdGlvbihvYmplY3QsIG1ldGhvZE5hbWVzKSB7XG4gICAgICBhcnJheUVhY2gobWV0aG9kTmFtZXMsIGZ1bmN0aW9uKGtleSkge1xuICAgICAgICBrZXkgPSB0b0tleShrZXkpO1xuICAgICAgICBiYXNlQXNzaWduVmFsdWUob2JqZWN0LCBrZXksIGJpbmQob2JqZWN0W2tleV0sIG9iamVjdCkpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gb2JqZWN0O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaXRlcmF0ZXMgb3ZlciBgcGFpcnNgIGFuZCBpbnZva2VzIHRoZSBjb3JyZXNwb25kaW5nXG4gICAgICogZnVuY3Rpb24gb2YgdGhlIGZpcnN0IHByZWRpY2F0ZSB0byByZXR1cm4gdHJ1dGh5LiBUaGUgcHJlZGljYXRlLWZ1bmN0aW9uXG4gICAgICogcGFpcnMgYXJlIGludm9rZWQgd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgYW5kIGFyZ3VtZW50cyBvZiB0aGUgY3JlYXRlZFxuICAgICAqIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBwYWlycyBUaGUgcHJlZGljYXRlLWZ1bmN0aW9uIHBhaXJzLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGNvbXBvc2l0ZSBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGZ1bmMgPSBfLmNvbmQoW1xuICAgICAqICAgW18ubWF0Y2hlcyh7ICdhJzogMSB9KSwgICAgICAgICAgIF8uY29uc3RhbnQoJ21hdGNoZXMgQScpXSxcbiAgICAgKiAgIFtfLmNvbmZvcm1zKHsgJ2InOiBfLmlzTnVtYmVyIH0pLCBfLmNvbnN0YW50KCdtYXRjaGVzIEInKV0sXG4gICAgICogICBbXy5zdHViVHJ1ZSwgICAgICAgICAgICAgICAgICAgICAgXy5jb25zdGFudCgnbm8gbWF0Y2gnKV1cbiAgICAgKiBdKTtcbiAgICAgKlxuICAgICAqIGZ1bmMoeyAnYSc6IDEsICdiJzogMiB9KTtcbiAgICAgKiAvLyA9PiAnbWF0Y2hlcyBBJ1xuICAgICAqXG4gICAgICogZnVuYyh7ICdhJzogMCwgJ2InOiAxIH0pO1xuICAgICAqIC8vID0+ICdtYXRjaGVzIEInXG4gICAgICpcbiAgICAgKiBmdW5jKHsgJ2EnOiAnMScsICdiJzogJzInIH0pO1xuICAgICAqIC8vID0+ICdubyBtYXRjaCdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb25kKHBhaXJzKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gcGFpcnMgPT0gbnVsbCA/IDAgOiBwYWlycy5sZW5ndGgsXG4gICAgICAgICAgdG9JdGVyYXRlZSA9IGdldEl0ZXJhdGVlKCk7XG5cbiAgICAgIHBhaXJzID0gIWxlbmd0aCA/IFtdIDogYXJyYXlNYXAocGFpcnMsIGZ1bmN0aW9uKHBhaXIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBwYWlyWzFdICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKEZVTkNfRVJST1JfVEVYVCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFt0b0l0ZXJhdGVlKHBhaXJbMF0pLCBwYWlyWzFdXTtcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gYmFzZVJlc3QoZnVuY3Rpb24oYXJncykge1xuICAgICAgICB2YXIgaW5kZXggPSAtMTtcbiAgICAgICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgICB2YXIgcGFpciA9IHBhaXJzW2luZGV4XTtcbiAgICAgICAgICBpZiAoYXBwbHkocGFpclswXSwgdGhpcywgYXJncykpIHtcbiAgICAgICAgICAgIHJldHVybiBhcHBseShwYWlyWzFdLCB0aGlzLCBhcmdzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXMgdGhlIHByZWRpY2F0ZSBwcm9wZXJ0aWVzIG9mIGBzb3VyY2VgIHdpdGhcbiAgICAgKiB0aGUgY29ycmVzcG9uZGluZyBwcm9wZXJ0eSB2YWx1ZXMgb2YgYSBnaXZlbiBvYmplY3QsIHJldHVybmluZyBgdHJ1ZWAgaWZcbiAgICAgKiBhbGwgcHJlZGljYXRlcyByZXR1cm4gdHJ1dGh5LCBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVGhlIGNyZWF0ZWQgZnVuY3Rpb24gaXMgZXF1aXZhbGVudCB0byBgXy5jb25mb3Jtc1RvYCB3aXRoXG4gICAgICogYHNvdXJjZWAgcGFydGlhbGx5IGFwcGxpZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCBvZiBwcm9wZXJ0eSBwcmVkaWNhdGVzIHRvIGNvbmZvcm0gdG8uXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgc3BlYyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbXG4gICAgICogICB7ICdhJzogMiwgJ2InOiAxIH0sXG4gICAgICogICB7ICdhJzogMSwgJ2InOiAyIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5maWx0ZXIob2JqZWN0cywgXy5jb25mb3Jtcyh7ICdiJzogZnVuY3Rpb24obikgeyByZXR1cm4gbiA+IDE7IH0gfSkpO1xuICAgICAqIC8vID0+IFt7ICdhJzogMSwgJ2InOiAyIH1dXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29uZm9ybXMoc291cmNlKSB7XG4gICAgICByZXR1cm4gYmFzZUNvbmZvcm1zKGJhc2VDbG9uZShzb3VyY2UsIENMT05FX0RFRVBfRkxBRykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHJldHVybnMgYHZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAyLjQuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcmV0dXJuIGZyb20gdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBjb25zdGFudCBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBfLnRpbWVzKDIsIF8uY29uc3RhbnQoeyAnYSc6IDEgfSkpO1xuICAgICAqXG4gICAgICogY29uc29sZS5sb2cob2JqZWN0cyk7XG4gICAgICogLy8gPT4gW3sgJ2EnOiAxIH0sIHsgJ2EnOiAxIH1dXG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhvYmplY3RzWzBdID09PSBvYmplY3RzWzFdKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICovXG4gICAgZnVuY3Rpb24gY29uc3RhbnQodmFsdWUpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgYHZhbHVlYCB0byBkZXRlcm1pbmUgd2hldGhlciBhIGRlZmF1bHQgdmFsdWUgc2hvdWxkIGJlIHJldHVybmVkIGluXG4gICAgICogaXRzIHBsYWNlLiBUaGUgYGRlZmF1bHRWYWx1ZWAgaXMgcmV0dXJuZWQgaWYgYHZhbHVlYCBpcyBgTmFOYCwgYG51bGxgLFxuICAgICAqIG9yIGB1bmRlZmluZWRgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMTQuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAgICogQHBhcmFtIHsqfSBkZWZhdWx0VmFsdWUgVGhlIGRlZmF1bHQgdmFsdWUuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHJlc29sdmVkIHZhbHVlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLmRlZmF1bHRUbygxLCAxMCk7XG4gICAgICogLy8gPT4gMVxuICAgICAqXG4gICAgICogXy5kZWZhdWx0VG8odW5kZWZpbmVkLCAxMCk7XG4gICAgICogLy8gPT4gMTBcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBkZWZhdWx0VG8odmFsdWUsIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgcmV0dXJuICh2YWx1ZSA9PSBudWxsIHx8IHZhbHVlICE9PSB2YWx1ZSkgPyBkZWZhdWx0VmFsdWUgOiB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZSByZXN1bHQgb2YgaW52b2tpbmcgdGhlIGdpdmVuIGZ1bmN0aW9uc1xuICAgICAqIHdpdGggdGhlIGB0aGlzYCBiaW5kaW5nIG9mIHRoZSBjcmVhdGVkIGZ1bmN0aW9uLCB3aGVyZSBlYWNoIHN1Y2Nlc3NpdmVcbiAgICAgKiBpbnZvY2F0aW9uIGlzIHN1cHBsaWVkIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlIHByZXZpb3VzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0gey4uLihGdW5jdGlvbnxGdW5jdGlvbltdKX0gW2Z1bmNzXSBUaGUgZnVuY3Rpb25zIHRvIGludm9rZS5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBjb21wb3NpdGUgZnVuY3Rpb24uXG4gICAgICogQHNlZSBfLmZsb3dSaWdodFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBzcXVhcmUobikge1xuICAgICAqICAgcmV0dXJuIG4gKiBuO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHZhciBhZGRTcXVhcmUgPSBfLmZsb3coW18uYWRkLCBzcXVhcmVdKTtcbiAgICAgKiBhZGRTcXVhcmUoMSwgMik7XG4gICAgICogLy8gPT4gOVxuICAgICAqL1xuICAgIHZhciBmbG93ID0gY3JlYXRlRmxvdygpO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5mbG93YCBleGNlcHQgdGhhdCBpdCBjcmVhdGVzIGEgZnVuY3Rpb24gdGhhdFxuICAgICAqIGludm9rZXMgdGhlIGdpdmVuIGZ1bmN0aW9ucyBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7Li4uKEZ1bmN0aW9ufEZ1bmN0aW9uW10pfSBbZnVuY3NdIFRoZSBmdW5jdGlvbnMgdG8gaW52b2tlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGNvbXBvc2l0ZSBmdW5jdGlvbi5cbiAgICAgKiBAc2VlIF8uZmxvd1xuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBzcXVhcmUobikge1xuICAgICAqICAgcmV0dXJuIG4gKiBuO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHZhciBhZGRTcXVhcmUgPSBfLmZsb3dSaWdodChbc3F1YXJlLCBfLmFkZF0pO1xuICAgICAqIGFkZFNxdWFyZSgxLCAyKTtcbiAgICAgKiAvLyA9PiA5XG4gICAgICovXG4gICAgdmFyIGZsb3dSaWdodCA9IGNyZWF0ZUZsb3codHJ1ZSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCByZXR1cm5zIHRoZSBmaXJzdCBhcmd1bWVudCBpdCByZWNlaXZlcy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAc2luY2UgMC4xLjBcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBBbnkgdmFsdWUuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgYHZhbHVlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdCA9IHsgJ2EnOiAxIH07XG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhfLmlkZW50aXR5KG9iamVjdCkgPT09IG9iamVjdCk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlkZW50aXR5KHZhbHVlKSB7XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBgZnVuY2Agd2l0aCB0aGUgYXJndW1lbnRzIG9mIHRoZSBjcmVhdGVkXG4gICAgICogZnVuY3Rpb24uIElmIGBmdW5jYCBpcyBhIHByb3BlcnR5IG5hbWUsIHRoZSBjcmVhdGVkIGZ1bmN0aW9uIHJldHVybnMgdGhlXG4gICAgICogcHJvcGVydHkgdmFsdWUgZm9yIGEgZ2l2ZW4gZWxlbWVudC4gSWYgYGZ1bmNgIGlzIGFuIGFycmF5IG9yIG9iamVjdCwgdGhlXG4gICAgICogY3JlYXRlZCBmdW5jdGlvbiByZXR1cm5zIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBjb250YWluIHRoZSBlcXVpdmFsZW50XG4gICAgICogc291cmNlIHByb3BlcnRpZXMsIG90aGVyd2lzZSBpdCByZXR1cm5zIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7Kn0gW2Z1bmM9Xy5pZGVudGl0eV0gVGhlIHZhbHVlIHRvIGNvbnZlcnQgdG8gYSBjYWxsYmFjay5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIGNhbGxiYWNrLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgdXNlcnMgPSBbXG4gICAgICogICB7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNiwgJ2FjdGl2ZSc6IHRydWUgfSxcbiAgICAgKiAgIHsgJ3VzZXInOiAnZnJlZCcsICAgJ2FnZSc6IDQwLCAnYWN0aXZlJzogZmFsc2UgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ubWF0Y2hlc2AgaXRlcmF0ZWUgc2hvcnRoYW5kLlxuICAgICAqIF8uZmlsdGVyKHVzZXJzLCBfLml0ZXJhdGVlKHsgJ3VzZXInOiAnYmFybmV5JywgJ2FjdGl2ZSc6IHRydWUgfSkpO1xuICAgICAqIC8vID0+IFt7ICd1c2VyJzogJ2Jhcm5leScsICdhZ2UnOiAzNiwgJ2FjdGl2ZSc6IHRydWUgfV1cbiAgICAgKlxuICAgICAqIC8vIFRoZSBgXy5tYXRjaGVzUHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLmZpbHRlcih1c2VycywgXy5pdGVyYXRlZShbJ3VzZXInLCAnZnJlZCddKSk7XG4gICAgICogLy8gPT4gW3sgJ3VzZXInOiAnZnJlZCcsICdhZ2UnOiA0MCB9XVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5tYXAodXNlcnMsIF8uaXRlcmF0ZWUoJ3VzZXInKSk7XG4gICAgICogLy8gPT4gWydiYXJuZXknLCAnZnJlZCddXG4gICAgICpcbiAgICAgKiAvLyBDcmVhdGUgY3VzdG9tIGl0ZXJhdGVlIHNob3J0aGFuZHMuXG4gICAgICogXy5pdGVyYXRlZSA9IF8ud3JhcChfLml0ZXJhdGVlLCBmdW5jdGlvbihpdGVyYXRlZSwgZnVuYykge1xuICAgICAqICAgcmV0dXJuICFfLmlzUmVnRXhwKGZ1bmMpID8gaXRlcmF0ZWUoZnVuYykgOiBmdW5jdGlvbihzdHJpbmcpIHtcbiAgICAgKiAgICAgcmV0dXJuIGZ1bmMudGVzdChzdHJpbmcpO1xuICAgICAqICAgfTtcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIF8uZmlsdGVyKFsnYWJjJywgJ2RlZiddLCAvZWYvKTtcbiAgICAgKiAvLyA9PiBbJ2RlZiddXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXRlcmF0ZWUoZnVuYykge1xuICAgICAgcmV0dXJuIGJhc2VJdGVyYXRlZSh0eXBlb2YgZnVuYyA9PSAnZnVuY3Rpb24nID8gZnVuYyA6IGJhc2VDbG9uZShmdW5jLCBDTE9ORV9ERUVQX0ZMQUcpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBwZXJmb3JtcyBhIHBhcnRpYWwgZGVlcCBjb21wYXJpc29uIGJldHdlZW4gYSBnaXZlblxuICAgICAqIG9iamVjdCBhbmQgYHNvdXJjZWAsIHJldHVybmluZyBgdHJ1ZWAgaWYgdGhlIGdpdmVuIG9iamVjdCBoYXMgZXF1aXZhbGVudFxuICAgICAqIHByb3BlcnR5IHZhbHVlcywgZWxzZSBgZmFsc2VgLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFRoZSBjcmVhdGVkIGZ1bmN0aW9uIGlzIGVxdWl2YWxlbnQgdG8gYF8uaXNNYXRjaGAgd2l0aCBgc291cmNlYFxuICAgICAqIHBhcnRpYWxseSBhcHBsaWVkLlxuICAgICAqXG4gICAgICogUGFydGlhbCBjb21wYXJpc29ucyB3aWxsIG1hdGNoIGVtcHR5IGFycmF5IGFuZCBlbXB0eSBvYmplY3QgYHNvdXJjZWBcbiAgICAgKiB2YWx1ZXMgYWdhaW5zdCBhbnkgYXJyYXkgb3Igb2JqZWN0IHZhbHVlLCByZXNwZWN0aXZlbHkuIFNlZSBgXy5pc0VxdWFsYFxuICAgICAqIGZvciBhIGxpc3Qgb2Ygc3VwcG9ydGVkIHZhbHVlIGNvbXBhcmlzb25zLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMC4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBvYmplY3Qgb2YgcHJvcGVydHkgdmFsdWVzIHRvIG1hdGNoLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHNwZWMgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW1xuICAgICAqICAgeyAnYSc6IDEsICdiJzogMiwgJ2MnOiAzIH0sXG4gICAgICogICB7ICdhJzogNCwgJ2InOiA1LCAnYyc6IDYgfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLmZpbHRlcihvYmplY3RzLCBfLm1hdGNoZXMoeyAnYSc6IDQsICdjJzogNiB9KSk7XG4gICAgICogLy8gPT4gW3sgJ2EnOiA0LCAnYic6IDUsICdjJzogNiB9XVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1hdGNoZXMoc291cmNlKSB7XG4gICAgICByZXR1cm4gYmFzZU1hdGNoZXMoYmFzZUNsb25lKHNvdXJjZSwgQ0xPTkVfREVFUF9GTEFHKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgcGVyZm9ybXMgYSBwYXJ0aWFsIGRlZXAgY29tcGFyaXNvbiBiZXR3ZWVuIHRoZVxuICAgICAqIHZhbHVlIGF0IGBwYXRoYCBvZiBhIGdpdmVuIG9iamVjdCB0byBgc3JjVmFsdWVgLCByZXR1cm5pbmcgYHRydWVgIGlmIHRoZVxuICAgICAqIG9iamVjdCB2YWx1ZSBpcyBlcXVpdmFsZW50LCBlbHNlIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogUGFydGlhbCBjb21wYXJpc29ucyB3aWxsIG1hdGNoIGVtcHR5IGFycmF5IGFuZCBlbXB0eSBvYmplY3RcbiAgICAgKiBgc3JjVmFsdWVgIHZhbHVlcyBhZ2FpbnN0IGFueSBhcnJheSBvciBvYmplY3QgdmFsdWUsIHJlc3BlY3RpdmVseS4gU2VlXG4gICAgICogYF8uaXNFcXVhbGAgZm9yIGEgbGlzdCBvZiBzdXBwb3J0ZWQgdmFsdWUgY29tcGFyaXNvbnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4yLjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBnZXQuXG4gICAgICogQHBhcmFtIHsqfSBzcmNWYWx1ZSBUaGUgdmFsdWUgdG8gbWF0Y2guXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgc3BlYyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbXG4gICAgICogICB7ICdhJzogMSwgJ2InOiAyLCAnYyc6IDMgfSxcbiAgICAgKiAgIHsgJ2EnOiA0LCAnYic6IDUsICdjJzogNiB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIF8uZmluZChvYmplY3RzLCBfLm1hdGNoZXNQcm9wZXJ0eSgnYScsIDQpKTtcbiAgICAgKiAvLyA9PiB7ICdhJzogNCwgJ2InOiA1LCAnYyc6IDYgfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1hdGNoZXNQcm9wZXJ0eShwYXRoLCBzcmNWYWx1ZSkge1xuICAgICAgcmV0dXJuIGJhc2VNYXRjaGVzUHJvcGVydHkocGF0aCwgYmFzZUNsb25lKHNyY1ZhbHVlLCBDTE9ORV9ERUVQX0ZMQUcpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIHRoZSBtZXRob2QgYXQgYHBhdGhgIG9mIGEgZ2l2ZW4gb2JqZWN0LlxuICAgICAqIEFueSBhZGRpdGlvbmFsIGFyZ3VtZW50cyBhcmUgcHJvdmlkZWQgdG8gdGhlIGludm9rZWQgbWV0aG9kLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuNy4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgbWV0aG9kIHRvIGludm9rZS5cbiAgICAgKiBAcGFyYW0gey4uLip9IFthcmdzXSBUaGUgYXJndW1lbnRzIHRvIGludm9rZSB0aGUgbWV0aG9kIHdpdGguXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgaW52b2tlciBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbXG4gICAgICogICB7ICdhJzogeyAnYic6IF8uY29uc3RhbnQoMikgfSB9LFxuICAgICAqICAgeyAnYSc6IHsgJ2InOiBfLmNvbnN0YW50KDEpIH0gfVxuICAgICAqIF07XG4gICAgICpcbiAgICAgKiBfLm1hcChvYmplY3RzLCBfLm1ldGhvZCgnYS5iJykpO1xuICAgICAqIC8vID0+IFsyLCAxXVxuICAgICAqXG4gICAgICogXy5tYXAob2JqZWN0cywgXy5tZXRob2QoWydhJywgJ2InXSkpO1xuICAgICAqIC8vID0+IFsyLCAxXVxuICAgICAqL1xuICAgIHZhciBtZXRob2QgPSBiYXNlUmVzdChmdW5jdGlvbihwYXRoLCBhcmdzKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgICAgIHJldHVybiBiYXNlSW52b2tlKG9iamVjdCwgcGF0aCwgYXJncyk7XG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogVGhlIG9wcG9zaXRlIG9mIGBfLm1ldGhvZGA7IHRoaXMgbWV0aG9kIGNyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGludm9rZXNcbiAgICAgKiB0aGUgbWV0aG9kIGF0IGEgZ2l2ZW4gcGF0aCBvZiBgb2JqZWN0YC4gQW55IGFkZGl0aW9uYWwgYXJndW1lbnRzIGFyZVxuICAgICAqIHByb3ZpZGVkIHRvIHRoZSBpbnZva2VkIG1ldGhvZC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjcuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEBwYXJhbSB7Li4uKn0gW2FyZ3NdIFRoZSBhcmd1bWVudHMgdG8gaW52b2tlIHRoZSBtZXRob2Qgd2l0aC5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBpbnZva2VyIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBfLnRpbWVzKDMsIF8uY29uc3RhbnQpLFxuICAgICAqICAgICBvYmplY3QgPSB7ICdhJzogYXJyYXksICdiJzogYXJyYXksICdjJzogYXJyYXkgfTtcbiAgICAgKlxuICAgICAqIF8ubWFwKFsnYVsyXScsICdjWzBdJ10sIF8ubWV0aG9kT2Yob2JqZWN0KSk7XG4gICAgICogLy8gPT4gWzIsIDBdXG4gICAgICpcbiAgICAgKiBfLm1hcChbWydhJywgJzInXSwgWydjJywgJzAnXV0sIF8ubWV0aG9kT2Yob2JqZWN0KSk7XG4gICAgICogLy8gPT4gWzIsIDBdXG4gICAgICovXG4gICAgdmFyIG1ldGhvZE9mID0gYmFzZVJlc3QoZnVuY3Rpb24ob2JqZWN0LCBhcmdzKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24ocGF0aCkge1xuICAgICAgICByZXR1cm4gYmFzZUludm9rZShvYmplY3QsIHBhdGgsIGFyZ3MpO1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIEFkZHMgYWxsIG93biBlbnVtZXJhYmxlIHN0cmluZyBrZXllZCBmdW5jdGlvbiBwcm9wZXJ0aWVzIG9mIGEgc291cmNlXG4gICAgICogb2JqZWN0IHRvIHRoZSBkZXN0aW5hdGlvbiBvYmplY3QuIElmIGBvYmplY3RgIGlzIGEgZnVuY3Rpb24sIHRoZW4gbWV0aG9kc1xuICAgICAqIGFyZSBhZGRlZCB0byBpdHMgcHJvdG90eXBlIGFzIHdlbGwuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogVXNlIGBfLnJ1bkluQ29udGV4dGAgdG8gY3JlYXRlIGEgcHJpc3RpbmUgYGxvZGFzaGAgZnVuY3Rpb24gdG9cbiAgICAgKiBhdm9pZCBjb25mbGljdHMgY2F1c2VkIGJ5IG1vZGlmeWluZyB0aGUgb3JpZ2luYWwuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb258T2JqZWN0fSBbb2JqZWN0PWxvZGFzaF0gVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBvYmplY3Qgb2YgZnVuY3Rpb25zIHRvIGFkZC5cbiAgICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIFRoZSBvcHRpb25zIG9iamVjdC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmNoYWluPXRydWVdIFNwZWNpZnkgd2hldGhlciBtaXhpbnMgYXJlIGNoYWluYWJsZS5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb258T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiB2b3dlbHMoc3RyaW5nKSB7XG4gICAgICogICByZXR1cm4gXy5maWx0ZXIoc3RyaW5nLCBmdW5jdGlvbih2KSB7XG4gICAgICogICAgIHJldHVybiAvW2FlaW91XS9pLnRlc3Qodik7XG4gICAgICogICB9KTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBfLm1peGluKHsgJ3Zvd2Vscyc6IHZvd2VscyB9KTtcbiAgICAgKiBfLnZvd2VscygnZnJlZCcpO1xuICAgICAqIC8vID0+IFsnZSddXG4gICAgICpcbiAgICAgKiBfKCdmcmVkJykudm93ZWxzKCkudmFsdWUoKTtcbiAgICAgKiAvLyA9PiBbJ2UnXVxuICAgICAqXG4gICAgICogXy5taXhpbih7ICd2b3dlbHMnOiB2b3dlbHMgfSwgeyAnY2hhaW4nOiBmYWxzZSB9KTtcbiAgICAgKiBfKCdmcmVkJykudm93ZWxzKCk7XG4gICAgICogLy8gPT4gWydlJ11cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtaXhpbihvYmplY3QsIHNvdXJjZSwgb3B0aW9ucykge1xuICAgICAgdmFyIHByb3BzID0ga2V5cyhzb3VyY2UpLFxuICAgICAgICAgIG1ldGhvZE5hbWVzID0gYmFzZUZ1bmN0aW9ucyhzb3VyY2UsIHByb3BzKTtcblxuICAgICAgaWYgKG9wdGlvbnMgPT0gbnVsbCAmJlxuICAgICAgICAgICEoaXNPYmplY3Qoc291cmNlKSAmJiAobWV0aG9kTmFtZXMubGVuZ3RoIHx8ICFwcm9wcy5sZW5ndGgpKSkge1xuICAgICAgICBvcHRpb25zID0gc291cmNlO1xuICAgICAgICBzb3VyY2UgPSBvYmplY3Q7XG4gICAgICAgIG9iamVjdCA9IHRoaXM7XG4gICAgICAgIG1ldGhvZE5hbWVzID0gYmFzZUZ1bmN0aW9ucyhzb3VyY2UsIGtleXMoc291cmNlKSk7XG4gICAgICB9XG4gICAgICB2YXIgY2hhaW4gPSAhKGlzT2JqZWN0KG9wdGlvbnMpICYmICdjaGFpbicgaW4gb3B0aW9ucykgfHwgISFvcHRpb25zLmNoYWluLFxuICAgICAgICAgIGlzRnVuYyA9IGlzRnVuY3Rpb24ob2JqZWN0KTtcblxuICAgICAgYXJyYXlFYWNoKG1ldGhvZE5hbWVzLCBmdW5jdGlvbihtZXRob2ROYW1lKSB7XG4gICAgICAgIHZhciBmdW5jID0gc291cmNlW21ldGhvZE5hbWVdO1xuICAgICAgICBvYmplY3RbbWV0aG9kTmFtZV0gPSBmdW5jO1xuICAgICAgICBpZiAoaXNGdW5jKSB7XG4gICAgICAgICAgb2JqZWN0LnByb3RvdHlwZVttZXRob2ROYW1lXSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIGNoYWluQWxsID0gdGhpcy5fX2NoYWluX187XG4gICAgICAgICAgICBpZiAoY2hhaW4gfHwgY2hhaW5BbGwpIHtcbiAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IG9iamVjdCh0aGlzLl9fd3JhcHBlZF9fKSxcbiAgICAgICAgICAgICAgICAgIGFjdGlvbnMgPSByZXN1bHQuX19hY3Rpb25zX18gPSBjb3B5QXJyYXkodGhpcy5fX2FjdGlvbnNfXyk7XG5cbiAgICAgICAgICAgICAgYWN0aW9ucy5wdXNoKHsgJ2Z1bmMnOiBmdW5jLCAnYXJncyc6IGFyZ3VtZW50cywgJ3RoaXNBcmcnOiBvYmplY3QgfSk7XG4gICAgICAgICAgICAgIHJlc3VsdC5fX2NoYWluX18gPSBjaGFpbkFsbDtcbiAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmdW5jLmFwcGx5KG9iamVjdCwgYXJyYXlQdXNoKFt0aGlzLnZhbHVlKCldLCBhcmd1bWVudHMpKTtcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXZlcnRzIHRoZSBgX2AgdmFyaWFibGUgdG8gaXRzIHByZXZpb3VzIHZhbHVlIGFuZCByZXR1cm5zIGEgcmVmZXJlbmNlIHRvXG4gICAgICogdGhlIGBsb2Rhc2hgIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIGBsb2Rhc2hgIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgbG9kYXNoID0gXy5ub0NvbmZsaWN0KCk7XG4gICAgICovXG4gICAgZnVuY3Rpb24gbm9Db25mbGljdCgpIHtcbiAgICAgIGlmIChyb290Ll8gPT09IHRoaXMpIHtcbiAgICAgICAgcm9vdC5fID0gb2xkRGFzaDtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWV0aG9kIHJldHVybnMgYHVuZGVmaW5lZGAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMi4zLjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRpbWVzKDIsIF8ubm9vcCk7XG4gICAgICogLy8gPT4gW3VuZGVmaW5lZCwgdW5kZWZpbmVkXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG5vb3AoKSB7XG4gICAgICAvLyBObyBvcGVyYXRpb24gcGVyZm9ybWVkLlxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGdldHMgdGhlIGFyZ3VtZW50IGF0IGluZGV4IGBuYC4gSWYgYG5gIGlzIG5lZ2F0aXZlLFxuICAgICAqIHRoZSBudGggYXJndW1lbnQgZnJvbSB0aGUgZW5kIGlzIHJldHVybmVkLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW249MF0gVGhlIGluZGV4IG9mIHRoZSBhcmd1bWVudCB0byByZXR1cm4uXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgcGFzcy10aHJ1IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgZnVuYyA9IF8ubnRoQXJnKDEpO1xuICAgICAqIGZ1bmMoJ2EnLCAnYicsICdjJywgJ2QnKTtcbiAgICAgKiAvLyA9PiAnYidcbiAgICAgKlxuICAgICAqIHZhciBmdW5jID0gXy5udGhBcmcoLTIpO1xuICAgICAqIGZ1bmMoJ2EnLCAnYicsICdjJywgJ2QnKTtcbiAgICAgKiAvLyA9PiAnYydcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBudGhBcmcobikge1xuICAgICAgbiA9IHRvSW50ZWdlcihuKTtcbiAgICAgIHJldHVybiBiYXNlUmVzdChmdW5jdGlvbihhcmdzKSB7XG4gICAgICAgIHJldHVybiBiYXNlTnRoKGFyZ3MsIG4pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBgaXRlcmF0ZWVzYCB3aXRoIHRoZSBhcmd1bWVudHMgaXQgcmVjZWl2ZXNcbiAgICAgKiBhbmQgcmV0dXJucyB0aGVpciByZXN1bHRzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0gey4uLihGdW5jdGlvbnxGdW5jdGlvbltdKX0gW2l0ZXJhdGVlcz1bXy5pZGVudGl0eV1dXG4gICAgICogIFRoZSBpdGVyYXRlZXMgdG8gaW52b2tlLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgZnVuYyA9IF8ub3ZlcihbTWF0aC5tYXgsIE1hdGgubWluXSk7XG4gICAgICpcbiAgICAgKiBmdW5jKDEsIDIsIDMsIDQpO1xuICAgICAqIC8vID0+IFs0LCAxXVxuICAgICAqL1xuICAgIHZhciBvdmVyID0gY3JlYXRlT3ZlcihhcnJheU1hcCk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBjaGVja3MgaWYgKiphbGwqKiBvZiB0aGUgYHByZWRpY2F0ZXNgIHJldHVyblxuICAgICAqIHRydXRoeSB3aGVuIGludm9rZWQgd2l0aCB0aGUgYXJndW1lbnRzIGl0IHJlY2VpdmVzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0gey4uLihGdW5jdGlvbnxGdW5jdGlvbltdKX0gW3ByZWRpY2F0ZXM9W18uaWRlbnRpdHldXVxuICAgICAqICBUaGUgcHJlZGljYXRlcyB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIGZ1bmMgPSBfLm92ZXJFdmVyeShbQm9vbGVhbiwgaXNGaW5pdGVdKTtcbiAgICAgKlxuICAgICAqIGZ1bmMoJzEnKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBmdW5jKG51bGwpO1xuICAgICAqIC8vID0+IGZhbHNlXG4gICAgICpcbiAgICAgKiBmdW5jKE5hTik7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICB2YXIgb3ZlckV2ZXJ5ID0gY3JlYXRlT3ZlcihhcnJheUV2ZXJ5KTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGNoZWNrcyBpZiAqKmFueSoqIG9mIHRoZSBgcHJlZGljYXRlc2AgcmV0dXJuXG4gICAgICogdHJ1dGh5IHdoZW4gaW52b2tlZCB3aXRoIHRoZSBhcmd1bWVudHMgaXQgcmVjZWl2ZXMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4wLjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7Li4uKEZ1bmN0aW9ufEZ1bmN0aW9uW10pfSBbcHJlZGljYXRlcz1bXy5pZGVudGl0eV1dXG4gICAgICogIFRoZSBwcmVkaWNhdGVzIHRvIGNoZWNrLlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgZnVuYyA9IF8ub3ZlclNvbWUoW0Jvb2xlYW4sIGlzRmluaXRlXSk7XG4gICAgICpcbiAgICAgKiBmdW5jKCcxJyk7XG4gICAgICogLy8gPT4gdHJ1ZVxuICAgICAqXG4gICAgICogZnVuYyhudWxsKTtcbiAgICAgKiAvLyA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBmdW5jKE5hTik7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICB2YXIgb3ZlclNvbWUgPSBjcmVhdGVPdmVyKGFycmF5U29tZSk7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZSB2YWx1ZSBhdCBgcGF0aGAgb2YgYSBnaXZlbiBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMi40LjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBnZXQuXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYWNjZXNzb3IgZnVuY3Rpb24uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW1xuICAgICAqICAgeyAnYSc6IHsgJ2InOiAyIH0gfSxcbiAgICAgKiAgIHsgJ2EnOiB7ICdiJzogMSB9IH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogXy5tYXAob2JqZWN0cywgXy5wcm9wZXJ0eSgnYS5iJykpO1xuICAgICAqIC8vID0+IFsyLCAxXVxuICAgICAqXG4gICAgICogXy5tYXAoXy5zb3J0Qnkob2JqZWN0cywgXy5wcm9wZXJ0eShbJ2EnLCAnYiddKSksICdhLmInKTtcbiAgICAgKiAvLyA9PiBbMSwgMl1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwcm9wZXJ0eShwYXRoKSB7XG4gICAgICByZXR1cm4gaXNLZXkocGF0aCkgPyBiYXNlUHJvcGVydHkodG9LZXkocGF0aCkpIDogYmFzZVByb3BlcnR5RGVlcChwYXRoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgb3Bwb3NpdGUgb2YgYF8ucHJvcGVydHlgOyB0aGlzIG1ldGhvZCBjcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zXG4gICAgICogdGhlIHZhbHVlIGF0IGEgZ2l2ZW4gcGF0aCBvZiBgb2JqZWN0YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjAuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGFjY2Vzc29yIGZ1bmN0aW9uLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXkgPSBbMCwgMSwgMl0sXG4gICAgICogICAgIG9iamVjdCA9IHsgJ2EnOiBhcnJheSwgJ2InOiBhcnJheSwgJ2MnOiBhcnJheSB9O1xuICAgICAqXG4gICAgICogXy5tYXAoWydhWzJdJywgJ2NbMF0nXSwgXy5wcm9wZXJ0eU9mKG9iamVjdCkpO1xuICAgICAqIC8vID0+IFsyLCAwXVxuICAgICAqXG4gICAgICogXy5tYXAoW1snYScsICcyJ10sIFsnYycsICcwJ11dLCBfLnByb3BlcnR5T2Yob2JqZWN0KSk7XG4gICAgICogLy8gPT4gWzIsIDBdXG4gICAgICovXG4gICAgZnVuY3Rpb24gcHJvcGVydHlPZihvYmplY3QpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihwYXRoKSB7XG4gICAgICAgIHJldHVybiBvYmplY3QgPT0gbnVsbCA/IHVuZGVmaW5lZCA6IGJhc2VHZXQob2JqZWN0LCBwYXRoKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhcnJheSBvZiBudW1iZXJzIChwb3NpdGl2ZSBhbmQvb3IgbmVnYXRpdmUpIHByb2dyZXNzaW5nIGZyb21cbiAgICAgKiBgc3RhcnRgIHVwIHRvLCBidXQgbm90IGluY2x1ZGluZywgYGVuZGAuIEEgc3RlcCBvZiBgLTFgIGlzIHVzZWQgaWYgYSBuZWdhdGl2ZVxuICAgICAqIGBzdGFydGAgaXMgc3BlY2lmaWVkIHdpdGhvdXQgYW4gYGVuZGAgb3IgYHN0ZXBgLiBJZiBgZW5kYCBpcyBub3Qgc3BlY2lmaWVkLFxuICAgICAqIGl0J3Mgc2V0IHRvIGBzdGFydGAgd2l0aCBgc3RhcnRgIHRoZW4gc2V0IHRvIGAwYC5cbiAgICAgKlxuICAgICAqICoqTm90ZToqKiBKYXZhU2NyaXB0IGZvbGxvd3MgdGhlIElFRUUtNzU0IHN0YW5kYXJkIGZvciByZXNvbHZpbmdcbiAgICAgKiBmbG9hdGluZy1wb2ludCB2YWx1ZXMgd2hpY2ggY2FuIHByb2R1Y2UgdW5leHBlY3RlZCByZXN1bHRzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0YXJ0PTBdIFRoZSBzdGFydCBvZiB0aGUgcmFuZ2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGVuZCBUaGUgZW5kIG9mIHRoZSByYW5nZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3N0ZXA9MV0gVGhlIHZhbHVlIHRvIGluY3JlbWVudCBvciBkZWNyZW1lbnQgYnkuXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSByYW5nZSBvZiBudW1iZXJzLlxuICAgICAqIEBzZWUgXy5pblJhbmdlLCBfLnJhbmdlUmlnaHRcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5yYW5nZSg0KTtcbiAgICAgKiAvLyA9PiBbMCwgMSwgMiwgM11cbiAgICAgKlxuICAgICAqIF8ucmFuZ2UoLTQpO1xuICAgICAqIC8vID0+IFswLCAtMSwgLTIsIC0zXVxuICAgICAqXG4gICAgICogXy5yYW5nZSgxLCA1KTtcbiAgICAgKiAvLyA9PiBbMSwgMiwgMywgNF1cbiAgICAgKlxuICAgICAqIF8ucmFuZ2UoMCwgMjAsIDUpO1xuICAgICAqIC8vID0+IFswLCA1LCAxMCwgMTVdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlKDAsIC00LCAtMSk7XG4gICAgICogLy8gPT4gWzAsIC0xLCAtMiwgLTNdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlKDEsIDQsIDApO1xuICAgICAqIC8vID0+IFsxLCAxLCAxXVxuICAgICAqXG4gICAgICogXy5yYW5nZSgwKTtcbiAgICAgKiAvLyA9PiBbXVxuICAgICAqL1xuICAgIHZhciByYW5nZSA9IGNyZWF0ZVJhbmdlKCk7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnJhbmdlYCBleGNlcHQgdGhhdCBpdCBwb3B1bGF0ZXMgdmFsdWVzIGluXG4gICAgICogZGVzY2VuZGluZyBvcmRlci5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGFydD0wXSBUaGUgc3RhcnQgb2YgdGhlIHJhbmdlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgVGhlIGVuZCBvZiB0aGUgcmFuZ2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtzdGVwPTFdIFRoZSB2YWx1ZSB0byBpbmNyZW1lbnQgb3IgZGVjcmVtZW50IGJ5LlxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgcmFuZ2Ugb2YgbnVtYmVycy5cbiAgICAgKiBAc2VlIF8uaW5SYW5nZSwgXy5yYW5nZVxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnJhbmdlUmlnaHQoNCk7XG4gICAgICogLy8gPT4gWzMsIDIsIDEsIDBdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlUmlnaHQoLTQpO1xuICAgICAqIC8vID0+IFstMywgLTIsIC0xLCAwXVxuICAgICAqXG4gICAgICogXy5yYW5nZVJpZ2h0KDEsIDUpO1xuICAgICAqIC8vID0+IFs0LCAzLCAyLCAxXVxuICAgICAqXG4gICAgICogXy5yYW5nZVJpZ2h0KDAsIDIwLCA1KTtcbiAgICAgKiAvLyA9PiBbMTUsIDEwLCA1LCAwXVxuICAgICAqXG4gICAgICogXy5yYW5nZVJpZ2h0KDAsIC00LCAtMSk7XG4gICAgICogLy8gPT4gWy0zLCAtMiwgLTEsIDBdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlUmlnaHQoMSwgNCwgMCk7XG4gICAgICogLy8gPT4gWzEsIDEsIDFdXG4gICAgICpcbiAgICAgKiBfLnJhbmdlUmlnaHQoMCk7XG4gICAgICogLy8gPT4gW11cbiAgICAgKi9cbiAgICB2YXIgcmFuZ2VSaWdodCA9IGNyZWF0ZVJhbmdlKHRydWUpO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgcmV0dXJucyBhIG5ldyBlbXB0eSBhcnJheS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjEzLjBcbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGVtcHR5IGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgYXJyYXlzID0gXy50aW1lcygyLCBfLnN0dWJBcnJheSk7XG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheXMpO1xuICAgICAqIC8vID0+IFtbXSwgW11dXG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhhcnJheXNbMF0gPT09IGFycmF5c1sxXSk7XG4gICAgICogLy8gPT4gZmFsc2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzdHViQXJyYXkoKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgcmV0dXJucyBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMTMuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYGZhbHNlYC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy50aW1lcygyLCBfLnN0dWJGYWxzZSk7XG4gICAgICogLy8gPT4gW2ZhbHNlLCBmYWxzZV1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzdHViRmFsc2UoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgcmV0dXJucyBhIG5ldyBlbXB0eSBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4xMy4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgZW1wdHkgb2JqZWN0LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IF8udGltZXMoMiwgXy5zdHViT2JqZWN0KTtcbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKG9iamVjdHMpO1xuICAgICAqIC8vID0+IFt7fSwge31dXG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhvYmplY3RzWzBdID09PSBvYmplY3RzWzFdKTtcbiAgICAgKiAvLyA9PiBmYWxzZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHN0dWJPYmplY3QoKSB7XG4gICAgICByZXR1cm4ge307XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgcmV0dXJucyBhbiBlbXB0eSBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4xMy4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBlbXB0eSBzdHJpbmcuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udGltZXMoMiwgXy5zdHViU3RyaW5nKTtcbiAgICAgKiAvLyA9PiBbJycsICcnXVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHN0dWJTdHJpbmcoKSB7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgcmV0dXJucyBgdHJ1ZWAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC4xMy4wXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udGltZXMoMiwgXy5zdHViVHJ1ZSk7XG4gICAgICogLy8gPT4gW3RydWUsIHRydWVdXG4gICAgICovXG4gICAgZnVuY3Rpb24gc3R1YlRydWUoKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnZva2VzIHRoZSBpdGVyYXRlZSBgbmAgdGltZXMsIHJldHVybmluZyBhbiBhcnJheSBvZiB0aGUgcmVzdWx0cyBvZlxuICAgICAqIGVhY2ggaW52b2NhdGlvbi4gVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ7IChpbmRleCkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgVXRpbFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBuIFRoZSBudW1iZXIgb2YgdGltZXMgdG8gaW52b2tlIGBpdGVyYXRlZWAuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiByZXN1bHRzLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRpbWVzKDMsIFN0cmluZyk7XG4gICAgICogLy8gPT4gWycwJywgJzEnLCAnMiddXG4gICAgICpcbiAgICAgKiAgXy50aW1lcyg0LCBfLmNvbnN0YW50KDApKTtcbiAgICAgKiAvLyA9PiBbMCwgMCwgMCwgMF1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB0aW1lcyhuLCBpdGVyYXRlZSkge1xuICAgICAgbiA9IHRvSW50ZWdlcihuKTtcbiAgICAgIGlmIChuIDwgMSB8fCBuID4gTUFYX1NBRkVfSU5URUdFUikge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICB2YXIgaW5kZXggPSBNQVhfQVJSQVlfTEVOR1RILFxuICAgICAgICAgIGxlbmd0aCA9IG5hdGl2ZU1pbihuLCBNQVhfQVJSQVlfTEVOR1RIKTtcblxuICAgICAgaXRlcmF0ZWUgPSBnZXRJdGVyYXRlZShpdGVyYXRlZSk7XG4gICAgICBuIC09IE1BWF9BUlJBWV9MRU5HVEg7XG5cbiAgICAgIHZhciByZXN1bHQgPSBiYXNlVGltZXMobGVuZ3RoLCBpdGVyYXRlZSk7XG4gICAgICB3aGlsZSAoKytpbmRleCA8IG4pIHtcbiAgICAgICAgaXRlcmF0ZWUoaW5kZXgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGEgcHJvcGVydHkgcGF0aCBhcnJheS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBVdGlsXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBwcm9wZXJ0eSBwYXRoIGFycmF5LlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnRvUGF0aCgnYS5iLmMnKTtcbiAgICAgKiAvLyA9PiBbJ2EnLCAnYicsICdjJ11cbiAgICAgKlxuICAgICAqIF8udG9QYXRoKCdhWzBdLmIuYycpO1xuICAgICAqIC8vID0+IFsnYScsICcwJywgJ2InLCAnYyddXG4gICAgICovXG4gICAgZnVuY3Rpb24gdG9QYXRoKHZhbHVlKSB7XG4gICAgICBpZiAoaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIGFycmF5TWFwKHZhbHVlLCB0b0tleSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gaXNTeW1ib2wodmFsdWUpID8gW3ZhbHVlXSA6IGNvcHlBcnJheShzdHJpbmdUb1BhdGgodG9TdHJpbmcodmFsdWUpKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGVzIGEgdW5pcXVlIElELiBJZiBgcHJlZml4YCBpcyBnaXZlbiwgdGhlIElEIGlzIGFwcGVuZGVkIHRvIGl0LlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBzaW5jZSAwLjEuMFxuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQGNhdGVnb3J5IFV0aWxcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW3ByZWZpeD0nJ10gVGhlIHZhbHVlIHRvIHByZWZpeCB0aGUgSUQgd2l0aC5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSB1bmlxdWUgSUQuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8udW5pcXVlSWQoJ2NvbnRhY3RfJyk7XG4gICAgICogLy8gPT4gJ2NvbnRhY3RfMTA0J1xuICAgICAqXG4gICAgICogXy51bmlxdWVJZCgpO1xuICAgICAqIC8vID0+ICcxMDUnXG4gICAgICovXG4gICAgZnVuY3Rpb24gdW5pcXVlSWQocHJlZml4KSB7XG4gICAgICB2YXIgaWQgPSArK2lkQ291bnRlcjtcbiAgICAgIHJldHVybiB0b1N0cmluZyhwcmVmaXgpICsgaWQ7XG4gICAgfVxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLyoqXG4gICAgICogQWRkcyB0d28gbnVtYmVycy5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSAzLjQuMFxuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGF1Z2VuZCBUaGUgZmlyc3QgbnVtYmVyIGluIGFuIGFkZGl0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBhZGRlbmQgVGhlIHNlY29uZCBudW1iZXIgaW4gYW4gYWRkaXRpb24uXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgdG90YWwuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uYWRkKDYsIDQpO1xuICAgICAqIC8vID0+IDEwXG4gICAgICovXG4gICAgdmFyIGFkZCA9IGNyZWF0ZU1hdGhPcGVyYXRpb24oZnVuY3Rpb24oYXVnZW5kLCBhZGRlbmQpIHtcbiAgICAgIHJldHVybiBhdWdlbmQgKyBhZGRlbmQ7XG4gICAgfSwgMCk7XG5cbiAgICAvKipcbiAgICAgKiBDb21wdXRlcyBgbnVtYmVyYCByb3VuZGVkIHVwIHRvIGBwcmVjaXNpb25gLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMTAuMFxuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG51bWJlciBUaGUgbnVtYmVyIHRvIHJvdW5kIHVwLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbcHJlY2lzaW9uPTBdIFRoZSBwcmVjaXNpb24gdG8gcm91bmQgdXAgdG8uXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgcm91bmRlZCB1cCBudW1iZXIuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8uY2VpbCg0LjAwNik7XG4gICAgICogLy8gPT4gNVxuICAgICAqXG4gICAgICogXy5jZWlsKDYuMDA0LCAyKTtcbiAgICAgKiAvLyA9PiA2LjAxXG4gICAgICpcbiAgICAgKiBfLmNlaWwoNjA0MCwgLTIpO1xuICAgICAqIC8vID0+IDYxMDBcbiAgICAgKi9cbiAgICB2YXIgY2VpbCA9IGNyZWF0ZVJvdW5kKCdjZWlsJyk7XG5cbiAgICAvKipcbiAgICAgKiBEaXZpZGUgdHdvIG51bWJlcnMuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC43LjBcbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBkaXZpZGVuZCBUaGUgZmlyc3QgbnVtYmVyIGluIGEgZGl2aXNpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGRpdmlzb3IgVGhlIHNlY29uZCBudW1iZXIgaW4gYSBkaXZpc2lvbi5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBxdW90aWVudC5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5kaXZpZGUoNiwgNCk7XG4gICAgICogLy8gPT4gMS41XG4gICAgICovXG4gICAgdmFyIGRpdmlkZSA9IGNyZWF0ZU1hdGhPcGVyYXRpb24oZnVuY3Rpb24oZGl2aWRlbmQsIGRpdmlzb3IpIHtcbiAgICAgIHJldHVybiBkaXZpZGVuZCAvIGRpdmlzb3I7XG4gICAgfSwgMSk7XG5cbiAgICAvKipcbiAgICAgKiBDb21wdXRlcyBgbnVtYmVyYCByb3VuZGVkIGRvd24gdG8gYHByZWNpc2lvbmAuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgMy4xMC4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbnVtYmVyIFRoZSBudW1iZXIgdG8gcm91bmQgZG93bi5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3ByZWNpc2lvbj0wXSBUaGUgcHJlY2lzaW9uIHRvIHJvdW5kIGRvd24gdG8uXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgcm91bmRlZCBkb3duIG51bWJlci5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5mbG9vcig0LjAwNik7XG4gICAgICogLy8gPT4gNFxuICAgICAqXG4gICAgICogXy5mbG9vcigwLjA0NiwgMik7XG4gICAgICogLy8gPT4gMC4wNFxuICAgICAqXG4gICAgICogXy5mbG9vcig0MDYwLCAtMik7XG4gICAgICogLy8gPT4gNDAwMFxuICAgICAqL1xuICAgIHZhciBmbG9vciA9IGNyZWF0ZVJvdW5kKCdmbG9vcicpO1xuXG4gICAgLyoqXG4gICAgICogQ29tcHV0ZXMgdGhlIG1heGltdW0gdmFsdWUgb2YgYGFycmF5YC4gSWYgYGFycmF5YCBpcyBlbXB0eSBvciBmYWxzZXksXG4gICAgICogYHVuZGVmaW5lZGAgaXMgcmV0dXJuZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG1heGltdW0gdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubWF4KFs0LCAyLCA4LCA2XSk7XG4gICAgICogLy8gPT4gOFxuICAgICAqXG4gICAgICogXy5tYXgoW10pO1xuICAgICAqIC8vID0+IHVuZGVmaW5lZFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1heChhcnJheSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpXG4gICAgICAgID8gYmFzZUV4dHJlbXVtKGFycmF5LCBpZGVudGl0eSwgYmFzZUd0KVxuICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLm1heGAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgIHdoaWNoIGlzXG4gICAgICogaW52b2tlZCBmb3IgZWFjaCBlbGVtZW50IGluIGBhcnJheWAgdG8gZ2VuZXJhdGUgdGhlIGNyaXRlcmlvbiBieSB3aGljaFxuICAgICAqIHRoZSB2YWx1ZSBpcyByYW5rZWQuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgbWF4aW11bSB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbeyAnbic6IDEgfSwgeyAnbic6IDIgfV07XG4gICAgICpcbiAgICAgKiBfLm1heEJ5KG9iamVjdHMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuIG8ubjsgfSk7XG4gICAgICogLy8gPT4geyAnbic6IDIgfVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5tYXhCeShvYmplY3RzLCAnbicpO1xuICAgICAqIC8vID0+IHsgJ24nOiAyIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYXhCeShhcnJheSwgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKVxuICAgICAgICA/IGJhc2VFeHRyZW11bShhcnJheSwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDIpLCBiYXNlR3QpXG4gICAgICAgIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbXB1dGVzIHRoZSBtZWFuIG9mIHRoZSB2YWx1ZXMgaW4gYGFycmF5YC5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBtZWFuLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLm1lYW4oWzQsIDIsIDgsIDZdKTtcbiAgICAgKiAvLyA9PiA1XG4gICAgICovXG4gICAgZnVuY3Rpb24gbWVhbihhcnJheSkge1xuICAgICAgcmV0dXJuIGJhc2VNZWFuKGFycmF5LCBpZGVudGl0eSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5tZWFuYCBleGNlcHQgdGhhdCBpdCBhY2NlcHRzIGBpdGVyYXRlZWAgd2hpY2ggaXNcbiAgICAgKiBpbnZva2VkIGZvciBlYWNoIGVsZW1lbnQgaW4gYGFycmF5YCB0byBnZW5lcmF0ZSB0aGUgdmFsdWUgdG8gYmUgYXZlcmFnZWQuXG4gICAgICogVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCBvbmUgYXJndW1lbnQ6ICh2YWx1ZSkuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAc2luY2UgNC43LjBcbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gW2l0ZXJhdGVlPV8uaWRlbnRpdHldIFRoZSBpdGVyYXRlZSBpbnZva2VkIHBlciBlbGVtZW50LlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIG1lYW4uXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIHZhciBvYmplY3RzID0gW3sgJ24nOiA0IH0sIHsgJ24nOiAyIH0sIHsgJ24nOiA4IH0sIHsgJ24nOiA2IH1dO1xuICAgICAqXG4gICAgICogXy5tZWFuQnkob2JqZWN0cywgZnVuY3Rpb24obykgeyByZXR1cm4gby5uOyB9KTtcbiAgICAgKiAvLyA9PiA1XG4gICAgICpcbiAgICAgKiAvLyBUaGUgYF8ucHJvcGVydHlgIGl0ZXJhdGVlIHNob3J0aGFuZC5cbiAgICAgKiBfLm1lYW5CeShvYmplY3RzLCAnbicpO1xuICAgICAqIC8vID0+IDVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtZWFuQnkoYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gYmFzZU1lYW4oYXJyYXksIGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAyKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29tcHV0ZXMgdGhlIG1pbmltdW0gdmFsdWUgb2YgYGFycmF5YC4gSWYgYGFycmF5YCBpcyBlbXB0eSBvciBmYWxzZXksXG4gICAgICogYHVuZGVmaW5lZGAgaXMgcmV0dXJuZWQuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHNpbmNlIDAuMS4wXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAY2F0ZWdvcnkgTWF0aFxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gICAgICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG1pbmltdW0gdmFsdWUuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubWluKFs0LCAyLCA4LCA2XSk7XG4gICAgICogLy8gPT4gMlxuICAgICAqXG4gICAgICogXy5taW4oW10pO1xuICAgICAqIC8vID0+IHVuZGVmaW5lZFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1pbihhcnJheSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpXG4gICAgICAgID8gYmFzZUV4dHJlbXVtKGFycmF5LCBpZGVudGl0eSwgYmFzZUx0KVxuICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLm1pbmAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgIHdoaWNoIGlzXG4gICAgICogaW52b2tlZCBmb3IgZWFjaCBlbGVtZW50IGluIGBhcnJheWAgdG8gZ2VuZXJhdGUgdGhlIGNyaXRlcmlvbiBieSB3aGljaFxuICAgICAqIHRoZSB2YWx1ZSBpcyByYW5rZWQuIFRoZSBpdGVyYXRlZSBpcyBpbnZva2VkIHdpdGggb25lIGFyZ3VtZW50OiAodmFsdWUpLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgaXRlcmF0ZWUgaW52b2tlZCBwZXIgZWxlbWVudC5cbiAgICAgKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgbWluaW11bSB2YWx1ZS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogdmFyIG9iamVjdHMgPSBbeyAnbic6IDEgfSwgeyAnbic6IDIgfV07XG4gICAgICpcbiAgICAgKiBfLm1pbkJ5KG9iamVjdHMsIGZ1bmN0aW9uKG8pIHsgcmV0dXJuIG8ubjsgfSk7XG4gICAgICogLy8gPT4geyAnbic6IDEgfVxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5taW5CeShvYmplY3RzLCAnbicpO1xuICAgICAqIC8vID0+IHsgJ24nOiAxIH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtaW5CeShhcnJheSwgaXRlcmF0ZWUpIHtcbiAgICAgIHJldHVybiAoYXJyYXkgJiYgYXJyYXkubGVuZ3RoKVxuICAgICAgICA/IGJhc2VFeHRyZW11bShhcnJheSwgZ2V0SXRlcmF0ZWUoaXRlcmF0ZWUsIDIpLCBiYXNlTHQpXG4gICAgICAgIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE11bHRpcGx5IHR3byBudW1iZXJzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuNy4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbXVsdGlwbGllciBUaGUgZmlyc3QgbnVtYmVyIGluIGEgbXVsdGlwbGljYXRpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG11bHRpcGxpY2FuZCBUaGUgc2Vjb25kIG51bWJlciBpbiBhIG11bHRpcGxpY2F0aW9uLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHByb2R1Y3QuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ubXVsdGlwbHkoNiwgNCk7XG4gICAgICogLy8gPT4gMjRcbiAgICAgKi9cbiAgICB2YXIgbXVsdGlwbHkgPSBjcmVhdGVNYXRoT3BlcmF0aW9uKGZ1bmN0aW9uKG11bHRpcGxpZXIsIG11bHRpcGxpY2FuZCkge1xuICAgICAgcmV0dXJuIG11bHRpcGxpZXIgKiBtdWx0aXBsaWNhbmQ7XG4gICAgfSwgMSk7XG5cbiAgICAvKipcbiAgICAgKiBDb21wdXRlcyBgbnVtYmVyYCByb3VuZGVkIHRvIGBwcmVjaXNpb25gLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuMTAuMFxuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG51bWJlciBUaGUgbnVtYmVyIHRvIHJvdW5kLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbcHJlY2lzaW9uPTBdIFRoZSBwcmVjaXNpb24gdG8gcm91bmQgdG8uXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgcm91bmRlZCBudW1iZXIuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIF8ucm91bmQoNC4wMDYpO1xuICAgICAqIC8vID0+IDRcbiAgICAgKlxuICAgICAqIF8ucm91bmQoNC4wMDYsIDIpO1xuICAgICAqIC8vID0+IDQuMDFcbiAgICAgKlxuICAgICAqIF8ucm91bmQoNDA2MCwgLTIpO1xuICAgICAqIC8vID0+IDQxMDBcbiAgICAgKi9cbiAgICB2YXIgcm91bmQgPSBjcmVhdGVSb3VuZCgncm91bmQnKTtcblxuICAgIC8qKlxuICAgICAqIFN1YnRyYWN0IHR3byBudW1iZXJzLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDQuMC4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbWludWVuZCBUaGUgZmlyc3QgbnVtYmVyIGluIGEgc3VidHJhY3Rpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHN1YnRyYWhlbmQgVGhlIHNlY29uZCBudW1iZXIgaW4gYSBzdWJ0cmFjdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBkaWZmZXJlbmNlLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBfLnN1YnRyYWN0KDYsIDQpO1xuICAgICAqIC8vID0+IDJcbiAgICAgKi9cbiAgICB2YXIgc3VidHJhY3QgPSBjcmVhdGVNYXRoT3BlcmF0aW9uKGZ1bmN0aW9uKG1pbnVlbmQsIHN1YnRyYWhlbmQpIHtcbiAgICAgIHJldHVybiBtaW51ZW5kIC0gc3VidHJhaGVuZDtcbiAgICB9LCAwKTtcblxuICAgIC8qKlxuICAgICAqIENvbXB1dGVzIHRoZSBzdW0gb2YgdGhlIHZhbHVlcyBpbiBgYXJyYXlgLlxuICAgICAqXG4gICAgICogQHN0YXRpY1xuICAgICAqIEBtZW1iZXJPZiBfXG4gICAgICogQHNpbmNlIDMuNC4wXG4gICAgICogQGNhdGVnb3J5IE1hdGhcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIHN1bS5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogXy5zdW0oWzQsIDIsIDgsIDZdKTtcbiAgICAgKiAvLyA9PiAyMFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHN1bShhcnJheSkge1xuICAgICAgcmV0dXJuIChhcnJheSAmJiBhcnJheS5sZW5ndGgpXG4gICAgICAgID8gYmFzZVN1bShhcnJheSwgaWRlbnRpdHkpXG4gICAgICAgIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLnN1bWAgZXhjZXB0IHRoYXQgaXQgYWNjZXB0cyBgaXRlcmF0ZWVgIHdoaWNoIGlzXG4gICAgICogaW52b2tlZCBmb3IgZWFjaCBlbGVtZW50IGluIGBhcnJheWAgdG8gZ2VuZXJhdGUgdGhlIHZhbHVlIHRvIGJlIHN1bW1lZC5cbiAgICAgKiBUaGUgaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDogKHZhbHVlKS5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAbWVtYmVyT2YgX1xuICAgICAqIEBzaW5jZSA0LjAuMFxuICAgICAqIEBjYXRlZ29yeSBNYXRoXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGl0ZXJhdGVlIGludm9rZWQgcGVyIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgc3VtLlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiB2YXIgb2JqZWN0cyA9IFt7ICduJzogNCB9LCB7ICduJzogMiB9LCB7ICduJzogOCB9LCB7ICduJzogNiB9XTtcbiAgICAgKlxuICAgICAqIF8uc3VtQnkob2JqZWN0cywgZnVuY3Rpb24obykgeyByZXR1cm4gby5uOyB9KTtcbiAgICAgKiAvLyA9PiAyMFxuICAgICAqXG4gICAgICogLy8gVGhlIGBfLnByb3BlcnR5YCBpdGVyYXRlZSBzaG9ydGhhbmQuXG4gICAgICogXy5zdW1CeShvYmplY3RzLCAnbicpO1xuICAgICAqIC8vID0+IDIwXG4gICAgICovXG4gICAgZnVuY3Rpb24gc3VtQnkoYXJyYXksIGl0ZXJhdGVlKSB7XG4gICAgICByZXR1cm4gKGFycmF5ICYmIGFycmF5Lmxlbmd0aClcbiAgICAgICAgPyBiYXNlU3VtKGFycmF5LCBnZXRJdGVyYXRlZShpdGVyYXRlZSwgMikpXG4gICAgICAgIDogMDtcbiAgICB9XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvLyBBZGQgbWV0aG9kcyB0aGF0IHJldHVybiB3cmFwcGVkIHZhbHVlcyBpbiBjaGFpbiBzZXF1ZW5jZXMuXG4gICAgbG9kYXNoLmFmdGVyID0gYWZ0ZXI7XG4gICAgbG9kYXNoLmFyeSA9IGFyeTtcbiAgICBsb2Rhc2guYXNzaWduID0gYXNzaWduO1xuICAgIGxvZGFzaC5hc3NpZ25JbiA9IGFzc2lnbkluO1xuICAgIGxvZGFzaC5hc3NpZ25JbldpdGggPSBhc3NpZ25JbldpdGg7XG4gICAgbG9kYXNoLmFzc2lnbldpdGggPSBhc3NpZ25XaXRoO1xuICAgIGxvZGFzaC5hdCA9IGF0O1xuICAgIGxvZGFzaC5iZWZvcmUgPSBiZWZvcmU7XG4gICAgbG9kYXNoLmJpbmQgPSBiaW5kO1xuICAgIGxvZGFzaC5iaW5kQWxsID0gYmluZEFsbDtcbiAgICBsb2Rhc2guYmluZEtleSA9IGJpbmRLZXk7XG4gICAgbG9kYXNoLmNhc3RBcnJheSA9IGNhc3RBcnJheTtcbiAgICBsb2Rhc2guY2hhaW4gPSBjaGFpbjtcbiAgICBsb2Rhc2guY2h1bmsgPSBjaHVuaztcbiAgICBsb2Rhc2guY29tcGFjdCA9IGNvbXBhY3Q7XG4gICAgbG9kYXNoLmNvbmNhdCA9IGNvbmNhdDtcbiAgICBsb2Rhc2guY29uZCA9IGNvbmQ7XG4gICAgbG9kYXNoLmNvbmZvcm1zID0gY29uZm9ybXM7XG4gICAgbG9kYXNoLmNvbnN0YW50ID0gY29uc3RhbnQ7XG4gICAgbG9kYXNoLmNvdW50QnkgPSBjb3VudEJ5O1xuICAgIGxvZGFzaC5jcmVhdGUgPSBjcmVhdGU7XG4gICAgbG9kYXNoLmN1cnJ5ID0gY3Vycnk7XG4gICAgbG9kYXNoLmN1cnJ5UmlnaHQgPSBjdXJyeVJpZ2h0O1xuICAgIGxvZGFzaC5kZWJvdW5jZSA9IGRlYm91bmNlO1xuICAgIGxvZGFzaC5kZWZhdWx0cyA9IGRlZmF1bHRzO1xuICAgIGxvZGFzaC5kZWZhdWx0c0RlZXAgPSBkZWZhdWx0c0RlZXA7XG4gICAgbG9kYXNoLmRlZmVyID0gZGVmZXI7XG4gICAgbG9kYXNoLmRlbGF5ID0gZGVsYXk7XG4gICAgbG9kYXNoLmRpZmZlcmVuY2UgPSBkaWZmZXJlbmNlO1xuICAgIGxvZGFzaC5kaWZmZXJlbmNlQnkgPSBkaWZmZXJlbmNlQnk7XG4gICAgbG9kYXNoLmRpZmZlcmVuY2VXaXRoID0gZGlmZmVyZW5jZVdpdGg7XG4gICAgbG9kYXNoLmRyb3AgPSBkcm9wO1xuICAgIGxvZGFzaC5kcm9wUmlnaHQgPSBkcm9wUmlnaHQ7XG4gICAgbG9kYXNoLmRyb3BSaWdodFdoaWxlID0gZHJvcFJpZ2h0V2hpbGU7XG4gICAgbG9kYXNoLmRyb3BXaGlsZSA9IGRyb3BXaGlsZTtcbiAgICBsb2Rhc2guZmlsbCA9IGZpbGw7XG4gICAgbG9kYXNoLmZpbHRlciA9IGZpbHRlcjtcbiAgICBsb2Rhc2guZmxhdE1hcCA9IGZsYXRNYXA7XG4gICAgbG9kYXNoLmZsYXRNYXBEZWVwID0gZmxhdE1hcERlZXA7XG4gICAgbG9kYXNoLmZsYXRNYXBEZXB0aCA9IGZsYXRNYXBEZXB0aDtcbiAgICBsb2Rhc2guZmxhdHRlbiA9IGZsYXR0ZW47XG4gICAgbG9kYXNoLmZsYXR0ZW5EZWVwID0gZmxhdHRlbkRlZXA7XG4gICAgbG9kYXNoLmZsYXR0ZW5EZXB0aCA9IGZsYXR0ZW5EZXB0aDtcbiAgICBsb2Rhc2guZmxpcCA9IGZsaXA7XG4gICAgbG9kYXNoLmZsb3cgPSBmbG93O1xuICAgIGxvZGFzaC5mbG93UmlnaHQgPSBmbG93UmlnaHQ7XG4gICAgbG9kYXNoLmZyb21QYWlycyA9IGZyb21QYWlycztcbiAgICBsb2Rhc2guZnVuY3Rpb25zID0gZnVuY3Rpb25zO1xuICAgIGxvZGFzaC5mdW5jdGlvbnNJbiA9IGZ1bmN0aW9uc0luO1xuICAgIGxvZGFzaC5ncm91cEJ5ID0gZ3JvdXBCeTtcbiAgICBsb2Rhc2guaW5pdGlhbCA9IGluaXRpYWw7XG4gICAgbG9kYXNoLmludGVyc2VjdGlvbiA9IGludGVyc2VjdGlvbjtcbiAgICBsb2Rhc2guaW50ZXJzZWN0aW9uQnkgPSBpbnRlcnNlY3Rpb25CeTtcbiAgICBsb2Rhc2guaW50ZXJzZWN0aW9uV2l0aCA9IGludGVyc2VjdGlvbldpdGg7XG4gICAgbG9kYXNoLmludmVydCA9IGludmVydDtcbiAgICBsb2Rhc2guaW52ZXJ0QnkgPSBpbnZlcnRCeTtcbiAgICBsb2Rhc2guaW52b2tlTWFwID0gaW52b2tlTWFwO1xuICAgIGxvZGFzaC5pdGVyYXRlZSA9IGl0ZXJhdGVlO1xuICAgIGxvZGFzaC5rZXlCeSA9IGtleUJ5O1xuICAgIGxvZGFzaC5rZXlzID0ga2V5cztcbiAgICBsb2Rhc2gua2V5c0luID0ga2V5c0luO1xuICAgIGxvZGFzaC5tYXAgPSBtYXA7XG4gICAgbG9kYXNoLm1hcEtleXMgPSBtYXBLZXlzO1xuICAgIGxvZGFzaC5tYXBWYWx1ZXMgPSBtYXBWYWx1ZXM7XG4gICAgbG9kYXNoLm1hdGNoZXMgPSBtYXRjaGVzO1xuICAgIGxvZGFzaC5tYXRjaGVzUHJvcGVydHkgPSBtYXRjaGVzUHJvcGVydHk7XG4gICAgbG9kYXNoLm1lbW9pemUgPSBtZW1vaXplO1xuICAgIGxvZGFzaC5tZXJnZSA9IG1lcmdlO1xuICAgIGxvZGFzaC5tZXJnZVdpdGggPSBtZXJnZVdpdGg7XG4gICAgbG9kYXNoLm1ldGhvZCA9IG1ldGhvZDtcbiAgICBsb2Rhc2gubWV0aG9kT2YgPSBtZXRob2RPZjtcbiAgICBsb2Rhc2gubWl4aW4gPSBtaXhpbjtcbiAgICBsb2Rhc2gubmVnYXRlID0gbmVnYXRlO1xuICAgIGxvZGFzaC5udGhBcmcgPSBudGhBcmc7XG4gICAgbG9kYXNoLm9taXQgPSBvbWl0O1xuICAgIGxvZGFzaC5vbWl0QnkgPSBvbWl0Qnk7XG4gICAgbG9kYXNoLm9uY2UgPSBvbmNlO1xuICAgIGxvZGFzaC5vcmRlckJ5ID0gb3JkZXJCeTtcbiAgICBsb2Rhc2gub3ZlciA9IG92ZXI7XG4gICAgbG9kYXNoLm92ZXJBcmdzID0gb3ZlckFyZ3M7XG4gICAgbG9kYXNoLm92ZXJFdmVyeSA9IG92ZXJFdmVyeTtcbiAgICBsb2Rhc2gub3ZlclNvbWUgPSBvdmVyU29tZTtcbiAgICBsb2Rhc2gucGFydGlhbCA9IHBhcnRpYWw7XG4gICAgbG9kYXNoLnBhcnRpYWxSaWdodCA9IHBhcnRpYWxSaWdodDtcbiAgICBsb2Rhc2gucGFydGl0aW9uID0gcGFydGl0aW9uO1xuICAgIGxvZGFzaC5waWNrID0gcGljaztcbiAgICBsb2Rhc2gucGlja0J5ID0gcGlja0J5O1xuICAgIGxvZGFzaC5wcm9wZXJ0eSA9IHByb3BlcnR5O1xuICAgIGxvZGFzaC5wcm9wZXJ0eU9mID0gcHJvcGVydHlPZjtcbiAgICBsb2Rhc2gucHVsbCA9IHB1bGw7XG4gICAgbG9kYXNoLnB1bGxBbGwgPSBwdWxsQWxsO1xuICAgIGxvZGFzaC5wdWxsQWxsQnkgPSBwdWxsQWxsQnk7XG4gICAgbG9kYXNoLnB1bGxBbGxXaXRoID0gcHVsbEFsbFdpdGg7XG4gICAgbG9kYXNoLnB1bGxBdCA9IHB1bGxBdDtcbiAgICBsb2Rhc2gucmFuZ2UgPSByYW5nZTtcbiAgICBsb2Rhc2gucmFuZ2VSaWdodCA9IHJhbmdlUmlnaHQ7XG4gICAgbG9kYXNoLnJlYXJnID0gcmVhcmc7XG4gICAgbG9kYXNoLnJlamVjdCA9IHJlamVjdDtcbiAgICBsb2Rhc2gucmVtb3ZlID0gcmVtb3ZlO1xuICAgIGxvZGFzaC5yZXN0ID0gcmVzdDtcbiAgICBsb2Rhc2gucmV2ZXJzZSA9IHJldmVyc2U7XG4gICAgbG9kYXNoLnNhbXBsZVNpemUgPSBzYW1wbGVTaXplO1xuICAgIGxvZGFzaC5zZXQgPSBzZXQ7XG4gICAgbG9kYXNoLnNldFdpdGggPSBzZXRXaXRoO1xuICAgIGxvZGFzaC5zaHVmZmxlID0gc2h1ZmZsZTtcbiAgICBsb2Rhc2guc2xpY2UgPSBzbGljZTtcbiAgICBsb2Rhc2guc29ydEJ5ID0gc29ydEJ5O1xuICAgIGxvZGFzaC5zb3J0ZWRVbmlxID0gc29ydGVkVW5pcTtcbiAgICBsb2Rhc2guc29ydGVkVW5pcUJ5ID0gc29ydGVkVW5pcUJ5O1xuICAgIGxvZGFzaC5zcGxpdCA9IHNwbGl0O1xuICAgIGxvZGFzaC5zcHJlYWQgPSBzcHJlYWQ7XG4gICAgbG9kYXNoLnRhaWwgPSB0YWlsO1xuICAgIGxvZGFzaC50YWtlID0gdGFrZTtcbiAgICBsb2Rhc2gudGFrZVJpZ2h0ID0gdGFrZVJpZ2h0O1xuICAgIGxvZGFzaC50YWtlUmlnaHRXaGlsZSA9IHRha2VSaWdodFdoaWxlO1xuICAgIGxvZGFzaC50YWtlV2hpbGUgPSB0YWtlV2hpbGU7XG4gICAgbG9kYXNoLnRhcCA9IHRhcDtcbiAgICBsb2Rhc2gudGhyb3R0bGUgPSB0aHJvdHRsZTtcbiAgICBsb2Rhc2gudGhydSA9IHRocnU7XG4gICAgbG9kYXNoLnRvQXJyYXkgPSB0b0FycmF5O1xuICAgIGxvZGFzaC50b1BhaXJzID0gdG9QYWlycztcbiAgICBsb2Rhc2gudG9QYWlyc0luID0gdG9QYWlyc0luO1xuICAgIGxvZGFzaC50b1BhdGggPSB0b1BhdGg7XG4gICAgbG9kYXNoLnRvUGxhaW5PYmplY3QgPSB0b1BsYWluT2JqZWN0O1xuICAgIGxvZGFzaC50cmFuc2Zvcm0gPSB0cmFuc2Zvcm07XG4gICAgbG9kYXNoLnVuYXJ5ID0gdW5hcnk7XG4gICAgbG9kYXNoLnVuaW9uID0gdW5pb247XG4gICAgbG9kYXNoLnVuaW9uQnkgPSB1bmlvbkJ5O1xuICAgIGxvZGFzaC51bmlvbldpdGggPSB1bmlvbldpdGg7XG4gICAgbG9kYXNoLnVuaXEgPSB1bmlxO1xuICAgIGxvZGFzaC51bmlxQnkgPSB1bmlxQnk7XG4gICAgbG9kYXNoLnVuaXFXaXRoID0gdW5pcVdpdGg7XG4gICAgbG9kYXNoLnVuc2V0ID0gdW5zZXQ7XG4gICAgbG9kYXNoLnVuemlwID0gdW56aXA7XG4gICAgbG9kYXNoLnVuemlwV2l0aCA9IHVuemlwV2l0aDtcbiAgICBsb2Rhc2gudXBkYXRlID0gdXBkYXRlO1xuICAgIGxvZGFzaC51cGRhdGVXaXRoID0gdXBkYXRlV2l0aDtcbiAgICBsb2Rhc2gudmFsdWVzID0gdmFsdWVzO1xuICAgIGxvZGFzaC52YWx1ZXNJbiA9IHZhbHVlc0luO1xuICAgIGxvZGFzaC53aXRob3V0ID0gd2l0aG91dDtcbiAgICBsb2Rhc2gud29yZHMgPSB3b3JkcztcbiAgICBsb2Rhc2gud3JhcCA9IHdyYXA7XG4gICAgbG9kYXNoLnhvciA9IHhvcjtcbiAgICBsb2Rhc2gueG9yQnkgPSB4b3JCeTtcbiAgICBsb2Rhc2gueG9yV2l0aCA9IHhvcldpdGg7XG4gICAgbG9kYXNoLnppcCA9IHppcDtcbiAgICBsb2Rhc2guemlwT2JqZWN0ID0gemlwT2JqZWN0O1xuICAgIGxvZGFzaC56aXBPYmplY3REZWVwID0gemlwT2JqZWN0RGVlcDtcbiAgICBsb2Rhc2guemlwV2l0aCA9IHppcFdpdGg7XG5cbiAgICAvLyBBZGQgYWxpYXNlcy5cbiAgICBsb2Rhc2guZW50cmllcyA9IHRvUGFpcnM7XG4gICAgbG9kYXNoLmVudHJpZXNJbiA9IHRvUGFpcnNJbjtcbiAgICBsb2Rhc2guZXh0ZW5kID0gYXNzaWduSW47XG4gICAgbG9kYXNoLmV4dGVuZFdpdGggPSBhc3NpZ25JbldpdGg7XG5cbiAgICAvLyBBZGQgbWV0aG9kcyB0byBgbG9kYXNoLnByb3RvdHlwZWAuXG4gICAgbWl4aW4obG9kYXNoLCBsb2Rhc2gpO1xuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgLy8gQWRkIG1ldGhvZHMgdGhhdCByZXR1cm4gdW53cmFwcGVkIHZhbHVlcyBpbiBjaGFpbiBzZXF1ZW5jZXMuXG4gICAgbG9kYXNoLmFkZCA9IGFkZDtcbiAgICBsb2Rhc2guYXR0ZW1wdCA9IGF0dGVtcHQ7XG4gICAgbG9kYXNoLmNhbWVsQ2FzZSA9IGNhbWVsQ2FzZTtcbiAgICBsb2Rhc2guY2FwaXRhbGl6ZSA9IGNhcGl0YWxpemU7XG4gICAgbG9kYXNoLmNlaWwgPSBjZWlsO1xuICAgIGxvZGFzaC5jbGFtcCA9IGNsYW1wO1xuICAgIGxvZGFzaC5jbG9uZSA9IGNsb25lO1xuICAgIGxvZGFzaC5jbG9uZURlZXAgPSBjbG9uZURlZXA7XG4gICAgbG9kYXNoLmNsb25lRGVlcFdpdGggPSBjbG9uZURlZXBXaXRoO1xuICAgIGxvZGFzaC5jbG9uZVdpdGggPSBjbG9uZVdpdGg7XG4gICAgbG9kYXNoLmNvbmZvcm1zVG8gPSBjb25mb3Jtc1RvO1xuICAgIGxvZGFzaC5kZWJ1cnIgPSBkZWJ1cnI7XG4gICAgbG9kYXNoLmRlZmF1bHRUbyA9IGRlZmF1bHRUbztcbiAgICBsb2Rhc2guZGl2aWRlID0gZGl2aWRlO1xuICAgIGxvZGFzaC5lbmRzV2l0aCA9IGVuZHNXaXRoO1xuICAgIGxvZGFzaC5lcSA9IGVxO1xuICAgIGxvZGFzaC5lc2NhcGUgPSBlc2NhcGU7XG4gICAgbG9kYXNoLmVzY2FwZVJlZ0V4cCA9IGVzY2FwZVJlZ0V4cDtcbiAgICBsb2Rhc2guZXZlcnkgPSBldmVyeTtcbiAgICBsb2Rhc2guZmluZCA9IGZpbmQ7XG4gICAgbG9kYXNoLmZpbmRJbmRleCA9IGZpbmRJbmRleDtcbiAgICBsb2Rhc2guZmluZEtleSA9IGZpbmRLZXk7XG4gICAgbG9kYXNoLmZpbmRMYXN0ID0gZmluZExhc3Q7XG4gICAgbG9kYXNoLmZpbmRMYXN0SW5kZXggPSBmaW5kTGFzdEluZGV4O1xuICAgIGxvZGFzaC5maW5kTGFzdEtleSA9IGZpbmRMYXN0S2V5O1xuICAgIGxvZGFzaC5mbG9vciA9IGZsb29yO1xuICAgIGxvZGFzaC5mb3JFYWNoID0gZm9yRWFjaDtcbiAgICBsb2Rhc2guZm9yRWFjaFJpZ2h0ID0gZm9yRWFjaFJpZ2h0O1xuICAgIGxvZGFzaC5mb3JJbiA9IGZvckluO1xuICAgIGxvZGFzaC5mb3JJblJpZ2h0ID0gZm9ySW5SaWdodDtcbiAgICBsb2Rhc2guZm9yT3duID0gZm9yT3duO1xuICAgIGxvZGFzaC5mb3JPd25SaWdodCA9IGZvck93blJpZ2h0O1xuICAgIGxvZGFzaC5nZXQgPSBnZXQ7XG4gICAgbG9kYXNoLmd0ID0gZ3Q7XG4gICAgbG9kYXNoLmd0ZSA9IGd0ZTtcbiAgICBsb2Rhc2guaGFzID0gaGFzO1xuICAgIGxvZGFzaC5oYXNJbiA9IGhhc0luO1xuICAgIGxvZGFzaC5oZWFkID0gaGVhZDtcbiAgICBsb2Rhc2guaWRlbnRpdHkgPSBpZGVudGl0eTtcbiAgICBsb2Rhc2guaW5jbHVkZXMgPSBpbmNsdWRlcztcbiAgICBsb2Rhc2guaW5kZXhPZiA9IGluZGV4T2Y7XG4gICAgbG9kYXNoLmluUmFuZ2UgPSBpblJhbmdlO1xuICAgIGxvZGFzaC5pbnZva2UgPSBpbnZva2U7XG4gICAgbG9kYXNoLmlzQXJndW1lbnRzID0gaXNBcmd1bWVudHM7XG4gICAgbG9kYXNoLmlzQXJyYXkgPSBpc0FycmF5O1xuICAgIGxvZGFzaC5pc0FycmF5QnVmZmVyID0gaXNBcnJheUJ1ZmZlcjtcbiAgICBsb2Rhc2guaXNBcnJheUxpa2UgPSBpc0FycmF5TGlrZTtcbiAgICBsb2Rhc2guaXNBcnJheUxpa2VPYmplY3QgPSBpc0FycmF5TGlrZU9iamVjdDtcbiAgICBsb2Rhc2guaXNCb29sZWFuID0gaXNCb29sZWFuO1xuICAgIGxvZGFzaC5pc0J1ZmZlciA9IGlzQnVmZmVyO1xuICAgIGxvZGFzaC5pc0RhdGUgPSBpc0RhdGU7XG4gICAgbG9kYXNoLmlzRWxlbWVudCA9IGlzRWxlbWVudDtcbiAgICBsb2Rhc2guaXNFbXB0eSA9IGlzRW1wdHk7XG4gICAgbG9kYXNoLmlzRXF1YWwgPSBpc0VxdWFsO1xuICAgIGxvZGFzaC5pc0VxdWFsV2l0aCA9IGlzRXF1YWxXaXRoO1xuICAgIGxvZGFzaC5pc0Vycm9yID0gaXNFcnJvcjtcbiAgICBsb2Rhc2guaXNGaW5pdGUgPSBpc0Zpbml0ZTtcbiAgICBsb2Rhc2guaXNGdW5jdGlvbiA9IGlzRnVuY3Rpb247XG4gICAgbG9kYXNoLmlzSW50ZWdlciA9IGlzSW50ZWdlcjtcbiAgICBsb2Rhc2guaXNMZW5ndGggPSBpc0xlbmd0aDtcbiAgICBsb2Rhc2guaXNNYXAgPSBpc01hcDtcbiAgICBsb2Rhc2guaXNNYXRjaCA9IGlzTWF0Y2g7XG4gICAgbG9kYXNoLmlzTWF0Y2hXaXRoID0gaXNNYXRjaFdpdGg7XG4gICAgbG9kYXNoLmlzTmFOID0gaXNOYU47XG4gICAgbG9kYXNoLmlzTmF0aXZlID0gaXNOYXRpdmU7XG4gICAgbG9kYXNoLmlzTmlsID0gaXNOaWw7XG4gICAgbG9kYXNoLmlzTnVsbCA9IGlzTnVsbDtcbiAgICBsb2Rhc2guaXNOdW1iZXIgPSBpc051bWJlcjtcbiAgICBsb2Rhc2guaXNPYmplY3QgPSBpc09iamVjdDtcbiAgICBsb2Rhc2guaXNPYmplY3RMaWtlID0gaXNPYmplY3RMaWtlO1xuICAgIGxvZGFzaC5pc1BsYWluT2JqZWN0ID0gaXNQbGFpbk9iamVjdDtcbiAgICBsb2Rhc2guaXNSZWdFeHAgPSBpc1JlZ0V4cDtcbiAgICBsb2Rhc2guaXNTYWZlSW50ZWdlciA9IGlzU2FmZUludGVnZXI7XG4gICAgbG9kYXNoLmlzU2V0ID0gaXNTZXQ7XG4gICAgbG9kYXNoLmlzU3RyaW5nID0gaXNTdHJpbmc7XG4gICAgbG9kYXNoLmlzU3ltYm9sID0gaXNTeW1ib2w7XG4gICAgbG9kYXNoLmlzVHlwZWRBcnJheSA9IGlzVHlwZWRBcnJheTtcbiAgICBsb2Rhc2guaXNVbmRlZmluZWQgPSBpc1VuZGVmaW5lZDtcbiAgICBsb2Rhc2guaXNXZWFrTWFwID0gaXNXZWFrTWFwO1xuICAgIGxvZGFzaC5pc1dlYWtTZXQgPSBpc1dlYWtTZXQ7XG4gICAgbG9kYXNoLmpvaW4gPSBqb2luO1xuICAgIGxvZGFzaC5rZWJhYkNhc2UgPSBrZWJhYkNhc2U7XG4gICAgbG9kYXNoLmxhc3QgPSBsYXN0O1xuICAgIGxvZGFzaC5sYXN0SW5kZXhPZiA9IGxhc3RJbmRleE9mO1xuICAgIGxvZGFzaC5sb3dlckNhc2UgPSBsb3dlckNhc2U7XG4gICAgbG9kYXNoLmxvd2VyRmlyc3QgPSBsb3dlckZpcnN0O1xuICAgIGxvZGFzaC5sdCA9IGx0O1xuICAgIGxvZGFzaC5sdGUgPSBsdGU7XG4gICAgbG9kYXNoLm1heCA9IG1heDtcbiAgICBsb2Rhc2gubWF4QnkgPSBtYXhCeTtcbiAgICBsb2Rhc2gubWVhbiA9IG1lYW47XG4gICAgbG9kYXNoLm1lYW5CeSA9IG1lYW5CeTtcbiAgICBsb2Rhc2gubWluID0gbWluO1xuICAgIGxvZGFzaC5taW5CeSA9IG1pbkJ5O1xuICAgIGxvZGFzaC5zdHViQXJyYXkgPSBzdHViQXJyYXk7XG4gICAgbG9kYXNoLnN0dWJGYWxzZSA9IHN0dWJGYWxzZTtcbiAgICBsb2Rhc2guc3R1Yk9iamVjdCA9IHN0dWJPYmplY3Q7XG4gICAgbG9kYXNoLnN0dWJTdHJpbmcgPSBzdHViU3RyaW5nO1xuICAgIGxvZGFzaC5zdHViVHJ1ZSA9IHN0dWJUcnVlO1xuICAgIGxvZGFzaC5tdWx0aXBseSA9IG11bHRpcGx5O1xuICAgIGxvZGFzaC5udGggPSBudGg7XG4gICAgbG9kYXNoLm5vQ29uZmxpY3QgPSBub0NvbmZsaWN0O1xuICAgIGxvZGFzaC5ub29wID0gbm9vcDtcbiAgICBsb2Rhc2gubm93ID0gbm93O1xuICAgIGxvZGFzaC5wYWQgPSBwYWQ7XG4gICAgbG9kYXNoLnBhZEVuZCA9IHBhZEVuZDtcbiAgICBsb2Rhc2gucGFkU3RhcnQgPSBwYWRTdGFydDtcbiAgICBsb2Rhc2gucGFyc2VJbnQgPSBwYXJzZUludDtcbiAgICBsb2Rhc2gucmFuZG9tID0gcmFuZG9tO1xuICAgIGxvZGFzaC5yZWR1Y2UgPSByZWR1Y2U7XG4gICAgbG9kYXNoLnJlZHVjZVJpZ2h0ID0gcmVkdWNlUmlnaHQ7XG4gICAgbG9kYXNoLnJlcGVhdCA9IHJlcGVhdDtcbiAgICBsb2Rhc2gucmVwbGFjZSA9IHJlcGxhY2U7XG4gICAgbG9kYXNoLnJlc3VsdCA9IHJlc3VsdDtcbiAgICBsb2Rhc2gucm91bmQgPSByb3VuZDtcbiAgICBsb2Rhc2gucnVuSW5Db250ZXh0ID0gcnVuSW5Db250ZXh0O1xuICAgIGxvZGFzaC5zYW1wbGUgPSBzYW1wbGU7XG4gICAgbG9kYXNoLnNpemUgPSBzaXplO1xuICAgIGxvZGFzaC5zbmFrZUNhc2UgPSBzbmFrZUNhc2U7XG4gICAgbG9kYXNoLnNvbWUgPSBzb21lO1xuICAgIGxvZGFzaC5zb3J0ZWRJbmRleCA9IHNvcnRlZEluZGV4O1xuICAgIGxvZGFzaC5zb3J0ZWRJbmRleEJ5ID0gc29ydGVkSW5kZXhCeTtcbiAgICBsb2Rhc2guc29ydGVkSW5kZXhPZiA9IHNvcnRlZEluZGV4T2Y7XG4gICAgbG9kYXNoLnNvcnRlZExhc3RJbmRleCA9IHNvcnRlZExhc3RJbmRleDtcbiAgICBsb2Rhc2guc29ydGVkTGFzdEluZGV4QnkgPSBzb3J0ZWRMYXN0SW5kZXhCeTtcbiAgICBsb2Rhc2guc29ydGVkTGFzdEluZGV4T2YgPSBzb3J0ZWRMYXN0SW5kZXhPZjtcbiAgICBsb2Rhc2guc3RhcnRDYXNlID0gc3RhcnRDYXNlO1xuICAgIGxvZGFzaC5zdGFydHNXaXRoID0gc3RhcnRzV2l0aDtcbiAgICBsb2Rhc2guc3VidHJhY3QgPSBzdWJ0cmFjdDtcbiAgICBsb2Rhc2guc3VtID0gc3VtO1xuICAgIGxvZGFzaC5zdW1CeSA9IHN1bUJ5O1xuICAgIGxvZGFzaC50ZW1wbGF0ZSA9IHRlbXBsYXRlO1xuICAgIGxvZGFzaC50aW1lcyA9IHRpbWVzO1xuICAgIGxvZGFzaC50b0Zpbml0ZSA9IHRvRmluaXRlO1xuICAgIGxvZGFzaC50b0ludGVnZXIgPSB0b0ludGVnZXI7XG4gICAgbG9kYXNoLnRvTGVuZ3RoID0gdG9MZW5ndGg7XG4gICAgbG9kYXNoLnRvTG93ZXIgPSB0b0xvd2VyO1xuICAgIGxvZGFzaC50b051bWJlciA9IHRvTnVtYmVyO1xuICAgIGxvZGFzaC50b1NhZmVJbnRlZ2VyID0gdG9TYWZlSW50ZWdlcjtcbiAgICBsb2Rhc2gudG9TdHJpbmcgPSB0b1N0cmluZztcbiAgICBsb2Rhc2gudG9VcHBlciA9IHRvVXBwZXI7XG4gICAgbG9kYXNoLnRyaW0gPSB0cmltO1xuICAgIGxvZGFzaC50cmltRW5kID0gdHJpbUVuZDtcbiAgICBsb2Rhc2gudHJpbVN0YXJ0ID0gdHJpbVN0YXJ0O1xuICAgIGxvZGFzaC50cnVuY2F0ZSA9IHRydW5jYXRlO1xuICAgIGxvZGFzaC51bmVzY2FwZSA9IHVuZXNjYXBlO1xuICAgIGxvZGFzaC51bmlxdWVJZCA9IHVuaXF1ZUlkO1xuICAgIGxvZGFzaC51cHBlckNhc2UgPSB1cHBlckNhc2U7XG4gICAgbG9kYXNoLnVwcGVyRmlyc3QgPSB1cHBlckZpcnN0O1xuXG4gICAgLy8gQWRkIGFsaWFzZXMuXG4gICAgbG9kYXNoLmVhY2ggPSBmb3JFYWNoO1xuICAgIGxvZGFzaC5lYWNoUmlnaHQgPSBmb3JFYWNoUmlnaHQ7XG4gICAgbG9kYXNoLmZpcnN0ID0gaGVhZDtcblxuICAgIG1peGluKGxvZGFzaCwgKGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHNvdXJjZSA9IHt9O1xuICAgICAgYmFzZUZvck93bihsb2Rhc2gsIGZ1bmN0aW9uKGZ1bmMsIG1ldGhvZE5hbWUpIHtcbiAgICAgICAgaWYgKCFoYXNPd25Qcm9wZXJ0eS5jYWxsKGxvZGFzaC5wcm90b3R5cGUsIG1ldGhvZE5hbWUpKSB7XG4gICAgICAgICAgc291cmNlW21ldGhvZE5hbWVdID0gZnVuYztcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gc291cmNlO1xuICAgIH0oKSksIHsgJ2NoYWluJzogZmFsc2UgfSk7XG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICAvKipcbiAgICAgKiBUaGUgc2VtYW50aWMgdmVyc2lvbiBudW1iZXIuXG4gICAgICpcbiAgICAgKiBAc3RhdGljXG4gICAgICogQG1lbWJlck9mIF9cbiAgICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgICAqL1xuICAgIGxvZGFzaC5WRVJTSU9OID0gVkVSU0lPTjtcblxuICAgIC8vIEFzc2lnbiBkZWZhdWx0IHBsYWNlaG9sZGVycy5cbiAgICBhcnJheUVhY2goWydiaW5kJywgJ2JpbmRLZXknLCAnY3VycnknLCAnY3VycnlSaWdodCcsICdwYXJ0aWFsJywgJ3BhcnRpYWxSaWdodCddLCBmdW5jdGlvbihtZXRob2ROYW1lKSB7XG4gICAgICBsb2Rhc2hbbWV0aG9kTmFtZV0ucGxhY2Vob2xkZXIgPSBsb2Rhc2g7XG4gICAgfSk7XG5cbiAgICAvLyBBZGQgYExhenlXcmFwcGVyYCBtZXRob2RzIGZvciBgXy5kcm9wYCBhbmQgYF8udGFrZWAgdmFyaWFudHMuXG4gICAgYXJyYXlFYWNoKFsnZHJvcCcsICd0YWtlJ10sIGZ1bmN0aW9uKG1ldGhvZE5hbWUsIGluZGV4KSB7XG4gICAgICBMYXp5V3JhcHBlci5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbihuKSB7XG4gICAgICAgIG4gPSBuID09PSB1bmRlZmluZWQgPyAxIDogbmF0aXZlTWF4KHRvSW50ZWdlcihuKSwgMCk7XG5cbiAgICAgICAgdmFyIHJlc3VsdCA9ICh0aGlzLl9fZmlsdGVyZWRfXyAmJiAhaW5kZXgpXG4gICAgICAgICAgPyBuZXcgTGF6eVdyYXBwZXIodGhpcylcbiAgICAgICAgICA6IHRoaXMuY2xvbmUoKTtcblxuICAgICAgICBpZiAocmVzdWx0Ll9fZmlsdGVyZWRfXykge1xuICAgICAgICAgIHJlc3VsdC5fX3Rha2VDb3VudF9fID0gbmF0aXZlTWluKG4sIHJlc3VsdC5fX3Rha2VDb3VudF9fKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXN1bHQuX192aWV3c19fLnB1c2goe1xuICAgICAgICAgICAgJ3NpemUnOiBuYXRpdmVNaW4obiwgTUFYX0FSUkFZX0xFTkdUSCksXG4gICAgICAgICAgICAndHlwZSc6IG1ldGhvZE5hbWUgKyAocmVzdWx0Ll9fZGlyX18gPCAwID8gJ1JpZ2h0JyA6ICcnKVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9O1xuXG4gICAgICBMYXp5V3JhcHBlci5wcm90b3R5cGVbbWV0aG9kTmFtZSArICdSaWdodCddID0gZnVuY3Rpb24obikge1xuICAgICAgICByZXR1cm4gdGhpcy5yZXZlcnNlKClbbWV0aG9kTmFtZV0obikucmV2ZXJzZSgpO1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIEFkZCBgTGF6eVdyYXBwZXJgIG1ldGhvZHMgdGhhdCBhY2NlcHQgYW4gYGl0ZXJhdGVlYCB2YWx1ZS5cbiAgICBhcnJheUVhY2goWydmaWx0ZXInLCAnbWFwJywgJ3Rha2VXaGlsZSddLCBmdW5jdGlvbihtZXRob2ROYW1lLCBpbmRleCkge1xuICAgICAgdmFyIHR5cGUgPSBpbmRleCArIDEsXG4gICAgICAgICAgaXNGaWx0ZXIgPSB0eXBlID09IExBWllfRklMVEVSX0ZMQUcgfHwgdHlwZSA9PSBMQVpZX1dISUxFX0ZMQUc7XG5cbiAgICAgIExhenlXcmFwcGVyLnByb3RvdHlwZVttZXRob2ROYW1lXSA9IGZ1bmN0aW9uKGl0ZXJhdGVlKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSB0aGlzLmNsb25lKCk7XG4gICAgICAgIHJlc3VsdC5fX2l0ZXJhdGVlc19fLnB1c2goe1xuICAgICAgICAgICdpdGVyYXRlZSc6IGdldEl0ZXJhdGVlKGl0ZXJhdGVlLCAzKSxcbiAgICAgICAgICAndHlwZSc6IHR5cGVcbiAgICAgICAgfSk7XG4gICAgICAgIHJlc3VsdC5fX2ZpbHRlcmVkX18gPSByZXN1bHQuX19maWx0ZXJlZF9fIHx8IGlzRmlsdGVyO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIEFkZCBgTGF6eVdyYXBwZXJgIG1ldGhvZHMgZm9yIGBfLmhlYWRgIGFuZCBgXy5sYXN0YC5cbiAgICBhcnJheUVhY2goWydoZWFkJywgJ2xhc3QnXSwgZnVuY3Rpb24obWV0aG9kTmFtZSwgaW5kZXgpIHtcbiAgICAgIHZhciB0YWtlTmFtZSA9ICd0YWtlJyArIChpbmRleCA/ICdSaWdodCcgOiAnJyk7XG5cbiAgICAgIExhenlXcmFwcGVyLnByb3RvdHlwZVttZXRob2ROYW1lXSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpc1t0YWtlTmFtZV0oMSkudmFsdWUoKVswXTtcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICAvLyBBZGQgYExhenlXcmFwcGVyYCBtZXRob2RzIGZvciBgXy5pbml0aWFsYCBhbmQgYF8udGFpbGAuXG4gICAgYXJyYXlFYWNoKFsnaW5pdGlhbCcsICd0YWlsJ10sIGZ1bmN0aW9uKG1ldGhvZE5hbWUsIGluZGV4KSB7XG4gICAgICB2YXIgZHJvcE5hbWUgPSAnZHJvcCcgKyAoaW5kZXggPyAnJyA6ICdSaWdodCcpO1xuXG4gICAgICBMYXp5V3JhcHBlci5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX19maWx0ZXJlZF9fID8gbmV3IExhenlXcmFwcGVyKHRoaXMpIDogdGhpc1tkcm9wTmFtZV0oMSk7XG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlLmNvbXBhY3QgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLmZpbHRlcihpZGVudGl0eSk7XG4gICAgfTtcblxuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS5maW5kID0gZnVuY3Rpb24ocHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gdGhpcy5maWx0ZXIocHJlZGljYXRlKS5oZWFkKCk7XG4gICAgfTtcblxuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS5maW5kTGFzdCA9IGZ1bmN0aW9uKHByZWRpY2F0ZSkge1xuICAgICAgcmV0dXJuIHRoaXMucmV2ZXJzZSgpLmZpbmQocHJlZGljYXRlKTtcbiAgICB9O1xuXG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlLmludm9rZU1hcCA9IGJhc2VSZXN0KGZ1bmN0aW9uKHBhdGgsIGFyZ3MpIHtcbiAgICAgIGlmICh0eXBlb2YgcGF0aCA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBuZXcgTGF6eVdyYXBwZXIodGhpcyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5tYXAoZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIGJhc2VJbnZva2UodmFsdWUsIHBhdGgsIGFyZ3MpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBMYXp5V3JhcHBlci5wcm90b3R5cGUucmVqZWN0ID0gZnVuY3Rpb24ocHJlZGljYXRlKSB7XG4gICAgICByZXR1cm4gdGhpcy5maWx0ZXIobmVnYXRlKGdldEl0ZXJhdGVlKHByZWRpY2F0ZSkpKTtcbiAgICB9O1xuXG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlLnNsaWNlID0gZnVuY3Rpb24oc3RhcnQsIGVuZCkge1xuICAgICAgc3RhcnQgPSB0b0ludGVnZXIoc3RhcnQpO1xuXG4gICAgICB2YXIgcmVzdWx0ID0gdGhpcztcbiAgICAgIGlmIChyZXN1bHQuX19maWx0ZXJlZF9fICYmIChzdGFydCA+IDAgfHwgZW5kIDwgMCkpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBMYXp5V3JhcHBlcihyZXN1bHQpO1xuICAgICAgfVxuICAgICAgaWYgKHN0YXJ0IDwgMCkge1xuICAgICAgICByZXN1bHQgPSByZXN1bHQudGFrZVJpZ2h0KC1zdGFydCk7XG4gICAgICB9IGVsc2UgaWYgKHN0YXJ0KSB7XG4gICAgICAgIHJlc3VsdCA9IHJlc3VsdC5kcm9wKHN0YXJ0KTtcbiAgICAgIH1cbiAgICAgIGlmIChlbmQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBlbmQgPSB0b0ludGVnZXIoZW5kKTtcbiAgICAgICAgcmVzdWx0ID0gZW5kIDwgMCA/IHJlc3VsdC5kcm9wUmlnaHQoLWVuZCkgOiByZXN1bHQudGFrZShlbmQgLSBzdGFydCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG5cbiAgICBMYXp5V3JhcHBlci5wcm90b3R5cGUudGFrZVJpZ2h0V2hpbGUgPSBmdW5jdGlvbihwcmVkaWNhdGUpIHtcbiAgICAgIHJldHVybiB0aGlzLnJldmVyc2UoKS50YWtlV2hpbGUocHJlZGljYXRlKS5yZXZlcnNlKCk7XG4gICAgfTtcblxuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS50b0FycmF5ID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy50YWtlKE1BWF9BUlJBWV9MRU5HVEgpO1xuICAgIH07XG5cbiAgICAvLyBBZGQgYExhenlXcmFwcGVyYCBtZXRob2RzIHRvIGBsb2Rhc2gucHJvdG90eXBlYC5cbiAgICBiYXNlRm9yT3duKExhenlXcmFwcGVyLnByb3RvdHlwZSwgZnVuY3Rpb24oZnVuYywgbWV0aG9kTmFtZSkge1xuICAgICAgdmFyIGNoZWNrSXRlcmF0ZWUgPSAvXig/OmZpbHRlcnxmaW5kfG1hcHxyZWplY3QpfFdoaWxlJC8udGVzdChtZXRob2ROYW1lKSxcbiAgICAgICAgICBpc1Rha2VyID0gL14oPzpoZWFkfGxhc3QpJC8udGVzdChtZXRob2ROYW1lKSxcbiAgICAgICAgICBsb2Rhc2hGdW5jID0gbG9kYXNoW2lzVGFrZXIgPyAoJ3Rha2UnICsgKG1ldGhvZE5hbWUgPT0gJ2xhc3QnID8gJ1JpZ2h0JyA6ICcnKSkgOiBtZXRob2ROYW1lXSxcbiAgICAgICAgICByZXRVbndyYXBwZWQgPSBpc1Rha2VyIHx8IC9eZmluZC8udGVzdChtZXRob2ROYW1lKTtcblxuICAgICAgaWYgKCFsb2Rhc2hGdW5jKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGxvZGFzaC5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gdGhpcy5fX3dyYXBwZWRfXyxcbiAgICAgICAgICAgIGFyZ3MgPSBpc1Rha2VyID8gWzFdIDogYXJndW1lbnRzLFxuICAgICAgICAgICAgaXNMYXp5ID0gdmFsdWUgaW5zdGFuY2VvZiBMYXp5V3JhcHBlcixcbiAgICAgICAgICAgIGl0ZXJhdGVlID0gYXJnc1swXSxcbiAgICAgICAgICAgIHVzZUxhenkgPSBpc0xhenkgfHwgaXNBcnJheSh2YWx1ZSk7XG5cbiAgICAgICAgdmFyIGludGVyY2VwdG9yID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgICB2YXIgcmVzdWx0ID0gbG9kYXNoRnVuYy5hcHBseShsb2Rhc2gsIGFycmF5UHVzaChbdmFsdWVdLCBhcmdzKSk7XG4gICAgICAgICAgcmV0dXJuIChpc1Rha2VyICYmIGNoYWluQWxsKSA/IHJlc3VsdFswXSA6IHJlc3VsdDtcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAodXNlTGF6eSAmJiBjaGVja0l0ZXJhdGVlICYmIHR5cGVvZiBpdGVyYXRlZSA9PSAnZnVuY3Rpb24nICYmIGl0ZXJhdGVlLmxlbmd0aCAhPSAxKSB7XG4gICAgICAgICAgLy8gQXZvaWQgbGF6eSB1c2UgaWYgdGhlIGl0ZXJhdGVlIGhhcyBhIFwibGVuZ3RoXCIgdmFsdWUgb3RoZXIgdGhhbiBgMWAuXG4gICAgICAgICAgaXNMYXp5ID0gdXNlTGF6eSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjaGFpbkFsbCA9IHRoaXMuX19jaGFpbl9fLFxuICAgICAgICAgICAgaXNIeWJyaWQgPSAhIXRoaXMuX19hY3Rpb25zX18ubGVuZ3RoLFxuICAgICAgICAgICAgaXNVbndyYXBwZWQgPSByZXRVbndyYXBwZWQgJiYgIWNoYWluQWxsLFxuICAgICAgICAgICAgb25seUxhenkgPSBpc0xhenkgJiYgIWlzSHlicmlkO1xuXG4gICAgICAgIGlmICghcmV0VW53cmFwcGVkICYmIHVzZUxhenkpIHtcbiAgICAgICAgICB2YWx1ZSA9IG9ubHlMYXp5ID8gdmFsdWUgOiBuZXcgTGF6eVdyYXBwZXIodGhpcyk7XG4gICAgICAgICAgdmFyIHJlc3VsdCA9IGZ1bmMuYXBwbHkodmFsdWUsIGFyZ3MpO1xuICAgICAgICAgIHJlc3VsdC5fX2FjdGlvbnNfXy5wdXNoKHsgJ2Z1bmMnOiB0aHJ1LCAnYXJncyc6IFtpbnRlcmNlcHRvcl0sICd0aGlzQXJnJzogdW5kZWZpbmVkIH0pO1xuICAgICAgICAgIHJldHVybiBuZXcgTG9kYXNoV3JhcHBlcihyZXN1bHQsIGNoYWluQWxsKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNVbndyYXBwZWQgJiYgb25seUxhenkpIHtcbiAgICAgICAgICByZXR1cm4gZnVuYy5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgfVxuICAgICAgICByZXN1bHQgPSB0aGlzLnRocnUoaW50ZXJjZXB0b3IpO1xuICAgICAgICByZXR1cm4gaXNVbndyYXBwZWQgPyAoaXNUYWtlciA/IHJlc3VsdC52YWx1ZSgpWzBdIDogcmVzdWx0LnZhbHVlKCkpIDogcmVzdWx0O1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIEFkZCBgQXJyYXlgIG1ldGhvZHMgdG8gYGxvZGFzaC5wcm90b3R5cGVgLlxuICAgIGFycmF5RWFjaChbJ3BvcCcsICdwdXNoJywgJ3NoaWZ0JywgJ3NvcnQnLCAnc3BsaWNlJywgJ3Vuc2hpZnQnXSwgZnVuY3Rpb24obWV0aG9kTmFtZSkge1xuICAgICAgdmFyIGZ1bmMgPSBhcnJheVByb3RvW21ldGhvZE5hbWVdLFxuICAgICAgICAgIGNoYWluTmFtZSA9IC9eKD86cHVzaHxzb3J0fHVuc2hpZnQpJC8udGVzdChtZXRob2ROYW1lKSA/ICd0YXAnIDogJ3RocnUnLFxuICAgICAgICAgIHJldFVud3JhcHBlZCA9IC9eKD86cG9wfHNoaWZ0KSQvLnRlc3QobWV0aG9kTmFtZSk7XG5cbiAgICAgIGxvZGFzaC5wcm90b3R5cGVbbWV0aG9kTmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgIGlmIChyZXRVbndyYXBwZWQgJiYgIXRoaXMuX19jaGFpbl9fKSB7XG4gICAgICAgICAgdmFyIHZhbHVlID0gdGhpcy52YWx1ZSgpO1xuICAgICAgICAgIHJldHVybiBmdW5jLmFwcGx5KGlzQXJyYXkodmFsdWUpID8gdmFsdWUgOiBbXSwgYXJncyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXNbY2hhaW5OYW1lXShmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgICAgIHJldHVybiBmdW5jLmFwcGx5KGlzQXJyYXkodmFsdWUpID8gdmFsdWUgOiBbXSwgYXJncyk7XG4gICAgICAgIH0pO1xuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIE1hcCBtaW5pZmllZCBtZXRob2QgbmFtZXMgdG8gdGhlaXIgcmVhbCBuYW1lcy5cbiAgICBiYXNlRm9yT3duKExhenlXcmFwcGVyLnByb3RvdHlwZSwgZnVuY3Rpb24oZnVuYywgbWV0aG9kTmFtZSkge1xuICAgICAgdmFyIGxvZGFzaEZ1bmMgPSBsb2Rhc2hbbWV0aG9kTmFtZV07XG4gICAgICBpZiAobG9kYXNoRnVuYykge1xuICAgICAgICB2YXIga2V5ID0gKGxvZGFzaEZ1bmMubmFtZSArICcnKSxcbiAgICAgICAgICAgIG5hbWVzID0gcmVhbE5hbWVzW2tleV0gfHwgKHJlYWxOYW1lc1trZXldID0gW10pO1xuXG4gICAgICAgIG5hbWVzLnB1c2goeyAnbmFtZSc6IG1ldGhvZE5hbWUsICdmdW5jJzogbG9kYXNoRnVuYyB9KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJlYWxOYW1lc1tjcmVhdGVIeWJyaWQodW5kZWZpbmVkLCBXUkFQX0JJTkRfS0VZX0ZMQUcpLm5hbWVdID0gW3tcbiAgICAgICduYW1lJzogJ3dyYXBwZXInLFxuICAgICAgJ2Z1bmMnOiB1bmRlZmluZWRcbiAgICB9XTtcblxuICAgIC8vIEFkZCBtZXRob2RzIHRvIGBMYXp5V3JhcHBlcmAuXG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlLmNsb25lID0gbGF6eUNsb25lO1xuICAgIExhenlXcmFwcGVyLnByb3RvdHlwZS5yZXZlcnNlID0gbGF6eVJldmVyc2U7XG4gICAgTGF6eVdyYXBwZXIucHJvdG90eXBlLnZhbHVlID0gbGF6eVZhbHVlO1xuXG4gICAgLy8gQWRkIGNoYWluIHNlcXVlbmNlIG1ldGhvZHMgdG8gdGhlIGBsb2Rhc2hgIHdyYXBwZXIuXG4gICAgbG9kYXNoLnByb3RvdHlwZS5hdCA9IHdyYXBwZXJBdDtcbiAgICBsb2Rhc2gucHJvdG90eXBlLmNoYWluID0gd3JhcHBlckNoYWluO1xuICAgIGxvZGFzaC5wcm90b3R5cGUuY29tbWl0ID0gd3JhcHBlckNvbW1pdDtcbiAgICBsb2Rhc2gucHJvdG90eXBlLm5leHQgPSB3cmFwcGVyTmV4dDtcbiAgICBsb2Rhc2gucHJvdG90eXBlLnBsYW50ID0gd3JhcHBlclBsYW50O1xuICAgIGxvZGFzaC5wcm90b3R5cGUucmV2ZXJzZSA9IHdyYXBwZXJSZXZlcnNlO1xuICAgIGxvZGFzaC5wcm90b3R5cGUudG9KU09OID0gbG9kYXNoLnByb3RvdHlwZS52YWx1ZU9mID0gbG9kYXNoLnByb3RvdHlwZS52YWx1ZSA9IHdyYXBwZXJWYWx1ZTtcblxuICAgIC8vIEFkZCBsYXp5IGFsaWFzZXMuXG4gICAgbG9kYXNoLnByb3RvdHlwZS5maXJzdCA9IGxvZGFzaC5wcm90b3R5cGUuaGVhZDtcblxuICAgIGlmIChzeW1JdGVyYXRvcikge1xuICAgICAgbG9kYXNoLnByb3RvdHlwZVtzeW1JdGVyYXRvcl0gPSB3cmFwcGVyVG9JdGVyYXRvcjtcbiAgICB9XG4gICAgcmV0dXJuIGxvZGFzaDtcbiAgfSk7XG5cbiAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgLy8gRXhwb3J0IGxvZGFzaC5cbiAgdmFyIF8gPSBydW5JbkNvbnRleHQoKTtcblxuICAvLyBTb21lIEFNRCBidWlsZCBvcHRpbWl6ZXJzLCBsaWtlIHIuanMsIGNoZWNrIGZvciBjb25kaXRpb24gcGF0dGVybnMgbGlrZTpcbiAgaWYgKHR5cGVvZiBkZWZpbmUgPT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PSAnb2JqZWN0JyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgLy8gRXhwb3NlIExvZGFzaCBvbiB0aGUgZ2xvYmFsIG9iamVjdCB0byBwcmV2ZW50IGVycm9ycyB3aGVuIExvZGFzaCBpc1xuICAgIC8vIGxvYWRlZCBieSBhIHNjcmlwdCB0YWcgaW4gdGhlIHByZXNlbmNlIG9mIGFuIEFNRCBsb2FkZXIuXG4gICAgLy8gU2VlIGh0dHA6Ly9yZXF1aXJlanMub3JnL2RvY3MvZXJyb3JzLmh0bWwjbWlzbWF0Y2ggZm9yIG1vcmUgZGV0YWlscy5cbiAgICAvLyBVc2UgYF8ubm9Db25mbGljdGAgdG8gcmVtb3ZlIExvZGFzaCBmcm9tIHRoZSBnbG9iYWwgb2JqZWN0LlxuICAgIHJvb3QuXyA9IF87XG5cbiAgICAvLyBEZWZpbmUgYXMgYW4gYW5vbnltb3VzIG1vZHVsZSBzbywgdGhyb3VnaCBwYXRoIG1hcHBpbmcsIGl0IGNhbiBiZVxuICAgIC8vIHJlZmVyZW5jZWQgYXMgdGhlIFwidW5kZXJzY29yZVwiIG1vZHVsZS5cbiAgICBkZWZpbmUoZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gXztcbiAgICB9KTtcbiAgfVxuICAvLyBDaGVjayBmb3IgYGV4cG9ydHNgIGFmdGVyIGBkZWZpbmVgIGluIGNhc2UgYSBidWlsZCBvcHRpbWl6ZXIgYWRkcyBpdC5cbiAgZWxzZSBpZiAoZnJlZU1vZHVsZSkge1xuICAgIC8vIEV4cG9ydCBmb3IgTm9kZS5qcy5cbiAgICAoZnJlZU1vZHVsZS5leHBvcnRzID0gXykuXyA9IF87XG4gICAgLy8gRXhwb3J0IGZvciBDb21tb25KUyBzdXBwb3J0LlxuICAgIGZyZWVFeHBvcnRzLl8gPSBfO1xuICB9XG4gIGVsc2Uge1xuICAgIC8vIEV4cG9ydCB0byB0aGUgZ2xvYmFsIG9iamVjdC5cbiAgICByb290Ll8gPSBfO1xuICB9XG59LmNhbGwodGhpcykpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2xvZGFzaC9sb2Rhc2guanNcbi8vIG1vZHVsZSBpZCA9IDc0XG4vLyBtb2R1bGUgY2h1bmtzID0gMCJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ },
- /* 75 */
- /***/ function(module, exports) {
- eval("module.exports = function(module) {\r\n\tif(!module.webpackPolyfill) {\r\n\t\tmodule.deprecate = function() {};\r\n\t\tmodule.paths = [];\r\n\t\t// module.parent = undefined by default\r\n\t\tmodule.children = [];\r\n\t\tmodule.webpackPolyfill = 1;\r\n\t}\r\n\treturn module;\r\n}\r\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNzUuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vKHdlYnBhY2spL2J1aWxkaW4vbW9kdWxlLmpzP2MzYzIiXSwic291cmNlc0NvbnRlbnQiOlsibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihtb2R1bGUpIHtcclxuXHRpZighbW9kdWxlLndlYnBhY2tQb2x5ZmlsbCkge1xyXG5cdFx0bW9kdWxlLmRlcHJlY2F0ZSA9IGZ1bmN0aW9uKCkge307XHJcblx0XHRtb2R1bGUucGF0aHMgPSBbXTtcclxuXHRcdC8vIG1vZHVsZS5wYXJlbnQgPSB1bmRlZmluZWQgYnkgZGVmYXVsdFxyXG5cdFx0bW9kdWxlLmNoaWxkcmVuID0gW107XHJcblx0XHRtb2R1bGUud2VicGFja1BvbHlmaWxsID0gMTtcclxuXHR9XHJcblx0cmV0dXJuIG1vZHVsZTtcclxufVxyXG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAod2VicGFjaykvYnVpbGRpbi9tb2R1bGUuanNcbi8vIG1vZHVsZSBpZCA9IDc1XG4vLyBtb2R1bGUgY2h1bmtzID0gMCJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 76 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar dragula = __webpack_require__(77);\nvar core_1 = __webpack_require__(4);\nvar DragulaService = (function () {\n function DragulaService() {\n this.cancel = new core_1.EventEmitter();\n this.cloned = new core_1.EventEmitter();\n this.drag = new core_1.EventEmitter();\n this.dragend = new core_1.EventEmitter();\n this.drop = new core_1.EventEmitter();\n this.out = new core_1.EventEmitter();\n this.over = new core_1.EventEmitter();\n this.remove = new core_1.EventEmitter();\n this.shadow = new core_1.EventEmitter();\n this.dropModel = new core_1.EventEmitter();\n this.removeModel = new core_1.EventEmitter();\n this.events = [\n 'cancel',\n 'cloned',\n 'drag',\n 'dragend',\n 'drop',\n 'out',\n 'over',\n 'remove',\n 'shadow',\n 'dropModel',\n 'removeModel'\n ];\n this.bags = [];\n }\n DragulaService.prototype.add = function (name, drake) {\n var bag = this.find(name);\n if (bag) {\n throw new Error('Bag named: \"' + name + '\" already exists.');\n }\n bag = {\n name: name,\n drake: drake\n };\n this.bags.push(bag);\n if (drake.models) {\n this.handleModels(name, drake);\n }\n if (!bag.initEvents) {\n this.setupEvents(bag);\n }\n return bag;\n };\n DragulaService.prototype.find = function (name) {\n for (var i = 0; i < this.bags.length; i++) {\n if (this.bags[i].name === name) {\n return this.bags[i];\n }\n }\n };\n DragulaService.prototype.destroy = function (name) {\n var bag = this.find(name);\n var i = this.bags.indexOf(bag);\n this.bags.splice(i, 1);\n bag.drake.destroy();\n };\n DragulaService.prototype.setOptions = function (name, options) {\n var bag = this.add(name, dragula(options));\n this.handleModels(name, bag.drake);\n };\n DragulaService.prototype.handleModels = function (name, drake) {\n var _this = this;\n var dragElm;\n var dragIndex;\n var dropIndex;\n var sourceModel;\n drake.on('remove', function (el, source) {\n if (!drake.models) {\n return;\n }\n sourceModel = drake.models[drake.containers.indexOf(source)];\n sourceModel.splice(dragIndex, 1);\n // console.log('REMOVE');\n // console.log(sourceModel);\n _this.removeModel.emit([name, el, source]);\n });\n drake.on('drag', function (el, source) {\n dragElm = el;\n dragIndex = _this.domIndexOf(el, source);\n });\n drake.on('drop', function (dropElm, target, source) {\n if (!drake.models || !target) {\n return;\n }\n dropIndex = _this.domIndexOf(dropElm, target);\n sourceModel = drake.models[drake.containers.indexOf(source)];\n // console.log('DROP');\n // console.log(sourceModel);\n if (target === source) {\n sourceModel.splice(dropIndex, 0, sourceModel.splice(dragIndex, 1)[0]);\n }\n else {\n var notCopy = dragElm === dropElm;\n var targetModel = drake.models[drake.containers.indexOf(target)];\n var dropElmModel = notCopy ? sourceModel[dragIndex] : JSON.parse(JSON.stringify(sourceModel[dragIndex]));\n if (notCopy) {\n sourceModel.splice(dragIndex, 1);\n }\n targetModel.splice(dropIndex, 0, dropElmModel);\n target.removeChild(dropElm); // element must be removed for ngFor to apply correctly\n }\n _this.dropModel.emit([name, dropElm, target, source]);\n });\n };\n DragulaService.prototype.setupEvents = function (bag) {\n bag.initEvents = true;\n var that = this;\n var emitter = function (type) {\n function replicate() {\n var args = Array.prototype.slice.call(arguments);\n that[type].emit([bag.name].concat(args));\n }\n bag.drake.on(type, replicate);\n };\n this.events.forEach(emitter);\n };\n DragulaService.prototype.domIndexOf = function (child, parent) {\n return Array.prototype.indexOf.call(parent.children, child);\n };\n DragulaService = __decorate([\n core_1.Injectable(), \n __metadata('design:paramtypes', [])\n ], DragulaService);\n return DragulaService;\n}());\nexports.DragulaService = DragulaService;\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNzYuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvYXBwL3Byb3ZpZGVycy9kcmFndWxhLnRzPzU1YmMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgZHJhZ3VsYSBmcm9tICdkcmFndWxhJztcbmltcG9ydCB7SW5qZWN0YWJsZSwgRXZlbnRFbWl0dGVyfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIERyYWd1bGFTZXJ2aWNlIHtcbiAgcHVibGljIGNhbmNlbDogICAgICBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgcHVibGljIGNsb25lZDogICAgICBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgcHVibGljIGRyYWc6ICAgICAgICBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgcHVibGljIGRyYWdlbmQ6ICAgICBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgcHVibGljIGRyb3A6ICAgICAgICBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgcHVibGljIG91dDogICAgICAgICBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgcHVibGljIG92ZXI6ICAgICAgICBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgcHVibGljIHJlbW92ZTogICAgICBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgcHVibGljIHNoYWRvdzogICAgICBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgcHVibGljIGRyb3BNb2RlbDogICBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgcHVibGljIHJlbW92ZU1vZGVsOiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgcHJpdmF0ZSBldmVudHM6IEFycmF5PHN0cmluZz4gPSBbXG4gICAgJ2NhbmNlbCcsXG4gICAgJ2Nsb25lZCcsXG4gICAgJ2RyYWcnLFxuICAgICdkcmFnZW5kJyxcbiAgICAnZHJvcCcsXG4gICAgJ291dCcsXG4gICAgJ292ZXInLFxuICAgICdyZW1vdmUnLFxuICAgICdzaGFkb3cnLFxuICAgICdkcm9wTW9kZWwnLFxuICAgICdyZW1vdmVNb2RlbCdcbiAgXTtcbiAgcHJpdmF0ZSBiYWdzOiBBcnJheTxhbnk+ID0gW107XG5cbiAgcHVibGljIGFkZChuYW1lOiBzdHJpbmcsIGRyYWtlOiBhbnkpOiBhbnkge1xuICAgIGxldCBiYWcgPSB0aGlzLmZpbmQobmFtZSk7XG4gICAgaWYgKGJhZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdCYWcgbmFtZWQ6IFwiJyArIG5hbWUgKyAnXCIgYWxyZWFkeSBleGlzdHMuJyk7XG4gICAgfVxuICAgIGJhZyA9IHtcbiAgICAgIG5hbWU6IG5hbWUsXG4gICAgICBkcmFrZTogZHJha2VcbiAgICB9O1xuICAgIHRoaXMuYmFncy5wdXNoKGJhZyk7XG4gICAgaWYgKGRyYWtlLm1vZGVscykgeyAvLyBtb2RlbHMgdG8gc3luYyB3aXRoIChtdXN0IGhhdmUgc2FtZSBzdHJ1Y3R1cmUgYXMgY29udGFpbmVycylcbiAgICAgIHRoaXMuaGFuZGxlTW9kZWxzKG5hbWUsIGRyYWtlKTtcbiAgICB9XG4gICAgaWYgKCFiYWcuaW5pdEV2ZW50cykge1xuICAgICAgdGhpcy5zZXR1cEV2ZW50cyhiYWcpO1xuICAgIH1cbiAgICByZXR1cm4gYmFnO1xuICB9XG5cbiAgcHVibGljIGZpbmQobmFtZTogc3RyaW5nKTogYW55IHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuYmFncy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHRoaXMuYmFnc1tpXS5uYW1lID09PSBuYW1lKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmJhZ3NbaV07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGRlc3Ryb3kobmFtZTogc3RyaW5nKTogdm9pZCB7XG4gICAgbGV0IGJhZyA9IHRoaXMuZmluZChuYW1lKTtcbiAgICBsZXQgaSA9IHRoaXMuYmFncy5pbmRleE9mKGJhZyk7XG4gICAgdGhpcy5iYWdzLnNwbGljZShpLCAxKTtcbiAgICBiYWcuZHJha2UuZGVzdHJveSgpO1xuICB9XG5cbiAgcHVibGljIHNldE9wdGlvbnMobmFtZTogc3RyaW5nLCBvcHRpb25zOiBhbnkpIHtcbiAgICBsZXQgYmFnID0gdGhpcy5hZGQobmFtZSwgZHJhZ3VsYShvcHRpb25zKSk7XG4gICAgdGhpcy5oYW5kbGVNb2RlbHMobmFtZSwgYmFnLmRyYWtlKTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlTW9kZWxzKG5hbWU6IHN0cmluZywgZHJha2U6IGFueSkge1xuICAgIGxldCBkcmFnRWxtOiBhbnk7XG4gICAgbGV0IGRyYWdJbmRleDogbnVtYmVyO1xuICAgIGxldCBkcm9wSW5kZXg6IG51bWJlcjtcbiAgICBsZXQgc291cmNlTW9kZWw6IGFueTtcbiAgICBkcmFrZS5vbigncmVtb3ZlJywgKGVsOiBhbnksIHNvdXJjZTogYW55KSA9PiB7XG4gICAgICBpZiAoIWRyYWtlLm1vZGVscykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBzb3VyY2VNb2RlbCA9IGRyYWtlLm1vZGVsc1tkcmFrZS5jb250YWluZXJzLmluZGV4T2Yoc291cmNlKV07XG4gICAgICBzb3VyY2VNb2RlbC5zcGxpY2UoZHJhZ0luZGV4LCAxKTtcbiAgICAgIC8vIGNvbnNvbGUubG9nKCdSRU1PVkUnKTtcbiAgICAgIC8vIGNvbnNvbGUubG9nKHNvdXJjZU1vZGVsKTtcbiAgICAgIHRoaXMucmVtb3ZlTW9kZWwuZW1pdChbbmFtZSwgZWwsIHNvdXJjZV0pO1xuICAgIH0pO1xuICAgIGRyYWtlLm9uKCdkcmFnJywgKGVsOiBhbnksIHNvdXJjZTogYW55KSA9PiB7XG4gICAgICBkcmFnRWxtID0gZWw7XG4gICAgICBkcmFnSW5kZXggPSB0aGlzLmRvbUluZGV4T2YoZWwsIHNvdXJjZSk7XG4gICAgfSk7XG4gICAgZHJha2Uub24oJ2Ryb3AnLCAoZHJvcEVsbTogYW55LCB0YXJnZXQ6IGFueSwgc291cmNlOiBhbnkpID0+IHtcbiAgICAgIGlmICghZHJha2UubW9kZWxzIHx8ICF0YXJnZXQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgZHJvcEluZGV4ID0gdGhpcy5kb21JbmRleE9mKGRyb3BFbG0sIHRhcmdldCk7XG4gICAgICBzb3VyY2VNb2RlbCA9IGRyYWtlLm1vZGVsc1tkcmFrZS5jb250YWluZXJzLmluZGV4T2Yoc291cmNlKV07XG4gICAgICAvLyBjb25zb2xlLmxvZygnRFJPUCcpO1xuICAgICAgLy8gY29uc29sZS5sb2coc291cmNlTW9kZWwpO1xuICAgICAgaWYgKHRhcmdldCA9PT0gc291cmNlKSB7XG4gICAgICAgIHNvdXJjZU1vZGVsLnNwbGljZShkcm9wSW5kZXgsIDAsIHNvdXJjZU1vZGVsLnNwbGljZShkcmFnSW5kZXgsIDEpWzBdKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxldCBub3RDb3B5ID0gZHJhZ0VsbSA9PT0gZHJvcEVsbTtcbiAgICAgICAgbGV0IHRhcmdldE1vZGVsID0gZHJha2UubW9kZWxzW2RyYWtlLmNvbnRhaW5lcnMuaW5kZXhPZih0YXJnZXQpXTtcbiAgICAgICAgbGV0IGRyb3BFbG1Nb2RlbCA9IG5vdENvcHkgPyBzb3VyY2VNb2RlbFtkcmFnSW5kZXhdIDogSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShzb3VyY2VNb2RlbFtkcmFnSW5kZXhdKSk7XG5cbiAgICAgICAgaWYgKG5vdENvcHkpIHtcbiAgICAgICAgICBzb3VyY2VNb2RlbC5zcGxpY2UoZHJhZ0luZGV4LCAxKTtcbiAgICAgICAgfVxuICAgICAgICB0YXJnZXRNb2RlbC5zcGxpY2UoZHJvcEluZGV4LCAwLCBkcm9wRWxtTW9kZWwpO1xuICAgICAgICB0YXJnZXQucmVtb3ZlQ2hpbGQoZHJvcEVsbSk7IC8vIGVsZW1lbnQgbXVzdCBiZSByZW1vdmVkIGZvciBuZ0ZvciB0byBhcHBseSBjb3JyZWN0bHlcbiAgICAgIH1cbiAgICAgIHRoaXMuZHJvcE1vZGVsLmVtaXQoW25hbWUsIGRyb3BFbG0sIHRhcmdldCwgc291cmNlXSk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHNldHVwRXZlbnRzKGJhZzogYW55KSB7XG4gICAgYmFnLmluaXRFdmVudHMgPSB0cnVlO1xuICAgIGxldCB0aGF0OiBhbnkgPSB0aGlzO1xuICAgIGxldCBlbWl0dGVyID0gKHR5cGU6IGFueSkgPT4ge1xuICAgICAgZnVuY3Rpb24gcmVwbGljYXRlICgpIHtcbiAgICAgICAgbGV0IGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuICAgICAgICB0aGF0W3R5cGVdLmVtaXQoW2JhZy5uYW1lXS5jb25jYXQoYXJncykpO1xuICAgICAgfVxuICAgICAgYmFnLmRyYWtlLm9uKHR5cGUsIHJlcGxpY2F0ZSk7XG4gICAgfTtcbiAgICB0aGlzLmV2ZW50cy5mb3JFYWNoKGVtaXR0ZXIpO1xuICB9XG5cbiAgcHJpdmF0ZSBkb21JbmRleE9mKGNoaWxkOiBhbnksIHBhcmVudDogYW55KSB7XG4gICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5pbmRleE9mLmNhbGwocGFyZW50LmNoaWxkcmVuLCBjaGlsZCk7XG4gIH1cbn1cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gbm9kZV9tb2R1bGVzL2FuZ3VsYXIyLXRlbXBsYXRlLWxvYWRlciEuL3NyYy9hcHAvcHJvdmlkZXJzL2RyYWd1bGEudHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBR0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBcUdBO0FBbkdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBOUhBO0FBQUE7O0FBQUE7QUErSEE7QUFBQTtBQTlIQTsiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ },
- /* 77 */
- /***/ function(module, exports, __webpack_require__) {
- eval("/* WEBPACK VAR INJECTION */(function(global) {'use strict';\n\nvar emitter = __webpack_require__(78);\nvar crossvent = __webpack_require__(84);\nvar classes = __webpack_require__(87);\nvar doc = document;\nvar documentElement = doc.documentElement;\n\nfunction dragula (initialContainers, options) {\n var len = arguments.length;\n if (len === 1 && Array.isArray(initialContainers) === false) {\n options = initialContainers;\n initialContainers = [];\n }\n var _mirror; // mirror image\n var _source; // source container\n var _item; // item being dragged\n var _offsetX; // reference x\n var _offsetY; // reference y\n var _moveX; // reference move x\n var _moveY; // reference move y\n var _initialSibling; // reference sibling when grabbed\n var _currentSibling; // reference sibling now\n var _copy; // item used for copying\n var _renderTimer; // timer for setTimeout renderMirrorImage\n var _lastDropTarget = null; // last container item was over\n var _grabbed; // holds mousedown context until first mousemove\n\n var o = options || {};\n if (o.moves === void 0) { o.moves = always; }\n if (o.accepts === void 0) { o.accepts = always; }\n if (o.invalid === void 0) { o.invalid = invalidTarget; }\n if (o.containers === void 0) { o.containers = initialContainers || []; }\n if (o.isContainer === void 0) { o.isContainer = never; }\n if (o.copy === void 0) { o.copy = false; }\n if (o.copySortSource === void 0) { o.copySortSource = false; }\n if (o.revertOnSpill === void 0) { o.revertOnSpill = false; }\n if (o.removeOnSpill === void 0) { o.removeOnSpill = false; }\n if (o.direction === void 0) { o.direction = 'vertical'; }\n if (o.ignoreInputTextSelection === void 0) { o.ignoreInputTextSelection = true; }\n if (o.mirrorContainer === void 0) { o.mirrorContainer = doc.body; }\n\n var drake = emitter({\n containers: o.containers,\n start: manualStart,\n end: end,\n cancel: cancel,\n remove: remove,\n destroy: destroy,\n canMove: canMove,\n dragging: false\n });\n\n if (o.removeOnSpill === true) {\n drake.on('over', spillOver).on('out', spillOut);\n }\n\n events();\n\n return drake;\n\n function isContainer (el) {\n return drake.containers.indexOf(el) !== -1 || o.isContainer(el);\n }\n\n function events (remove) {\n var op = remove ? 'remove' : 'add';\n touchy(documentElement, op, 'mousedown', grab);\n touchy(documentElement, op, 'mouseup', release);\n }\n\n function eventualMovements (remove) {\n var op = remove ? 'remove' : 'add';\n touchy(documentElement, op, 'mousemove', startBecauseMouseMoved);\n }\n\n function movements (remove) {\n var op = remove ? 'remove' : 'add';\n crossvent[op](documentElement, 'selectstart', preventGrabbed); // IE8\n crossvent[op](documentElement, 'click', preventGrabbed);\n }\n\n function destroy () {\n events(true);\n release({});\n }\n\n function preventGrabbed (e) {\n if (_grabbed) {\n e.preventDefault();\n }\n }\n\n function grab (e) {\n _moveX = e.clientX;\n _moveY = e.clientY;\n\n var ignore = whichMouseButton(e) !== 1 || e.metaKey || e.ctrlKey;\n if (ignore) {\n return; // we only care about honest-to-god left clicks and touch events\n }\n var item = e.target;\n var context = canStart(item);\n if (!context) {\n return;\n }\n _grabbed = context;\n eventualMovements();\n if (e.type === 'mousedown') {\n if (isInput(item)) { // see also: https://github.com/bevacqua/dragula/issues/208\n item.focus(); // fixes https://github.com/bevacqua/dragula/issues/176\n } else {\n e.preventDefault(); // fixes https://github.com/bevacqua/dragula/issues/155\n }\n }\n }\n\n function startBecauseMouseMoved (e) {\n if (!_grabbed) {\n return;\n }\n if (whichMouseButton(e) === 0) {\n release({});\n return; // when text is selected on an input and then dragged, mouseup doesn't fire. this is our only hope\n }\n // truthy check fixes #239, equality fixes #207\n if (e.clientX !== void 0 && e.clientX === _moveX && e.clientY !== void 0 && e.clientY === _moveY) {\n return;\n }\n if (o.ignoreInputTextSelection) {\n var clientX = getCoord('clientX', e);\n var clientY = getCoord('clientY', e);\n var elementBehindCursor = doc.elementFromPoint(clientX, clientY);\n if (isInput(elementBehindCursor)) {\n return;\n }\n }\n\n var grabbed = _grabbed; // call to end() unsets _grabbed\n eventualMovements(true);\n movements();\n end();\n start(grabbed);\n\n var offset = getOffset(_item);\n _offsetX = getCoord('pageX', e) - offset.left;\n _offsetY = getCoord('pageY', e) - offset.top;\n\n classes.add(_copy || _item, 'gu-transit');\n renderMirrorImage();\n drag(e);\n }\n\n function canStart (item) {\n if (drake.dragging && _mirror) {\n return;\n }\n if (isContainer(item)) {\n return; // don't drag container itself\n }\n var handle = item;\n while (getParent(item) && isContainer(getParent(item)) === false) {\n if (o.invalid(item, handle)) {\n return;\n }\n item = getParent(item); // drag target should be a top element\n if (!item) {\n return;\n }\n }\n var source = getParent(item);\n if (!source) {\n return;\n }\n if (o.invalid(item, handle)) {\n return;\n }\n\n var movable = o.moves(item, source, handle, nextEl(item));\n if (!movable) {\n return;\n }\n\n return {\n item: item,\n source: source\n };\n }\n\n function canMove (item) {\n return !!canStart(item);\n }\n\n function manualStart (item) {\n var context = canStart(item);\n if (context) {\n start(context);\n }\n }\n\n function start (context) {\n if (isCopy(context.item, context.source)) {\n _copy = context.item.cloneNode(true);\n drake.emit('cloned', _copy, context.item, 'copy');\n }\n\n _source = context.source;\n _item = context.item;\n _initialSibling = _currentSibling = nextEl(context.item);\n\n drake.dragging = true;\n drake.emit('drag', _item, _source);\n }\n\n function invalidTarget () {\n return false;\n }\n\n function end () {\n if (!drake.dragging) {\n return;\n }\n var item = _copy || _item;\n drop(item, getParent(item));\n }\n\n function ungrab () {\n _grabbed = false;\n eventualMovements(true);\n movements(true);\n }\n\n function release (e) {\n ungrab();\n\n if (!drake.dragging) {\n return;\n }\n var item = _copy || _item;\n var clientX = getCoord('clientX', e);\n var clientY = getCoord('clientY', e);\n var elementBehindCursor = getElementBehindPoint(_mirror, clientX, clientY);\n var dropTarget = findDropTarget(elementBehindCursor, clientX, clientY);\n if (dropTarget && ((_copy && o.copySortSource) || (!_copy || dropTarget !== _source))) {\n drop(item, dropTarget);\n } else if (o.removeOnSpill) {\n remove();\n } else {\n cancel();\n }\n }\n\n function drop (item, target) {\n var parent = getParent(item);\n if (_copy && o.copySortSource && target === _source) {\n parent.removeChild(_item);\n }\n if (isInitialPlacement(target)) {\n drake.emit('cancel', item, _source, _source);\n } else {\n drake.emit('drop', item, target, _source, _currentSibling);\n }\n cleanup();\n }\n\n function remove () {\n if (!drake.dragging) {\n return;\n }\n var item = _copy || _item;\n var parent = getParent(item);\n if (parent) {\n parent.removeChild(item);\n }\n drake.emit(_copy ? 'cancel' : 'remove', item, parent, _source);\n cleanup();\n }\n\n function cancel (revert) {\n if (!drake.dragging) {\n return;\n }\n var reverts = arguments.length > 0 ? revert : o.revertOnSpill;\n var item = _copy || _item;\n var parent = getParent(item);\n var initial = isInitialPlacement(parent);\n if (initial === false && reverts) {\n if (_copy) {\n if (parent) {\n parent.removeChild(_copy);\n }\n } else {\n _source.insertBefore(item, _initialSibling);\n }\n }\n if (initial || reverts) {\n drake.emit('cancel', item, _source, _source);\n } else {\n drake.emit('drop', item, parent, _source, _currentSibling);\n }\n cleanup();\n }\n\n function cleanup () {\n var item = _copy || _item;\n ungrab();\n removeMirrorImage();\n if (item) {\n classes.rm(item, 'gu-transit');\n }\n if (_renderTimer) {\n clearTimeout(_renderTimer);\n }\n drake.dragging = false;\n if (_lastDropTarget) {\n drake.emit('out', item, _lastDropTarget, _source);\n }\n drake.emit('dragend', item);\n _source = _item = _copy = _initialSibling = _currentSibling = _renderTimer = _lastDropTarget = null;\n }\n\n function isInitialPlacement (target, s) {\n var sibling;\n if (s !== void 0) {\n sibling = s;\n } else if (_mirror) {\n sibling = _currentSibling;\n } else {\n sibling = nextEl(_copy || _item);\n }\n return target === _source && sibling === _initialSibling;\n }\n\n function findDropTarget (elementBehindCursor, clientX, clientY) {\n var target = elementBehindCursor;\n while (target && !accepted()) {\n target = getParent(target);\n }\n return target;\n\n function accepted () {\n var droppable = isContainer(target);\n if (droppable === false) {\n return false;\n }\n\n var immediate = getImmediateChild(target, elementBehindCursor);\n var reference = getReference(target, immediate, clientX, clientY);\n var initial = isInitialPlacement(target, reference);\n if (initial) {\n return true; // should always be able to drop it right back where it was\n }\n return o.accepts(_item, target, _source, reference);\n }\n }\n\n function drag (e) {\n if (!_mirror) {\n return;\n }\n e.preventDefault();\n\n var clientX = getCoord('clientX', e);\n var clientY = getCoord('clientY', e);\n var x = clientX - _offsetX;\n var y = clientY - _offsetY;\n\n _mirror.style.left = x + 'px';\n _mirror.style.top = y + 'px';\n\n var item = _copy || _item;\n var elementBehindCursor = getElementBehindPoint(_mirror, clientX, clientY);\n var dropTarget = findDropTarget(elementBehindCursor, clientX, clientY);\n var changed = dropTarget !== null && dropTarget !== _lastDropTarget;\n if (changed || dropTarget === null) {\n out();\n _lastDropTarget = dropTarget;\n over();\n }\n var parent = getParent(item);\n if (dropTarget === _source && _copy && !o.copySortSource) {\n if (parent) {\n parent.removeChild(item);\n }\n return;\n }\n var reference;\n var immediate = getImmediateChild(dropTarget, elementBehindCursor);\n if (immediate !== null) {\n reference = getReference(dropTarget, immediate, clientX, clientY);\n } else if (o.revertOnSpill === true && !_copy) {\n reference = _initialSibling;\n dropTarget = _source;\n } else {\n if (_copy && parent) {\n parent.removeChild(item);\n }\n return;\n }\n if (\n (reference === null && changed) ||\n reference !== item &&\n reference !== nextEl(item)\n ) {\n _currentSibling = reference;\n dropTarget.insertBefore(item, reference);\n drake.emit('shadow', item, dropTarget, _source);\n }\n function moved (type) { drake.emit(type, item, _lastDropTarget, _source); }\n function over () { if (changed) { moved('over'); } }\n function out () { if (_lastDropTarget) { moved('out'); } }\n }\n\n function spillOver (el) {\n classes.rm(el, 'gu-hide');\n }\n\n function spillOut (el) {\n if (drake.dragging) { classes.add(el, 'gu-hide'); }\n }\n\n function renderMirrorImage () {\n if (_mirror) {\n return;\n }\n var rect = _item.getBoundingClientRect();\n _mirror = _item.cloneNode(true);\n _mirror.style.width = getRectWidth(rect) + 'px';\n _mirror.style.height = getRectHeight(rect) + 'px';\n classes.rm(_mirror, 'gu-transit');\n classes.add(_mirror, 'gu-mirror');\n o.mirrorContainer.appendChild(_mirror);\n touchy(documentElement, 'add', 'mousemove', drag);\n classes.add(o.mirrorContainer, 'gu-unselectable');\n drake.emit('cloned', _mirror, _item, 'mirror');\n }\n\n function removeMirrorImage () {\n if (_mirror) {\n classes.rm(o.mirrorContainer, 'gu-unselectable');\n touchy(documentElement, 'remove', 'mousemove', drag);\n getParent(_mirror).removeChild(_mirror);\n _mirror = null;\n }\n }\n\n function getImmediateChild (dropTarget, target) {\n var immediate = target;\n while (immediate !== dropTarget && getParent(immediate) !== dropTarget) {\n immediate = getParent(immediate);\n }\n if (immediate === documentElement) {\n return null;\n }\n return immediate;\n }\n\n function getReference (dropTarget, target, x, y) {\n var horizontal = o.direction === 'horizontal';\n var reference = target !== dropTarget ? inside() : outside();\n return reference;\n\n function outside () { // slower, but able to figure out any position\n var len = dropTarget.children.length;\n var i;\n var el;\n var rect;\n for (i = 0; i < len; i++) {\n el = dropTarget.children[i];\n rect = el.getBoundingClientRect();\n if (horizontal && (rect.left + rect.width / 2) > x) { return el; }\n if (!horizontal && (rect.top + rect.height / 2) > y) { return el; }\n }\n return null;\n }\n\n function inside () { // faster, but only available if dropped inside a child element\n var rect = target.getBoundingClientRect();\n if (horizontal) {\n return resolve(x > rect.left + getRectWidth(rect) / 2);\n }\n return resolve(y > rect.top + getRectHeight(rect) / 2);\n }\n\n function resolve (after) {\n return after ? nextEl(target) : target;\n }\n }\n\n function isCopy (item, container) {\n return typeof o.copy === 'boolean' ? o.copy : o.copy(item, container);\n }\n}\n\nfunction touchy (el, op, type, fn) {\n var touch = {\n mouseup: 'touchend',\n mousedown: 'touchstart',\n mousemove: 'touchmove'\n };\n var pointers = {\n mouseup: 'pointerup',\n mousedown: 'pointerdown',\n mousemove: 'pointermove'\n };\n var microsoft = {\n mouseup: 'MSPointerUp',\n mousedown: 'MSPointerDown',\n mousemove: 'MSPointerMove'\n };\n if (global.navigator.pointerEnabled) {\n crossvent[op](el, pointers[type], fn);\n } else if (global.navigator.msPointerEnabled) {\n crossvent[op](el, microsoft[type], fn);\n } else {\n crossvent[op](el, touch[type], fn);\n crossvent[op](el, type, fn);\n }\n}\n\nfunction whichMouseButton (e) {\n if (e.touches !== void 0) { return e.touches.length; }\n if (e.which !== void 0 && e.which !== 0) { return e.which; } // see https://github.com/bevacqua/dragula/issues/261\n if (e.buttons !== void 0) { return e.buttons; }\n var button = e.button;\n if (button !== void 0) { // see https://github.com/jquery/jquery/blob/99e8ff1baa7ae341e94bb89c3e84570c7c3ad9ea/src/event.js#L573-L575\n return button & 1 ? 1 : button & 2 ? 3 : (button & 4 ? 2 : 0);\n }\n}\n\nfunction getOffset (el) {\n var rect = el.getBoundingClientRect();\n return {\n left: rect.left + getScroll('scrollLeft', 'pageXOffset'),\n top: rect.top + getScroll('scrollTop', 'pageYOffset')\n };\n}\n\nfunction getScroll (scrollProp, offsetProp) {\n if (typeof global[offsetProp] !== 'undefined') {\n return global[offsetProp];\n }\n if (documentElement.clientHeight) {\n return documentElement[scrollProp];\n }\n return doc.body[scrollProp];\n}\n\nfunction getElementBehindPoint (point, x, y) {\n var p = point || {};\n var state = p.className;\n var el;\n p.className += ' gu-hide';\n el = doc.elementFromPoint(x, y);\n p.className = state;\n return el;\n}\n\nfunction never () { return false; }\nfunction always () { return true; }\nfunction getRectWidth (rect) { return rect.width || (rect.right - rect.left); }\nfunction getRectHeight (rect) { return rect.height || (rect.bottom - rect.top); }\nfunction getParent (el) { return el.parentNode === doc ? null : el.parentNode; }\nfunction isInput (el) { return el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.tagName === 'SELECT' || isEditable(el); }\nfunction isEditable (el) {\n if (!el) { return false; } // no parents were editable\n if (el.contentEditable === 'false') { return false; } // stop the lookup\n if (el.contentEditable === 'true') { return true; } // found a contentEditable element in the chain\n return isEditable(getParent(el)); // contentEditable is set to 'inherit'\n}\n\nfunction nextEl (el) {\n return el.nextElementSibling || manually();\n function manually () {\n var sibling = el;\n do {\n sibling = sibling.nextSibling;\n } while (sibling && sibling.nodeType !== 1);\n return sibling;\n }\n}\n\nfunction getEventHost (e) {\n // on touchend event, we have to use `e.changedTouches`\n // see http://stackoverflow.com/questions/7192563/touchend-event-properties\n // see https://github.com/bevacqua/dragula/issues/34\n if (e.targetTouches && e.targetTouches.length) {\n return e.targetTouches[0];\n }\n if (e.changedTouches && e.changedTouches.length) {\n return e.changedTouches[0];\n }\n return e;\n}\n\nfunction getCoord (coord, e) {\n var host = getEventHost(e);\n var missMap = {\n pageX: 'clientX', // IE8\n pageY: 'clientY' // IE8\n };\n if (coord in missMap && !(coord in host) && missMap[coord] in host) {\n coord = missMap[coord];\n }\n return host[coord];\n}\n\nmodule.exports = dragula;\n\n/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNzcuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2RyYWd1bGEvZHJhZ3VsYS5qcz8xYTUzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxudmFyIGVtaXR0ZXIgPSByZXF1aXJlKCdjb250cmEvZW1pdHRlcicpO1xudmFyIGNyb3NzdmVudCA9IHJlcXVpcmUoJ2Nyb3NzdmVudCcpO1xudmFyIGNsYXNzZXMgPSByZXF1aXJlKCcuL2NsYXNzZXMnKTtcbnZhciBkb2MgPSBkb2N1bWVudDtcbnZhciBkb2N1bWVudEVsZW1lbnQgPSBkb2MuZG9jdW1lbnRFbGVtZW50O1xuXG5mdW5jdGlvbiBkcmFndWxhIChpbml0aWFsQ29udGFpbmVycywgb3B0aW9ucykge1xuICB2YXIgbGVuID0gYXJndW1lbnRzLmxlbmd0aDtcbiAgaWYgKGxlbiA9PT0gMSAmJiBBcnJheS5pc0FycmF5KGluaXRpYWxDb250YWluZXJzKSA9PT0gZmFsc2UpIHtcbiAgICBvcHRpb25zID0gaW5pdGlhbENvbnRhaW5lcnM7XG4gICAgaW5pdGlhbENvbnRhaW5lcnMgPSBbXTtcbiAgfVxuICB2YXIgX21pcnJvcjsgLy8gbWlycm9yIGltYWdlXG4gIHZhciBfc291cmNlOyAvLyBzb3VyY2UgY29udGFpbmVyXG4gIHZhciBfaXRlbTsgLy8gaXRlbSBiZWluZyBkcmFnZ2VkXG4gIHZhciBfb2Zmc2V0WDsgLy8gcmVmZXJlbmNlIHhcbiAgdmFyIF9vZmZzZXRZOyAvLyByZWZlcmVuY2UgeVxuICB2YXIgX21vdmVYOyAvLyByZWZlcmVuY2UgbW92ZSB4XG4gIHZhciBfbW92ZVk7IC8vIHJlZmVyZW5jZSBtb3ZlIHlcbiAgdmFyIF9pbml0aWFsU2libGluZzsgLy8gcmVmZXJlbmNlIHNpYmxpbmcgd2hlbiBncmFiYmVkXG4gIHZhciBfY3VycmVudFNpYmxpbmc7IC8vIHJlZmVyZW5jZSBzaWJsaW5nIG5vd1xuICB2YXIgX2NvcHk7IC8vIGl0ZW0gdXNlZCBmb3IgY29weWluZ1xuICB2YXIgX3JlbmRlclRpbWVyOyAvLyB0aW1lciBmb3Igc2V0VGltZW91dCByZW5kZXJNaXJyb3JJbWFnZVxuICB2YXIgX2xhc3REcm9wVGFyZ2V0ID0gbnVsbDsgLy8gbGFzdCBjb250YWluZXIgaXRlbSB3YXMgb3ZlclxuICB2YXIgX2dyYWJiZWQ7IC8vIGhvbGRzIG1vdXNlZG93biBjb250ZXh0IHVudGlsIGZpcnN0IG1vdXNlbW92ZVxuXG4gIHZhciBvID0gb3B0aW9ucyB8fCB7fTtcbiAgaWYgKG8ubW92ZXMgPT09IHZvaWQgMCkgeyBvLm1vdmVzID0gYWx3YXlzOyB9XG4gIGlmIChvLmFjY2VwdHMgPT09IHZvaWQgMCkgeyBvLmFjY2VwdHMgPSBhbHdheXM7IH1cbiAgaWYgKG8uaW52YWxpZCA9PT0gdm9pZCAwKSB7IG8uaW52YWxpZCA9IGludmFsaWRUYXJnZXQ7IH1cbiAgaWYgKG8uY29udGFpbmVycyA9PT0gdm9pZCAwKSB7IG8uY29udGFpbmVycyA9IGluaXRpYWxDb250YWluZXJzIHx8IFtdOyB9XG4gIGlmIChvLmlzQ29udGFpbmVyID09PSB2b2lkIDApIHsgby5pc0NvbnRhaW5lciA9IG5ldmVyOyB9XG4gIGlmIChvLmNvcHkgPT09IHZvaWQgMCkgeyBvLmNvcHkgPSBmYWxzZTsgfVxuICBpZiAoby5jb3B5U29ydFNvdXJjZSA9PT0gdm9pZCAwKSB7IG8uY29weVNvcnRTb3VyY2UgPSBmYWxzZTsgfVxuICBpZiAoby5yZXZlcnRPblNwaWxsID09PSB2b2lkIDApIHsgby5yZXZlcnRPblNwaWxsID0gZmFsc2U7IH1cbiAgaWYgKG8ucmVtb3ZlT25TcGlsbCA9PT0gdm9pZCAwKSB7IG8ucmVtb3ZlT25TcGlsbCA9IGZhbHNlOyB9XG4gIGlmIChvLmRpcmVjdGlvbiA9PT0gdm9pZCAwKSB7IG8uZGlyZWN0aW9uID0gJ3ZlcnRpY2FsJzsgfVxuICBpZiAoby5pZ25vcmVJbnB1dFRleHRTZWxlY3Rpb24gPT09IHZvaWQgMCkgeyBvLmlnbm9yZUlucHV0VGV4dFNlbGVjdGlvbiA9IHRydWU7IH1cbiAgaWYgKG8ubWlycm9yQ29udGFpbmVyID09PSB2b2lkIDApIHsgby5taXJyb3JDb250YWluZXIgPSBkb2MuYm9keTsgfVxuXG4gIHZhciBkcmFrZSA9IGVtaXR0ZXIoe1xuICAgIGNvbnRhaW5lcnM6IG8uY29udGFpbmVycyxcbiAgICBzdGFydDogbWFudWFsU3RhcnQsXG4gICAgZW5kOiBlbmQsXG4gICAgY2FuY2VsOiBjYW5jZWwsXG4gICAgcmVtb3ZlOiByZW1vdmUsXG4gICAgZGVzdHJveTogZGVzdHJveSxcbiAgICBjYW5Nb3ZlOiBjYW5Nb3ZlLFxuICAgIGRyYWdnaW5nOiBmYWxzZVxuICB9KTtcblxuICBpZiAoby5yZW1vdmVPblNwaWxsID09PSB0cnVlKSB7XG4gICAgZHJha2Uub24oJ292ZXInLCBzcGlsbE92ZXIpLm9uKCdvdXQnLCBzcGlsbE91dCk7XG4gIH1cblxuICBldmVudHMoKTtcblxuICByZXR1cm4gZHJha2U7XG5cbiAgZnVuY3Rpb24gaXNDb250YWluZXIgKGVsKSB7XG4gICAgcmV0dXJuIGRyYWtlLmNvbnRhaW5lcnMuaW5kZXhPZihlbCkgIT09IC0xIHx8IG8uaXNDb250YWluZXIoZWwpO1xuICB9XG5cbiAgZnVuY3Rpb24gZXZlbnRzIChyZW1vdmUpIHtcbiAgICB2YXIgb3AgPSByZW1vdmUgPyAncmVtb3ZlJyA6ICdhZGQnO1xuICAgIHRvdWNoeShkb2N1bWVudEVsZW1lbnQsIG9wLCAnbW91c2Vkb3duJywgZ3JhYik7XG4gICAgdG91Y2h5KGRvY3VtZW50RWxlbWVudCwgb3AsICdtb3VzZXVwJywgcmVsZWFzZSk7XG4gIH1cblxuICBmdW5jdGlvbiBldmVudHVhbE1vdmVtZW50cyAocmVtb3ZlKSB7XG4gICAgdmFyIG9wID0gcmVtb3ZlID8gJ3JlbW92ZScgOiAnYWRkJztcbiAgICB0b3VjaHkoZG9jdW1lbnRFbGVtZW50LCBvcCwgJ21vdXNlbW92ZScsIHN0YXJ0QmVjYXVzZU1vdXNlTW92ZWQpO1xuICB9XG5cbiAgZnVuY3Rpb24gbW92ZW1lbnRzIChyZW1vdmUpIHtcbiAgICB2YXIgb3AgPSByZW1vdmUgPyAncmVtb3ZlJyA6ICdhZGQnO1xuICAgIGNyb3NzdmVudFtvcF0oZG9jdW1lbnRFbGVtZW50LCAnc2VsZWN0c3RhcnQnLCBwcmV2ZW50R3JhYmJlZCk7IC8vIElFOFxuICAgIGNyb3NzdmVudFtvcF0oZG9jdW1lbnRFbGVtZW50LCAnY2xpY2snLCBwcmV2ZW50R3JhYmJlZCk7XG4gIH1cblxuICBmdW5jdGlvbiBkZXN0cm95ICgpIHtcbiAgICBldmVudHModHJ1ZSk7XG4gICAgcmVsZWFzZSh7fSk7XG4gIH1cblxuICBmdW5jdGlvbiBwcmV2ZW50R3JhYmJlZCAoZSkge1xuICAgIGlmIChfZ3JhYmJlZCkge1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGdyYWIgKGUpIHtcbiAgICBfbW92ZVggPSBlLmNsaWVudFg7XG4gICAgX21vdmVZID0gZS5jbGllbnRZO1xuXG4gICAgdmFyIGlnbm9yZSA9IHdoaWNoTW91c2VCdXR0b24oZSkgIT09IDEgfHwgZS5tZXRhS2V5IHx8IGUuY3RybEtleTtcbiAgICBpZiAoaWdub3JlKSB7XG4gICAgICByZXR1cm47IC8vIHdlIG9ubHkgY2FyZSBhYm91dCBob25lc3QtdG8tZ29kIGxlZnQgY2xpY2tzIGFuZCB0b3VjaCBldmVudHNcbiAgICB9XG4gICAgdmFyIGl0ZW0gPSBlLnRhcmdldDtcbiAgICB2YXIgY29udGV4dCA9IGNhblN0YXJ0KGl0ZW0pO1xuICAgIGlmICghY29udGV4dCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBfZ3JhYmJlZCA9IGNvbnRleHQ7XG4gICAgZXZlbnR1YWxNb3ZlbWVudHMoKTtcbiAgICBpZiAoZS50eXBlID09PSAnbW91c2Vkb3duJykge1xuICAgICAgaWYgKGlzSW5wdXQoaXRlbSkpIHsgLy8gc2VlIGFsc286IGh0dHBzOi8vZ2l0aHViLmNvbS9iZXZhY3F1YS9kcmFndWxhL2lzc3Vlcy8yMDhcbiAgICAgICAgaXRlbS5mb2N1cygpOyAvLyBmaXhlcyBodHRwczovL2dpdGh1Yi5jb20vYmV2YWNxdWEvZHJhZ3VsYS9pc3N1ZXMvMTc2XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7IC8vIGZpeGVzIGh0dHBzOi8vZ2l0aHViLmNvbS9iZXZhY3F1YS9kcmFndWxhL2lzc3Vlcy8xNTVcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBzdGFydEJlY2F1c2VNb3VzZU1vdmVkIChlKSB7XG4gICAgaWYgKCFfZ3JhYmJlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAod2hpY2hNb3VzZUJ1dHRvbihlKSA9PT0gMCkge1xuICAgICAgcmVsZWFzZSh7fSk7XG4gICAgICByZXR1cm47IC8vIHdoZW4gdGV4dCBpcyBzZWxlY3RlZCBvbiBhbiBpbnB1dCBhbmQgdGhlbiBkcmFnZ2VkLCBtb3VzZXVwIGRvZXNuJ3QgZmlyZS4gdGhpcyBpcyBvdXIgb25seSBob3BlXG4gICAgfVxuICAgIC8vIHRydXRoeSBjaGVjayBmaXhlcyAjMjM5LCBlcXVhbGl0eSBmaXhlcyAjMjA3XG4gICAgaWYgKGUuY2xpZW50WCAhPT0gdm9pZCAwICYmIGUuY2xpZW50WCA9PT0gX21vdmVYICYmIGUuY2xpZW50WSAhPT0gdm9pZCAwICYmIGUuY2xpZW50WSA9PT0gX21vdmVZKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChvLmlnbm9yZUlucHV0VGV4dFNlbGVjdGlvbikge1xuICAgICAgdmFyIGNsaWVudFggPSBnZXRDb29yZCgnY2xpZW50WCcsIGUpO1xuICAgICAgdmFyIGNsaWVudFkgPSBnZXRDb29yZCgnY2xpZW50WScsIGUpO1xuICAgICAgdmFyIGVsZW1lbnRCZWhpbmRDdXJzb3IgPSBkb2MuZWxlbWVudEZyb21Qb2ludChjbGllbnRYLCBjbGllbnRZKTtcbiAgICAgIGlmIChpc0lucHV0KGVsZW1lbnRCZWhpbmRDdXJzb3IpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgZ3JhYmJlZCA9IF9ncmFiYmVkOyAvLyBjYWxsIHRvIGVuZCgpIHVuc2V0cyBfZ3JhYmJlZFxuICAgIGV2ZW50dWFsTW92ZW1lbnRzKHRydWUpO1xuICAgIG1vdmVtZW50cygpO1xuICAgIGVuZCgpO1xuICAgIHN0YXJ0KGdyYWJiZWQpO1xuXG4gICAgdmFyIG9mZnNldCA9IGdldE9mZnNldChfaXRlbSk7XG4gICAgX29mZnNldFggPSBnZXRDb29yZCgncGFnZVgnLCBlKSAtIG9mZnNldC5sZWZ0O1xuICAgIF9vZmZzZXRZID0gZ2V0Q29vcmQoJ3BhZ2VZJywgZSkgLSBvZmZzZXQudG9wO1xuXG4gICAgY2xhc3Nlcy5hZGQoX2NvcHkgfHwgX2l0ZW0sICdndS10cmFuc2l0Jyk7XG4gICAgcmVuZGVyTWlycm9ySW1hZ2UoKTtcbiAgICBkcmFnKGUpO1xuICB9XG5cbiAgZnVuY3Rpb24gY2FuU3RhcnQgKGl0ZW0pIHtcbiAgICBpZiAoZHJha2UuZHJhZ2dpbmcgJiYgX21pcnJvcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoaXNDb250YWluZXIoaXRlbSkpIHtcbiAgICAgIHJldHVybjsgLy8gZG9uJ3QgZHJhZyBjb250YWluZXIgaXRzZWxmXG4gICAgfVxuICAgIHZhciBoYW5kbGUgPSBpdGVtO1xuICAgIHdoaWxlIChnZXRQYXJlbnQoaXRlbSkgJiYgaXNDb250YWluZXIoZ2V0UGFyZW50KGl0ZW0pKSA9PT0gZmFsc2UpIHtcbiAgICAgIGlmIChvLmludmFsaWQoaXRlbSwgaGFuZGxlKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpdGVtID0gZ2V0UGFyZW50KGl0ZW0pOyAvLyBkcmFnIHRhcmdldCBzaG91bGQgYmUgYSB0b3AgZWxlbWVudFxuICAgICAgaWYgKCFpdGVtKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG4gICAgdmFyIHNvdXJjZSA9IGdldFBhcmVudChpdGVtKTtcbiAgICBpZiAoIXNvdXJjZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoby5pbnZhbGlkKGl0ZW0sIGhhbmRsZSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgbW92YWJsZSA9IG8ubW92ZXMoaXRlbSwgc291cmNlLCBoYW5kbGUsIG5leHRFbChpdGVtKSk7XG4gICAgaWYgKCFtb3ZhYmxlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGl0ZW06IGl0ZW0sXG4gICAgICBzb3VyY2U6IHNvdXJjZVxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBjYW5Nb3ZlIChpdGVtKSB7XG4gICAgcmV0dXJuICEhY2FuU3RhcnQoaXRlbSk7XG4gIH1cblxuICBmdW5jdGlvbiBtYW51YWxTdGFydCAoaXRlbSkge1xuICAgIHZhciBjb250ZXh0ID0gY2FuU3RhcnQoaXRlbSk7XG4gICAgaWYgKGNvbnRleHQpIHtcbiAgICAgIHN0YXJ0KGNvbnRleHQpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHN0YXJ0IChjb250ZXh0KSB7XG4gICAgaWYgKGlzQ29weShjb250ZXh0Lml0ZW0sIGNvbnRleHQuc291cmNlKSkge1xuICAgICAgX2NvcHkgPSBjb250ZXh0Lml0ZW0uY2xvbmVOb2RlKHRydWUpO1xuICAgICAgZHJha2UuZW1pdCgnY2xvbmVkJywgX2NvcHksIGNvbnRleHQuaXRlbSwgJ2NvcHknKTtcbiAgICB9XG5cbiAgICBfc291cmNlID0gY29udGV4dC5zb3VyY2U7XG4gICAgX2l0ZW0gPSBjb250ZXh0Lml0ZW07XG4gICAgX2luaXRpYWxTaWJsaW5nID0gX2N1cnJlbnRTaWJsaW5nID0gbmV4dEVsKGNvbnRleHQuaXRlbSk7XG5cbiAgICBkcmFrZS5kcmFnZ2luZyA9IHRydWU7XG4gICAgZHJha2UuZW1pdCgnZHJhZycsIF9pdGVtLCBfc291cmNlKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGludmFsaWRUYXJnZXQgKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGVuZCAoKSB7XG4gICAgaWYgKCFkcmFrZS5kcmFnZ2luZykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB2YXIgaXRlbSA9IF9jb3B5IHx8IF9pdGVtO1xuICAgIGRyb3AoaXRlbSwgZ2V0UGFyZW50KGl0ZW0pKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHVuZ3JhYiAoKSB7XG4gICAgX2dyYWJiZWQgPSBmYWxzZTtcbiAgICBldmVudHVhbE1vdmVtZW50cyh0cnVlKTtcbiAgICBtb3ZlbWVudHModHJ1ZSk7XG4gIH1cblxuICBmdW5jdGlvbiByZWxlYXNlIChlKSB7XG4gICAgdW5ncmFiKCk7XG5cbiAgICBpZiAoIWRyYWtlLmRyYWdnaW5nKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciBpdGVtID0gX2NvcHkgfHwgX2l0ZW07XG4gICAgdmFyIGNsaWVudFggPSBnZXRDb29yZCgnY2xpZW50WCcsIGUpO1xuICAgIHZhciBjbGllbnRZID0gZ2V0Q29vcmQoJ2NsaWVudFknLCBlKTtcbiAgICB2YXIgZWxlbWVudEJlaGluZEN1cnNvciA9IGdldEVsZW1lbnRCZWhpbmRQb2ludChfbWlycm9yLCBjbGllbnRYLCBjbGllbnRZKTtcbiAgICB2YXIgZHJvcFRhcmdldCA9IGZpbmREcm9wVGFyZ2V0KGVsZW1lbnRCZWhpbmRDdXJzb3IsIGNsaWVudFgsIGNsaWVudFkpO1xuICAgIGlmIChkcm9wVGFyZ2V0ICYmICgoX2NvcHkgJiYgby5jb3B5U29ydFNvdXJjZSkgfHwgKCFfY29weSB8fCBkcm9wVGFyZ2V0ICE9PSBfc291cmNlKSkpIHtcbiAgICAgIGRyb3AoaXRlbSwgZHJvcFRhcmdldCk7XG4gICAgfSBlbHNlIGlmIChvLnJlbW92ZU9uU3BpbGwpIHtcbiAgICAgIHJlbW92ZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjYW5jZWwoKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBkcm9wIChpdGVtLCB0YXJnZXQpIHtcbiAgICB2YXIgcGFyZW50ID0gZ2V0UGFyZW50KGl0ZW0pO1xuICAgIGlmIChfY29weSAmJiBvLmNvcHlTb3J0U291cmNlICYmIHRhcmdldCA9PT0gX3NvdXJjZSkge1xuICAgICAgcGFyZW50LnJlbW92ZUNoaWxkKF9pdGVtKTtcbiAgICB9XG4gICAgaWYgKGlzSW5pdGlhbFBsYWNlbWVudCh0YXJnZXQpKSB7XG4gICAgICBkcmFrZS5lbWl0KCdjYW5jZWwnLCBpdGVtLCBfc291cmNlLCBfc291cmNlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZHJha2UuZW1pdCgnZHJvcCcsIGl0ZW0sIHRhcmdldCwgX3NvdXJjZSwgX2N1cnJlbnRTaWJsaW5nKTtcbiAgICB9XG4gICAgY2xlYW51cCgpO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVtb3ZlICgpIHtcbiAgICBpZiAoIWRyYWtlLmRyYWdnaW5nKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciBpdGVtID0gX2NvcHkgfHwgX2l0ZW07XG4gICAgdmFyIHBhcmVudCA9IGdldFBhcmVudChpdGVtKTtcbiAgICBpZiAocGFyZW50KSB7XG4gICAgICBwYXJlbnQucmVtb3ZlQ2hpbGQoaXRlbSk7XG4gICAgfVxuICAgIGRyYWtlLmVtaXQoX2NvcHkgPyAnY2FuY2VsJyA6ICdyZW1vdmUnLCBpdGVtLCBwYXJlbnQsIF9zb3VyY2UpO1xuICAgIGNsZWFudXAoKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNhbmNlbCAocmV2ZXJ0KSB7XG4gICAgaWYgKCFkcmFrZS5kcmFnZ2luZykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB2YXIgcmV2ZXJ0cyA9IGFyZ3VtZW50cy5sZW5ndGggPiAwID8gcmV2ZXJ0IDogby5yZXZlcnRPblNwaWxsO1xuICAgIHZhciBpdGVtID0gX2NvcHkgfHwgX2l0ZW07XG4gICAgdmFyIHBhcmVudCA9IGdldFBhcmVudChpdGVtKTtcbiAgICB2YXIgaW5pdGlhbCA9IGlzSW5pdGlhbFBsYWNlbWVudChwYXJlbnQpO1xuICAgIGlmIChpbml0aWFsID09PSBmYWxzZSAmJiByZXZlcnRzKSB7XG4gICAgICBpZiAoX2NvcHkpIHtcbiAgICAgICAgaWYgKHBhcmVudCkge1xuICAgICAgICAgIHBhcmVudC5yZW1vdmVDaGlsZChfY29weSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIF9zb3VyY2UuaW5zZXJ0QmVmb3JlKGl0ZW0sIF9pbml0aWFsU2libGluZyk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChpbml0aWFsIHx8IHJldmVydHMpIHtcbiAgICAgIGRyYWtlLmVtaXQoJ2NhbmNlbCcsIGl0ZW0sIF9zb3VyY2UsIF9zb3VyY2UpO1xuICAgIH0gZWxzZSB7XG4gICAgICBkcmFrZS5lbWl0KCdkcm9wJywgaXRlbSwgcGFyZW50LCBfc291cmNlLCBfY3VycmVudFNpYmxpbmcpO1xuICAgIH1cbiAgICBjbGVhbnVwKCk7XG4gIH1cblxuICBmdW5jdGlvbiBjbGVhbnVwICgpIHtcbiAgICB2YXIgaXRlbSA9IF9jb3B5IHx8IF9pdGVtO1xuICAgIHVuZ3JhYigpO1xuICAgIHJlbW92ZU1pcnJvckltYWdlKCk7XG4gICAgaWYgKGl0ZW0pIHtcbiAgICAgIGNsYXNzZXMucm0oaXRlbSwgJ2d1LXRyYW5zaXQnKTtcbiAgICB9XG4gICAgaWYgKF9yZW5kZXJUaW1lcikge1xuICAgICAgY2xlYXJUaW1lb3V0KF9yZW5kZXJUaW1lcik7XG4gICAgfVxuICAgIGRyYWtlLmRyYWdnaW5nID0gZmFsc2U7XG4gICAgaWYgKF9sYXN0RHJvcFRhcmdldCkge1xuICAgICAgZHJha2UuZW1pdCgnb3V0JywgaXRlbSwgX2xhc3REcm9wVGFyZ2V0LCBfc291cmNlKTtcbiAgICB9XG4gICAgZHJha2UuZW1pdCgnZHJhZ2VuZCcsIGl0ZW0pO1xuICAgIF9zb3VyY2UgPSBfaXRlbSA9IF9jb3B5ID0gX2luaXRpYWxTaWJsaW5nID0gX2N1cnJlbnRTaWJsaW5nID0gX3JlbmRlclRpbWVyID0gX2xhc3REcm9wVGFyZ2V0ID0gbnVsbDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzSW5pdGlhbFBsYWNlbWVudCAodGFyZ2V0LCBzKSB7XG4gICAgdmFyIHNpYmxpbmc7XG4gICAgaWYgKHMgIT09IHZvaWQgMCkge1xuICAgICAgc2libGluZyA9IHM7XG4gICAgfSBlbHNlIGlmIChfbWlycm9yKSB7XG4gICAgICBzaWJsaW5nID0gX2N1cnJlbnRTaWJsaW5nO1xuICAgIH0gZWxzZSB7XG4gICAgICBzaWJsaW5nID0gbmV4dEVsKF9jb3B5IHx8IF9pdGVtKTtcbiAgICB9XG4gICAgcmV0dXJuIHRhcmdldCA9PT0gX3NvdXJjZSAmJiBzaWJsaW5nID09PSBfaW5pdGlhbFNpYmxpbmc7XG4gIH1cblxuICBmdW5jdGlvbiBmaW5kRHJvcFRhcmdldCAoZWxlbWVudEJlaGluZEN1cnNvciwgY2xpZW50WCwgY2xpZW50WSkge1xuICAgIHZhciB0YXJnZXQgPSBlbGVtZW50QmVoaW5kQ3Vyc29yO1xuICAgIHdoaWxlICh0YXJnZXQgJiYgIWFjY2VwdGVkKCkpIHtcbiAgICAgIHRhcmdldCA9IGdldFBhcmVudCh0YXJnZXQpO1xuICAgIH1cbiAgICByZXR1cm4gdGFyZ2V0O1xuXG4gICAgZnVuY3Rpb24gYWNjZXB0ZWQgKCkge1xuICAgICAgdmFyIGRyb3BwYWJsZSA9IGlzQ29udGFpbmVyKHRhcmdldCk7XG4gICAgICBpZiAoZHJvcHBhYmxlID09PSBmYWxzZSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIHZhciBpbW1lZGlhdGUgPSBnZXRJbW1lZGlhdGVDaGlsZCh0YXJnZXQsIGVsZW1lbnRCZWhpbmRDdXJzb3IpO1xuICAgICAgdmFyIHJlZmVyZW5jZSA9IGdldFJlZmVyZW5jZSh0YXJnZXQsIGltbWVkaWF0ZSwgY2xpZW50WCwgY2xpZW50WSk7XG4gICAgICB2YXIgaW5pdGlhbCA9IGlzSW5pdGlhbFBsYWNlbWVudCh0YXJnZXQsIHJlZmVyZW5jZSk7XG4gICAgICBpZiAoaW5pdGlhbCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTsgLy8gc2hvdWxkIGFsd2F5cyBiZSBhYmxlIHRvIGRyb3AgaXQgcmlnaHQgYmFjayB3aGVyZSBpdCB3YXNcbiAgICAgIH1cbiAgICAgIHJldHVybiBvLmFjY2VwdHMoX2l0ZW0sIHRhcmdldCwgX3NvdXJjZSwgcmVmZXJlbmNlKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBkcmFnIChlKSB7XG4gICAgaWYgKCFfbWlycm9yKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgIHZhciBjbGllbnRYID0gZ2V0Q29vcmQoJ2NsaWVudFgnLCBlKTtcbiAgICB2YXIgY2xpZW50WSA9IGdldENvb3JkKCdjbGllbnRZJywgZSk7XG4gICAgdmFyIHggPSBjbGllbnRYIC0gX29mZnNldFg7XG4gICAgdmFyIHkgPSBjbGllbnRZIC0gX29mZnNldFk7XG5cbiAgICBfbWlycm9yLnN0eWxlLmxlZnQgPSB4ICsgJ3B4JztcbiAgICBfbWlycm9yLnN0eWxlLnRvcCA9IHkgKyAncHgnO1xuXG4gICAgdmFyIGl0ZW0gPSBfY29weSB8fCBfaXRlbTtcbiAgICB2YXIgZWxlbWVudEJlaGluZEN1cnNvciA9IGdldEVsZW1lbnRCZWhpbmRQb2ludChfbWlycm9yLCBjbGllbnRYLCBjbGllbnRZKTtcbiAgICB2YXIgZHJvcFRhcmdldCA9IGZpbmREcm9wVGFyZ2V0KGVsZW1lbnRCZWhpbmRDdXJzb3IsIGNsaWVudFgsIGNsaWVudFkpO1xuICAgIHZhciBjaGFuZ2VkID0gZHJvcFRhcmdldCAhPT0gbnVsbCAmJiBkcm9wVGFyZ2V0ICE9PSBfbGFzdERyb3BUYXJnZXQ7XG4gICAgaWYgKGNoYW5nZWQgfHwgZHJvcFRhcmdldCA9PT0gbnVsbCkge1xuICAgICAgb3V0KCk7XG4gICAgICBfbGFzdERyb3BUYXJnZXQgPSBkcm9wVGFyZ2V0O1xuICAgICAgb3ZlcigpO1xuICAgIH1cbiAgICB2YXIgcGFyZW50ID0gZ2V0UGFyZW50KGl0ZW0pO1xuICAgIGlmIChkcm9wVGFyZ2V0ID09PSBfc291cmNlICYmIF9jb3B5ICYmICFvLmNvcHlTb3J0U291cmNlKSB7XG4gICAgICBpZiAocGFyZW50KSB7XG4gICAgICAgIHBhcmVudC5yZW1vdmVDaGlsZChpdGVtKTtcbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHJlZmVyZW5jZTtcbiAgICB2YXIgaW1tZWRpYXRlID0gZ2V0SW1tZWRpYXRlQ2hpbGQoZHJvcFRhcmdldCwgZWxlbWVudEJlaGluZEN1cnNvcik7XG4gICAgaWYgKGltbWVkaWF0ZSAhPT0gbnVsbCkge1xuICAgICAgcmVmZXJlbmNlID0gZ2V0UmVmZXJlbmNlKGRyb3BUYXJnZXQsIGltbWVkaWF0ZSwgY2xpZW50WCwgY2xpZW50WSk7XG4gICAgfSBlbHNlIGlmIChvLnJldmVydE9uU3BpbGwgPT09IHRydWUgJiYgIV9jb3B5KSB7XG4gICAgICByZWZlcmVuY2UgPSBfaW5pdGlhbFNpYmxpbmc7XG4gICAgICBkcm9wVGFyZ2V0ID0gX3NvdXJjZTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKF9jb3B5ICYmIHBhcmVudCkge1xuICAgICAgICBwYXJlbnQucmVtb3ZlQ2hpbGQoaXRlbSk7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChcbiAgICAgIChyZWZlcmVuY2UgPT09IG51bGwgJiYgY2hhbmdlZCkgfHxcbiAgICAgIHJlZmVyZW5jZSAhPT0gaXRlbSAmJlxuICAgICAgcmVmZXJlbmNlICE9PSBuZXh0RWwoaXRlbSlcbiAgICApIHtcbiAgICAgIF9jdXJyZW50U2libGluZyA9IHJlZmVyZW5jZTtcbiAgICAgIGRyb3BUYXJnZXQuaW5zZXJ0QmVmb3JlKGl0ZW0sIHJlZmVyZW5jZSk7XG4gICAgICBkcmFrZS5lbWl0KCdzaGFkb3cnLCBpdGVtLCBkcm9wVGFyZ2V0LCBfc291cmNlKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gbW92ZWQgKHR5cGUpIHsgZHJha2UuZW1pdCh0eXBlLCBpdGVtLCBfbGFzdERyb3BUYXJnZXQsIF9zb3VyY2UpOyB9XG4gICAgZnVuY3Rpb24gb3ZlciAoKSB7IGlmIChjaGFuZ2VkKSB7IG1vdmVkKCdvdmVyJyk7IH0gfVxuICAgIGZ1bmN0aW9uIG91dCAoKSB7IGlmIChfbGFzdERyb3BUYXJnZXQpIHsgbW92ZWQoJ291dCcpOyB9IH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHNwaWxsT3ZlciAoZWwpIHtcbiAgICBjbGFzc2VzLnJtKGVsLCAnZ3UtaGlkZScpO1xuICB9XG5cbiAgZnVuY3Rpb24gc3BpbGxPdXQgKGVsKSB7XG4gICAgaWYgKGRyYWtlLmRyYWdnaW5nKSB7IGNsYXNzZXMuYWRkKGVsLCAnZ3UtaGlkZScpOyB9XG4gIH1cblxuICBmdW5jdGlvbiByZW5kZXJNaXJyb3JJbWFnZSAoKSB7XG4gICAgaWYgKF9taXJyb3IpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHJlY3QgPSBfaXRlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICBfbWlycm9yID0gX2l0ZW0uY2xvbmVOb2RlKHRydWUpO1xuICAgIF9taXJyb3Iuc3R5bGUud2lkdGggPSBnZXRSZWN0V2lkdGgocmVjdCkgKyAncHgnO1xuICAgIF9taXJyb3Iuc3R5bGUuaGVpZ2h0ID0gZ2V0UmVjdEhlaWdodChyZWN0KSArICdweCc7XG4gICAgY2xhc3Nlcy5ybShfbWlycm9yLCAnZ3UtdHJhbnNpdCcpO1xuICAgIGNsYXNzZXMuYWRkKF9taXJyb3IsICdndS1taXJyb3InKTtcbiAgICBvLm1pcnJvckNvbnRhaW5lci5hcHBlbmRDaGlsZChfbWlycm9yKTtcbiAgICB0b3VjaHkoZG9jdW1lbnRFbGVtZW50LCAnYWRkJywgJ21vdXNlbW92ZScsIGRyYWcpO1xuICAgIGNsYXNzZXMuYWRkKG8ubWlycm9yQ29udGFpbmVyLCAnZ3UtdW5zZWxlY3RhYmxlJyk7XG4gICAgZHJha2UuZW1pdCgnY2xvbmVkJywgX21pcnJvciwgX2l0ZW0sICdtaXJyb3InKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlbW92ZU1pcnJvckltYWdlICgpIHtcbiAgICBpZiAoX21pcnJvcikge1xuICAgICAgY2xhc3Nlcy5ybShvLm1pcnJvckNvbnRhaW5lciwgJ2d1LXVuc2VsZWN0YWJsZScpO1xuICAgICAgdG91Y2h5KGRvY3VtZW50RWxlbWVudCwgJ3JlbW92ZScsICdtb3VzZW1vdmUnLCBkcmFnKTtcbiAgICAgIGdldFBhcmVudChfbWlycm9yKS5yZW1vdmVDaGlsZChfbWlycm9yKTtcbiAgICAgIF9taXJyb3IgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGdldEltbWVkaWF0ZUNoaWxkIChkcm9wVGFyZ2V0LCB0YXJnZXQpIHtcbiAgICB2YXIgaW1tZWRpYXRlID0gdGFyZ2V0O1xuICAgIHdoaWxlIChpbW1lZGlhdGUgIT09IGRyb3BUYXJnZXQgJiYgZ2V0UGFyZW50KGltbWVkaWF0ZSkgIT09IGRyb3BUYXJnZXQpIHtcbiAgICAgIGltbWVkaWF0ZSA9IGdldFBhcmVudChpbW1lZGlhdGUpO1xuICAgIH1cbiAgICBpZiAoaW1tZWRpYXRlID09PSBkb2N1bWVudEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gaW1tZWRpYXRlO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0UmVmZXJlbmNlIChkcm9wVGFyZ2V0LCB0YXJnZXQsIHgsIHkpIHtcbiAgICB2YXIgaG9yaXpvbnRhbCA9IG8uZGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCc7XG4gICAgdmFyIHJlZmVyZW5jZSA9IHRhcmdldCAhPT0gZHJvcFRhcmdldCA/IGluc2lkZSgpIDogb3V0c2lkZSgpO1xuICAgIHJldHVybiByZWZlcmVuY2U7XG5cbiAgICBmdW5jdGlvbiBvdXRzaWRlICgpIHsgLy8gc2xvd2VyLCBidXQgYWJsZSB0byBmaWd1cmUgb3V0IGFueSBwb3NpdGlvblxuICAgICAgdmFyIGxlbiA9IGRyb3BUYXJnZXQuY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgdmFyIGk7XG4gICAgICB2YXIgZWw7XG4gICAgICB2YXIgcmVjdDtcbiAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICBlbCA9IGRyb3BUYXJnZXQuY2hpbGRyZW5baV07XG4gICAgICAgIHJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgaWYgKGhvcml6b250YWwgJiYgKHJlY3QubGVmdCArIHJlY3Qud2lkdGggLyAyKSA+IHgpIHsgcmV0dXJuIGVsOyB9XG4gICAgICAgIGlmICghaG9yaXpvbnRhbCAmJiAocmVjdC50b3AgKyByZWN0LmhlaWdodCAvIDIpID4geSkgeyByZXR1cm4gZWw7IH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGluc2lkZSAoKSB7IC8vIGZhc3RlciwgYnV0IG9ubHkgYXZhaWxhYmxlIGlmIGRyb3BwZWQgaW5zaWRlIGEgY2hpbGQgZWxlbWVudFxuICAgICAgdmFyIHJlY3QgPSB0YXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICBpZiAoaG9yaXpvbnRhbCkge1xuICAgICAgICByZXR1cm4gcmVzb2x2ZSh4ID4gcmVjdC5sZWZ0ICsgZ2V0UmVjdFdpZHRoKHJlY3QpIC8gMik7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzb2x2ZSh5ID4gcmVjdC50b3AgKyBnZXRSZWN0SGVpZ2h0KHJlY3QpIC8gMik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVzb2x2ZSAoYWZ0ZXIpIHtcbiAgICAgIHJldHVybiBhZnRlciA/IG5leHRFbCh0YXJnZXQpIDogdGFyZ2V0O1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGlzQ29weSAoaXRlbSwgY29udGFpbmVyKSB7XG4gICAgcmV0dXJuIHR5cGVvZiBvLmNvcHkgPT09ICdib29sZWFuJyA/IG8uY29weSA6IG8uY29weShpdGVtLCBjb250YWluZXIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRvdWNoeSAoZWwsIG9wLCB0eXBlLCBmbikge1xuICB2YXIgdG91Y2ggPSB7XG4gICAgbW91c2V1cDogJ3RvdWNoZW5kJyxcbiAgICBtb3VzZWRvd246ICd0b3VjaHN0YXJ0JyxcbiAgICBtb3VzZW1vdmU6ICd0b3VjaG1vdmUnXG4gIH07XG4gIHZhciBwb2ludGVycyA9IHtcbiAgICBtb3VzZXVwOiAncG9pbnRlcnVwJyxcbiAgICBtb3VzZWRvd246ICdwb2ludGVyZG93bicsXG4gICAgbW91c2Vtb3ZlOiAncG9pbnRlcm1vdmUnXG4gIH07XG4gIHZhciBtaWNyb3NvZnQgPSB7XG4gICAgbW91c2V1cDogJ01TUG9pbnRlclVwJyxcbiAgICBtb3VzZWRvd246ICdNU1BvaW50ZXJEb3duJyxcbiAgICBtb3VzZW1vdmU6ICdNU1BvaW50ZXJNb3ZlJ1xuICB9O1xuICBpZiAoZ2xvYmFsLm5hdmlnYXRvci5wb2ludGVyRW5hYmxlZCkge1xuICAgIGNyb3NzdmVudFtvcF0oZWwsIHBvaW50ZXJzW3R5cGVdLCBmbik7XG4gIH0gZWxzZSBpZiAoZ2xvYmFsLm5hdmlnYXRvci5tc1BvaW50ZXJFbmFibGVkKSB7XG4gICAgY3Jvc3N2ZW50W29wXShlbCwgbWljcm9zb2Z0W3R5cGVdLCBmbik7XG4gIH0gZWxzZSB7XG4gICAgY3Jvc3N2ZW50W29wXShlbCwgdG91Y2hbdHlwZV0sIGZuKTtcbiAgICBjcm9zc3ZlbnRbb3BdKGVsLCB0eXBlLCBmbik7XG4gIH1cbn1cblxuZnVuY3Rpb24gd2hpY2hNb3VzZUJ1dHRvbiAoZSkge1xuICBpZiAoZS50b3VjaGVzICE9PSB2b2lkIDApIHsgcmV0dXJuIGUudG91Y2hlcy5sZW5ndGg7IH1cbiAgaWYgKGUud2hpY2ggIT09IHZvaWQgMCAmJiBlLndoaWNoICE9PSAwKSB7IHJldHVybiBlLndoaWNoOyB9IC8vIHNlZSBodHRwczovL2dpdGh1Yi5jb20vYmV2YWNxdWEvZHJhZ3VsYS9pc3N1ZXMvMjYxXG4gIGlmIChlLmJ1dHRvbnMgIT09IHZvaWQgMCkgeyByZXR1cm4gZS5idXR0b25zOyB9XG4gIHZhciBidXR0b24gPSBlLmJ1dHRvbjtcbiAgaWYgKGJ1dHRvbiAhPT0gdm9pZCAwKSB7IC8vIHNlZSBodHRwczovL2dpdGh1Yi5jb20vanF1ZXJ5L2pxdWVyeS9ibG9iLzk5ZThmZjFiYWE3YWUzNDFlOTRiYjg5YzNlODQ1NzBjN2MzYWQ5ZWEvc3JjL2V2ZW50LmpzI0w1NzMtTDU3NVxuICAgIHJldHVybiBidXR0b24gJiAxID8gMSA6IGJ1dHRvbiAmIDIgPyAzIDogKGJ1dHRvbiAmIDQgPyAyIDogMCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZ2V0T2Zmc2V0IChlbCkge1xuICB2YXIgcmVjdCA9IGVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICByZXR1cm4ge1xuICAgIGxlZnQ6IHJlY3QubGVmdCArIGdldFNjcm9sbCgnc2Nyb2xsTGVmdCcsICdwYWdlWE9mZnNldCcpLFxuICAgIHRvcDogcmVjdC50b3AgKyBnZXRTY3JvbGwoJ3Njcm9sbFRvcCcsICdwYWdlWU9mZnNldCcpXG4gIH07XG59XG5cbmZ1bmN0aW9uIGdldFNjcm9sbCAoc2Nyb2xsUHJvcCwgb2Zmc2V0UHJvcCkge1xuICBpZiAodHlwZW9mIGdsb2JhbFtvZmZzZXRQcm9wXSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gZ2xvYmFsW29mZnNldFByb3BdO1xuICB9XG4gIGlmIChkb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0KSB7XG4gICAgcmV0dXJuIGRvY3VtZW50RWxlbWVudFtzY3JvbGxQcm9wXTtcbiAgfVxuICByZXR1cm4gZG9jLmJvZHlbc2Nyb2xsUHJvcF07XG59XG5cbmZ1bmN0aW9uIGdldEVsZW1lbnRCZWhpbmRQb2ludCAocG9pbnQsIHgsIHkpIHtcbiAgdmFyIHAgPSBwb2ludCB8fCB7fTtcbiAgdmFyIHN0YXRlID0gcC5jbGFzc05hbWU7XG4gIHZhciBlbDtcbiAgcC5jbGFzc05hbWUgKz0gJyBndS1oaWRlJztcbiAgZWwgPSBkb2MuZWxlbWVudEZyb21Qb2ludCh4LCB5KTtcbiAgcC5jbGFzc05hbWUgPSBzdGF0ZTtcbiAgcmV0dXJuIGVsO1xufVxuXG5mdW5jdGlvbiBuZXZlciAoKSB7IHJldHVybiBmYWxzZTsgfVxuZnVuY3Rpb24gYWx3YXlzICgpIHsgcmV0dXJuIHRydWU7IH1cbmZ1bmN0aW9uIGdldFJlY3RXaWR0aCAocmVjdCkgeyByZXR1cm4gcmVjdC53aWR0aCB8fCAocmVjdC5yaWdodCAtIHJlY3QubGVmdCk7IH1cbmZ1bmN0aW9uIGdldFJlY3RIZWlnaHQgKHJlY3QpIHsgcmV0dXJuIHJlY3QuaGVpZ2h0IHx8IChyZWN0LmJvdHRvbSAtIHJlY3QudG9wKTsgfVxuZnVuY3Rpb24gZ2V0UGFyZW50IChlbCkgeyByZXR1cm4gZWwucGFyZW50Tm9kZSA9PT0gZG9jID8gbnVsbCA6IGVsLnBhcmVudE5vZGU7IH1cbmZ1bmN0aW9uIGlzSW5wdXQgKGVsKSB7IHJldHVybiBlbC50YWdOYW1lID09PSAnSU5QVVQnIHx8IGVsLnRhZ05hbWUgPT09ICdURVhUQVJFQScgfHwgZWwudGFnTmFtZSA9PT0gJ1NFTEVDVCcgfHwgaXNFZGl0YWJsZShlbCk7IH1cbmZ1bmN0aW9uIGlzRWRpdGFibGUgKGVsKSB7XG4gIGlmICghZWwpIHsgcmV0dXJuIGZhbHNlOyB9IC8vIG5vIHBhcmVudHMgd2VyZSBlZGl0YWJsZVxuICBpZiAoZWwuY29udGVudEVkaXRhYmxlID09PSAnZmFsc2UnKSB7IHJldHVybiBmYWxzZTsgfSAvLyBzdG9wIHRoZSBsb29rdXBcbiAgaWYgKGVsLmNvbnRlbnRFZGl0YWJsZSA9PT0gJ3RydWUnKSB7IHJldHVybiB0cnVlOyB9IC8vIGZvdW5kIGEgY29udGVudEVkaXRhYmxlIGVsZW1lbnQgaW4gdGhlIGNoYWluXG4gIHJldHVybiBpc0VkaXRhYmxlKGdldFBhcmVudChlbCkpOyAvLyBjb250ZW50RWRpdGFibGUgaXMgc2V0IHRvICdpbmhlcml0J1xufVxuXG5mdW5jdGlvbiBuZXh0RWwgKGVsKSB7XG4gIHJldHVybiBlbC5uZXh0RWxlbWVudFNpYmxpbmcgfHwgbWFudWFsbHkoKTtcbiAgZnVuY3Rpb24gbWFudWFsbHkgKCkge1xuICAgIHZhciBzaWJsaW5nID0gZWw7XG4gICAgZG8ge1xuICAgICAgc2libGluZyA9IHNpYmxpbmcubmV4dFNpYmxpbmc7XG4gICAgfSB3aGlsZSAoc2libGluZyAmJiBzaWJsaW5nLm5vZGVUeXBlICE9PSAxKTtcbiAgICByZXR1cm4gc2libGluZztcbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRFdmVudEhvc3QgKGUpIHtcbiAgLy8gb24gdG91Y2hlbmQgZXZlbnQsIHdlIGhhdmUgdG8gdXNlIGBlLmNoYW5nZWRUb3VjaGVzYFxuICAvLyBzZWUgaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy83MTkyNTYzL3RvdWNoZW5kLWV2ZW50LXByb3BlcnRpZXNcbiAgLy8gc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9iZXZhY3F1YS9kcmFndWxhL2lzc3Vlcy8zNFxuICBpZiAoZS50YXJnZXRUb3VjaGVzICYmIGUudGFyZ2V0VG91Y2hlcy5sZW5ndGgpIHtcbiAgICByZXR1cm4gZS50YXJnZXRUb3VjaGVzWzBdO1xuICB9XG4gIGlmIChlLmNoYW5nZWRUb3VjaGVzICYmIGUuY2hhbmdlZFRvdWNoZXMubGVuZ3RoKSB7XG4gICAgcmV0dXJuIGUuY2hhbmdlZFRvdWNoZXNbMF07XG4gIH1cbiAgcmV0dXJuIGU7XG59XG5cbmZ1bmN0aW9uIGdldENvb3JkIChjb29yZCwgZSkge1xuICB2YXIgaG9zdCA9IGdldEV2ZW50SG9zdChlKTtcbiAgdmFyIG1pc3NNYXAgPSB7XG4gICAgcGFnZVg6ICdjbGllbnRYJywgLy8gSUU4XG4gICAgcGFnZVk6ICdjbGllbnRZJyAvLyBJRThcbiAgfTtcbiAgaWYgKGNvb3JkIGluIG1pc3NNYXAgJiYgIShjb29yZCBpbiBob3N0KSAmJiBtaXNzTWFwW2Nvb3JkXSBpbiBob3N0KSB7XG4gICAgY29vcmQgPSBtaXNzTWFwW2Nvb3JkXTtcbiAgfVxuICByZXR1cm4gaG9zdFtjb29yZF07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZHJhZ3VsYTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9kcmFndWxhL2RyYWd1bGEuanNcbi8vIG1vZHVsZSBpZCA9IDc3XG4vLyBtb2R1bGUgY2h1bmtzID0gMCJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ },
- /* 78 */
- /***/ function(module, exports, __webpack_require__) {
- eval("'use strict';\n\nvar atoa = __webpack_require__(79);\nvar debounce = __webpack_require__(80);\n\nmodule.exports = function emitter (thing, options) {\n var opts = options || {};\n var evt = {};\n if (thing === undefined) { thing = {}; }\n thing.on = function (type, fn) {\n if (!evt[type]) {\n evt[type] = [fn];\n } else {\n evt[type].push(fn);\n }\n return thing;\n };\n thing.once = function (type, fn) {\n fn._once = true; // thing.off(fn) still works!\n thing.on(type, fn);\n return thing;\n };\n thing.off = function (type, fn) {\n var c = arguments.length;\n if (c === 1) {\n delete evt[type];\n } else if (c === 0) {\n evt = {};\n } else {\n var et = evt[type];\n if (!et) { return thing; }\n et.splice(et.indexOf(fn), 1);\n }\n return thing;\n };\n thing.emit = function () {\n var args = atoa(arguments);\n return thing.emitterSnapshot(args.shift()).apply(this, args);\n };\n thing.emitterSnapshot = function (type) {\n var et = (evt[type] || []).slice(0);\n return function () {\n var args = atoa(arguments);\n var ctx = this || thing;\n if (type === 'error' && opts.throws !== false && !et.length) { throw args.length === 1 ? args[0] : args; }\n et.forEach(function emitter (listen) {\n if (opts.async) { debounce(listen, args, ctx); } else { listen.apply(ctx, args); }\n if (listen._once) { thing.off(type, listen); }\n });\n return thing;\n };\n };\n return thing;\n};\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNzguanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2NvbnRyYS9lbWl0dGVyLmpzP2I0MjEiXSwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYXRvYSA9IHJlcXVpcmUoJ2F0b2EnKTtcbnZhciBkZWJvdW5jZSA9IHJlcXVpcmUoJy4vZGVib3VuY2UnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBlbWl0dGVyICh0aGluZywgb3B0aW9ucykge1xuICB2YXIgb3B0cyA9IG9wdGlvbnMgfHwge307XG4gIHZhciBldnQgPSB7fTtcbiAgaWYgKHRoaW5nID09PSB1bmRlZmluZWQpIHsgdGhpbmcgPSB7fTsgfVxuICB0aGluZy5vbiA9IGZ1bmN0aW9uICh0eXBlLCBmbikge1xuICAgIGlmICghZXZ0W3R5cGVdKSB7XG4gICAgICBldnRbdHlwZV0gPSBbZm5dO1xuICAgIH0gZWxzZSB7XG4gICAgICBldnRbdHlwZV0ucHVzaChmbik7XG4gICAgfVxuICAgIHJldHVybiB0aGluZztcbiAgfTtcbiAgdGhpbmcub25jZSA9IGZ1bmN0aW9uICh0eXBlLCBmbikge1xuICAgIGZuLl9vbmNlID0gdHJ1ZTsgLy8gdGhpbmcub2ZmKGZuKSBzdGlsbCB3b3JrcyFcbiAgICB0aGluZy5vbih0eXBlLCBmbik7XG4gICAgcmV0dXJuIHRoaW5nO1xuICB9O1xuICB0aGluZy5vZmYgPSBmdW5jdGlvbiAodHlwZSwgZm4pIHtcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgaWYgKGMgPT09IDEpIHtcbiAgICAgIGRlbGV0ZSBldnRbdHlwZV07XG4gICAgfSBlbHNlIGlmIChjID09PSAwKSB7XG4gICAgICBldnQgPSB7fTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGV0ID0gZXZ0W3R5cGVdO1xuICAgICAgaWYgKCFldCkgeyByZXR1cm4gdGhpbmc7IH1cbiAgICAgIGV0LnNwbGljZShldC5pbmRleE9mKGZuKSwgMSk7XG4gICAgfVxuICAgIHJldHVybiB0aGluZztcbiAgfTtcbiAgdGhpbmcuZW1pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgYXJncyA9IGF0b2EoYXJndW1lbnRzKTtcbiAgICByZXR1cm4gdGhpbmcuZW1pdHRlclNuYXBzaG90KGFyZ3Muc2hpZnQoKSkuYXBwbHkodGhpcywgYXJncyk7XG4gIH07XG4gIHRoaW5nLmVtaXR0ZXJTbmFwc2hvdCA9IGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgdmFyIGV0ID0gKGV2dFt0eXBlXSB8fCBbXSkuc2xpY2UoMCk7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBhcmdzID0gYXRvYShhcmd1bWVudHMpO1xuICAgICAgdmFyIGN0eCA9IHRoaXMgfHwgdGhpbmc7XG4gICAgICBpZiAodHlwZSA9PT0gJ2Vycm9yJyAmJiBvcHRzLnRocm93cyAhPT0gZmFsc2UgJiYgIWV0Lmxlbmd0aCkgeyB0aHJvdyBhcmdzLmxlbmd0aCA9PT0gMSA/IGFyZ3NbMF0gOiBhcmdzOyB9XG4gICAgICBldC5mb3JFYWNoKGZ1bmN0aW9uIGVtaXR0ZXIgKGxpc3Rlbikge1xuICAgICAgICBpZiAob3B0cy5hc3luYykgeyBkZWJvdW5jZShsaXN0ZW4sIGFyZ3MsIGN0eCk7IH0gZWxzZSB7IGxpc3Rlbi5hcHBseShjdHgsIGFyZ3MpOyB9XG4gICAgICAgIGlmIChsaXN0ZW4uX29uY2UpIHsgdGhpbmcub2ZmKHR5cGUsIGxpc3Rlbik7IH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHRoaW5nO1xuICAgIH07XG4gIH07XG4gIHJldHVybiB0aGluZztcbn07XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vY29udHJhL2VtaXR0ZXIuanNcbi8vIG1vZHVsZSBpZCA9IDc4XG4vLyBtb2R1bGUgY2h1bmtzID0gMCJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOyIsInNvdXJjZVJvb3QiOiIifQ==");
- /***/ },
- /* 79 */
- /***/ function(module, exports) {
- eval("module.exports = function atoa (a, n) { return Array.prototype.slice.call(a, n); }\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNzkuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2F0b2EvYXRvYS5qcz81MzJiIl0sInNvdXJjZXNDb250ZW50IjpbIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gYXRvYSAoYSwgbikgeyByZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYSwgbik7IH1cblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9hdG9hL2F0b2EuanNcbi8vIG1vZHVsZSBpZCA9IDc5XG4vLyBtb2R1bGUgY2h1bmtzID0gMCJdLCJtYXBwaW5ncyI6IkFBQUE7Iiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 80 */
- /***/ function(module, exports, __webpack_require__) {
- eval("'use strict';\n\nvar ticky = __webpack_require__(81);\n\nmodule.exports = function debounce (fn, args, ctx) {\n if (!fn) { return; }\n ticky(function run () {\n fn.apply(ctx || null, args || []);\n });\n};\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiODAuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2NvbnRyYS9kZWJvdW5jZS5qcz9hZWMyIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxudmFyIHRpY2t5ID0gcmVxdWlyZSgndGlja3knKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBkZWJvdW5jZSAoZm4sIGFyZ3MsIGN0eCkge1xuICBpZiAoIWZuKSB7IHJldHVybjsgfVxuICB0aWNreShmdW5jdGlvbiBydW4gKCkge1xuICAgIGZuLmFwcGx5KGN0eCB8fCBudWxsLCBhcmdzIHx8IFtdKTtcbiAgfSk7XG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2NvbnRyYS9kZWJvdW5jZS5qc1xuLy8gbW9kdWxlIGlkID0gODBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ },
- /* 81 */
- /***/ function(module, exports, __webpack_require__) {
- eval("/* WEBPACK VAR INJECTION */(function(setImmediate) {var si = typeof setImmediate === 'function', tick;\nif (si) {\n tick = function (fn) { setImmediate(fn); };\n} else {\n tick = function (fn) { setTimeout(fn, 0); };\n}\n\nmodule.exports = tick;\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(82).setImmediate))//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiODEuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L3RpY2t5L3RpY2t5LWJyb3dzZXIuanM/MDFmZiJdLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgc2kgPSB0eXBlb2Ygc2V0SW1tZWRpYXRlID09PSAnZnVuY3Rpb24nLCB0aWNrO1xuaWYgKHNpKSB7XG4gIHRpY2sgPSBmdW5jdGlvbiAoZm4pIHsgc2V0SW1tZWRpYXRlKGZuKTsgfTtcbn0gZWxzZSB7XG4gIHRpY2sgPSBmdW5jdGlvbiAoZm4pIHsgc2V0VGltZW91dChmbiwgMCk7IH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdGljaztcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vdGlja3kvdGlja3ktYnJvd3Nlci5qc1xuLy8gbW9kdWxlIGlkID0gODFcbi8vIG1vZHVsZSBjaHVua3MgPSAwIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ },
- /* 82 */,
- /* 83 */,
- /* 84 */
- /***/ function(module, exports, __webpack_require__) {
- eval("/* WEBPACK VAR INJECTION */(function(global) {'use strict';\n\nvar customEvent = __webpack_require__(85);\nvar eventmap = __webpack_require__(86);\nvar doc = global.document;\nvar addEvent = addEventEasy;\nvar removeEvent = removeEventEasy;\nvar hardCache = [];\n\nif (!global.addEventListener) {\n addEvent = addEventHard;\n removeEvent = removeEventHard;\n}\n\nmodule.exports = {\n add: addEvent,\n remove: removeEvent,\n fabricate: fabricateEvent\n};\n\nfunction addEventEasy (el, type, fn, capturing) {\n return el.addEventListener(type, fn, capturing);\n}\n\nfunction addEventHard (el, type, fn) {\n return el.attachEvent('on' + type, wrap(el, type, fn));\n}\n\nfunction removeEventEasy (el, type, fn, capturing) {\n return el.removeEventListener(type, fn, capturing);\n}\n\nfunction removeEventHard (el, type, fn) {\n var listener = unwrap(el, type, fn);\n if (listener) {\n return el.detachEvent('on' + type, listener);\n }\n}\n\nfunction fabricateEvent (el, type, model) {\n var e = eventmap.indexOf(type) === -1 ? makeCustomEvent() : makeClassicEvent();\n if (el.dispatchEvent) {\n el.dispatchEvent(e);\n } else {\n el.fireEvent('on' + type, e);\n }\n function makeClassicEvent () {\n var e;\n if (doc.createEvent) {\n e = doc.createEvent('Event');\n e.initEvent(type, true, true);\n } else if (doc.createEventObject) {\n e = doc.createEventObject();\n }\n return e;\n }\n function makeCustomEvent () {\n return new customEvent(type, { detail: model });\n }\n}\n\nfunction wrapperFactory (el, type, fn) {\n return function wrapper (originalEvent) {\n var e = originalEvent || global.event;\n e.target = e.target || e.srcElement;\n e.preventDefault = e.preventDefault || function preventDefault () { e.returnValue = false; };\n e.stopPropagation = e.stopPropagation || function stopPropagation () { e.cancelBubble = true; };\n e.which = e.which || e.keyCode;\n fn.call(el, e);\n };\n}\n\nfunction wrap (el, type, fn) {\n var wrapper = unwrap(el, type, fn) || wrapperFactory(el, type, fn);\n hardCache.push({\n wrapper: wrapper,\n element: el,\n type: type,\n fn: fn\n });\n return wrapper;\n}\n\nfunction unwrap (el, type, fn) {\n var i = find(el, type, fn);\n if (i) {\n var wrapper = hardCache[i].wrapper;\n hardCache.splice(i, 1); // free up a tad of memory\n return wrapper;\n }\n}\n\nfunction find (el, type, fn) {\n var i, item;\n for (i = 0; i < hardCache.length; i++) {\n item = hardCache[i];\n if (item.element === el && item.type === type && item.fn === fn) {\n return i;\n }\n }\n}\n\n/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiODQuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2Nyb3NzdmVudC9zcmMvY3Jvc3N2ZW50LmpzPzUzNzkiXSwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG52YXIgY3VzdG9tRXZlbnQgPSByZXF1aXJlKCdjdXN0b20tZXZlbnQnKTtcbnZhciBldmVudG1hcCA9IHJlcXVpcmUoJy4vZXZlbnRtYXAnKTtcbnZhciBkb2MgPSBnbG9iYWwuZG9jdW1lbnQ7XG52YXIgYWRkRXZlbnQgPSBhZGRFdmVudEVhc3k7XG52YXIgcmVtb3ZlRXZlbnQgPSByZW1vdmVFdmVudEVhc3k7XG52YXIgaGFyZENhY2hlID0gW107XG5cbmlmICghZ2xvYmFsLmFkZEV2ZW50TGlzdGVuZXIpIHtcbiAgYWRkRXZlbnQgPSBhZGRFdmVudEhhcmQ7XG4gIHJlbW92ZUV2ZW50ID0gcmVtb3ZlRXZlbnRIYXJkO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgYWRkOiBhZGRFdmVudCxcbiAgcmVtb3ZlOiByZW1vdmVFdmVudCxcbiAgZmFicmljYXRlOiBmYWJyaWNhdGVFdmVudFxufTtcblxuZnVuY3Rpb24gYWRkRXZlbnRFYXN5IChlbCwgdHlwZSwgZm4sIGNhcHR1cmluZykge1xuICByZXR1cm4gZWwuYWRkRXZlbnRMaXN0ZW5lcih0eXBlLCBmbiwgY2FwdHVyaW5nKTtcbn1cblxuZnVuY3Rpb24gYWRkRXZlbnRIYXJkIChlbCwgdHlwZSwgZm4pIHtcbiAgcmV0dXJuIGVsLmF0dGFjaEV2ZW50KCdvbicgKyB0eXBlLCB3cmFwKGVsLCB0eXBlLCBmbikpO1xufVxuXG5mdW5jdGlvbiByZW1vdmVFdmVudEVhc3kgKGVsLCB0eXBlLCBmbiwgY2FwdHVyaW5nKSB7XG4gIHJldHVybiBlbC5yZW1vdmVFdmVudExpc3RlbmVyKHR5cGUsIGZuLCBjYXB0dXJpbmcpO1xufVxuXG5mdW5jdGlvbiByZW1vdmVFdmVudEhhcmQgKGVsLCB0eXBlLCBmbikge1xuICB2YXIgbGlzdGVuZXIgPSB1bndyYXAoZWwsIHR5cGUsIGZuKTtcbiAgaWYgKGxpc3RlbmVyKSB7XG4gICAgcmV0dXJuIGVsLmRldGFjaEV2ZW50KCdvbicgKyB0eXBlLCBsaXN0ZW5lcik7XG4gIH1cbn1cblxuZnVuY3Rpb24gZmFicmljYXRlRXZlbnQgKGVsLCB0eXBlLCBtb2RlbCkge1xuICB2YXIgZSA9IGV2ZW50bWFwLmluZGV4T2YodHlwZSkgPT09IC0xID8gbWFrZUN1c3RvbUV2ZW50KCkgOiBtYWtlQ2xhc3NpY0V2ZW50KCk7XG4gIGlmIChlbC5kaXNwYXRjaEV2ZW50KSB7XG4gICAgZWwuZGlzcGF0Y2hFdmVudChlKTtcbiAgfSBlbHNlIHtcbiAgICBlbC5maXJlRXZlbnQoJ29uJyArIHR5cGUsIGUpO1xuICB9XG4gIGZ1bmN0aW9uIG1ha2VDbGFzc2ljRXZlbnQgKCkge1xuICAgIHZhciBlO1xuICAgIGlmIChkb2MuY3JlYXRlRXZlbnQpIHtcbiAgICAgIGUgPSBkb2MuY3JlYXRlRXZlbnQoJ0V2ZW50Jyk7XG4gICAgICBlLmluaXRFdmVudCh0eXBlLCB0cnVlLCB0cnVlKTtcbiAgICB9IGVsc2UgaWYgKGRvYy5jcmVhdGVFdmVudE9iamVjdCkge1xuICAgICAgZSA9IGRvYy5jcmVhdGVFdmVudE9iamVjdCgpO1xuICAgIH1cbiAgICByZXR1cm4gZTtcbiAgfVxuICBmdW5jdGlvbiBtYWtlQ3VzdG9tRXZlbnQgKCkge1xuICAgIHJldHVybiBuZXcgY3VzdG9tRXZlbnQodHlwZSwgeyBkZXRhaWw6IG1vZGVsIH0pO1xuICB9XG59XG5cbmZ1bmN0aW9uIHdyYXBwZXJGYWN0b3J5IChlbCwgdHlwZSwgZm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIHdyYXBwZXIgKG9yaWdpbmFsRXZlbnQpIHtcbiAgICB2YXIgZSA9IG9yaWdpbmFsRXZlbnQgfHwgZ2xvYmFsLmV2ZW50O1xuICAgIGUudGFyZ2V0ID0gZS50YXJnZXQgfHwgZS5zcmNFbGVtZW50O1xuICAgIGUucHJldmVudERlZmF1bHQgPSBlLnByZXZlbnREZWZhdWx0IHx8IGZ1bmN0aW9uIHByZXZlbnREZWZhdWx0ICgpIHsgZS5yZXR1cm5WYWx1ZSA9IGZhbHNlOyB9O1xuICAgIGUuc3RvcFByb3BhZ2F0aW9uID0gZS5zdG9wUHJvcGFnYXRpb24gfHwgZnVuY3Rpb24gc3RvcFByb3BhZ2F0aW9uICgpIHsgZS5jYW5jZWxCdWJibGUgPSB0cnVlOyB9O1xuICAgIGUud2hpY2ggPSBlLndoaWNoIHx8IGUua2V5Q29kZTtcbiAgICBmbi5jYWxsKGVsLCBlKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gd3JhcCAoZWwsIHR5cGUsIGZuKSB7XG4gIHZhciB3cmFwcGVyID0gdW53cmFwKGVsLCB0eXBlLCBmbikgfHwgd3JhcHBlckZhY3RvcnkoZWwsIHR5cGUsIGZuKTtcbiAgaGFyZENhY2hlLnB1c2goe1xuICAgIHdyYXBwZXI6IHdyYXBwZXIsXG4gICAgZWxlbWVudDogZWwsXG4gICAgdHlwZTogdHlwZSxcbiAgICBmbjogZm5cbiAgfSk7XG4gIHJldHVybiB3cmFwcGVyO1xufVxuXG5mdW5jdGlvbiB1bndyYXAgKGVsLCB0eXBlLCBmbikge1xuICB2YXIgaSA9IGZpbmQoZWwsIHR5cGUsIGZuKTtcbiAgaWYgKGkpIHtcbiAgICB2YXIgd3JhcHBlciA9IGhhcmRDYWNoZVtpXS53cmFwcGVyO1xuICAgIGhhcmRDYWNoZS5zcGxpY2UoaSwgMSk7IC8vIGZyZWUgdXAgYSB0YWQgb2YgbWVtb3J5XG4gICAgcmV0dXJuIHdyYXBwZXI7XG4gIH1cbn1cblxuZnVuY3Rpb24gZmluZCAoZWwsIHR5cGUsIGZuKSB7XG4gIHZhciBpLCBpdGVtO1xuICBmb3IgKGkgPSAwOyBpIDwgaGFyZENhY2hlLmxlbmd0aDsgaSsrKSB7XG4gICAgaXRlbSA9IGhhcmRDYWNoZVtpXTtcbiAgICBpZiAoaXRlbS5lbGVtZW50ID09PSBlbCAmJiBpdGVtLnR5cGUgPT09IHR5cGUgJiYgaXRlbS5mbiA9PT0gZm4pIHtcbiAgICAgIHJldHVybiBpO1xuICAgIH1cbiAgfVxufVxuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2Nyb3NzdmVudC9zcmMvY3Jvc3N2ZW50LmpzXG4vLyBtb2R1bGUgaWQgPSA4NFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 85 */
- /***/ function(module, exports) {
- eval("/* WEBPACK VAR INJECTION */(function(global) {\nvar NativeCustomEvent = global.CustomEvent;\n\nfunction useNative () {\n try {\n var p = new NativeCustomEvent('cat', { detail: { foo: 'bar' } });\n return 'cat' === p.type && 'bar' === p.detail.foo;\n } catch (e) {\n }\n return false;\n}\n\n/**\n * Cross-browser `CustomEvent` constructor.\n *\n * https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent.CustomEvent\n *\n * @public\n */\n\nmodule.exports = useNative() ? NativeCustomEvent :\n\n// IE >= 9\n'function' === typeof document.createEvent ? function CustomEvent (type, params) {\n var e = document.createEvent('CustomEvent');\n if (params) {\n e.initCustomEvent(type, params.bubbles, params.cancelable, params.detail);\n } else {\n e.initCustomEvent(type, false, false, void 0);\n }\n return e;\n} :\n\n// IE <= 8\nfunction CustomEvent (type, params) {\n var e = document.createEventObject();\n e.type = type;\n if (params) {\n e.bubbles = Boolean(params.bubbles);\n e.cancelable = Boolean(params.cancelable);\n e.detail = params.detail;\n } else {\n e.bubbles = false;\n e.cancelable = false;\n e.detail = void 0;\n }\n return e;\n}\n\n/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiODUuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2N1c3RvbS1ldmVudC9pbmRleC5qcz8wNDBkIl0sInNvdXJjZXNDb250ZW50IjpbIlxudmFyIE5hdGl2ZUN1c3RvbUV2ZW50ID0gZ2xvYmFsLkN1c3RvbUV2ZW50O1xuXG5mdW5jdGlvbiB1c2VOYXRpdmUgKCkge1xuICB0cnkge1xuICAgIHZhciBwID0gbmV3IE5hdGl2ZUN1c3RvbUV2ZW50KCdjYXQnLCB7IGRldGFpbDogeyBmb286ICdiYXInIH0gfSk7XG4gICAgcmV0dXJuICAnY2F0JyA9PT0gcC50eXBlICYmICdiYXInID09PSBwLmRldGFpbC5mb287XG4gIH0gY2F0Y2ggKGUpIHtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbi8qKlxuICogQ3Jvc3MtYnJvd3NlciBgQ3VzdG9tRXZlbnRgIGNvbnN0cnVjdG9yLlxuICpcbiAqIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9DdXN0b21FdmVudC5DdXN0b21FdmVudFxuICpcbiAqIEBwdWJsaWNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IHVzZU5hdGl2ZSgpID8gTmF0aXZlQ3VzdG9tRXZlbnQgOlxuXG4vLyBJRSA+PSA5XG4nZnVuY3Rpb24nID09PSB0eXBlb2YgZG9jdW1lbnQuY3JlYXRlRXZlbnQgPyBmdW5jdGlvbiBDdXN0b21FdmVudCAodHlwZSwgcGFyYW1zKSB7XG4gIHZhciBlID0gZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ0N1c3RvbUV2ZW50Jyk7XG4gIGlmIChwYXJhbXMpIHtcbiAgICBlLmluaXRDdXN0b21FdmVudCh0eXBlLCBwYXJhbXMuYnViYmxlcywgcGFyYW1zLmNhbmNlbGFibGUsIHBhcmFtcy5kZXRhaWwpO1xuICB9IGVsc2Uge1xuICAgIGUuaW5pdEN1c3RvbUV2ZW50KHR5cGUsIGZhbHNlLCBmYWxzZSwgdm9pZCAwKTtcbiAgfVxuICByZXR1cm4gZTtcbn0gOlxuXG4vLyBJRSA8PSA4XG5mdW5jdGlvbiBDdXN0b21FdmVudCAodHlwZSwgcGFyYW1zKSB7XG4gIHZhciBlID0gZG9jdW1lbnQuY3JlYXRlRXZlbnRPYmplY3QoKTtcbiAgZS50eXBlID0gdHlwZTtcbiAgaWYgKHBhcmFtcykge1xuICAgIGUuYnViYmxlcyA9IEJvb2xlYW4ocGFyYW1zLmJ1YmJsZXMpO1xuICAgIGUuY2FuY2VsYWJsZSA9IEJvb2xlYW4ocGFyYW1zLmNhbmNlbGFibGUpO1xuICAgIGUuZGV0YWlsID0gcGFyYW1zLmRldGFpbDtcbiAgfSBlbHNlIHtcbiAgICBlLmJ1YmJsZXMgPSBmYWxzZTtcbiAgICBlLmNhbmNlbGFibGUgPSBmYWxzZTtcbiAgICBlLmRldGFpbCA9IHZvaWQgMDtcbiAgfVxuICByZXR1cm4gZTtcbn1cblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jdXN0b20tZXZlbnQvaW5kZXguanNcbi8vIG1vZHVsZSBpZCA9IDg1XG4vLyBtb2R1bGUgY2h1bmtzID0gMCJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZVJvb3QiOiIifQ==");
- /***/ },
- /* 86 */
- /***/ function(module, exports) {
- eval("/* WEBPACK VAR INJECTION */(function(global) {'use strict';\n\nvar eventmap = [];\nvar eventname = '';\nvar ron = /^on/;\n\nfor (eventname in global) {\n if (ron.test(eventname)) {\n eventmap.push(eventname.slice(2));\n }\n}\n\nmodule.exports = eventmap;\n\n/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiODYuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2Nyb3NzdmVudC9zcmMvZXZlbnRtYXAuanM/OTM1NyJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbnZhciBldmVudG1hcCA9IFtdO1xudmFyIGV2ZW50bmFtZSA9ICcnO1xudmFyIHJvbiA9IC9eb24vO1xuXG5mb3IgKGV2ZW50bmFtZSBpbiBnbG9iYWwpIHtcbiAgaWYgKHJvbi50ZXN0KGV2ZW50bmFtZSkpIHtcbiAgICBldmVudG1hcC5wdXNoKGV2ZW50bmFtZS5zbGljZSgyKSk7XG4gIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBldmVudG1hcDtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9jcm9zc3ZlbnQvc3JjL2V2ZW50bWFwLmpzXG4vLyBtb2R1bGUgaWQgPSA4NlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZVJvb3QiOiIifQ==");
- /***/ },
- /* 87 */
- /***/ function(module, exports) {
- eval("'use strict';\n\nvar cache = {};\nvar start = '(?:^|\\\\s)';\nvar end = '(?:\\\\s|$)';\n\nfunction lookupClass (className) {\n var cached = cache[className];\n if (cached) {\n cached.lastIndex = 0;\n } else {\n cache[className] = cached = new RegExp(start + className + end, 'g');\n }\n return cached;\n}\n\nfunction addClass (el, className) {\n var current = el.className;\n if (!current.length) {\n el.className = className;\n } else if (!lookupClass(className).test(current)) {\n el.className += ' ' + className;\n }\n}\n\nfunction rmClass (el, className) {\n el.className = el.className.replace(lookupClass(className), ' ').trim();\n}\n\nmodule.exports = {\n add: addClass,\n rm: rmClass\n};\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiODcuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2RyYWd1bGEvY2xhc3Nlcy5qcz9kZmQ5Il0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxudmFyIGNhY2hlID0ge307XG52YXIgc3RhcnQgPSAnKD86XnxcXFxccyknO1xudmFyIGVuZCA9ICcoPzpcXFxcc3wkKSc7XG5cbmZ1bmN0aW9uIGxvb2t1cENsYXNzIChjbGFzc05hbWUpIHtcbiAgdmFyIGNhY2hlZCA9IGNhY2hlW2NsYXNzTmFtZV07XG4gIGlmIChjYWNoZWQpIHtcbiAgICBjYWNoZWQubGFzdEluZGV4ID0gMDtcbiAgfSBlbHNlIHtcbiAgICBjYWNoZVtjbGFzc05hbWVdID0gY2FjaGVkID0gbmV3IFJlZ0V4cChzdGFydCArIGNsYXNzTmFtZSArIGVuZCwgJ2cnKTtcbiAgfVxuICByZXR1cm4gY2FjaGVkO1xufVxuXG5mdW5jdGlvbiBhZGRDbGFzcyAoZWwsIGNsYXNzTmFtZSkge1xuICB2YXIgY3VycmVudCA9IGVsLmNsYXNzTmFtZTtcbiAgaWYgKCFjdXJyZW50Lmxlbmd0aCkge1xuICAgIGVsLmNsYXNzTmFtZSA9IGNsYXNzTmFtZTtcbiAgfSBlbHNlIGlmICghbG9va3VwQ2xhc3MoY2xhc3NOYW1lKS50ZXN0KGN1cnJlbnQpKSB7XG4gICAgZWwuY2xhc3NOYW1lICs9ICcgJyArIGNsYXNzTmFtZTtcbiAgfVxufVxuXG5mdW5jdGlvbiBybUNsYXNzIChlbCwgY2xhc3NOYW1lKSB7XG4gIGVsLmNsYXNzTmFtZSA9IGVsLmNsYXNzTmFtZS5yZXBsYWNlKGxvb2t1cENsYXNzKGNsYXNzTmFtZSksICcgJykudHJpbSgpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgYWRkOiBhZGRDbGFzcyxcbiAgcm06IHJtQ2xhc3Ncbn07XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vZHJhZ3VsYS9jbGFzc2VzLmpzXG4vLyBtb2R1bGUgaWQgPSA4N1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ },
- /* 88 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar core_1 = __webpack_require__(4);\nvar BehaviorSubject_1 = __webpack_require__(33);\nvar PouchDB = __webpack_require__(89);\nexports.NOTES_TABLES = [];\nvar localDB = new PouchDB('notes_table');\nvar orderDB = new PouchDB('order');\nvar NotesTableService = (function () {\n function NotesTableService() {\n this._notes_tables_source = new BehaviorSubject_1.BehaviorSubject([]);\n this.notes_tables$ = this._notes_tables_source.asObservable();\n this.localDB = localDB;\n this.order = orderDB;\n }\n NotesTableService.prototype.getNotes = function () {\n var docs = this.localDB.allDocs({\n include_docs: true\n });\n return docs;\n };\n NotesTableService.prototype.saveNote = function (note) {\n return this.localDB.put(note);\n };\n NotesTableService.prototype.deleteNote = function (note) {\n return this.localDB.remove(note);\n };\n NotesTableService.prototype.updateNote = function (note) {\n return this.localDB.put(note);\n };\n NotesTableService.prototype.getOrder = function (order) {\n var docs = this.order.allDocs({\n include_docs: true\n });\n return docs;\n };\n NotesTableService.prototype.saveOrder = function (order) {\n return this.order.put(order);\n };\n NotesTableService = __decorate([\n core_1.Injectable(), \n __metadata('design:paramtypes', [])\n ], NotesTableService);\n return NotesTableService;\n}());\nexports.NotesTableService = NotesTableService;\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiODguanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvYXBwL3NlcnZpY2VzL25vdGVzX3RhYmxlLnNlcnZpY2UudHM/OTEzOCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0JlaGF2aW9yU3ViamVjdH0gZnJvbSAncnhqcy9CZWhhdmlvclN1YmplY3QnO1xuaW1wb3J0ICogYXMgUG91Y2hEQiBmcm9tICdwb3VjaGRiJztcblxuaW1wb3J0IHsgTm90ZXNUYWJsZSB9IGZyb20gJy4vbm90ZXNfdGFibGUnO1xuXG5leHBvcnQgdmFyIE5PVEVTX1RBQkxFUzogTm90ZXNUYWJsZVtdID0gW107XG5cbmxldCBsb2NhbERCID0gbmV3IFBvdWNoREIoJ25vdGVzX3RhYmxlJyk7XG5sZXQgb3JkZXJEQiA9IG5ldyBQb3VjaERCKCdvcmRlcicpO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgTm90ZXNUYWJsZVNlcnZpY2Uge1xuICBwcml2YXRlIF9ub3Rlc190YWJsZXNfc291cmNlID0gbmV3IEJlaGF2aW9yU3ViamVjdDxOb3Rlc1RhYmxlW10+KFtdKTtcbiAgbm90ZXNfdGFibGVzJCA9IHRoaXMuX25vdGVzX3RhYmxlc19zb3VyY2UuYXNPYnNlcnZhYmxlKCk7XG4gIGxvY2FsREIgPSBsb2NhbERCO1xuICBvcmRlciA9IG9yZGVyREI7XG4gIGNvbnN0cnVjdG9yKCkge31cblxuICBnZXROb3RlcygpIHtcbiAgICB2YXIgZG9jcyA9IHRoaXMubG9jYWxEQi5hbGxEb2NzKHtcbiAgICAgIGluY2x1ZGVfZG9jczogdHJ1ZVxuICAgIH0pO1xuICAgIHJldHVybiBkb2NzO1xuICB9XG5cbiAgc2F2ZU5vdGUobm90ZTogYW55KSB7XG4gICAgcmV0dXJuIHRoaXMubG9jYWxEQi5wdXQobm90ZSk7XG4gIH1cblxuICBkZWxldGVOb3RlKG5vdGU6IGFueSkge1xuICAgIHJldHVybiB0aGlzLmxvY2FsREIucmVtb3ZlKG5vdGUpO1xuICB9XG5cbiAgdXBkYXRlTm90ZShub3RlOiBhbnkpIHtcbiAgICByZXR1cm4gdGhpcy5sb2NhbERCLnB1dChub3RlKTtcbiAgfVxuXG4gIGdldE9yZGVyKG9yZGVyOiBhbnkpIHtcbiAgICB2YXIgZG9jcyA9IHRoaXMub3JkZXIuYWxsRG9jcyh7XG4gICAgICBpbmNsdWRlX2RvY3M6IHRydWVcbiAgICB9KTtcbiAgICByZXR1cm4gZG9jcztcbiAgfVxuXG4gIHNhdmVPcmRlcihvcmRlcjogYW55KSB7XG4gICAgcmV0dXJuIHRoaXMub3JkZXIucHV0KG9yZGVyKTtcbiAgfVxufVxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIG5vZGVfbW9kdWxlcy9hbmd1bGFyMi10ZW1wbGF0ZS1sb2FkZXIhLi9zcmMvYXBwL3NlcnZpY2VzL25vdGVzX3RhYmxlLnNlcnZpY2UudHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFJQTtBQUVBO0FBQ0E7QUFHQTtBQUtBO0FBSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQXBDQTtBQUFBOztBQUFBO0FBcUNBO0FBQUE7QUFwQ0E7Iiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 89 */
- /***/ function(module, exports, __webpack_require__) {
- eval("/* WEBPACK VAR INJECTION */(function(global) {'use strict';\n\nfunction _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }\n\nvar lie = _interopDefault(__webpack_require__(90));\nvar getArguments = _interopDefault(__webpack_require__(92));\nvar debug = _interopDefault(__webpack_require__(93));\nvar events = __webpack_require__(96);\nvar inherits = _interopDefault(__webpack_require__(97));\nvar immediate = _interopDefault(__webpack_require__(91));\nvar scopedEval = _interopDefault(__webpack_require__(98));\nvar Md5 = _interopDefault(__webpack_require__(99));\nvar vuvuzela = _interopDefault(__webpack_require__(100));\n\n/* istanbul ignore next */\nvar PouchPromise = typeof Promise === 'function' ? Promise : lie;\n\nfunction isBinaryObject(object) {\n return (typeof ArrayBuffer !== 'undefined' && object instanceof ArrayBuffer) ||\n (typeof Blob !== 'undefined' && object instanceof Blob);\n}\n\nfunction cloneArrayBuffer(buff) {\n if (typeof buff.slice === 'function') {\n return buff.slice(0);\n }\n // IE10-11 slice() polyfill\n var target = new ArrayBuffer(buff.byteLength);\n var targetArray = new Uint8Array(target);\n var sourceArray = new Uint8Array(buff);\n targetArray.set(sourceArray);\n return target;\n}\n\nfunction cloneBinaryObject(object) {\n if (object instanceof ArrayBuffer) {\n return cloneArrayBuffer(object);\n }\n var size = object.size;\n var type = object.type;\n // Blob\n if (typeof object.slice === 'function') {\n return object.slice(0, size, type);\n }\n // PhantomJS slice() replacement\n return object.webkitSlice(0, size, type);\n}\n\n// most of this is borrowed from lodash.isPlainObject:\n// https://github.com/fis-components/lodash.isplainobject/\n// blob/29c358140a74f252aeb08c9eb28bef86f2217d4a/index.js\n\nvar funcToString = Function.prototype.toString;\nvar objectCtorString = funcToString.call(Object);\n\nfunction isPlainObject(value) {\n var proto = Object.getPrototypeOf(value);\n /* istanbul ignore if */\n if (proto === null) { // not sure when this happens, but I guess it can\n return true;\n }\n var Ctor = proto.constructor;\n return (typeof Ctor == 'function' &&\n Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString);\n}\n\nfunction clone(object) {\n var newObject;\n var i;\n var len;\n\n if (!object || typeof object !== 'object') {\n return object;\n }\n\n if (Array.isArray(object)) {\n newObject = [];\n for (i = 0, len = object.length; i < len; i++) {\n newObject[i] = clone(object[i]);\n }\n return newObject;\n }\n\n // special case: to avoid inconsistencies between IndexedDB\n // and other backends, we automatically stringify Dates\n if (object instanceof Date) {\n return object.toISOString();\n }\n\n if (isBinaryObject(object)) {\n return cloneBinaryObject(object);\n }\n\n if (!isPlainObject(object)) {\n return object; // don't clone objects like Workers\n }\n\n newObject = {};\n for (i in object) {\n /* istanbul ignore else */\n if (Object.prototype.hasOwnProperty.call(object, i)) {\n var value = clone(object[i]);\n if (typeof value !== 'undefined') {\n newObject[i] = value;\n }\n }\n }\n return newObject;\n}\n\nfunction once(fun) {\n var called = false;\n return getArguments(function (args) {\n /* istanbul ignore if */\n if (called) {\n // this is a smoke test and should never actually happen\n throw new Error('once called more than once');\n } else {\n called = true;\n fun.apply(this, args);\n }\n });\n}\n\nfunction toPromise(func) {\n //create the function we will be returning\n return getArguments(function (args) {\n // Clone arguments\n args = clone(args);\n var self = this;\n // if the last argument is a function, assume its a callback\n var usedCB = (typeof args[args.length - 1] === 'function') ? args.pop() : false;\n var promise = new PouchPromise(function (fulfill, reject) {\n var resp;\n try {\n var callback = once(function (err, mesg) {\n if (err) {\n reject(err);\n } else {\n fulfill(mesg);\n }\n });\n // create a callback for this invocation\n // apply the function in the orig context\n args.push(callback);\n resp = func.apply(self, args);\n if (resp && typeof resp.then === 'function') {\n fulfill(resp);\n }\n } catch (e) {\n reject(e);\n }\n });\n // if there is a callback, call it back\n if (usedCB) {\n promise.then(function (result) {\n usedCB(null, result);\n }, usedCB);\n }\n return promise;\n });\n}\n\nvar log = debug('pouchdb:api');\n\nfunction adapterFun(name, callback) {\n function logApiCall(self, name, args) {\n /* istanbul ignore if */\n if (log.enabled) {\n var logArgs = [self.name, name];\n for (var i = 0; i < args.length - 1; i++) {\n logArgs.push(args[i]);\n }\n log.apply(null, logArgs);\n\n // override the callback itself to log the response\n var origCallback = args[args.length - 1];\n args[args.length - 1] = function (err, res) {\n var responseArgs = [self.name, name];\n responseArgs = responseArgs.concat(\n err ? ['error', err] : ['success', res]\n );\n log.apply(null, responseArgs);\n origCallback(err, res);\n };\n }\n }\n\n return toPromise(getArguments(function (args) {\n if (this._closed) {\n return PouchPromise.reject(new Error('database is closed'));\n }\n if (this._destroyed) {\n return PouchPromise.reject(new Error('database is destroyed'));\n }\n var self = this;\n logApiCall(self, name, args);\n if (!this.taskqueue.isReady) {\n return new PouchPromise(function (fulfill, reject) {\n self.taskqueue.addTask(function (failed) {\n if (failed) {\n reject(failed);\n } else {\n fulfill(self[name].apply(self, args));\n }\n });\n });\n }\n return callback.apply(this, args);\n }));\n}\n\n// like underscore/lodash _.pick()\nfunction pick(obj, arr) {\n var res = {};\n for (var i = 0, len = arr.length; i < len; i++) {\n var prop = arr[i];\n if (prop in obj) {\n res[prop] = obj[prop];\n }\n }\n return res;\n}\n\n// based on https://github.com/montagejs/collections\nfunction mangle(key) {\n return '$' + key;\n}\nfunction unmangle(key) {\n return key.substring(1);\n}\nfunction _Map() {\n this._store = {};\n}\n_Map.prototype.get = function (key) {\n var mangled = mangle(key);\n return this._store[mangled];\n};\n_Map.prototype.set = function (key, value) {\n var mangled = mangle(key);\n this._store[mangled] = value;\n return true;\n};\n_Map.prototype.has = function (key) {\n var mangled = mangle(key);\n return mangled in this._store;\n};\n_Map.prototype.delete = function (key) {\n var mangled = mangle(key);\n var res = mangled in this._store;\n delete this._store[mangled];\n return res;\n};\n_Map.prototype.forEach = function (cb) {\n var keys = Object.keys(this._store);\n for (var i = 0, len = keys.length; i < len; i++) {\n var key = keys[i];\n var value = this._store[key];\n key = unmangle(key);\n cb(value, key);\n }\n};\nObject.defineProperty(_Map.prototype, 'size', {\n get: function () {\n return Object.keys(this._store).length;\n }\n});\n\nfunction _Set(array) {\n this._store = new _Map();\n\n // init with an array\n if (array && Array.isArray(array)) {\n for (var i = 0, len = array.length; i < len; i++) {\n this.add(array[i]);\n }\n }\n}\n_Set.prototype.add = function (key) {\n return this._store.set(key, true);\n};\n_Set.prototype.has = function (key) {\n return this._store.has(key);\n};\n\n// Most browsers throttle concurrent requests at 6, so it's silly\n// to shim _bulk_get by trying to launch potentially hundreds of requests\n// and then letting the majority time out. We can handle this ourselves.\nvar MAX_NUM_CONCURRENT_REQUESTS = 6;\n\nfunction identityFunction(x) {\n return x;\n}\n\nfunction formatResultForOpenRevsGet(result) {\n return [{\n ok: result\n }];\n}\n\n// shim for P/CouchDB adapters that don't directly implement _bulk_get\nfunction bulkGet(db, opts, callback) {\n var requests = opts.docs;\n\n // consolidate into one request per doc if possible\n var requestsById = new _Map();\n requests.forEach(function (request) {\n if (requestsById.has(request.id)) {\n requestsById.get(request.id).push(request);\n } else {\n requestsById.set(request.id, [request]);\n }\n });\n\n var numDocs = requestsById.size;\n var numDone = 0;\n var perDocResults = new Array(numDocs);\n\n function collapseResultsAndFinish() {\n var results = [];\n perDocResults.forEach(function (res) {\n res.docs.forEach(function (info) {\n results.push({\n id: res.id,\n docs: [info]\n });\n });\n });\n callback(null, {results: results});\n }\n\n function checkDone() {\n if (++numDone === numDocs) {\n collapseResultsAndFinish();\n }\n }\n\n function gotResult(docIndex, id, docs) {\n perDocResults[docIndex] = {id: id, docs: docs};\n checkDone();\n }\n\n var allRequests = [];\n requestsById.forEach(function (value, key) {\n allRequests.push(key);\n });\n\n var i = 0;\n\n function nextBatch() {\n\n if (i >= allRequests.length) {\n return;\n }\n\n var upTo = Math.min(i + MAX_NUM_CONCURRENT_REQUESTS, allRequests.length);\n var batch = allRequests.slice(i, upTo);\n processBatch(batch, i);\n i += batch.length;\n }\n\n function processBatch(batch, offset) {\n batch.forEach(function (docId, j) {\n var docIdx = offset + j;\n var docRequests = requestsById.get(docId);\n\n // just use the first request as the \"template\"\n // TODO: The _bulk_get API allows for more subtle use cases than this,\n // but for now it is unlikely that there will be a mix of different\n // \"atts_since\" or \"attachments\" in the same request, since it's just\n // replicate.js that is using this for the moment.\n // Also, atts_since is aspirational, since we don't support it yet.\n var docOpts = pick(docRequests[0], ['atts_since', 'attachments']);\n docOpts.open_revs = docRequests.map(function (request) {\n // rev is optional, open_revs disallowed\n return request.rev;\n });\n\n // remove falsey / undefined revisions\n docOpts.open_revs = docOpts.open_revs.filter(identityFunction);\n\n var formatResult = identityFunction;\n\n if (docOpts.open_revs.length === 0) {\n delete docOpts.open_revs;\n\n // when fetching only the \"winning\" leaf,\n // transform the result so it looks like an open_revs\n // request\n formatResult = formatResultForOpenRevsGet;\n }\n\n // globally-supplied options\n ['revs', 'attachments', 'binary', 'ajax', 'latest'].forEach(function (param) {\n if (param in opts) {\n docOpts[param] = opts[param];\n }\n });\n db.get(docId, docOpts, function (err, res) {\n var result;\n /* istanbul ignore if */\n if (err) {\n result = [{error: err}];\n } else {\n result = formatResult(res);\n }\n gotResult(docIdx, docId, result);\n nextBatch();\n });\n });\n }\n\n nextBatch();\n\n}\n\nfunction isChromeApp() {\n return (typeof chrome !== \"undefined\" &&\n typeof chrome.storage !== \"undefined\" &&\n typeof chrome.storage.local !== \"undefined\");\n}\n\nvar hasLocal;\n\nif (isChromeApp()) {\n hasLocal = false;\n} else {\n try {\n localStorage.setItem('_pouch_check_localstorage', 1);\n hasLocal = !!localStorage.getItem('_pouch_check_localstorage');\n } catch (e) {\n hasLocal = false;\n }\n}\n\nfunction hasLocalStorage() {\n return hasLocal;\n}\n\ninherits(Changes, events.EventEmitter);\n\n/* istanbul ignore next */\nfunction attachBrowserEvents(self) {\n if (isChromeApp()) {\n chrome.storage.onChanged.addListener(function (e) {\n // make sure it's event addressed to us\n if (e.db_name != null) {\n //object only has oldValue, newValue members\n self.emit(e.dbName.newValue);\n }\n });\n } else if (hasLocalStorage()) {\n if (typeof addEventListener !== 'undefined') {\n addEventListener(\"storage\", function (e) {\n self.emit(e.key);\n });\n } else { // old IE\n window.attachEvent(\"storage\", function (e) {\n self.emit(e.key);\n });\n }\n }\n}\n\nfunction Changes() {\n events.EventEmitter.call(this);\n this._listeners = {};\n\n attachBrowserEvents(this);\n}\nChanges.prototype.addListener = function (dbName, id, db, opts) {\n /* istanbul ignore if */\n if (this._listeners[id]) {\n return;\n }\n var self = this;\n var inprogress = false;\n function eventFunction() {\n /* istanbul ignore if */\n if (!self._listeners[id]) {\n return;\n }\n if (inprogress) {\n inprogress = 'waiting';\n return;\n }\n inprogress = true;\n var changesOpts = pick(opts, [\n 'style', 'include_docs', 'attachments', 'conflicts', 'filter',\n 'doc_ids', 'view', 'since', 'query_params', 'binary'\n ]);\n\n /* istanbul ignore next */\n function onError() {\n inprogress = false;\n }\n\n db.changes(changesOpts).on('change', function (c) {\n if (c.seq > opts.since && !opts.cancelled) {\n opts.since = c.seq;\n opts.onChange(c);\n }\n }).on('complete', function () {\n if (inprogress === 'waiting') {\n immediate(eventFunction);\n }\n inprogress = false;\n }).on('error', onError);\n }\n this._listeners[id] = eventFunction;\n this.on(dbName, eventFunction);\n};\n\nChanges.prototype.removeListener = function (dbName, id) {\n /* istanbul ignore if */\n if (!(id in this._listeners)) {\n return;\n }\n events.EventEmitter.prototype.removeListener.call(this, dbName,\n this._listeners[id]);\n delete this._listeners[id];\n};\n\n\n/* istanbul ignore next */\nChanges.prototype.notifyLocalWindows = function (dbName) {\n //do a useless change on a storage thing\n //in order to get other windows's listeners to activate\n if (isChromeApp()) {\n chrome.storage.local.set({dbName: dbName});\n } else if (hasLocalStorage()) {\n localStorage[dbName] = (localStorage[dbName] === \"a\") ? \"b\" : \"a\";\n }\n};\n\nChanges.prototype.notify = function (dbName) {\n this.emit(dbName);\n this.notifyLocalWindows(dbName);\n};\n\nfunction guardedConsole(method) {\n /* istanbul ignore else */\n if (console !== 'undefined' && method in console) {\n var args = Array.prototype.slice.call(arguments, 1);\n console[method].apply(console, args);\n }\n}\n\nfunction randomNumber(min, max) {\n var maxTimeout = 600000; // Hard-coded default of 10 minutes\n min = parseInt(min, 10) || 0;\n max = parseInt(max, 10);\n if (max !== max || max <= min) {\n max = (min || 1) << 1; //doubling\n } else {\n max = max + 1;\n }\n // In order to not exceed maxTimeout, pick a random value between half of maxTimeout and maxTimeout\n if(max > maxTimeout) {\n min = maxTimeout >> 1; // divide by two\n max = maxTimeout;\n }\n var ratio = Math.random();\n var range = max - min;\n\n return ~~(range * ratio + min); // ~~ coerces to an int, but fast.\n}\n\nfunction defaultBackOff(min) {\n var max = 0;\n if (!min) {\n max = 2000;\n }\n return randomNumber(min, max);\n}\n\n// designed to give info to browser users, who are disturbed\n// when they see http errors in the console\nfunction explainError(status, str) {\n guardedConsole('info', 'The above ' + status + ' is totally normal. ' + str);\n}\n\n// forked from\n// https://github.com/vmattos/js-extend/blob/7023fd69a9e9552688086b8b8006b1fcf916a306/extend.js\n// TODO: I don't know why we have two different extend() functions in PouchDB\n\nvar slice = Array.prototype.slice;\nvar each = Array.prototype.forEach;\n\nfunction extend$1(obj) {\n if (typeof obj !== 'object') {\n throw obj + ' is not an object' ;\n }\n\n var sources = slice.call(arguments, 1);\n\n each.call(sources, function (source) {\n if (source) {\n for (var prop in source) {\n if (typeof source[prop] === 'object' && obj[prop]) {\n extend$1.call(obj, obj[prop], source[prop]);\n } else {\n obj[prop] = source[prop];\n }\n }\n }\n });\n\n return obj;\n}\n\ninherits(PouchError, Error);\n\nfunction PouchError(status, error, reason) {\n Error.call(this, reason);\n this.status = status;\n this.name = error;\n this.message = reason;\n this.error = true;\n}\n\nPouchError.prototype.toString = function () {\n return JSON.stringify({\n status: this.status,\n name: this.name,\n message: this.message,\n reason: this.reason\n });\n};\n\nvar UNAUTHORIZED = new PouchError(401, 'unauthorized', \"Name or password is incorrect.\");\nvar MISSING_BULK_DOCS = new PouchError(400, 'bad_request', \"Missing JSON list of 'docs'\");\nvar MISSING_DOC = new PouchError(404, 'not_found', 'missing');\nvar REV_CONFLICT = new PouchError(409, 'conflict', 'Document update conflict');\nvar INVALID_ID = new PouchError(400, 'bad_request', '_id field must contain a string');\nvar MISSING_ID = new PouchError(412, 'missing_id', '_id is required for puts');\nvar RESERVED_ID = new PouchError(400, 'bad_request', 'Only reserved document ids may start with underscore.');\nvar NOT_OPEN = new PouchError(412, 'precondition_failed', 'Database not open');\nvar UNKNOWN_ERROR = new PouchError(500, 'unknown_error', 'Database encountered an unknown error');\nvar BAD_ARG = new PouchError(500, 'badarg', 'Some query argument is invalid');\nvar INVALID_REQUEST = new PouchError(400, 'invalid_request', 'Request was invalid');\nvar QUERY_PARSE_ERROR = new PouchError(400, 'query_parse_error', 'Some query parameter is invalid');\nvar DOC_VALIDATION = new PouchError(500, 'doc_validation', 'Bad special document member');\nvar BAD_REQUEST = new PouchError(400, 'bad_request', 'Something wrong with the request');\nvar NOT_AN_OBJECT = new PouchError(400, 'bad_request', 'Document must be a JSON object');\nvar DB_MISSING = new PouchError(404, 'not_found', 'Database not found');\nvar IDB_ERROR = new PouchError(500, 'indexed_db_went_bad', 'unknown');\nvar WSQ_ERROR = new PouchError(500, 'web_sql_went_bad', 'unknown');\nvar LDB_ERROR = new PouchError(500, 'levelDB_went_went_bad', 'unknown');\nvar FORBIDDEN = new PouchError(403, 'forbidden', 'Forbidden by design doc validate_doc_update function');\nvar INVALID_REV = new PouchError(400, 'bad_request', 'Invalid rev format');\nvar FILE_EXISTS = new PouchError(412, 'file_exists', 'The database could not be created, the file already exists.');\nvar MISSING_STUB = new PouchError(412, 'missing_stub', 'A pre-existing attachment stub wasn\\'t found');\nvar INVALID_URL = new PouchError(413, 'invalid_url', 'Provided URL is invalid');\n\nfunction createError(error, reason) {\n function CustomPouchError(reason) {\n // inherit error properties from our parent error manually\n // so as to allow proper JSON parsing.\n /* jshint ignore:start */\n for (var p in error) {\n if (typeof error[p] !== 'function') {\n this[p] = error[p];\n }\n }\n /* jshint ignore:end */\n if (reason !== undefined) {\n this.reason = reason;\n }\n }\n CustomPouchError.prototype = PouchError.prototype;\n return new CustomPouchError(reason);\n}\n\nfunction generateErrorFromResponse(err) {\n\n if (typeof err !== 'object') {\n var data = err;\n err = UNKNOWN_ERROR;\n err.data = data;\n }\n\n if ('error' in err && err.error === 'conflict') {\n err.name = 'conflict';\n err.status = 409;\n }\n\n if (!('name' in err)) {\n err.name = err.error || 'unknown';\n }\n\n if (!('status' in err)) {\n err.status = 500;\n }\n\n if (!('message' in err)) {\n err.message = err.message || err.reason;\n }\n\n return err;\n}\n\nfunction tryFilter(filter, doc, req) {\n try {\n return !filter(doc, req);\n } catch (err) {\n var msg = 'Filter function threw: ' + err.toString();\n return createError(BAD_REQUEST, msg);\n }\n}\n\nfunction filterChange(opts) {\n var req = {};\n var hasFilter = opts.filter && typeof opts.filter === 'function';\n req.query = opts.query_params;\n\n return function filter(change) {\n if (!change.doc) {\n // CSG sends events on the changes feed that don't have documents,\n // this hack makes a whole lot of existing code robust.\n change.doc = {};\n }\n\n var filterReturn = hasFilter && tryFilter(opts.filter, change.doc, req);\n\n if (typeof filterReturn === 'object') {\n return filterReturn;\n }\n\n if (filterReturn) {\n return false;\n }\n\n if (!opts.include_docs) {\n delete change.doc;\n } else if (!opts.attachments) {\n for (var att in change.doc._attachments) {\n /* istanbul ignore else */\n if (change.doc._attachments.hasOwnProperty(att)) {\n change.doc._attachments[att].stub = true;\n }\n }\n }\n return true;\n };\n}\n\nfunction flatten(arrs) {\n var res = [];\n for (var i = 0, len = arrs.length; i < len; i++) {\n res = res.concat(arrs[i]);\n }\n return res;\n}\n\n// Determine id an ID is valid\n// - invalid IDs begin with an underescore that does not begin '_design' or\n// '_local'\n// - any other string value is a valid id\n// Returns the specific error object for each case\nfunction invalidIdError(id) {\n var err;\n if (!id) {\n err = createError(MISSING_ID);\n } else if (typeof id !== 'string') {\n err = createError(INVALID_ID);\n } else if (/^_/.test(id) && !(/^_(design|local)/).test(id)) {\n err = createError(RESERVED_ID);\n }\n if (err) {\n throw err;\n }\n}\n\nfunction listenerCount(ee, type) {\n return 'listenerCount' in ee ? ee.listenerCount(type) :\n events.EventEmitter.listenerCount(ee, type);\n}\n\n// Custom nextTick() shim for browsers. In node, this will just be process.nextTick(). We\n// avoid using process.nextTick() directly because the polyfill is very large and we don't\n// need all of it (see: https://github.com/defunctzombie/node-process).\n// \"immediate\" 3.0.8 is used by lie, and it's a smaller version of the latest \"immediate\"\n// package, so it's the one we use.\n// When we use nextTick() in our codebase, we only care about not releasing Zalgo\n// (see: http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony).\n// Microtask vs macrotask doesn't matter to us. So we're free to use the fastest\n// (least latency) option, which is \"immediate\" due to use of microtasks.\n// All of our nextTicks are isolated to this one function so we can easily swap out one\n// implementation for another.\n\nfunction parseDesignDocFunctionName(s) {\n if (!s) {\n return null;\n }\n var parts = s.split('/');\n if (parts.length === 2) {\n return parts;\n }\n if (parts.length === 1) {\n return [s, s];\n }\n return null;\n}\n\nfunction normalizeDesignDocFunctionName(s) {\n var normalized = parseDesignDocFunctionName(s);\n return normalized ? normalized.join('/') : null;\n}\n\n// originally parseUri 1.2.2, now patched by us\n// (c) Steven Levithan <stevenlevithan.com>\n// MIT License\nvar keys = [\"source\", \"protocol\", \"authority\", \"userInfo\", \"user\", \"password\",\n \"host\", \"port\", \"relative\", \"path\", \"directory\", \"file\", \"query\", \"anchor\"];\nvar qName =\"queryKey\";\nvar qParser = /(?:^|&)([^&=]*)=?([^&]*)/g;\n\n// use the \"loose\" parser\n/* jshint maxlen: false */\nvar parser = /^(?:(?![^:@]+:[^:@\\/]*@)([^:\\/?#.]+):)?(?:\\/\\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\\/?#]*)(?::(\\d*))?)(((\\/(?:[^?#](?![^?#\\/]*\\.[^?#\\/.]+(?:[?#]|$)))*\\/?)?([^?#\\/]*))(?:\\?([^#]*))?(?:#(.*))?)/;\n\nfunction parseUri(str) {\n var m = parser.exec(str);\n var uri = {};\n var i = 14;\n\n while (i--) {\n var key = keys[i];\n var value = m[i] || \"\";\n var encoded = ['user', 'password'].indexOf(key) !== -1;\n uri[key] = encoded ? decodeURIComponent(value) : value;\n }\n\n uri[qName] = {};\n uri[keys[12]].replace(qParser, function ($0, $1, $2) {\n if ($1) {\n uri[qName][$1] = $2;\n }\n });\n\n return uri;\n}\n\n// this is essentially the \"update sugar\" function from daleharvey/pouchdb#1388\n// the diffFun tells us what delta to apply to the doc. it either returns\n// the doc, or false if it doesn't need to do an update after all\nfunction upsert(db, docId, diffFun) {\n return new PouchPromise(function (fulfill, reject) {\n db.get(docId, function (err, doc) {\n if (err) {\n /* istanbul ignore next */\n if (err.status !== 404) {\n return reject(err);\n }\n doc = {};\n }\n\n // the user might change the _rev, so save it for posterity\n var docRev = doc._rev;\n var newDoc = diffFun(doc);\n\n if (!newDoc) {\n // if the diffFun returns falsy, we short-circuit as\n // an optimization\n return fulfill({updated: false, rev: docRev});\n }\n\n // users aren't allowed to modify these values,\n // so reset them here\n newDoc._id = docId;\n newDoc._rev = docRev;\n fulfill(tryAndPut(db, newDoc, diffFun));\n });\n });\n}\n\nfunction tryAndPut(db, doc, diffFun) {\n return db.put(doc).then(function (res) {\n return {\n updated: true,\n rev: res.rev\n };\n }, function (err) {\n /* istanbul ignore next */\n if (err.status !== 409) {\n throw err;\n }\n return upsert(db, doc._id, diffFun);\n });\n}\n\n// BEGIN Math.uuid.js\n\n/*!\nMath.uuid.js (v1.4)\nhttp://www.broofa.com\nmailto:robert@broofa.com\n\nCopyright (c) 2010 Robert Kieffer\nDual licensed under the MIT and GPL licenses.\n*/\n\n/*\n * Generate a random uuid.\n *\n * USAGE: Math.uuid(length, radix)\n * length - the desired number of characters\n * radix - the number of allowable values for each character.\n *\n * EXAMPLES:\n * // No arguments - returns RFC4122, version 4 ID\n * >>> Math.uuid()\n * \"92329D39-6F5C-4520-ABFC-AAB64544E172\"\n *\n * // One argument - returns ID of the specified length\n * >>> Math.uuid(15) // 15 character ID (default base=62)\n * \"VcydxgltxrVZSTV\"\n *\n * // Two arguments - returns ID of the specified length, and radix. \n * // (Radix must be <= 62)\n * >>> Math.uuid(8, 2) // 8 character ID (base=2)\n * \"01001010\"\n * >>> Math.uuid(8, 10) // 8 character ID (base=10)\n * \"47473046\"\n * >>> Math.uuid(8, 16) // 8 character ID (base=16)\n * \"098F4D35\"\n */\nvar chars = (\n '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' +\n 'abcdefghijklmnopqrstuvwxyz'\n).split('');\nfunction getValue(radix) {\n return 0 | Math.random() * radix;\n}\nfunction uuid(len, radix) {\n radix = radix || chars.length;\n var out = '';\n var i = -1;\n\n if (len) {\n // Compact form\n while (++i < len) {\n out += chars[getValue(radix)];\n }\n return out;\n }\n // rfc4122, version 4 form\n // Fill in random data. At i==19 set the high bits of clock sequence as\n // per rfc4122, sec. 4.1.5\n while (++i < 36) {\n switch (i) {\n case 8:\n case 13:\n case 18:\n case 23:\n out += '-';\n break;\n case 19:\n out += chars[(getValue(16) & 0x3) | 0x8];\n break;\n default:\n out += chars[getValue(16)];\n }\n }\n\n return out;\n}\n\n// We fetch all leafs of the revision tree, and sort them based on tree length\n// and whether they were deleted, undeleted documents with the longest revision\n// tree (most edits) win\n// The final sort algorithm is slightly documented in a sidebar here:\n// http://guide.couchdb.org/draft/conflicts.html\nfunction winningRev(metadata) {\n var winningId;\n var winningPos;\n var winningDeleted;\n var toVisit = metadata.rev_tree.slice();\n var node;\n while ((node = toVisit.pop())) {\n var tree = node.ids;\n var branches = tree[2];\n var pos = node.pos;\n if (branches.length) { // non-leaf\n for (var i = 0, len = branches.length; i < len; i++) {\n toVisit.push({pos: pos + 1, ids: branches[i]});\n }\n continue;\n }\n var deleted = !!tree[1].deleted;\n var id = tree[0];\n // sort by deleted, then pos, then id\n if (!winningId || (winningDeleted !== deleted ? winningDeleted :\n winningPos !== pos ? winningPos < pos : winningId < id)) {\n winningId = id;\n winningPos = pos;\n winningDeleted = deleted;\n }\n }\n\n return winningPos + '-' + winningId;\n}\n\n// Pretty much all below can be combined into a higher order function to\n// traverse revisions\n// The return value from the callback will be passed as context to all\n// children of that node\nfunction traverseRevTree(revs, callback) {\n var toVisit = revs.slice();\n\n var node;\n while ((node = toVisit.pop())) {\n var pos = node.pos;\n var tree = node.ids;\n var branches = tree[2];\n var newCtx =\n callback(branches.length === 0, pos, tree[0], node.ctx, tree[1]);\n for (var i = 0, len = branches.length; i < len; i++) {\n toVisit.push({pos: pos + 1, ids: branches[i], ctx: newCtx});\n }\n }\n}\n\nfunction sortByPos(a, b) {\n return a.pos - b.pos;\n}\n\nfunction collectLeaves(revs) {\n var leaves = [];\n traverseRevTree(revs, function (isLeaf, pos, id, acc, opts) {\n if (isLeaf) {\n leaves.push({rev: pos + \"-\" + id, pos: pos, opts: opts});\n }\n });\n leaves.sort(sortByPos).reverse();\n for (var i = 0, len = leaves.length; i < len; i++) {\n delete leaves[i].pos;\n }\n return leaves;\n}\n\n// returns revs of all conflicts that is leaves such that\n// 1. are not deleted and\n// 2. are different than winning revision\nfunction collectConflicts(metadata) {\n var win = winningRev(metadata);\n var leaves = collectLeaves(metadata.rev_tree);\n var conflicts = [];\n for (var i = 0, len = leaves.length; i < len; i++) {\n var leaf = leaves[i];\n if (leaf.rev !== win && !leaf.opts.deleted) {\n conflicts.push(leaf.rev);\n }\n }\n return conflicts;\n}\n\n// compact a tree by marking its non-leafs as missing,\n// and return a list of revs to delete\nfunction compactTree(metadata) {\n var revs = [];\n traverseRevTree(metadata.rev_tree, function (isLeaf, pos,\n revHash, ctx, opts) {\n if (opts.status === 'available' && !isLeaf) {\n revs.push(pos + '-' + revHash);\n opts.status = 'missing';\n }\n });\n return revs;\n}\n\n// build up a list of all the paths to the leafs in this revision tree\nfunction rootToLeaf(revs) {\n var paths = [];\n var toVisit = revs.slice();\n var node;\n while ((node = toVisit.pop())) {\n var pos = node.pos;\n var tree = node.ids;\n var id = tree[0];\n var opts = tree[1];\n var branches = tree[2];\n var isLeaf = branches.length === 0;\n\n var history = node.history ? node.history.slice() : [];\n history.push({id: id, opts: opts});\n if (isLeaf) {\n paths.push({pos: (pos + 1 - history.length), ids: history});\n }\n for (var i = 0, len = branches.length; i < len; i++) {\n toVisit.push({pos: pos + 1, ids: branches[i], history: history});\n }\n }\n return paths.reverse();\n}\n\n// for a better overview of what this is doing, read:\n// https://github.com/apache/couchdb-couch/blob/master/src/couch_key_tree.erl\n//\n// But for a quick intro, CouchDB uses a revision tree to store a documents\n// history, A -> B -> C, when a document has conflicts, that is a branch in the\n// tree, A -> (B1 | B2 -> C), We store these as a nested array in the format\n//\n// KeyTree = [Path ... ]\n// Path = {pos: position_from_root, ids: Tree}\n// Tree = [Key, Opts, [Tree, ...]], in particular single node: [Key, []]\n\nfunction sortByPos$1(a, b) {\n return a.pos - b.pos;\n}\n\n// classic binary search\nfunction binarySearch(arr, item, comparator) {\n var low = 0;\n var high = arr.length;\n var mid;\n while (low < high) {\n mid = (low + high) >>> 1;\n if (comparator(arr[mid], item) < 0) {\n low = mid + 1;\n } else {\n high = mid;\n }\n }\n return low;\n}\n\n// assuming the arr is sorted, insert the item in the proper place\nfunction insertSorted(arr, item, comparator) {\n var idx = binarySearch(arr, item, comparator);\n arr.splice(idx, 0, item);\n}\n\n// Turn a path as a flat array into a tree with a single branch.\n// If any should be stemmed from the beginning of the array, that's passed\n// in as the second argument\nfunction pathToTree(path, numStemmed) {\n var root;\n var leaf;\n for (var i = numStemmed, len = path.length; i < len; i++) {\n var node = path[i];\n var currentLeaf = [node.id, node.opts, []];\n if (leaf) {\n leaf[2].push(currentLeaf);\n leaf = currentLeaf;\n } else {\n root = leaf = currentLeaf;\n }\n }\n return root;\n}\n\n// compare the IDs of two trees\nfunction compareTree(a, b) {\n return a[0] < b[0] ? -1 : 1;\n}\n\n// Merge two trees together\n// The roots of tree1 and tree2 must be the same revision\nfunction mergeTree(in_tree1, in_tree2) {\n var queue = [{tree1: in_tree1, tree2: in_tree2}];\n var conflicts = false;\n while (queue.length > 0) {\n var item = queue.pop();\n var tree1 = item.tree1;\n var tree2 = item.tree2;\n\n if (tree1[1].status || tree2[1].status) {\n tree1[1].status =\n (tree1[1].status === 'available' ||\n tree2[1].status === 'available') ? 'available' : 'missing';\n }\n\n for (var i = 0; i < tree2[2].length; i++) {\n if (!tree1[2][0]) {\n conflicts = 'new_leaf';\n tree1[2][0] = tree2[2][i];\n continue;\n }\n\n var merged = false;\n for (var j = 0; j < tree1[2].length; j++) {\n if (tree1[2][j][0] === tree2[2][i][0]) {\n queue.push({tree1: tree1[2][j], tree2: tree2[2][i]});\n merged = true;\n }\n }\n if (!merged) {\n conflicts = 'new_branch';\n insertSorted(tree1[2], tree2[2][i], compareTree);\n }\n }\n }\n return {conflicts: conflicts, tree: in_tree1};\n}\n\nfunction doMerge(tree, path, dontExpand) {\n var restree = [];\n var conflicts = false;\n var merged = false;\n var res;\n\n if (!tree.length) {\n return {tree: [path], conflicts: 'new_leaf'};\n }\n\n for (var i = 0, len = tree.length; i < len; i++) {\n var branch = tree[i];\n if (branch.pos === path.pos && branch.ids[0] === path.ids[0]) {\n // Paths start at the same position and have the same root, so they need\n // merged\n res = mergeTree(branch.ids, path.ids);\n restree.push({pos: branch.pos, ids: res.tree});\n conflicts = conflicts || res.conflicts;\n merged = true;\n } else if (dontExpand !== true) {\n // The paths start at a different position, take the earliest path and\n // traverse up until it as at the same point from root as the path we\n // want to merge. If the keys match we return the longer path with the\n // other merged After stemming we dont want to expand the trees\n\n var t1 = branch.pos < path.pos ? branch : path;\n var t2 = branch.pos < path.pos ? path : branch;\n var diff = t2.pos - t1.pos;\n\n var candidateParents = [];\n\n var trees = [];\n trees.push({ids: t1.ids, diff: diff, parent: null, parentIdx: null});\n while (trees.length > 0) {\n var item = trees.pop();\n if (item.diff === 0) {\n if (item.ids[0] === t2.ids[0]) {\n candidateParents.push(item);\n }\n continue;\n }\n var elements = item.ids[2];\n for (var j = 0, elementsLen = elements.length; j < elementsLen; j++) {\n trees.push({\n ids: elements[j],\n diff: item.diff - 1,\n parent: item.ids,\n parentIdx: j\n });\n }\n }\n\n var el = candidateParents[0];\n\n if (!el) {\n restree.push(branch);\n } else {\n res = mergeTree(el.ids, t2.ids);\n el.parent[2][el.parentIdx] = res.tree;\n restree.push({pos: t1.pos, ids: t1.ids});\n conflicts = conflicts || res.conflicts;\n merged = true;\n }\n } else {\n restree.push(branch);\n }\n }\n\n // We didnt find\n if (!merged) {\n restree.push(path);\n }\n\n restree.sort(sortByPos$1);\n\n return {\n tree: restree,\n conflicts: conflicts || 'internal_node'\n };\n}\n\n// To ensure we dont grow the revision tree infinitely, we stem old revisions\nfunction stem(tree, depth) {\n // First we break out the tree into a complete list of root to leaf paths\n var paths = rootToLeaf(tree);\n var maybeStem = {};\n\n var result;\n for (var i = 0, len = paths.length; i < len; i++) {\n // Then for each path, we cut off the start of the path based on the\n // `depth` to stem to, and generate a new set of flat trees\n var path = paths[i];\n var stemmed = path.ids;\n var numStemmed = Math.max(0, stemmed.length - depth);\n var stemmedNode = {\n pos: path.pos + numStemmed,\n ids: pathToTree(stemmed, numStemmed)\n };\n\n for (var s = 0; s < numStemmed; s++) {\n var rev = (path.pos + s) + '-' + stemmed[s].id;\n maybeStem[rev] = true;\n }\n\n // Then we remerge all those flat trees together, ensuring that we dont\n // connect trees that would go beyond the depth limit\n if (result) {\n result = doMerge(result, stemmedNode, true).tree;\n } else {\n result = [stemmedNode];\n }\n }\n\n traverseRevTree(result, function (isLeaf, pos, revHash) {\n // some revisions may have been removed in a branch but not in another\n delete maybeStem[pos + '-' + revHash];\n });\n\n return {\n tree: result,\n revs: Object.keys(maybeStem)\n };\n}\n\nfunction merge(tree, path, depth) {\n var newTree = doMerge(tree, path);\n var stemmed = stem(newTree.tree, depth);\n return {\n tree: stemmed.tree,\n stemmedRevs: stemmed.revs,\n conflicts: newTree.conflicts\n };\n}\n\n// return true if a rev exists in the rev tree, false otherwise\nfunction revExists(revs, rev) {\n var toVisit = revs.slice();\n var splitRev = rev.split('-');\n var targetPos = parseInt(splitRev[0], 10);\n var targetId = splitRev[1];\n\n var node;\n while ((node = toVisit.pop())) {\n if (node.pos === targetPos && node.ids[0] === targetId) {\n return true;\n }\n var branches = node.ids[2];\n for (var i = 0, len = branches.length; i < len; i++) {\n toVisit.push({pos: node.pos + 1, ids: branches[i]});\n }\n }\n return false;\n}\n\nfunction getTrees(node) {\n return node.ids;\n}\n\n// check if a specific revision of a doc has been deleted\n// - metadata: the metadata object from the doc store\n// - rev: (optional) the revision to check. defaults to winning revision\nfunction isDeleted(metadata, rev) {\n if (!rev) {\n rev = winningRev(metadata);\n }\n var id = rev.substring(rev.indexOf('-') + 1);\n var toVisit = metadata.rev_tree.map(getTrees);\n\n var tree;\n while ((tree = toVisit.pop())) {\n if (tree[0] === id) {\n return !!tree[1].deleted;\n }\n toVisit = toVisit.concat(tree[2]);\n }\n}\n\nfunction isLocalId(id) {\n return (/^_local/).test(id);\n}\n\n// returns the current leaf node for a given revision\nfunction latest(rev, metadata) {\n var toVisit = metadata.rev_tree.slice();\n var node;\n while ((node = toVisit.pop())) {\n var pos = node.pos;\n var tree = node.ids;\n var id = tree[0];\n var opts = tree[1];\n var branches = tree[2];\n var isLeaf = branches.length === 0;\n\n var history = node.history ? node.history.slice() : [];\n history.push({id: id, pos: pos, opts: opts});\n\n if (isLeaf) {\n for (var i = 0, len = history.length; i < len; i++) {\n var historyNode = history[i];\n var historyRev = historyNode.pos + '-' + historyNode.id;\n\n if (historyRev === rev) {\n // return the rev of this leaf\n return pos + '-' + id;\n }\n }\n }\n\n for (var j = 0, l = branches.length; j < l; j++) {\n toVisit.push({pos: pos + 1, ids: branches[j], history: history});\n }\n }\n\n /* istanbul ignore next */\n throw new Error('Unable to resolve latest revision for id ' + metadata.id + ', rev ' + rev);\n}\n\nfunction evalFilter(input) {\n return scopedEval('\"use strict\";\\nreturn ' + input + ';', {});\n}\n\nfunction evalView(input) {\n var code = [\n 'return function(doc) {',\n ' \"use strict\";',\n ' var emitted = false;',\n ' var emit = function (a, b) {',\n ' emitted = true;',\n ' };',\n ' var view = ' + input + ';',\n ' view(doc);',\n ' if (emitted) {',\n ' return true;',\n ' }',\n '};'\n ].join('\\n');\n\n return scopedEval(code, {});\n}\n\ninherits(Changes$1, events.EventEmitter);\n\nfunction tryCatchInChangeListener(self, change) {\n // isolate try/catches to avoid V8 deoptimizations\n try {\n self.emit('change', change);\n } catch (e) {\n guardedConsole('error', 'Error in .on(\"change\", function):', e);\n }\n}\n\nfunction Changes$1(db, opts, callback) {\n events.EventEmitter.call(this);\n var self = this;\n this.db = db;\n opts = opts ? clone(opts) : {};\n var complete = opts.complete = once(function (err, resp) {\n if (err) {\n if (listenerCount(self, 'error') > 0) {\n self.emit('error', err);\n }\n } else {\n self.emit('complete', resp);\n }\n self.removeAllListeners();\n db.removeListener('destroyed', onDestroy);\n });\n if (callback) {\n self.on('complete', function (resp) {\n callback(null, resp);\n });\n self.on('error', callback);\n }\n function onDestroy() {\n self.cancel();\n }\n db.once('destroyed', onDestroy);\n\n opts.onChange = function (change) {\n /* istanbul ignore if */\n if (opts.isCancelled) {\n return;\n }\n tryCatchInChangeListener(self, change);\n };\n\n var promise = new PouchPromise(function (fulfill, reject) {\n opts.complete = function (err, res) {\n if (err) {\n reject(err);\n } else {\n fulfill(res);\n }\n };\n });\n self.once('cancel', function () {\n db.removeListener('destroyed', onDestroy);\n opts.complete(null, {status: 'cancelled'});\n });\n this.then = promise.then.bind(promise);\n this['catch'] = promise['catch'].bind(promise);\n this.then(function (result) {\n complete(null, result);\n }, complete);\n\n\n\n if (!db.taskqueue.isReady) {\n db.taskqueue.addTask(function (failed) {\n if (failed) {\n opts.complete(failed);\n } else if (self.isCancelled) {\n self.emit('cancel');\n } else {\n self.doChanges(opts);\n }\n });\n } else {\n self.doChanges(opts);\n }\n}\nChanges$1.prototype.cancel = function () {\n this.isCancelled = true;\n if (this.db.taskqueue.isReady) {\n this.emit('cancel');\n }\n};\nfunction processChange(doc, metadata, opts) {\n var changeList = [{rev: doc._rev}];\n if (opts.style === 'all_docs') {\n changeList = collectLeaves(metadata.rev_tree)\n .map(function (x) { return {rev: x.rev}; });\n }\n var change = {\n id: metadata.id,\n changes: changeList,\n doc: doc\n };\n\n if (isDeleted(metadata, doc._rev)) {\n change.deleted = true;\n }\n if (opts.conflicts) {\n change.doc._conflicts = collectConflicts(metadata);\n if (!change.doc._conflicts.length) {\n delete change.doc._conflicts;\n }\n }\n return change;\n}\n\nChanges$1.prototype.doChanges = function (opts) {\n var self = this;\n var callback = opts.complete;\n\n opts = clone(opts);\n if ('live' in opts && !('continuous' in opts)) {\n opts.continuous = opts.live;\n }\n opts.processChange = processChange;\n\n if (opts.since === 'latest') {\n opts.since = 'now';\n }\n if (!opts.since) {\n opts.since = 0;\n }\n if (opts.since === 'now') {\n this.db.info().then(function (info) {\n /* istanbul ignore if */\n if (self.isCancelled) {\n callback(null, {status: 'cancelled'});\n return;\n }\n opts.since = info.update_seq;\n self.doChanges(opts);\n }, callback);\n return;\n }\n\n\n if (opts.view && !opts.filter) {\n opts.filter = '_view';\n }\n\n if (opts.filter && typeof opts.filter === 'string') {\n if (opts.filter === '_view') {\n opts.view = normalizeDesignDocFunctionName(opts.view);\n } else {\n opts.filter = normalizeDesignDocFunctionName(opts.filter);\n }\n\n if (this.db.type() !== 'http' && !opts.doc_ids) {\n return this.filterChanges(opts);\n }\n }\n\n if (!('descending' in opts)) {\n opts.descending = false;\n }\n\n // 0 and 1 should return 1 document\n opts.limit = opts.limit === 0 ? 1 : opts.limit;\n opts.complete = callback;\n var newPromise = this.db._changes(opts);\n /* istanbul ignore else */\n if (newPromise && typeof newPromise.cancel === 'function') {\n var cancel = self.cancel;\n self.cancel = getArguments(function (args) {\n newPromise.cancel();\n cancel.apply(this, args);\n });\n }\n};\n\nChanges$1.prototype.filterChanges = function (opts) {\n var self = this;\n var callback = opts.complete;\n if (opts.filter === '_view') {\n if (!opts.view || typeof opts.view !== 'string') {\n var err = createError(BAD_REQUEST,\n '`view` filter parameter not found or invalid.');\n return callback(err);\n }\n // fetch a view from a design doc, make it behave like a filter\n var viewName = parseDesignDocFunctionName(opts.view);\n this.db.get('_design/' + viewName[0], function (err, ddoc) {\n /* istanbul ignore if */\n if (self.isCancelled) {\n return callback(null, {status: 'cancelled'});\n }\n /* istanbul ignore next */\n if (err) {\n return callback(generateErrorFromResponse(err));\n }\n var mapFun = ddoc && ddoc.views && ddoc.views[viewName[1]] &&\n ddoc.views[viewName[1]].map;\n if (!mapFun) {\n return callback(createError(MISSING_DOC,\n (ddoc.views ? 'missing json key: ' + viewName[1] :\n 'missing json key: views')));\n }\n opts.filter = evalView(mapFun);\n self.doChanges(opts);\n });\n } else {\n // fetch a filter from a design doc\n var filterName = parseDesignDocFunctionName(opts.filter);\n if (!filterName) {\n return self.doChanges(opts);\n }\n this.db.get('_design/' + filterName[0], function (err, ddoc) {\n /* istanbul ignore if */\n if (self.isCancelled) {\n return callback(null, {status: 'cancelled'});\n }\n /* istanbul ignore next */\n if (err) {\n return callback(generateErrorFromResponse(err));\n }\n var filterFun = ddoc && ddoc.filters && ddoc.filters[filterName[1]];\n if (!filterFun) {\n return callback(createError(MISSING_DOC,\n ((ddoc && ddoc.filters) ? 'missing json key: ' + filterName[1]\n : 'missing json key: filters')));\n }\n opts.filter = evalFilter(filterFun);\n self.doChanges(opts);\n });\n }\n};\n\n/*\n * A generic pouch adapter\n */\n\nfunction compare(left, right) {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\n// Wrapper for functions that call the bulkdocs api with a single doc,\n// if the first result is an error, return an error\nfunction yankError(callback) {\n return function (err, results) {\n if (err || (results[0] && results[0].error)) {\n callback(err || results[0]);\n } else {\n callback(null, results.length ? results[0] : results);\n }\n };\n}\n\n// clean docs given to us by the user\nfunction cleanDocs(docs) {\n for (var i = 0; i < docs.length; i++) {\n var doc = docs[i];\n if (doc._deleted) {\n delete doc._attachments; // ignore atts for deleted docs\n } else if (doc._attachments) {\n // filter out extraneous keys from _attachments\n var atts = Object.keys(doc._attachments);\n for (var j = 0; j < atts.length; j++) {\n var att = atts[j];\n doc._attachments[att] = pick(doc._attachments[att],\n ['data', 'digest', 'content_type', 'length', 'revpos', 'stub']);\n }\n }\n }\n}\n\n// compare two docs, first by _id then by _rev\nfunction compareByIdThenRev(a, b) {\n var idCompare = compare(a._id, b._id);\n if (idCompare !== 0) {\n return idCompare;\n }\n var aStart = a._revisions ? a._revisions.start : 0;\n var bStart = b._revisions ? b._revisions.start : 0;\n return compare(aStart, bStart);\n}\n\n// for every node in a revision tree computes its distance from the closest\n// leaf\nfunction computeHeight(revs) {\n var height = {};\n var edges = [];\n traverseRevTree(revs, function (isLeaf, pos, id, prnt) {\n var rev = pos + \"-\" + id;\n if (isLeaf) {\n height[rev] = 0;\n }\n if (prnt !== undefined) {\n edges.push({from: prnt, to: rev});\n }\n return rev;\n });\n\n edges.reverse();\n edges.forEach(function (edge) {\n if (height[edge.from] === undefined) {\n height[edge.from] = 1 + height[edge.to];\n } else {\n height[edge.from] = Math.min(height[edge.from], 1 + height[edge.to]);\n }\n });\n return height;\n}\n\nfunction allDocsKeysQuery(api, opts, callback) {\n var keys = ('limit' in opts) ?\n opts.keys.slice(opts.skip, opts.limit + opts.skip) :\n (opts.skip > 0) ? opts.keys.slice(opts.skip) : opts.keys;\n if (opts.descending) {\n keys.reverse();\n }\n if (!keys.length) {\n return api._allDocs({limit: 0}, callback);\n }\n var finalResults = {\n offset: opts.skip\n };\n return PouchPromise.all(keys.map(function (key) {\n var subOpts = extend$1({key: key, deleted: 'ok'}, opts);\n ['limit', 'skip', 'keys'].forEach(function (optKey) {\n delete subOpts[optKey];\n });\n return new PouchPromise(function (resolve, reject) {\n api._allDocs(subOpts, function (err, res) {\n /* istanbul ignore if */\n if (err) {\n return reject(err);\n }\n finalResults.total_rows = res.total_rows;\n resolve(res.rows[0] || {key: key, error: 'not_found'});\n });\n });\n })).then(function (results) {\n finalResults.rows = results;\n return finalResults;\n });\n}\n\n// all compaction is done in a queue, to avoid attaching\n// too many listeners at once\nfunction doNextCompaction(self) {\n var task = self._compactionQueue[0];\n var opts = task.opts;\n var callback = task.callback;\n self.get('_local/compaction').catch(function () {\n return false;\n }).then(function (doc) {\n if (doc && doc.last_seq) {\n opts.last_seq = doc.last_seq;\n }\n self._compact(opts, function (err, res) {\n /* istanbul ignore if */\n if (err) {\n callback(err);\n } else {\n callback(null, res);\n }\n immediate(function () {\n self._compactionQueue.shift();\n if (self._compactionQueue.length) {\n doNextCompaction(self);\n }\n });\n });\n });\n}\n\nfunction attachmentNameError(name) {\n if (name.charAt(0) === '_') {\n return name + 'is not a valid attachment name, attachment ' +\n 'names cannot start with \\'_\\'';\n }\n return false;\n}\n\ninherits(AbstractPouchDB, events.EventEmitter);\n\nfunction AbstractPouchDB() {\n events.EventEmitter.call(this);\n}\n\nAbstractPouchDB.prototype.post =\n adapterFun('post', function (doc, opts, callback) {\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n if (typeof doc !== 'object' || Array.isArray(doc)) {\n return callback(createError(NOT_AN_OBJECT));\n }\n this.bulkDocs({docs: [doc]}, opts, yankError(callback));\n});\n\nAbstractPouchDB.prototype.put = adapterFun('put', function (doc, opts, cb) {\n if (typeof opts === 'function') {\n cb = opts;\n opts = {};\n }\n if (typeof doc !== 'object' || Array.isArray(doc)) {\n return cb(createError(NOT_AN_OBJECT));\n }\n invalidIdError(doc._id);\n if (isLocalId(doc._id) && typeof this._putLocal === 'function') {\n if (doc._deleted) {\n return this._removeLocal(doc, cb);\n } else {\n return this._putLocal(doc, cb);\n }\n }\n if (typeof this._put === 'function' && opts.new_edits !== false) {\n this._put(doc, opts, cb);\n } else {\n this.bulkDocs({docs: [doc]}, opts, yankError(cb));\n }\n});\n\nAbstractPouchDB.prototype.putAttachment =\n adapterFun('putAttachment', function (docId, attachmentId, rev,\n blob, type) {\n var api = this;\n if (typeof type === 'function') {\n type = blob;\n blob = rev;\n rev = null;\n }\n // Lets fix in https://github.com/pouchdb/pouchdb/issues/3267\n /* istanbul ignore if */\n if (typeof type === 'undefined') {\n type = blob;\n blob = rev;\n rev = null;\n }\n if (!type) {\n guardedConsole('warn', 'Attachment', attachmentId, 'on document', docId, 'is missing content_type');\n }\n\n function createAttachment(doc) {\n var prevrevpos = '_rev' in doc ? parseInt(doc._rev, 10) : 0;\n doc._attachments = doc._attachments || {};\n doc._attachments[attachmentId] = {\n content_type: type,\n data: blob,\n revpos: ++prevrevpos\n };\n return api.put(doc);\n }\n\n return api.get(docId).then(function (doc) {\n if (doc._rev !== rev) {\n throw createError(REV_CONFLICT);\n }\n\n return createAttachment(doc);\n }, function (err) {\n // create new doc\n /* istanbul ignore else */\n if (err.reason === MISSING_DOC.message) {\n return createAttachment({_id: docId});\n } else {\n throw err;\n }\n });\n});\n\nAbstractPouchDB.prototype.removeAttachment =\n adapterFun('removeAttachment', function (docId, attachmentId, rev,\n callback) {\n var self = this;\n self.get(docId, function (err, obj) {\n /* istanbul ignore if */\n if (err) {\n callback(err);\n return;\n }\n if (obj._rev !== rev) {\n callback(createError(REV_CONFLICT));\n return;\n }\n /* istanbul ignore if */\n if (!obj._attachments) {\n return callback();\n }\n delete obj._attachments[attachmentId];\n if (Object.keys(obj._attachments).length === 0) {\n delete obj._attachments;\n }\n self.put(obj, callback);\n });\n});\n\nAbstractPouchDB.prototype.remove =\n adapterFun('remove', function (docOrId, optsOrRev, opts, callback) {\n var doc;\n if (typeof optsOrRev === 'string') {\n // id, rev, opts, callback style\n doc = {\n _id: docOrId,\n _rev: optsOrRev\n };\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n } else {\n // doc, opts, callback style\n doc = docOrId;\n if (typeof optsOrRev === 'function') {\n callback = optsOrRev;\n opts = {};\n } else {\n callback = opts;\n opts = optsOrRev;\n }\n }\n opts = opts || {};\n opts.was_delete = true;\n var newDoc = {_id: doc._id, _rev: (doc._rev || opts.rev)};\n newDoc._deleted = true;\n if (isLocalId(newDoc._id) && typeof this._removeLocal === 'function') {\n return this._removeLocal(doc, callback);\n }\n this.bulkDocs({docs: [newDoc]}, opts, yankError(callback));\n});\n\nAbstractPouchDB.prototype.revsDiff =\n adapterFun('revsDiff', function (req, opts, callback) {\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n var ids = Object.keys(req);\n\n if (!ids.length) {\n return callback(null, {});\n }\n\n var count = 0;\n var missing = new _Map();\n\n function addToMissing(id, revId) {\n if (!missing.has(id)) {\n missing.set(id, {missing: []});\n }\n missing.get(id).missing.push(revId);\n }\n\n function processDoc(id, rev_tree) {\n // Is this fast enough? Maybe we should switch to a set simulated by a map\n var missingForId = req[id].slice(0);\n traverseRevTree(rev_tree, function (isLeaf, pos, revHash, ctx,\n opts) {\n var rev = pos + '-' + revHash;\n var idx = missingForId.indexOf(rev);\n if (idx === -1) {\n return;\n }\n\n missingForId.splice(idx, 1);\n /* istanbul ignore if */\n if (opts.status !== 'available') {\n addToMissing(id, rev);\n }\n });\n\n // Traversing the tree is synchronous, so now `missingForId` contains\n // revisions that were not found in the tree\n missingForId.forEach(function (rev) {\n addToMissing(id, rev);\n });\n }\n\n ids.map(function (id) {\n this._getRevisionTree(id, function (err, rev_tree) {\n if (err && err.status === 404 && err.message === 'missing') {\n missing.set(id, {missing: req[id]});\n } else if (err) {\n /* istanbul ignore next */\n return callback(err);\n } else {\n processDoc(id, rev_tree);\n }\n\n if (++count === ids.length) {\n // convert LazyMap to object\n var missingObj = {};\n missing.forEach(function (value, key) {\n missingObj[key] = value;\n });\n return callback(null, missingObj);\n }\n });\n }, this);\n});\n\n// _bulk_get API for faster replication, as described in\n// https://github.com/apache/couchdb-chttpd/pull/33\n// At the \"abstract\" level, it will just run multiple get()s in\n// parallel, because this isn't much of a performance cost\n// for local databases (except the cost of multiple transactions, which is\n// small). The http adapter overrides this in order\n// to do a more efficient single HTTP request.\nAbstractPouchDB.prototype.bulkGet =\n adapterFun('bulkGet', function (opts, callback) {\n bulkGet(this, opts, callback);\n});\n\n// compact one document and fire callback\n// by compacting we mean removing all revisions which\n// are further from the leaf in revision tree than max_height\nAbstractPouchDB.prototype.compactDocument =\n adapterFun('compactDocument', function (docId, maxHeight, callback) {\n var self = this;\n this._getRevisionTree(docId, function (err, revTree) {\n /* istanbul ignore if */\n if (err) {\n return callback(err);\n }\n var height = computeHeight(revTree);\n var candidates = [];\n var revs = [];\n Object.keys(height).forEach(function (rev) {\n if (height[rev] > maxHeight) {\n candidates.push(rev);\n }\n });\n\n traverseRevTree(revTree, function (isLeaf, pos, revHash, ctx, opts) {\n var rev = pos + '-' + revHash;\n if (opts.status === 'available' && candidates.indexOf(rev) !== -1) {\n revs.push(rev);\n }\n });\n self._doCompaction(docId, revs, callback);\n });\n});\n\n// compact the whole database using single document\n// compaction\nAbstractPouchDB.prototype.compact =\n adapterFun('compact', function (opts, callback) {\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n\n var self = this;\n opts = opts || {};\n\n self._compactionQueue = self._compactionQueue || [];\n self._compactionQueue.push({opts: opts, callback: callback});\n if (self._compactionQueue.length === 1) {\n doNextCompaction(self);\n }\n});\nAbstractPouchDB.prototype._compact = function (opts, callback) {\n var self = this;\n var changesOpts = {\n return_docs: false,\n last_seq: opts.last_seq || 0\n };\n var promises = [];\n\n function onChange(row) {\n promises.push(self.compactDocument(row.id, 0));\n }\n function onComplete(resp) {\n var lastSeq = resp.last_seq;\n PouchPromise.all(promises).then(function () {\n return upsert(self, '_local/compaction', function deltaFunc(doc) {\n if (!doc.last_seq || doc.last_seq < lastSeq) {\n doc.last_seq = lastSeq;\n return doc;\n }\n return false; // somebody else got here first, don't update\n });\n }).then(function () {\n callback(null, {ok: true});\n }).catch(callback);\n }\n self.changes(changesOpts)\n .on('change', onChange)\n .on('complete', onComplete)\n .on('error', callback);\n};\n\n/* Begin api wrappers. Specific functionality to storage belongs in the\n _[method] */\nAbstractPouchDB.prototype.get = adapterFun('get', function (id, opts, cb) {\n if (typeof opts === 'function') {\n cb = opts;\n opts = {};\n }\n if (typeof id !== 'string') {\n return cb(createError(INVALID_ID));\n }\n if (isLocalId(id) && typeof this._getLocal === 'function') {\n return this._getLocal(id, cb);\n }\n var leaves = [], self = this;\n\n function finishOpenRevs() {\n var result = [];\n var count = leaves.length;\n /* istanbul ignore if */\n if (!count) {\n return cb(null, result);\n }\n\n // order with open_revs is unspecified\n leaves.forEach(function (leaf) {\n self.get(id, {\n rev: leaf,\n revs: opts.revs,\n latest: opts.latest,\n attachments: opts.attachments\n }, function (err, doc) {\n if (!err) {\n // using latest=true can produce duplicates\n var existing;\n for (var i = 0, l = result.length; i < l; i++) {\n if (result[i].ok && result[i].ok._rev === doc._rev) {\n existing = true;\n break;\n }\n }\n if (!existing) {\n result.push({ok: doc});\n }\n } else {\n result.push({missing: leaf});\n }\n count--;\n if (!count) {\n cb(null, result);\n }\n });\n });\n }\n\n if (opts.open_revs) {\n if (opts.open_revs === \"all\") {\n this._getRevisionTree(id, function (err, rev_tree) {\n if (err) {\n return cb(err);\n }\n leaves = collectLeaves(rev_tree).map(function (leaf) {\n return leaf.rev;\n });\n finishOpenRevs();\n });\n } else {\n if (Array.isArray(opts.open_revs)) {\n leaves = opts.open_revs;\n for (var i = 0; i < leaves.length; i++) {\n var l = leaves[i];\n // looks like it's the only thing couchdb checks\n if (!(typeof (l) === \"string\" && /^\\d+-/.test(l))) {\n return cb(createError(INVALID_REV));\n }\n }\n finishOpenRevs();\n } else {\n return cb(createError(UNKNOWN_ERROR, 'function_clause'));\n }\n }\n return; // open_revs does not like other options\n }\n\n return this._get(id, opts, function (err, result) {\n if (err) {\n return cb(err);\n }\n\n var doc = result.doc;\n var metadata = result.metadata;\n var ctx = result.ctx;\n\n if (opts.conflicts) {\n var conflicts = collectConflicts(metadata);\n if (conflicts.length) {\n doc._conflicts = conflicts;\n }\n }\n\n if (isDeleted(metadata, doc._rev)) {\n doc._deleted = true;\n }\n\n if (opts.revs || opts.revs_info) {\n var splittedRev = doc._rev.split('-');\n var revNo = parseInt(splittedRev[0], 10);\n var revHash = splittedRev[1];\n\n var paths = rootToLeaf(metadata.rev_tree);\n var path = null;\n\n for (var i = 0; i < paths.length; i++) {\n var currentPath = paths[i];\n var hashIndex = currentPath.ids.map(function (x) { return x.id; })\n .indexOf(revHash);\n var hashFoundAtRevPos = hashIndex === (revNo - 1);\n\n if (hashFoundAtRevPos || (!path && hashIndex !== -1)) {\n path = currentPath;\n }\n }\n\n var indexOfRev = path.ids.map(function (x) { return x.id; })\n .indexOf(doc._rev.split('-')[1]) + 1;\n var howMany = path.ids.length - indexOfRev;\n path.ids.splice(indexOfRev, howMany);\n path.ids.reverse();\n\n if (opts.revs) {\n doc._revisions = {\n start: (path.pos + path.ids.length) - 1,\n ids: path.ids.map(function (rev) {\n return rev.id;\n })\n };\n }\n if (opts.revs_info) {\n var pos = path.pos + path.ids.length;\n doc._revs_info = path.ids.map(function (rev) {\n pos--;\n return {\n rev: pos + '-' + rev.id,\n status: rev.opts.status\n };\n });\n }\n }\n\n if (opts.attachments && doc._attachments) {\n var attachments = doc._attachments;\n var count = Object.keys(attachments).length;\n if (count === 0) {\n return cb(null, doc);\n }\n Object.keys(attachments).forEach(function (key) {\n this._getAttachment(doc._id, key, attachments[key], {\n // Previously the revision handling was done in adapter.js\n // getAttachment, however since idb-next doesnt we need to\n // pass the rev through\n rev: doc._rev,\n binary: opts.binary,\n ctx: ctx\n }, function (err, data) {\n var att = doc._attachments[key];\n att.data = data;\n delete att.stub;\n delete att.length;\n if (!--count) {\n cb(null, doc);\n }\n });\n }, self);\n } else {\n if (doc._attachments) {\n for (var key in doc._attachments) {\n /* istanbul ignore else */\n if (doc._attachments.hasOwnProperty(key)) {\n doc._attachments[key].stub = true;\n }\n }\n }\n cb(null, doc);\n }\n });\n});\n\n// TODO: I dont like this, it forces an extra read for every\n// attachment read and enforces a confusing api between\n// adapter.js and the adapter implementation\nAbstractPouchDB.prototype.getAttachment =\n adapterFun('getAttachment', function (docId, attachmentId, opts, callback) {\n var self = this;\n if (opts instanceof Function) {\n callback = opts;\n opts = {};\n }\n this._get(docId, opts, function (err, res) {\n if (err) {\n return callback(err);\n }\n if (res.doc._attachments && res.doc._attachments[attachmentId]) {\n opts.ctx = res.ctx;\n opts.binary = true;\n self._getAttachment(docId, attachmentId,\n res.doc._attachments[attachmentId], opts, callback);\n } else {\n return callback(createError(MISSING_DOC));\n }\n });\n});\n\nAbstractPouchDB.prototype.allDocs =\n adapterFun('allDocs', function (opts, callback) {\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n opts.skip = typeof opts.skip !== 'undefined' ? opts.skip : 0;\n if (opts.start_key) {\n opts.startkey = opts.start_key;\n }\n if (opts.end_key) {\n opts.endkey = opts.end_key;\n }\n if ('keys' in opts) {\n if (!Array.isArray(opts.keys)) {\n return callback(new TypeError('options.keys must be an array'));\n }\n var incompatibleOpt =\n ['startkey', 'endkey', 'key'].filter(function (incompatibleOpt) {\n return incompatibleOpt in opts;\n })[0];\n if (incompatibleOpt) {\n callback(createError(QUERY_PARSE_ERROR,\n 'Query parameter `' + incompatibleOpt +\n '` is not compatible with multi-get'\n ));\n return;\n }\n if (this.type() !== 'http') {\n return allDocsKeysQuery(this, opts, callback);\n }\n }\n\n return this._allDocs(opts, callback);\n});\n\nAbstractPouchDB.prototype.changes = function (opts, callback) {\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n return new Changes$1(this, opts, callback);\n};\n\nAbstractPouchDB.prototype.close = adapterFun('close', function (callback) {\n this._closed = true;\n this.emit('closed');\n return this._close(callback);\n});\n\nAbstractPouchDB.prototype.info = adapterFun('info', function (callback) {\n var self = this;\n this._info(function (err, info) {\n if (err) {\n return callback(err);\n }\n // assume we know better than the adapter, unless it informs us\n info.db_name = info.db_name || self.name;\n info.auto_compaction = !!(self.auto_compaction && self.type() !== 'http');\n info.adapter = self.type();\n callback(null, info);\n });\n});\n\nAbstractPouchDB.prototype.id = adapterFun('id', function (callback) {\n return this._id(callback);\n});\n\n/* istanbul ignore next */\nAbstractPouchDB.prototype.type = function () {\n return (typeof this._type === 'function') ? this._type() : this.adapter;\n};\n\nAbstractPouchDB.prototype.bulkDocs =\n adapterFun('bulkDocs', function (req, opts, callback) {\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n\n opts = opts || {};\n\n if (Array.isArray(req)) {\n req = {\n docs: req\n };\n }\n\n if (!req || !req.docs || !Array.isArray(req.docs)) {\n return callback(createError(MISSING_BULK_DOCS));\n }\n\n for (var i = 0; i < req.docs.length; ++i) {\n if (typeof req.docs[i] !== 'object' || Array.isArray(req.docs[i])) {\n return callback(createError(NOT_AN_OBJECT));\n }\n }\n\n var attachmentError;\n req.docs.forEach(function (doc) {\n if (doc._attachments) {\n Object.keys(doc._attachments).forEach(function (name) {\n attachmentError = attachmentError || attachmentNameError(name);\n if (!doc._attachments[name].content_type) {\n guardedConsole('warn', 'Attachment', name, 'on document', doc._id, 'is missing content_type');\n }\n });\n }\n });\n\n if (attachmentError) {\n return callback(createError(BAD_REQUEST, attachmentError));\n }\n\n if (!('new_edits' in opts)) {\n if ('new_edits' in req) {\n opts.new_edits = req.new_edits;\n } else {\n opts.new_edits = true;\n }\n }\n\n if (!opts.new_edits && this.type() !== 'http') {\n // ensure revisions of the same doc are sorted, so that\n // the local adapter processes them correctly (#2935)\n req.docs.sort(compareByIdThenRev);\n }\n\n cleanDocs(req.docs);\n\n return this._bulkDocs(req, opts, function (err, res) {\n if (err) {\n return callback(err);\n }\n if (!opts.new_edits) {\n // this is what couch does when new_edits is false\n res = res.filter(function (x) {\n return x.error;\n });\n }\n callback(null, res);\n });\n});\n\nAbstractPouchDB.prototype.registerDependentDatabase =\n adapterFun('registerDependentDatabase', function (dependentDb,\n callback) {\n var depDB = new this.constructor(dependentDb, this.__opts);\n\n function diffFun(doc) {\n doc.dependentDbs = doc.dependentDbs || {};\n if (doc.dependentDbs[dependentDb]) {\n return false; // no update required\n }\n doc.dependentDbs[dependentDb] = true;\n return doc;\n }\n upsert(this, '_local/_pouch_dependentDbs', diffFun)\n .then(function () {\n callback(null, {db: depDB});\n }).catch(callback);\n});\n\nAbstractPouchDB.prototype.destroy =\n adapterFun('destroy', function (opts, callback) {\n\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n\n var self = this;\n var usePrefix = 'use_prefix' in self ? self.use_prefix : true;\n\n function destroyDb() {\n // call destroy method of the particular adaptor\n self._destroy(opts, function (err, resp) {\n if (err) {\n return callback(err);\n }\n self._destroyed = true;\n self.emit('destroyed');\n callback(null, resp || { 'ok': true });\n });\n }\n\n if (self.type() === 'http') {\n // no need to check for dependent DBs if it's a remote DB\n return destroyDb();\n }\n\n self.get('_local/_pouch_dependentDbs', function (err, localDoc) {\n if (err) {\n /* istanbul ignore if */\n if (err.status !== 404) {\n return callback(err);\n } else { // no dependencies\n return destroyDb();\n }\n }\n var dependentDbs = localDoc.dependentDbs;\n var PouchDB = self.constructor;\n var deletedMap = Object.keys(dependentDbs).map(function (name) {\n // use_prefix is only false in the browser\n /* istanbul ignore next */\n var trueName = usePrefix ?\n name.replace(new RegExp('^' + PouchDB.prefix), '') : name;\n return new PouchDB(trueName, self.__opts).destroy();\n });\n PouchPromise.all(deletedMap).then(destroyDb, callback);\n });\n});\n\nfunction TaskQueue() {\n this.isReady = false;\n this.failed = false;\n this.queue = [];\n}\n\nTaskQueue.prototype.execute = function () {\n var fun;\n if (this.failed) {\n while ((fun = this.queue.shift())) {\n fun(this.failed);\n }\n } else {\n while ((fun = this.queue.shift())) {\n fun();\n }\n }\n};\n\nTaskQueue.prototype.fail = function (err) {\n this.failed = err;\n this.execute();\n};\n\nTaskQueue.prototype.ready = function (db) {\n this.isReady = true;\n this.db = db;\n this.execute();\n};\n\nTaskQueue.prototype.addTask = function (fun) {\n this.queue.push(fun);\n if (this.failed) {\n this.execute();\n }\n};\n\nfunction parseAdapter(name, opts) {\n var match = name.match(/([a-z\\-]*):\\/\\/(.*)/);\n if (match) {\n // the http adapter expects the fully qualified name\n return {\n name: /https?/.test(match[1]) ? match[1] + '://' + match[2] : match[2],\n adapter: match[1]\n };\n }\n\n var adapters = PouchDB.adapters;\n var preferredAdapters = PouchDB.preferredAdapters;\n var prefix = PouchDB.prefix;\n var adapterName = opts.adapter;\n\n if (!adapterName) { // automatically determine adapter\n for (var i = 0; i < preferredAdapters.length; ++i) {\n adapterName = preferredAdapters[i];\n // check for browsers that have been upgraded from websql-only to websql+idb\n /* istanbul ignore if */\n if (adapterName === 'idb' && 'websql' in adapters &&\n hasLocalStorage() && localStorage['_pouch__websqldb_' + prefix + name]) {\n // log it, because this can be confusing during development\n guardedConsole('log', 'PouchDB is downgrading \"' + name + '\" to WebSQL to' +\n ' avoid data loss, because it was already opened with WebSQL.');\n continue; // keep using websql to avoid user data loss\n }\n break;\n }\n }\n\n var adapter = adapters[adapterName];\n\n // if adapter is invalid, then an error will be thrown later\n var usePrefix = (adapter && 'use_prefix' in adapter) ?\n adapter.use_prefix : true;\n\n return {\n name: usePrefix ? (prefix + name) : name,\n adapter: adapterName\n };\n}\n\n// OK, so here's the deal. Consider this code:\n// var db1 = new PouchDB('foo');\n// var db2 = new PouchDB('foo');\n// db1.destroy();\n// ^ these two both need to emit 'destroyed' events,\n// as well as the PouchDB constructor itself.\n// So we have one db object (whichever one got destroy() called on it)\n// responsible for emitting the initial event, which then gets emitted\n// by the constructor, which then broadcasts it to any other dbs\n// that may have been created with the same name.\nfunction prepareForDestruction(self) {\n\n var destructionListeners = self.constructor._destructionListeners;\n\n function onDestroyed() {\n self.removeListener('closed', onClosed);\n self.constructor.emit('destroyed', self.name);\n }\n\n function onConstructorDestroyed() {\n self.removeListener('destroyed', onDestroyed);\n self.removeListener('closed', onClosed);\n self.emit('destroyed');\n }\n\n function onClosed() {\n self.removeListener('destroyed', onDestroyed);\n destructionListeners.delete(self.name);\n }\n\n self.once('destroyed', onDestroyed);\n self.once('closed', onClosed);\n\n // in setup.js, the constructor is primed to listen for destroy events\n if (!destructionListeners.has(self.name)) {\n destructionListeners.set(self.name, []);\n }\n destructionListeners.get(self.name).push(onConstructorDestroyed);\n}\n\ninherits(PouchDB, AbstractPouchDB);\nfunction PouchDB(name, opts) {\n // In Node our test suite only tests this for PouchAlt unfortunately\n /* istanbul ignore if */\n if (!(this instanceof PouchDB)) {\n return new PouchDB(name, opts);\n }\n\n var self = this;\n opts = opts || {};\n\n if (name && typeof name === 'object') {\n opts = name;\n name = opts.name;\n delete opts.name;\n }\n\n this.__opts = opts = clone(opts);\n\n self.auto_compaction = opts.auto_compaction;\n self.prefix = PouchDB.prefix;\n\n if (typeof name !== 'string') {\n throw new Error('Missing/invalid DB name');\n }\n\n var prefixedName = (opts.prefix || '') + name;\n var backend = parseAdapter(prefixedName, opts);\n\n opts.name = backend.name;\n opts.adapter = opts.adapter || backend.adapter;\n\n self.name = name;\n self._adapter = opts.adapter;\n debug('pouchdb:adapter')('Picked adapter: ' + opts.adapter);\n\n if (!PouchDB.adapters[opts.adapter] ||\n !PouchDB.adapters[opts.adapter].valid()) {\n throw new Error('Invalid Adapter: ' + opts.adapter);\n }\n\n AbstractPouchDB.call(self);\n self.taskqueue = new TaskQueue();\n\n self.adapter = opts.adapter;\n\n PouchDB.adapters[opts.adapter].call(self, opts, function (err) {\n if (err) {\n return self.taskqueue.fail(err);\n }\n prepareForDestruction(self);\n\n self.emit('created', self);\n PouchDB.emit('created', self.name);\n self.taskqueue.ready(self);\n });\n\n}\n\nPouchDB.debug = debug;\n\nPouchDB.adapters = {};\nPouchDB.preferredAdapters = [];\n\nPouchDB.prefix = '_pouch_';\n\nvar eventEmitter = new events.EventEmitter();\n\nfunction setUpEventEmitter(Pouch) {\n Object.keys(events.EventEmitter.prototype).forEach(function (key) {\n if (typeof events.EventEmitter.prototype[key] === 'function') {\n Pouch[key] = eventEmitter[key].bind(eventEmitter);\n }\n });\n\n // these are created in constructor.js, and allow us to notify each DB with\n // the same name that it was destroyed, via the constructor object\n var destructListeners = Pouch._destructionListeners = new _Map();\n Pouch.on('destroyed', function onConstructorDestroyed(name) {\n destructListeners.get(name).forEach(function (callback) {\n callback();\n });\n destructListeners.delete(name);\n });\n}\n\nsetUpEventEmitter(PouchDB);\n\nPouchDB.adapter = function (id, obj, addToPreferredAdapters) {\n /* istanbul ignore else */\n if (obj.valid()) {\n PouchDB.adapters[id] = obj;\n if (addToPreferredAdapters) {\n PouchDB.preferredAdapters.push(id);\n }\n }\n};\n\nPouchDB.plugin = function (obj) {\n if (typeof obj === 'function') { // function style for plugins\n obj(PouchDB);\n } else if (typeof obj !== 'object' || Object.keys(obj).length === 0){\n throw new Error('Invalid plugin: got \\\"' + obj + '\\\", expected an object or a function');\n } else {\n Object.keys(obj).forEach(function (id) { // object style for plugins\n PouchDB.prototype[id] = obj[id];\n });\n }\n return PouchDB;\n};\n\nPouchDB.defaults = function (defaultOpts) {\n function PouchAlt(name, opts) {\n if (!(this instanceof PouchAlt)) {\n return new PouchAlt(name, opts);\n }\n\n opts = opts || {};\n\n if (name && typeof name === 'object') {\n opts = name;\n name = opts.name;\n delete opts.name;\n }\n\n opts = extend$1({}, PouchAlt.__defaults, opts);\n PouchDB.call(this, name, opts);\n }\n\n inherits(PouchAlt, PouchDB);\n\n PouchAlt.preferredAdapters = PouchDB.preferredAdapters.slice();\n Object.keys(PouchDB).forEach(function (key) {\n if (!(key in PouchAlt)) {\n PouchAlt[key] = PouchDB[key];\n }\n });\n\n // make default options transitive\n // https://github.com/pouchdb/pouchdb/issues/5922\n PouchAlt.__defaults = extend$1({}, this.__defaults, defaultOpts);\n\n return PouchAlt;\n};\n\n// managed automatically by set-version.js\nvar version = \"6.1.0\";\n\nPouchDB.version = version;\n\nfunction toObject(array) {\n return array.reduce(function (obj, item) {\n obj[item] = true;\n return obj;\n }, {});\n}\n// List of top level reserved words for doc\nvar reservedWords = toObject([\n '_id',\n '_rev',\n '_attachments',\n '_deleted',\n '_revisions',\n '_revs_info',\n '_conflicts',\n '_deleted_conflicts',\n '_local_seq',\n '_rev_tree',\n //replication documents\n '_replication_id',\n '_replication_state',\n '_replication_state_time',\n '_replication_state_reason',\n '_replication_stats',\n // Specific to Couchbase Sync Gateway\n '_removed'\n]);\n\n// List of reserved words that should end up the document\nvar dataWords = toObject([\n '_attachments',\n //replication documents\n '_replication_id',\n '_replication_state',\n '_replication_state_time',\n '_replication_state_reason',\n '_replication_stats'\n]);\n\nfunction parseRevisionInfo(rev) {\n if (!/^\\d+\\-./.test(rev)) {\n return createError(INVALID_REV);\n }\n var idx = rev.indexOf('-');\n var left = rev.substring(0, idx);\n var right = rev.substring(idx + 1);\n return {\n prefix: parseInt(left, 10),\n id: right\n };\n}\n\nfunction makeRevTreeFromRevisions(revisions, opts) {\n var pos = revisions.start - revisions.ids.length + 1;\n\n var revisionIds = revisions.ids;\n var ids = [revisionIds[0], opts, []];\n\n for (var i = 1, len = revisionIds.length; i < len; i++) {\n ids = [revisionIds[i], {status: 'missing'}, [ids]];\n }\n\n return [{\n pos: pos,\n ids: ids\n }];\n}\n\n// Preprocess documents, parse their revisions, assign an id and a\n// revision for new writes that are missing them, etc\nfunction parseDoc(doc, newEdits) {\n\n var nRevNum;\n var newRevId;\n var revInfo;\n var opts = {status: 'available'};\n if (doc._deleted) {\n opts.deleted = true;\n }\n\n if (newEdits) {\n if (!doc._id) {\n doc._id = uuid();\n }\n newRevId = uuid(32, 16).toLowerCase();\n if (doc._rev) {\n revInfo = parseRevisionInfo(doc._rev);\n if (revInfo.error) {\n return revInfo;\n }\n doc._rev_tree = [{\n pos: revInfo.prefix,\n ids: [revInfo.id, {status: 'missing'}, [[newRevId, opts, []]]]\n }];\n nRevNum = revInfo.prefix + 1;\n } else {\n doc._rev_tree = [{\n pos: 1,\n ids : [newRevId, opts, []]\n }];\n nRevNum = 1;\n }\n } else {\n if (doc._revisions) {\n doc._rev_tree = makeRevTreeFromRevisions(doc._revisions, opts);\n nRevNum = doc._revisions.start;\n newRevId = doc._revisions.ids[0];\n }\n if (!doc._rev_tree) {\n revInfo = parseRevisionInfo(doc._rev);\n if (revInfo.error) {\n return revInfo;\n }\n nRevNum = revInfo.prefix;\n newRevId = revInfo.id;\n doc._rev_tree = [{\n pos: nRevNum,\n ids: [newRevId, opts, []]\n }];\n }\n }\n\n invalidIdError(doc._id);\n\n doc._rev = nRevNum + '-' + newRevId;\n\n var result = {metadata : {}, data : {}};\n for (var key in doc) {\n /* istanbul ignore else */\n if (Object.prototype.hasOwnProperty.call(doc, key)) {\n var specialKey = key[0] === '_';\n if (specialKey && !reservedWords[key]) {\n var error = createError(DOC_VALIDATION, key);\n error.message = DOC_VALIDATION.message + ': ' + key;\n throw error;\n } else if (specialKey && !dataWords[key]) {\n result.metadata[key.slice(1)] = doc[key];\n } else {\n result.data[key] = doc[key];\n }\n }\n }\n return result;\n}\n\nvar atob$1 = function (str) {\n return atob(str);\n};\n\nvar btoa$1 = function (str) {\n return btoa(str);\n};\n\n// Abstracts constructing a Blob object, so it also works in older\n// browsers that don't support the native Blob constructor (e.g.\n// old QtWebKit versions, Android < 4.4).\nfunction createBlob(parts, properties) {\n /* global BlobBuilder,MSBlobBuilder,MozBlobBuilder,WebKitBlobBuilder */\n parts = parts || [];\n properties = properties || {};\n try {\n return new Blob(parts, properties);\n } catch (e) {\n if (e.name !== \"TypeError\") {\n throw e;\n }\n var Builder = typeof BlobBuilder !== 'undefined' ? BlobBuilder :\n typeof MSBlobBuilder !== 'undefined' ? MSBlobBuilder :\n typeof MozBlobBuilder !== 'undefined' ? MozBlobBuilder :\n WebKitBlobBuilder;\n var builder = new Builder();\n for (var i = 0; i < parts.length; i += 1) {\n builder.append(parts[i]);\n }\n return builder.getBlob(properties.type);\n }\n}\n\n// From http://stackoverflow.com/questions/14967647/ (continues on next line)\n// encode-decode-image-with-base64-breaks-image (2013-04-21)\nfunction binaryStringToArrayBuffer(bin) {\n var length = bin.length;\n var buf = new ArrayBuffer(length);\n var arr = new Uint8Array(buf);\n for (var i = 0; i < length; i++) {\n arr[i] = bin.charCodeAt(i);\n }\n return buf;\n}\n\nfunction binStringToBluffer(binString, type) {\n return createBlob([binaryStringToArrayBuffer(binString)], {type: type});\n}\n\nfunction b64ToBluffer(b64, type) {\n return binStringToBluffer(atob$1(b64), type);\n}\n\n//Can't find original post, but this is close\n//http://stackoverflow.com/questions/6965107/ (continues on next line)\n//converting-between-strings-and-arraybuffers\nfunction arrayBufferToBinaryString(buffer) {\n var binary = '';\n var bytes = new Uint8Array(buffer);\n var length = bytes.byteLength;\n for (var i = 0; i < length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return binary;\n}\n\n// shim for browsers that don't support it\nfunction readAsBinaryString(blob, callback) {\n if (typeof FileReader === 'undefined') {\n // fix for Firefox in a web worker\n // https://bugzilla.mozilla.org/show_bug.cgi?id=901097\n return callback(arrayBufferToBinaryString(\n new FileReaderSync().readAsArrayBuffer(blob)));\n }\n\n var reader = new FileReader();\n var hasBinaryString = typeof reader.readAsBinaryString === 'function';\n reader.onloadend = function (e) {\n var result = e.target.result || '';\n if (hasBinaryString) {\n return callback(result);\n }\n callback(arrayBufferToBinaryString(result));\n };\n if (hasBinaryString) {\n reader.readAsBinaryString(blob);\n } else {\n reader.readAsArrayBuffer(blob);\n }\n}\n\nfunction blobToBinaryString(blobOrBuffer, callback) {\n readAsBinaryString(blobOrBuffer, function (bin) {\n callback(bin);\n });\n}\n\nfunction blobToBase64(blobOrBuffer, callback) {\n blobToBinaryString(blobOrBuffer, function (base64) {\n callback(btoa$1(base64));\n });\n}\n\n// simplified API. universal browser support is assumed\nfunction readAsArrayBuffer(blob, callback) {\n if (typeof FileReader === 'undefined') {\n // fix for Firefox in a web worker:\n // https://bugzilla.mozilla.org/show_bug.cgi?id=901097\n return callback(new FileReaderSync().readAsArrayBuffer(blob));\n }\n\n var reader = new FileReader();\n reader.onloadend = function (e) {\n var result = e.target.result || new ArrayBuffer(0);\n callback(result);\n };\n reader.readAsArrayBuffer(blob);\n}\n\nvar setImmediateShim = global.setImmediate || global.setTimeout;\nvar MD5_CHUNK_SIZE = 32768;\n\nfunction rawToBase64(raw) {\n return btoa$1(raw);\n}\n\nfunction sliceBlob(blob, start, end) {\n if (blob.webkitSlice) {\n return blob.webkitSlice(start, end);\n }\n return blob.slice(start, end);\n}\n\nfunction appendBlob(buffer, blob, start, end, callback) {\n if (start > 0 || end < blob.size) {\n // only slice blob if we really need to\n blob = sliceBlob(blob, start, end);\n }\n readAsArrayBuffer(blob, function (arrayBuffer) {\n buffer.append(arrayBuffer);\n callback();\n });\n}\n\nfunction appendString(buffer, string, start, end, callback) {\n if (start > 0 || end < string.length) {\n // only create a substring if we really need to\n string = string.substring(start, end);\n }\n buffer.appendBinary(string);\n callback();\n}\n\nfunction binaryMd5(data, callback) {\n var inputIsString = typeof data === 'string';\n var len = inputIsString ? data.length : data.size;\n var chunkSize = Math.min(MD5_CHUNK_SIZE, len);\n var chunks = Math.ceil(len / chunkSize);\n var currentChunk = 0;\n var buffer = inputIsString ? new Md5() : new Md5.ArrayBuffer();\n\n var append = inputIsString ? appendString : appendBlob;\n\n function next() {\n setImmediateShim(loadNextChunk);\n }\n\n function done() {\n var raw = buffer.end(true);\n var base64 = rawToBase64(raw);\n callback(base64);\n buffer.destroy();\n }\n\n function loadNextChunk() {\n var start = currentChunk * chunkSize;\n var end = start + chunkSize;\n currentChunk++;\n if (currentChunk < chunks) {\n append(buffer, data, start, end, next);\n } else {\n append(buffer, data, start, end, done);\n }\n }\n loadNextChunk();\n}\n\nfunction stringMd5(string) {\n return Md5.hash(string);\n}\n\nfunction parseBase64(data) {\n try {\n return atob$1(data);\n } catch (e) {\n var err = createError(BAD_ARG,\n 'Attachment is not a valid base64 string');\n return {error: err};\n }\n}\n\nfunction preprocessString(att, blobType, callback) {\n var asBinary = parseBase64(att.data);\n if (asBinary.error) {\n return callback(asBinary.error);\n }\n\n att.length = asBinary.length;\n if (blobType === 'blob') {\n att.data = binStringToBluffer(asBinary, att.content_type);\n } else if (blobType === 'base64') {\n att.data = btoa$1(asBinary);\n } else { // binary\n att.data = asBinary;\n }\n binaryMd5(asBinary, function (result) {\n att.digest = 'md5-' + result;\n callback();\n });\n}\n\nfunction preprocessBlob(att, blobType, callback) {\n binaryMd5(att.data, function (md5) {\n att.digest = 'md5-' + md5;\n // size is for blobs (browser), length is for buffers (node)\n att.length = att.data.size || att.data.length || 0;\n if (blobType === 'binary') {\n blobToBinaryString(att.data, function (binString) {\n att.data = binString;\n callback();\n });\n } else if (blobType === 'base64') {\n blobToBase64(att.data, function (b64) {\n att.data = b64;\n callback();\n });\n } else {\n callback();\n }\n });\n}\n\nfunction preprocessAttachment(att, blobType, callback) {\n if (att.stub) {\n return callback();\n }\n if (typeof att.data === 'string') { // input is a base64 string\n preprocessString(att, blobType, callback);\n } else { // input is a blob\n preprocessBlob(att, blobType, callback);\n }\n}\n\nfunction preprocessAttachments(docInfos, blobType, callback) {\n\n if (!docInfos.length) {\n return callback();\n }\n\n var docv = 0;\n var overallErr;\n\n docInfos.forEach(function (docInfo) {\n var attachments = docInfo.data && docInfo.data._attachments ?\n Object.keys(docInfo.data._attachments) : [];\n var recv = 0;\n\n if (!attachments.length) {\n return done();\n }\n\n function processedAttachment(err) {\n overallErr = err;\n recv++;\n if (recv === attachments.length) {\n done();\n }\n }\n\n for (var key in docInfo.data._attachments) {\n if (docInfo.data._attachments.hasOwnProperty(key)) {\n preprocessAttachment(docInfo.data._attachments[key],\n blobType, processedAttachment);\n }\n }\n });\n\n function done() {\n docv++;\n if (docInfos.length === docv) {\n if (overallErr) {\n callback(overallErr);\n } else {\n callback();\n }\n }\n }\n}\n\nfunction updateDoc(revLimit, prev, docInfo, results,\n i, cb, writeDoc, newEdits) {\n\n if (revExists(prev.rev_tree, docInfo.metadata.rev)) {\n results[i] = docInfo;\n return cb();\n }\n\n // sometimes this is pre-calculated. historically not always\n var previousWinningRev = prev.winningRev || winningRev(prev);\n var previouslyDeleted = 'deleted' in prev ? prev.deleted :\n isDeleted(prev, previousWinningRev);\n var deleted = 'deleted' in docInfo.metadata ? docInfo.metadata.deleted :\n isDeleted(docInfo.metadata);\n var isRoot = /^1-/.test(docInfo.metadata.rev);\n\n if (previouslyDeleted && !deleted && newEdits && isRoot) {\n var newDoc = docInfo.data;\n newDoc._rev = previousWinningRev;\n newDoc._id = docInfo.metadata.id;\n docInfo = parseDoc(newDoc, newEdits);\n }\n\n var merged = merge(prev.rev_tree, docInfo.metadata.rev_tree[0], revLimit);\n\n var inConflict = newEdits && (((previouslyDeleted && deleted) ||\n (!previouslyDeleted && merged.conflicts !== 'new_leaf') ||\n (previouslyDeleted && !deleted && merged.conflicts === 'new_branch')));\n\n if (inConflict) {\n var err = createError(REV_CONFLICT);\n results[i] = err;\n return cb();\n }\n\n var newRev = docInfo.metadata.rev;\n docInfo.metadata.rev_tree = merged.tree;\n docInfo.stemmedRevs = merged.stemmedRevs || [];\n /* istanbul ignore else */\n if (prev.rev_map) {\n docInfo.metadata.rev_map = prev.rev_map; // used only by leveldb\n }\n\n // recalculate\n var winningRev$$ = winningRev(docInfo.metadata);\n var winningRevIsDeleted = isDeleted(docInfo.metadata, winningRev$$);\n\n // calculate the total number of documents that were added/removed,\n // from the perspective of total_rows/doc_count\n var delta = (previouslyDeleted === winningRevIsDeleted) ? 0 :\n previouslyDeleted < winningRevIsDeleted ? -1 : 1;\n\n var newRevIsDeleted;\n if (newRev === winningRev$$) {\n // if the new rev is the same as the winning rev, we can reuse that value\n newRevIsDeleted = winningRevIsDeleted;\n } else {\n // if they're not the same, then we need to recalculate\n newRevIsDeleted = isDeleted(docInfo.metadata, newRev);\n }\n\n writeDoc(docInfo, winningRev$$, winningRevIsDeleted, newRevIsDeleted,\n true, delta, i, cb);\n}\n\nfunction rootIsMissing(docInfo) {\n return docInfo.metadata.rev_tree[0].ids[1].status === 'missing';\n}\n\nfunction processDocs(revLimit, docInfos, api, fetchedDocs, tx, results,\n writeDoc, opts, overallCallback) {\n\n // Default to 1000 locally\n revLimit = revLimit || 1000;\n\n function insertDoc(docInfo, resultsIdx, callback) {\n // Cant insert new deleted documents\n var winningRev$$ = winningRev(docInfo.metadata);\n var deleted = isDeleted(docInfo.metadata, winningRev$$);\n if ('was_delete' in opts && deleted) {\n results[resultsIdx] = createError(MISSING_DOC, 'deleted');\n return callback();\n }\n\n // 4712 - detect whether a new document was inserted with a _rev\n var inConflict = newEdits && rootIsMissing(docInfo);\n\n if (inConflict) {\n var err = createError(REV_CONFLICT);\n results[resultsIdx] = err;\n return callback();\n }\n\n var delta = deleted ? 0 : 1;\n\n writeDoc(docInfo, winningRev$$, deleted, deleted, false,\n delta, resultsIdx, callback);\n }\n\n var newEdits = opts.new_edits;\n var idsToDocs = new _Map();\n\n var docsDone = 0;\n var docsToDo = docInfos.length;\n\n function checkAllDocsDone() {\n if (++docsDone === docsToDo && overallCallback) {\n overallCallback();\n }\n }\n\n docInfos.forEach(function (currentDoc, resultsIdx) {\n\n if (currentDoc._id && isLocalId(currentDoc._id)) {\n var fun = currentDoc._deleted ? '_removeLocal' : '_putLocal';\n api[fun](currentDoc, {ctx: tx}, function (err, res) {\n results[resultsIdx] = err || res;\n checkAllDocsDone();\n });\n return;\n }\n\n var id = currentDoc.metadata.id;\n if (idsToDocs.has(id)) {\n docsToDo--; // duplicate\n idsToDocs.get(id).push([currentDoc, resultsIdx]);\n } else {\n idsToDocs.set(id, [[currentDoc, resultsIdx]]);\n }\n });\n\n // in the case of new_edits, the user can provide multiple docs\n // with the same id. these need to be processed sequentially\n idsToDocs.forEach(function (docs, id) {\n var numDone = 0;\n\n function docWritten() {\n if (++numDone < docs.length) {\n nextDoc();\n } else {\n checkAllDocsDone();\n }\n }\n function nextDoc() {\n var value = docs[numDone];\n var currentDoc = value[0];\n var resultsIdx = value[1];\n\n if (fetchedDocs.has(id)) {\n updateDoc(revLimit, fetchedDocs.get(id), currentDoc, results,\n resultsIdx, docWritten, writeDoc, newEdits);\n } else {\n // Ensure stemming applies to new writes as well\n var merged = merge([], currentDoc.metadata.rev_tree[0], revLimit);\n currentDoc.metadata.rev_tree = merged.tree;\n currentDoc.stemmedRevs = merged.stemmedRevs || [];\n insertDoc(currentDoc, resultsIdx, docWritten);\n }\n }\n nextDoc();\n });\n}\n\n// IndexedDB requires a versioned database structure, so we use the\n// version here to manage migrations.\nvar ADAPTER_VERSION = 5;\n\n// The object stores created for each database\n// DOC_STORE stores the document meta data, its revision history and state\n// Keyed by document id\nvar DOC_STORE = 'document-store';\n// BY_SEQ_STORE stores a particular version of a document, keyed by its\n// sequence id\nvar BY_SEQ_STORE = 'by-sequence';\n// Where we store attachments\nvar ATTACH_STORE = 'attach-store';\n// Where we store many-to-many relations\n// between attachment digests and seqs\nvar ATTACH_AND_SEQ_STORE = 'attach-seq-store';\n\n// Where we store database-wide meta data in a single record\n// keyed by id: META_STORE\nvar META_STORE = 'meta-store';\n// Where we store local documents\nvar LOCAL_STORE = 'local-store';\n// Where we detect blob support\nvar DETECT_BLOB_SUPPORT_STORE = 'detect-blob-support';\n\nfunction safeJsonParse(str) {\n // This try/catch guards against stack overflow errors.\n // JSON.parse() is faster than vuvuzela.parse() but vuvuzela\n // cannot overflow.\n try {\n return JSON.parse(str);\n } catch (e) {\n /* istanbul ignore next */\n return vuvuzela.parse(str);\n }\n}\n\nfunction safeJsonStringify(json) {\n try {\n return JSON.stringify(json);\n } catch (e) {\n /* istanbul ignore next */\n return vuvuzela.stringify(json);\n }\n}\n\nfunction idbError(callback) {\n return function (evt) {\n var message = 'unknown_error';\n if (evt.target && evt.target.error) {\n message = evt.target.error.name || evt.target.error.message;\n }\n callback(createError(IDB_ERROR, message, evt.type));\n };\n}\n\n// Unfortunately, the metadata has to be stringified\n// when it is put into the database, because otherwise\n// IndexedDB can throw errors for deeply-nested objects.\n// Originally we just used JSON.parse/JSON.stringify; now\n// we use this custom vuvuzela library that avoids recursion.\n// If we could do it all over again, we'd probably use a\n// format for the revision trees other than JSON.\nfunction encodeMetadata(metadata, winningRev, deleted) {\n return {\n data: safeJsonStringify(metadata),\n winningRev: winningRev,\n deletedOrLocal: deleted ? '1' : '0',\n seq: metadata.seq, // highest seq for this doc\n id: metadata.id\n };\n}\n\nfunction decodeMetadata(storedObject) {\n if (!storedObject) {\n return null;\n }\n var metadata = safeJsonParse(storedObject.data);\n metadata.winningRev = storedObject.winningRev;\n metadata.deleted = storedObject.deletedOrLocal === '1';\n metadata.seq = storedObject.seq;\n return metadata;\n}\n\n// read the doc back out from the database. we don't store the\n// _id or _rev because we already have _doc_id_rev.\nfunction decodeDoc(doc) {\n if (!doc) {\n return doc;\n }\n var idx = doc._doc_id_rev.lastIndexOf(':');\n doc._id = doc._doc_id_rev.substring(0, idx - 1);\n doc._rev = doc._doc_id_rev.substring(idx + 1);\n delete doc._doc_id_rev;\n return doc;\n}\n\n// Read a blob from the database, encoding as necessary\n// and translating from base64 if the IDB doesn't support\n// native Blobs\nfunction readBlobData(body, type, asBlob, callback) {\n if (asBlob) {\n if (!body) {\n callback(createBlob([''], {type: type}));\n } else if (typeof body !== 'string') { // we have blob support\n callback(body);\n } else { // no blob support\n callback(b64ToBluffer(body, type));\n }\n } else { // as base64 string\n if (!body) {\n callback('');\n } else if (typeof body !== 'string') { // we have blob support\n readAsBinaryString(body, function (binary) {\n callback(btoa$1(binary));\n });\n } else { // no blob support\n callback(body);\n }\n }\n}\n\nfunction fetchAttachmentsIfNecessary(doc, opts, txn, cb) {\n var attachments = Object.keys(doc._attachments || {});\n if (!attachments.length) {\n return cb && cb();\n }\n var numDone = 0;\n\n function checkDone() {\n if (++numDone === attachments.length && cb) {\n cb();\n }\n }\n\n function fetchAttachment(doc, att) {\n var attObj = doc._attachments[att];\n var digest = attObj.digest;\n var req = txn.objectStore(ATTACH_STORE).get(digest);\n req.onsuccess = function (e) {\n attObj.body = e.target.result.body;\n checkDone();\n };\n }\n\n attachments.forEach(function (att) {\n if (opts.attachments && opts.include_docs) {\n fetchAttachment(doc, att);\n } else {\n doc._attachments[att].stub = true;\n checkDone();\n }\n });\n}\n\n// IDB-specific postprocessing necessary because\n// we don't know whether we stored a true Blob or\n// a base64-encoded string, and if it's a Blob it\n// needs to be read outside of the transaction context\nfunction postProcessAttachments(results, asBlob) {\n return PouchPromise.all(results.map(function (row) {\n if (row.doc && row.doc._attachments) {\n var attNames = Object.keys(row.doc._attachments);\n return PouchPromise.all(attNames.map(function (att) {\n var attObj = row.doc._attachments[att];\n if (!('body' in attObj)) { // already processed\n return;\n }\n var body = attObj.body;\n var type = attObj.content_type;\n return new PouchPromise(function (resolve) {\n readBlobData(body, type, asBlob, function (data) {\n row.doc._attachments[att] = extend$1(\n pick(attObj, ['digest', 'content_type']),\n {data: data}\n );\n resolve();\n });\n });\n }));\n }\n }));\n}\n\nfunction compactRevs(revs, docId, txn) {\n\n var possiblyOrphanedDigests = [];\n var seqStore = txn.objectStore(BY_SEQ_STORE);\n var attStore = txn.objectStore(ATTACH_STORE);\n var attAndSeqStore = txn.objectStore(ATTACH_AND_SEQ_STORE);\n var count = revs.length;\n\n function checkDone() {\n count--;\n if (!count) { // done processing all revs\n deleteOrphanedAttachments();\n }\n }\n\n function deleteOrphanedAttachments() {\n if (!possiblyOrphanedDigests.length) {\n return;\n }\n possiblyOrphanedDigests.forEach(function (digest) {\n var countReq = attAndSeqStore.index('digestSeq').count(\n IDBKeyRange.bound(\n digest + '::', digest + '::\\uffff', false, false));\n countReq.onsuccess = function (e) {\n var count = e.target.result;\n if (!count) {\n // orphaned\n attStore.delete(digest);\n }\n };\n });\n }\n\n revs.forEach(function (rev) {\n var index = seqStore.index('_doc_id_rev');\n var key = docId + \"::\" + rev;\n index.getKey(key).onsuccess = function (e) {\n var seq = e.target.result;\n if (typeof seq !== 'number') {\n return checkDone();\n }\n seqStore.delete(seq);\n\n var cursor = attAndSeqStore.index('seq')\n .openCursor(IDBKeyRange.only(seq));\n\n cursor.onsuccess = function (event) {\n var cursor = event.target.result;\n if (cursor) {\n var digest = cursor.value.digestSeq.split('::')[0];\n possiblyOrphanedDigests.push(digest);\n attAndSeqStore.delete(cursor.primaryKey);\n cursor.continue();\n } else { // done\n checkDone();\n }\n };\n };\n });\n}\n\nfunction openTransactionSafely(idb, stores, mode) {\n try {\n return {\n txn: idb.transaction(stores, mode)\n };\n } catch (err) {\n return {\n error: err\n };\n }\n}\n\nfunction idbBulkDocs(dbOpts, req, opts, api, idb, idbChanges, callback) {\n var docInfos = req.docs;\n var txn;\n var docStore;\n var bySeqStore;\n var attachStore;\n var attachAndSeqStore;\n var docInfoError;\n var docCountDelta = 0;\n\n for (var i = 0, len = docInfos.length; i < len; i++) {\n var doc = docInfos[i];\n if (doc._id && isLocalId(doc._id)) {\n continue;\n }\n doc = docInfos[i] = parseDoc(doc, opts.new_edits);\n if (doc.error && !docInfoError) {\n docInfoError = doc;\n }\n }\n\n if (docInfoError) {\n return callback(docInfoError);\n }\n\n var results = new Array(docInfos.length);\n var fetchedDocs = new _Map();\n var preconditionErrored = false;\n var blobType = api._meta.blobSupport ? 'blob' : 'base64';\n\n preprocessAttachments(docInfos, blobType, function (err) {\n if (err) {\n return callback(err);\n }\n startTransaction();\n });\n\n function startTransaction() {\n\n var stores = [\n DOC_STORE, BY_SEQ_STORE,\n ATTACH_STORE,\n LOCAL_STORE, ATTACH_AND_SEQ_STORE\n ];\n var txnResult = openTransactionSafely(idb, stores, 'readwrite');\n if (txnResult.error) {\n return callback(txnResult.error);\n }\n txn = txnResult.txn;\n txn.onabort = idbError(callback);\n txn.ontimeout = idbError(callback);\n txn.oncomplete = complete;\n docStore = txn.objectStore(DOC_STORE);\n bySeqStore = txn.objectStore(BY_SEQ_STORE);\n attachStore = txn.objectStore(ATTACH_STORE);\n attachAndSeqStore = txn.objectStore(ATTACH_AND_SEQ_STORE);\n\n verifyAttachments(function (err) {\n if (err) {\n preconditionErrored = true;\n return callback(err);\n }\n fetchExistingDocs();\n });\n }\n\n function idbProcessDocs() {\n processDocs(dbOpts.revs_limit, docInfos, api, fetchedDocs,\n txn, results, writeDoc, opts);\n }\n\n function fetchExistingDocs() {\n\n if (!docInfos.length) {\n return;\n }\n\n var numFetched = 0;\n\n function checkDone() {\n if (++numFetched === docInfos.length) {\n idbProcessDocs();\n }\n }\n\n function readMetadata(event) {\n var metadata = decodeMetadata(event.target.result);\n\n if (metadata) {\n fetchedDocs.set(metadata.id, metadata);\n }\n checkDone();\n }\n\n for (var i = 0, len = docInfos.length; i < len; i++) {\n var docInfo = docInfos[i];\n if (docInfo._id && isLocalId(docInfo._id)) {\n checkDone(); // skip local docs\n continue;\n }\n var req = docStore.get(docInfo.metadata.id);\n req.onsuccess = readMetadata;\n }\n }\n\n function complete() {\n if (preconditionErrored) {\n return;\n }\n\n idbChanges.notify(api._meta.name);\n api._meta.docCount += docCountDelta;\n callback(null, results);\n }\n\n function verifyAttachment(digest, callback) {\n\n var req = attachStore.get(digest);\n req.onsuccess = function (e) {\n if (!e.target.result) {\n var err = createError(MISSING_STUB,\n 'unknown stub attachment with digest ' +\n digest);\n err.status = 412;\n callback(err);\n } else {\n callback();\n }\n };\n }\n\n function verifyAttachments(finish) {\n\n\n var digests = [];\n docInfos.forEach(function (docInfo) {\n if (docInfo.data && docInfo.data._attachments) {\n Object.keys(docInfo.data._attachments).forEach(function (filename) {\n var att = docInfo.data._attachments[filename];\n if (att.stub) {\n digests.push(att.digest);\n }\n });\n }\n });\n if (!digests.length) {\n return finish();\n }\n var numDone = 0;\n var err;\n\n function checkDone() {\n if (++numDone === digests.length) {\n finish(err);\n }\n }\n digests.forEach(function (digest) {\n verifyAttachment(digest, function (attErr) {\n if (attErr && !err) {\n err = attErr;\n }\n checkDone();\n });\n });\n }\n\n function writeDoc(docInfo, winningRev, winningRevIsDeleted, newRevIsDeleted,\n isUpdate, delta, resultsIdx, callback) {\n\n docCountDelta += delta;\n\n docInfo.metadata.winningRev = winningRev;\n docInfo.metadata.deleted = winningRevIsDeleted;\n\n var doc = docInfo.data;\n doc._id = docInfo.metadata.id;\n doc._rev = docInfo.metadata.rev;\n\n if (newRevIsDeleted) {\n doc._deleted = true;\n }\n\n var hasAttachments = doc._attachments &&\n Object.keys(doc._attachments).length;\n if (hasAttachments) {\n return writeAttachments(docInfo, winningRev, winningRevIsDeleted,\n isUpdate, resultsIdx, callback);\n }\n\n finishDoc(docInfo, winningRev, winningRevIsDeleted,\n isUpdate, resultsIdx, callback);\n }\n\n function finishDoc(docInfo, winningRev, winningRevIsDeleted,\n isUpdate, resultsIdx, callback) {\n\n var doc = docInfo.data;\n var metadata = docInfo.metadata;\n\n doc._doc_id_rev = metadata.id + '::' + metadata.rev;\n delete doc._id;\n delete doc._rev;\n\n function afterPutDoc(e) {\n var revsToDelete = docInfo.stemmedRevs || [];\n\n if (isUpdate && api.auto_compaction) {\n revsToDelete = revsToDelete.concat(compactTree(docInfo.metadata));\n }\n\n if (revsToDelete && revsToDelete.length) {\n compactRevs(revsToDelete, docInfo.metadata.id, txn);\n }\n\n metadata.seq = e.target.result;\n // Current _rev is calculated from _rev_tree on read\n // delete metadata.rev;\n var metadataToStore = encodeMetadata(metadata, winningRev,\n winningRevIsDeleted);\n var metaDataReq = docStore.put(metadataToStore);\n metaDataReq.onsuccess = afterPutMetadata;\n }\n\n function afterPutDocError(e) {\n // ConstraintError, need to update, not put (see #1638 for details)\n e.preventDefault(); // avoid transaction abort\n e.stopPropagation(); // avoid transaction onerror\n var index = bySeqStore.index('_doc_id_rev');\n var getKeyReq = index.getKey(doc._doc_id_rev);\n getKeyReq.onsuccess = function (e) {\n var putReq = bySeqStore.put(doc, e.target.result);\n putReq.onsuccess = afterPutDoc;\n };\n }\n\n function afterPutMetadata() {\n results[resultsIdx] = {\n ok: true,\n id: metadata.id,\n rev: metadata.rev\n };\n fetchedDocs.set(docInfo.metadata.id, docInfo.metadata);\n insertAttachmentMappings(docInfo, metadata.seq, callback);\n }\n\n var putReq = bySeqStore.put(doc);\n\n putReq.onsuccess = afterPutDoc;\n putReq.onerror = afterPutDocError;\n }\n\n function writeAttachments(docInfo, winningRev, winningRevIsDeleted,\n isUpdate, resultsIdx, callback) {\n\n\n var doc = docInfo.data;\n\n var numDone = 0;\n var attachments = Object.keys(doc._attachments);\n\n function collectResults() {\n if (numDone === attachments.length) {\n finishDoc(docInfo, winningRev, winningRevIsDeleted,\n isUpdate, resultsIdx, callback);\n }\n }\n\n function attachmentSaved() {\n numDone++;\n collectResults();\n }\n\n attachments.forEach(function (key) {\n var att = docInfo.data._attachments[key];\n if (!att.stub) {\n var data = att.data;\n delete att.data;\n att.revpos = parseInt(winningRev, 10);\n var digest = att.digest;\n saveAttachment(digest, data, attachmentSaved);\n } else {\n numDone++;\n collectResults();\n }\n });\n }\n\n // map seqs to attachment digests, which\n // we will need later during compaction\n function insertAttachmentMappings(docInfo, seq, callback) {\n\n var attsAdded = 0;\n var attsToAdd = Object.keys(docInfo.data._attachments || {});\n\n if (!attsToAdd.length) {\n return callback();\n }\n\n function checkDone() {\n if (++attsAdded === attsToAdd.length) {\n callback();\n }\n }\n\n function add(att) {\n var digest = docInfo.data._attachments[att].digest;\n var req = attachAndSeqStore.put({\n seq: seq,\n digestSeq: digest + '::' + seq\n });\n\n req.onsuccess = checkDone;\n req.onerror = function (e) {\n // this callback is for a constaint error, which we ignore\n // because this docid/rev has already been associated with\n // the digest (e.g. when new_edits == false)\n e.preventDefault(); // avoid transaction abort\n e.stopPropagation(); // avoid transaction onerror\n checkDone();\n };\n }\n for (var i = 0; i < attsToAdd.length; i++) {\n add(attsToAdd[i]); // do in parallel\n }\n }\n\n function saveAttachment(digest, data, callback) {\n\n\n var getKeyReq = attachStore.count(digest);\n getKeyReq.onsuccess = function (e) {\n var count = e.target.result;\n if (count) {\n return callback(); // already exists\n }\n var newAtt = {\n digest: digest,\n body: data\n };\n var putReq = attachStore.put(newAtt);\n putReq.onsuccess = callback;\n };\n }\n}\n\nfunction createKeyRange(start, end, inclusiveEnd, key, descending) {\n try {\n if (start && end) {\n if (descending) {\n return IDBKeyRange.bound(end, start, !inclusiveEnd, false);\n } else {\n return IDBKeyRange.bound(start, end, false, !inclusiveEnd);\n }\n } else if (start) {\n if (descending) {\n return IDBKeyRange.upperBound(start);\n } else {\n return IDBKeyRange.lowerBound(start);\n }\n } else if (end) {\n if (descending) {\n return IDBKeyRange.lowerBound(end, !inclusiveEnd);\n } else {\n return IDBKeyRange.upperBound(end, !inclusiveEnd);\n }\n } else if (key) {\n return IDBKeyRange.only(key);\n }\n } catch (e) {\n return {error: e};\n }\n return null;\n}\n\nfunction handleKeyRangeError(api, opts, err, callback) {\n if (err.name === \"DataError\" && err.code === 0) {\n // data error, start is less than end\n return callback(null, {\n total_rows: api._meta.docCount,\n offset: opts.skip,\n rows: []\n });\n }\n callback(createError(IDB_ERROR, err.name, err.message));\n}\n\nfunction idbAllDocs(opts, api, idb, callback) {\n\n function allDocsQuery(opts, callback) {\n var start = 'startkey' in opts ? opts.startkey : false;\n var end = 'endkey' in opts ? opts.endkey : false;\n var key = 'key' in opts ? opts.key : false;\n var skip = opts.skip || 0;\n var limit = typeof opts.limit === 'number' ? opts.limit : -1;\n var inclusiveEnd = opts.inclusive_end !== false;\n var descending = 'descending' in opts && opts.descending ? 'prev' : null;\n\n var keyRange = createKeyRange(start, end, inclusiveEnd, key, descending);\n if (keyRange && keyRange.error) {\n return handleKeyRangeError(api, opts, keyRange.error, callback);\n }\n\n var stores = [DOC_STORE, BY_SEQ_STORE];\n\n if (opts.attachments) {\n stores.push(ATTACH_STORE);\n }\n var txnResult = openTransactionSafely(idb, stores, 'readonly');\n if (txnResult.error) {\n return callback(txnResult.error);\n }\n var txn = txnResult.txn;\n var docStore = txn.objectStore(DOC_STORE);\n var seqStore = txn.objectStore(BY_SEQ_STORE);\n var cursor = descending ?\n docStore.openCursor(keyRange, descending) :\n docStore.openCursor(keyRange);\n var docIdRevIndex = seqStore.index('_doc_id_rev');\n var results = [];\n var docCount = 0;\n\n // if the user specifies include_docs=true, then we don't\n // want to block the main cursor while we're fetching the doc\n function fetchDocAsynchronously(metadata, row, winningRev) {\n var key = metadata.id + \"::\" + winningRev;\n docIdRevIndex.get(key).onsuccess = function onGetDoc(e) {\n row.doc = decodeDoc(e.target.result);\n if (opts.conflicts) {\n var conflicts = collectConflicts(metadata);\n if (conflicts.length) {\n row.doc._conflicts = conflicts;\n }\n }\n fetchAttachmentsIfNecessary(row.doc, opts, txn);\n };\n }\n\n function allDocsInner(cursor, winningRev, metadata) {\n var row = {\n id: metadata.id,\n key: metadata.id,\n value: {\n rev: winningRev\n }\n };\n var deleted = metadata.deleted;\n if (opts.deleted === 'ok') {\n results.push(row);\n // deleted docs are okay with \"keys\" requests\n if (deleted) {\n row.value.deleted = true;\n row.doc = null;\n } else if (opts.include_docs) {\n fetchDocAsynchronously(metadata, row, winningRev);\n }\n } else if (!deleted && skip-- <= 0) {\n results.push(row);\n if (opts.include_docs) {\n fetchDocAsynchronously(metadata, row, winningRev);\n }\n if (--limit === 0) {\n return;\n }\n }\n cursor.continue();\n }\n\n function onGetCursor(e) {\n docCount = api._meta.docCount; // do this within the txn for consistency\n var cursor = e.target.result;\n if (!cursor) {\n return;\n }\n var metadata = decodeMetadata(cursor.value);\n var winningRev = metadata.winningRev;\n\n allDocsInner(cursor, winningRev, metadata);\n }\n\n function onResultsReady() {\n callback(null, {\n total_rows: docCount,\n offset: opts.skip,\n rows: results\n });\n }\n\n function onTxnComplete() {\n if (opts.attachments) {\n postProcessAttachments(results, opts.binary).then(onResultsReady);\n } else {\n onResultsReady();\n }\n }\n\n txn.oncomplete = onTxnComplete;\n cursor.onsuccess = onGetCursor;\n }\n\n function allDocs(opts, callback) {\n\n if (opts.limit === 0) {\n return callback(null, {\n total_rows: api._meta.docCount,\n offset: opts.skip,\n rows: []\n });\n }\n allDocsQuery(opts, callback);\n }\n\n allDocs(opts, callback);\n}\n\n//\n// Blobs are not supported in all versions of IndexedDB, notably\n// Chrome <37 and Android <5. In those versions, storing a blob will throw.\n//\n// Various other blob bugs exist in Chrome v37-42 (inclusive).\n// Detecting them is expensive and confusing to users, and Chrome 37-42\n// is at very low usage worldwide, so we do a hacky userAgent check instead.\n//\n// content-type bug: https://code.google.com/p/chromium/issues/detail?id=408120\n// 404 bug: https://code.google.com/p/chromium/issues/detail?id=447916\n// FileReader bug: https://code.google.com/p/chromium/issues/detail?id=447836\n//\nfunction checkBlobSupport(txn) {\n return new PouchPromise(function (resolve) {\n var blob = createBlob(['']);\n txn.objectStore(DETECT_BLOB_SUPPORT_STORE).put(blob, 'key');\n\n txn.onabort = function (e) {\n // If the transaction aborts now its due to not being able to\n // write to the database, likely due to the disk being full\n e.preventDefault();\n e.stopPropagation();\n resolve(false);\n };\n\n txn.oncomplete = function () {\n var matchedChrome = navigator.userAgent.match(/Chrome\\/(\\d+)/);\n var matchedEdge = navigator.userAgent.match(/Edge\\//);\n // MS Edge pretends to be Chrome 42:\n // https://msdn.microsoft.com/en-us/library/hh869301%28v=vs.85%29.aspx\n resolve(matchedEdge || !matchedChrome ||\n parseInt(matchedChrome[1], 10) >= 43);\n };\n }).catch(function () {\n return false; // error, so assume unsupported\n });\n}\n\n// This task queue ensures that IDB open calls are done in their own tick\n// and sequentially - i.e. we wait for the async IDB open to *fully* complete\n// before calling the next one. This works around IE/Edge race conditions in IDB.\n\nvar running = false;\nvar queue = [];\n\nfunction tryCode(fun, err, res, PouchDB) {\n try {\n fun(err, res);\n } catch (err) {\n // Shouldn't happen, but in some odd cases\n // IndexedDB implementations might throw a sync\n // error, in which case this will at least log it.\n PouchDB.emit('error', err);\n }\n}\n\nfunction applyNext() {\n if (running || !queue.length) {\n return;\n }\n running = true;\n queue.shift()();\n}\n\nfunction enqueueTask(action, callback, PouchDB) {\n queue.push(function runAction() {\n action(function runCallback(err, res) {\n tryCode(callback, err, res, PouchDB);\n running = false;\n immediate(function runNext() {\n applyNext(PouchDB);\n });\n });\n });\n applyNext();\n}\n\nvar cachedDBs = new _Map();\nvar blobSupportPromise;\nvar idbChanges = new Changes();\nvar openReqList = new _Map();\n\nfunction IdbPouch(opts, callback) {\n var api = this;\n\n enqueueTask(function (thisCallback) {\n init(api, opts, thisCallback);\n }, callback, api.constructor);\n}\n\nfunction init(api, opts, callback) {\n\n var dbName = opts.name;\n\n var idb = null;\n api._meta = null;\n\n // called when creating a fresh new database\n function createSchema(db) {\n var docStore = db.createObjectStore(DOC_STORE, {keyPath : 'id'});\n db.createObjectStore(BY_SEQ_STORE, {autoIncrement: true})\n .createIndex('_doc_id_rev', '_doc_id_rev', {unique: true});\n db.createObjectStore(ATTACH_STORE, {keyPath: 'digest'});\n db.createObjectStore(META_STORE, {keyPath: 'id', autoIncrement: false});\n db.createObjectStore(DETECT_BLOB_SUPPORT_STORE);\n\n // added in v2\n docStore.createIndex('deletedOrLocal', 'deletedOrLocal', {unique : false});\n\n // added in v3\n db.createObjectStore(LOCAL_STORE, {keyPath: '_id'});\n\n // added in v4\n var attAndSeqStore = db.createObjectStore(ATTACH_AND_SEQ_STORE,\n {autoIncrement: true});\n attAndSeqStore.createIndex('seq', 'seq');\n attAndSeqStore.createIndex('digestSeq', 'digestSeq', {unique: true});\n }\n\n // migration to version 2\n // unfortunately \"deletedOrLocal\" is a misnomer now that we no longer\n // store local docs in the main doc-store, but whaddyagonnado\n function addDeletedOrLocalIndex(txn, callback) {\n var docStore = txn.objectStore(DOC_STORE);\n docStore.createIndex('deletedOrLocal', 'deletedOrLocal', {unique : false});\n\n docStore.openCursor().onsuccess = function (event) {\n var cursor = event.target.result;\n if (cursor) {\n var metadata = cursor.value;\n var deleted = isDeleted(metadata);\n metadata.deletedOrLocal = deleted ? \"1\" : \"0\";\n docStore.put(metadata);\n cursor.continue();\n } else {\n callback();\n }\n };\n }\n\n // migration to version 3 (part 1)\n function createLocalStoreSchema(db) {\n db.createObjectStore(LOCAL_STORE, {keyPath: '_id'})\n .createIndex('_doc_id_rev', '_doc_id_rev', {unique: true});\n }\n\n // migration to version 3 (part 2)\n function migrateLocalStore(txn, cb) {\n var localStore = txn.objectStore(LOCAL_STORE);\n var docStore = txn.objectStore(DOC_STORE);\n var seqStore = txn.objectStore(BY_SEQ_STORE);\n\n var cursor = docStore.openCursor();\n cursor.onsuccess = function (event) {\n var cursor = event.target.result;\n if (cursor) {\n var metadata = cursor.value;\n var docId = metadata.id;\n var local = isLocalId(docId);\n var rev = winningRev(metadata);\n if (local) {\n var docIdRev = docId + \"::\" + rev;\n // remove all seq entries\n // associated with this docId\n var start = docId + \"::\";\n var end = docId + \"::~\";\n var index = seqStore.index('_doc_id_rev');\n var range = IDBKeyRange.bound(start, end, false, false);\n var seqCursor = index.openCursor(range);\n seqCursor.onsuccess = function (e) {\n seqCursor = e.target.result;\n if (!seqCursor) {\n // done\n docStore.delete(cursor.primaryKey);\n cursor.continue();\n } else {\n var data = seqCursor.value;\n if (data._doc_id_rev === docIdRev) {\n localStore.put(data);\n }\n seqStore.delete(seqCursor.primaryKey);\n seqCursor.continue();\n }\n };\n } else {\n cursor.continue();\n }\n } else if (cb) {\n cb();\n }\n };\n }\n\n // migration to version 4 (part 1)\n function addAttachAndSeqStore(db) {\n var attAndSeqStore = db.createObjectStore(ATTACH_AND_SEQ_STORE,\n {autoIncrement: true});\n attAndSeqStore.createIndex('seq', 'seq');\n attAndSeqStore.createIndex('digestSeq', 'digestSeq', {unique: true});\n }\n\n // migration to version 4 (part 2)\n function migrateAttsAndSeqs(txn, callback) {\n var seqStore = txn.objectStore(BY_SEQ_STORE);\n var attStore = txn.objectStore(ATTACH_STORE);\n var attAndSeqStore = txn.objectStore(ATTACH_AND_SEQ_STORE);\n\n // need to actually populate the table. this is the expensive part,\n // so as an optimization, check first that this database even\n // contains attachments\n var req = attStore.count();\n req.onsuccess = function (e) {\n var count = e.target.result;\n if (!count) {\n return callback(); // done\n }\n\n seqStore.openCursor().onsuccess = function (e) {\n var cursor = e.target.result;\n if (!cursor) {\n return callback(); // done\n }\n var doc = cursor.value;\n var seq = cursor.primaryKey;\n var atts = Object.keys(doc._attachments || {});\n var digestMap = {};\n for (var j = 0; j < atts.length; j++) {\n var att = doc._attachments[atts[j]];\n digestMap[att.digest] = true; // uniq digests, just in case\n }\n var digests = Object.keys(digestMap);\n for (j = 0; j < digests.length; j++) {\n var digest = digests[j];\n attAndSeqStore.put({\n seq: seq,\n digestSeq: digest + '::' + seq\n });\n }\n cursor.continue();\n };\n };\n }\n\n // migration to version 5\n // Instead of relying on on-the-fly migration of metadata,\n // this brings the doc-store to its modern form:\n // - metadata.winningrev\n // - metadata.seq\n // - stringify the metadata when storing it\n function migrateMetadata(txn) {\n\n function decodeMetadataCompat(storedObject) {\n if (!storedObject.data) {\n // old format, when we didn't store it stringified\n storedObject.deleted = storedObject.deletedOrLocal === '1';\n return storedObject;\n }\n return decodeMetadata(storedObject);\n }\n\n // ensure that every metadata has a winningRev and seq,\n // which was previously created on-the-fly but better to migrate\n var bySeqStore = txn.objectStore(BY_SEQ_STORE);\n var docStore = txn.objectStore(DOC_STORE);\n var cursor = docStore.openCursor();\n cursor.onsuccess = function (e) {\n var cursor = e.target.result;\n if (!cursor) {\n return; // done\n }\n var metadata = decodeMetadataCompat(cursor.value);\n\n metadata.winningRev = metadata.winningRev ||\n winningRev(metadata);\n\n function fetchMetadataSeq() {\n // metadata.seq was added post-3.2.0, so if it's missing,\n // we need to fetch it manually\n var start = metadata.id + '::';\n var end = metadata.id + '::\\uffff';\n var req = bySeqStore.index('_doc_id_rev').openCursor(\n IDBKeyRange.bound(start, end));\n\n var metadataSeq = 0;\n req.onsuccess = function (e) {\n var cursor = e.target.result;\n if (!cursor) {\n metadata.seq = metadataSeq;\n return onGetMetadataSeq();\n }\n var seq = cursor.primaryKey;\n if (seq > metadataSeq) {\n metadataSeq = seq;\n }\n cursor.continue();\n };\n }\n\n function onGetMetadataSeq() {\n var metadataToStore = encodeMetadata(metadata,\n metadata.winningRev, metadata.deleted);\n\n var req = docStore.put(metadataToStore);\n req.onsuccess = function () {\n cursor.continue();\n };\n }\n\n if (metadata.seq) {\n return onGetMetadataSeq();\n }\n\n fetchMetadataSeq();\n };\n\n }\n\n api.type = function () {\n return 'idb';\n };\n\n api._id = toPromise(function (callback) {\n callback(null, api._meta.instanceId);\n });\n\n api._bulkDocs = function idb_bulkDocs(req, reqOpts, callback) {\n idbBulkDocs(opts, req, reqOpts, api, idb, idbChanges, callback);\n };\n\n // First we look up the metadata in the ids database, then we fetch the\n // current revision(s) from the by sequence store\n api._get = function idb_get(id, opts, callback) {\n var doc;\n var metadata;\n var err;\n var txn = opts.ctx;\n if (!txn) {\n var txnResult = openTransactionSafely(idb,\n [DOC_STORE, BY_SEQ_STORE, ATTACH_STORE], 'readonly');\n if (txnResult.error) {\n return callback(txnResult.error);\n }\n txn = txnResult.txn;\n }\n\n function finish() {\n callback(err, {doc: doc, metadata: metadata, ctx: txn});\n }\n\n txn.objectStore(DOC_STORE).get(id).onsuccess = function (e) {\n metadata = decodeMetadata(e.target.result);\n // we can determine the result here if:\n // 1. there is no such document\n // 2. the document is deleted and we don't ask about specific rev\n // When we ask with opts.rev we expect the answer to be either\n // doc (possibly with _deleted=true) or missing error\n if (!metadata) {\n err = createError(MISSING_DOC, 'missing');\n return finish();\n }\n\n var rev;\n if(!opts.rev) {\n rev = metadata.winningRev;\n var deleted = isDeleted(metadata);\n if (deleted) {\n err = createError(MISSING_DOC, \"deleted\");\n return finish();\n }\n } else {\n rev = opts.latest ? latest(opts.rev, metadata) : opts.rev;\n }\n\n var objectStore = txn.objectStore(BY_SEQ_STORE);\n var key = metadata.id + '::' + rev;\n\n objectStore.index('_doc_id_rev').get(key).onsuccess = function (e) {\n doc = e.target.result;\n if (doc) {\n doc = decodeDoc(doc);\n }\n if (!doc) {\n err = createError(MISSING_DOC, 'missing');\n return finish();\n }\n finish();\n };\n };\n };\n\n api._getAttachment = function (docId, attachId, attachment, opts, callback) {\n var txn;\n if (opts.ctx) {\n txn = opts.ctx;\n } else {\n var txnResult = openTransactionSafely(idb,\n [DOC_STORE, BY_SEQ_STORE, ATTACH_STORE], 'readonly');\n if (txnResult.error) {\n return callback(txnResult.error);\n }\n txn = txnResult.txn;\n }\n var digest = attachment.digest;\n var type = attachment.content_type;\n\n txn.objectStore(ATTACH_STORE).get(digest).onsuccess = function (e) {\n var body = e.target.result.body;\n readBlobData(body, type, opts.binary, function (blobData) {\n callback(null, blobData);\n });\n };\n };\n\n api._info = function idb_info(callback) {\n\n if (idb === null || !cachedDBs.has(dbName)) {\n var error = new Error('db isn\\'t open');\n error.id = 'idbNull';\n return callback(error);\n }\n var updateSeq;\n var docCount;\n\n var txnResult = openTransactionSafely(idb, [BY_SEQ_STORE], 'readonly');\n if (txnResult.error) {\n return callback(txnResult.error);\n }\n var txn = txnResult.txn;\n var cursor = txn.objectStore(BY_SEQ_STORE).openCursor(null, 'prev');\n cursor.onsuccess = function (event) {\n var cursor = event.target.result;\n updateSeq = cursor ? cursor.key : 0;\n // count within the same txn for consistency\n docCount = api._meta.docCount;\n };\n\n txn.oncomplete = function () {\n callback(null, {\n doc_count: docCount,\n update_seq: updateSeq,\n // for debugging\n idb_attachment_format: (api._meta.blobSupport ? 'binary' : 'base64')\n });\n };\n };\n\n api._allDocs = function idb_allDocs(opts, callback) {\n idbAllDocs(opts, api, idb, callback);\n };\n\n api._changes = function (opts) {\n opts = clone(opts);\n\n if (opts.continuous) {\n var id = dbName + ':' + uuid();\n idbChanges.addListener(dbName, id, api, opts);\n idbChanges.notify(dbName);\n return {\n cancel: function () {\n idbChanges.removeListener(dbName, id);\n }\n };\n }\n\n var docIds = opts.doc_ids && new _Set(opts.doc_ids);\n\n opts.since = opts.since || 0;\n var lastSeq = opts.since;\n\n var limit = 'limit' in opts ? opts.limit : -1;\n if (limit === 0) {\n limit = 1; // per CouchDB _changes spec\n }\n var returnDocs;\n if ('return_docs' in opts) {\n returnDocs = opts.return_docs;\n } else if ('returnDocs' in opts) {\n // TODO: Remove 'returnDocs' in favor of 'return_docs' in a future release\n returnDocs = opts.returnDocs;\n } else {\n returnDocs = true;\n }\n\n var results = [];\n var numResults = 0;\n var filter = filterChange(opts);\n var docIdsToMetadata = new _Map();\n\n var txn;\n var bySeqStore;\n var docStore;\n var docIdRevIndex;\n\n function onGetCursor(cursor) {\n\n var doc = decodeDoc(cursor.value);\n var seq = cursor.key;\n\n if (docIds && !docIds.has(doc._id)) {\n return cursor.continue();\n }\n\n var metadata;\n\n function onGetMetadata() {\n if (metadata.seq !== seq) {\n // some other seq is later\n return cursor.continue();\n }\n\n lastSeq = seq;\n\n if (metadata.winningRev === doc._rev) {\n return onGetWinningDoc(doc);\n }\n\n fetchWinningDoc();\n }\n\n function fetchWinningDoc() {\n var docIdRev = doc._id + '::' + metadata.winningRev;\n var req = docIdRevIndex.get(docIdRev);\n req.onsuccess = function (e) {\n onGetWinningDoc(decodeDoc(e.target.result));\n };\n }\n\n function onGetWinningDoc(winningDoc) {\n\n var change = opts.processChange(winningDoc, metadata, opts);\n change.seq = metadata.seq;\n\n var filtered = filter(change);\n if (typeof filtered === 'object') {\n return opts.complete(filtered);\n }\n\n if (filtered) {\n numResults++;\n if (returnDocs) {\n results.push(change);\n }\n // process the attachment immediately\n // for the benefit of live listeners\n if (opts.attachments && opts.include_docs) {\n fetchAttachmentsIfNecessary(winningDoc, opts, txn, function () {\n postProcessAttachments([change], opts.binary).then(function () {\n opts.onChange(change);\n });\n });\n } else {\n opts.onChange(change);\n }\n }\n if (numResults !== limit) {\n cursor.continue();\n }\n }\n\n metadata = docIdsToMetadata.get(doc._id);\n if (metadata) { // cached\n return onGetMetadata();\n }\n // metadata not cached, have to go fetch it\n docStore.get(doc._id).onsuccess = function (event) {\n metadata = decodeMetadata(event.target.result);\n docIdsToMetadata.set(doc._id, metadata);\n onGetMetadata();\n };\n }\n\n function onsuccess(event) {\n var cursor = event.target.result;\n\n if (!cursor) {\n return;\n }\n onGetCursor(cursor);\n }\n\n function fetchChanges() {\n var objectStores = [DOC_STORE, BY_SEQ_STORE];\n if (opts.attachments) {\n objectStores.push(ATTACH_STORE);\n }\n var txnResult = openTransactionSafely(idb, objectStores, 'readonly');\n if (txnResult.error) {\n return opts.complete(txnResult.error);\n }\n txn = txnResult.txn;\n txn.onabort = idbError(opts.complete);\n txn.oncomplete = onTxnComplete;\n\n bySeqStore = txn.objectStore(BY_SEQ_STORE);\n docStore = txn.objectStore(DOC_STORE);\n docIdRevIndex = bySeqStore.index('_doc_id_rev');\n\n var req;\n\n if (opts.descending) {\n req = bySeqStore.openCursor(null, 'prev');\n } else {\n req = bySeqStore.openCursor(IDBKeyRange.lowerBound(opts.since, true));\n }\n\n req.onsuccess = onsuccess;\n }\n\n fetchChanges();\n\n function onTxnComplete() {\n\n function finish() {\n opts.complete(null, {\n results: results,\n last_seq: lastSeq\n });\n }\n\n if (!opts.continuous && opts.attachments) {\n // cannot guarantee that postProcessing was already done,\n // so do it again\n postProcessAttachments(results).then(finish);\n } else {\n finish();\n }\n }\n };\n\n api._close = function (callback) {\n if (idb === null) {\n return callback(createError(NOT_OPEN));\n }\n\n // https://developer.mozilla.org/en-US/docs/IndexedDB/IDBDatabase#close\n // \"Returns immediately and closes the connection in a separate thread...\"\n idb.close();\n cachedDBs.delete(dbName);\n idb = null;\n callback();\n };\n\n api._getRevisionTree = function (docId, callback) {\n var txnResult = openTransactionSafely(idb, [DOC_STORE], 'readonly');\n if (txnResult.error) {\n return callback(txnResult.error);\n }\n var txn = txnResult.txn;\n var req = txn.objectStore(DOC_STORE).get(docId);\n req.onsuccess = function (event) {\n var doc = decodeMetadata(event.target.result);\n if (!doc) {\n callback(createError(MISSING_DOC));\n } else {\n callback(null, doc.rev_tree);\n }\n };\n };\n\n // This function removes revisions of document docId\n // which are listed in revs and sets this document\n // revision to to rev_tree\n api._doCompaction = function (docId, revs, callback) {\n var stores = [\n DOC_STORE,\n BY_SEQ_STORE,\n ATTACH_STORE,\n ATTACH_AND_SEQ_STORE\n ];\n var txnResult = openTransactionSafely(idb, stores, 'readwrite');\n if (txnResult.error) {\n return callback(txnResult.error);\n }\n var txn = txnResult.txn;\n\n var docStore = txn.objectStore(DOC_STORE);\n\n docStore.get(docId).onsuccess = function (event) {\n var metadata = decodeMetadata(event.target.result);\n traverseRevTree(metadata.rev_tree, function (isLeaf, pos,\n revHash, ctx, opts) {\n var rev = pos + '-' + revHash;\n if (revs.indexOf(rev) !== -1) {\n opts.status = 'missing';\n }\n });\n compactRevs(revs, docId, txn);\n var winningRev = metadata.winningRev;\n var deleted = metadata.deleted;\n txn.objectStore(DOC_STORE).put(\n encodeMetadata(metadata, winningRev, deleted));\n };\n txn.onabort = idbError(callback);\n txn.oncomplete = function () {\n callback();\n };\n };\n\n\n api._getLocal = function (id, callback) {\n var txnResult = openTransactionSafely(idb, [LOCAL_STORE], 'readonly');\n if (txnResult.error) {\n return callback(txnResult.error);\n }\n var tx = txnResult.txn;\n var req = tx.objectStore(LOCAL_STORE).get(id);\n\n req.onerror = idbError(callback);\n req.onsuccess = function (e) {\n var doc = e.target.result;\n if (!doc) {\n callback(createError(MISSING_DOC));\n } else {\n delete doc['_doc_id_rev']; // for backwards compat\n callback(null, doc);\n }\n };\n };\n\n api._putLocal = function (doc, opts, callback) {\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n delete doc._revisions; // ignore this, trust the rev\n var oldRev = doc._rev;\n var id = doc._id;\n if (!oldRev) {\n doc._rev = '0-1';\n } else {\n doc._rev = '0-' + (parseInt(oldRev.split('-')[1], 10) + 1);\n }\n\n var tx = opts.ctx;\n var ret;\n if (!tx) {\n var txnResult = openTransactionSafely(idb, [LOCAL_STORE], 'readwrite');\n if (txnResult.error) {\n return callback(txnResult.error);\n }\n tx = txnResult.txn;\n tx.onerror = idbError(callback);\n tx.oncomplete = function () {\n if (ret) {\n callback(null, ret);\n }\n };\n }\n\n var oStore = tx.objectStore(LOCAL_STORE);\n var req;\n if (oldRev) {\n req = oStore.get(id);\n req.onsuccess = function (e) {\n var oldDoc = e.target.result;\n if (!oldDoc || oldDoc._rev !== oldRev) {\n callback(createError(REV_CONFLICT));\n } else { // update\n var req = oStore.put(doc);\n req.onsuccess = function () {\n ret = {ok: true, id: doc._id, rev: doc._rev};\n if (opts.ctx) { // return immediately\n callback(null, ret);\n }\n };\n }\n };\n } else { // new doc\n req = oStore.add(doc);\n req.onerror = function (e) {\n // constraint error, already exists\n callback(createError(REV_CONFLICT));\n e.preventDefault(); // avoid transaction abort\n e.stopPropagation(); // avoid transaction onerror\n };\n req.onsuccess = function () {\n ret = {ok: true, id: doc._id, rev: doc._rev};\n if (opts.ctx) { // return immediately\n callback(null, ret);\n }\n };\n }\n };\n\n api._removeLocal = function (doc, opts, callback) {\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n var tx = opts.ctx;\n if (!tx) {\n var txnResult = openTransactionSafely(idb, [LOCAL_STORE], 'readwrite');\n if (txnResult.error) {\n return callback(txnResult.error);\n }\n tx = txnResult.txn;\n tx.oncomplete = function () {\n if (ret) {\n callback(null, ret);\n }\n };\n }\n var ret;\n var id = doc._id;\n var oStore = tx.objectStore(LOCAL_STORE);\n var req = oStore.get(id);\n\n req.onerror = idbError(callback);\n req.onsuccess = function (e) {\n var oldDoc = e.target.result;\n if (!oldDoc || oldDoc._rev !== doc._rev) {\n callback(createError(MISSING_DOC));\n } else {\n oStore.delete(id);\n ret = {ok: true, id: id, rev: '0-0'};\n if (opts.ctx) { // return immediately\n callback(null, ret);\n }\n }\n };\n };\n\n api._destroy = function (opts, callback) {\n idbChanges.removeAllListeners(dbName);\n\n //Close open request for \"dbName\" database to fix ie delay.\n var openReq = openReqList.get(dbName);\n if (openReq && openReq.result) {\n openReq.result.close();\n cachedDBs.delete(dbName);\n }\n var req = indexedDB.deleteDatabase(dbName);\n\n req.onsuccess = function () {\n //Remove open request from the list.\n openReqList.delete(dbName);\n if (hasLocalStorage() && (dbName in localStorage)) {\n delete localStorage[dbName];\n }\n callback(null, { 'ok': true });\n };\n\n req.onerror = idbError(callback);\n };\n\n var cached = cachedDBs.get(dbName);\n\n if (cached) {\n idb = cached.idb;\n api._meta = cached.global;\n return immediate(function () {\n callback(null, api);\n });\n }\n\n var req;\n if (opts.storage) {\n req = tryStorageOption(dbName, opts.storage);\n } else {\n req = indexedDB.open(dbName, ADAPTER_VERSION);\n }\n\n openReqList.set(dbName, req);\n\n req.onupgradeneeded = function (e) {\n var db = e.target.result;\n if (e.oldVersion < 1) {\n return createSchema(db); // new db, initial schema\n }\n // do migrations\n\n var txn = e.currentTarget.transaction;\n // these migrations have to be done in this function, before\n // control is returned to the event loop, because IndexedDB\n\n if (e.oldVersion < 3) {\n createLocalStoreSchema(db); // v2 -> v3\n }\n if (e.oldVersion < 4) {\n addAttachAndSeqStore(db); // v3 -> v4\n }\n\n var migrations = [\n addDeletedOrLocalIndex, // v1 -> v2\n migrateLocalStore, // v2 -> v3\n migrateAttsAndSeqs, // v3 -> v4\n migrateMetadata // v4 -> v5\n ];\n\n var i = e.oldVersion;\n\n function next() {\n var migration = migrations[i - 1];\n i++;\n if (migration) {\n migration(txn, next);\n }\n }\n\n next();\n };\n\n req.onsuccess = function (e) {\n\n idb = e.target.result;\n\n idb.onversionchange = function () {\n idb.close();\n cachedDBs.delete(dbName);\n };\n\n idb.onabort = function (e) {\n guardedConsole('error', 'Database has a global failure', e.target.error);\n idb.close();\n cachedDBs.delete(dbName);\n };\n\n var txn = idb.transaction([\n META_STORE,\n DETECT_BLOB_SUPPORT_STORE,\n DOC_STORE\n ], 'readwrite');\n\n var req = txn.objectStore(META_STORE).get(META_STORE);\n\n var blobSupport = null;\n var docCount = null;\n var instanceId = null;\n\n req.onsuccess = function (e) {\n\n var checkSetupComplete = function () {\n if (blobSupport === null || docCount === null ||\n instanceId === null) {\n return;\n } else {\n api._meta = {\n name: dbName,\n instanceId: instanceId,\n blobSupport: blobSupport,\n docCount: docCount\n };\n\n cachedDBs.set(dbName, {\n idb: idb,\n global: api._meta\n });\n callback(null, api);\n }\n };\n\n //\n // fetch/store the id\n //\n\n var meta = e.target.result || {id: META_STORE};\n if (dbName + '_id' in meta) {\n instanceId = meta[dbName + '_id'];\n checkSetupComplete();\n } else {\n instanceId = uuid();\n meta[dbName + '_id'] = instanceId;\n txn.objectStore(META_STORE).put(meta).onsuccess = function () {\n checkSetupComplete();\n };\n }\n\n //\n // check blob support\n //\n\n if (!blobSupportPromise) {\n // make sure blob support is only checked once\n blobSupportPromise = checkBlobSupport(txn);\n }\n\n blobSupportPromise.then(function (val) {\n blobSupport = val;\n checkSetupComplete();\n });\n\n //\n // count docs\n //\n\n var index = txn.objectStore(DOC_STORE).index('deletedOrLocal');\n index.count(IDBKeyRange.only('0')).onsuccess = function (e) {\n docCount = e.target.result;\n checkSetupComplete();\n };\n\n };\n };\n\n req.onerror = function () {\n var msg = 'Failed to open indexedDB, are you in private browsing mode?';\n guardedConsole('error', msg);\n callback(createError(IDB_ERROR, msg));\n };\n}\n\nIdbPouch.valid = function () {\n // Issue #2533, we finally gave up on doing bug\n // detection instead of browser sniffing. Safari brought us\n // to our knees.\n var isSafari = typeof openDatabase !== 'undefined' &&\n /(Safari|iPhone|iPad|iPod)/.test(navigator.userAgent) &&\n !/Chrome/.test(navigator.userAgent) &&\n !/BlackBerry/.test(navigator.platform);\n\n // some outdated implementations of IDB that appear on Samsung\n // and HTC Android devices <4.4 are missing IDBKeyRange\n return !isSafari && typeof indexedDB !== 'undefined' &&\n typeof IDBKeyRange !== 'undefined';\n};\n\nfunction tryStorageOption(dbName, storage) {\n try { // option only available in Firefox 26+\n return indexedDB.open(dbName, {\n version: ADAPTER_VERSION,\n storage: storage\n });\n } catch(err) {\n return indexedDB.open(dbName, ADAPTER_VERSION);\n }\n}\n\nfunction IDBPouch (PouchDB) {\n PouchDB.adapter('idb', IdbPouch, true);\n}\n\n//\n// Parsing hex strings. Yeah.\n//\n// So basically we need this because of a bug in WebSQL:\n// https://code.google.com/p/chromium/issues/detail?id=422690\n// https://bugs.webkit.org/show_bug.cgi?id=137637\n//\n// UTF-8 and UTF-16 are provided as separate functions\n// for meager performance improvements\n//\n\nfunction decodeUtf8(str) {\n return decodeURIComponent(escape(str));\n}\n\nfunction hexToInt(charCode) {\n // '0'-'9' is 48-57\n // 'A'-'F' is 65-70\n // SQLite will only give us uppercase hex\n return charCode < 65 ? (charCode - 48) : (charCode - 55);\n}\n\n\n// Example:\n// pragma encoding=utf8;\n// select hex('A');\n// returns '41'\nfunction parseHexUtf8(str, start, end) {\n var result = '';\n while (start < end) {\n result += String.fromCharCode(\n (hexToInt(str.charCodeAt(start++)) << 4) |\n hexToInt(str.charCodeAt(start++)));\n }\n return result;\n}\n\n// Example:\n// pragma encoding=utf16;\n// select hex('A');\n// returns '4100'\n// notice that the 00 comes after the 41 (i.e. it's swizzled)\nfunction parseHexUtf16(str, start, end) {\n var result = '';\n while (start < end) {\n // UTF-16, so swizzle the bytes\n result += String.fromCharCode(\n (hexToInt(str.charCodeAt(start + 2)) << 12) |\n (hexToInt(str.charCodeAt(start + 3)) << 8) |\n (hexToInt(str.charCodeAt(start)) << 4) |\n hexToInt(str.charCodeAt(start + 1)));\n start += 4;\n }\n return result;\n}\n\nfunction parseHexString(str, encoding) {\n if (encoding === 'UTF-8') {\n return decodeUtf8(parseHexUtf8(str, 0, str.length));\n } else {\n return parseHexUtf16(str, 0, str.length);\n }\n}\n\nfunction quote(str) {\n return \"'\" + str + \"'\";\n}\n\nvar ADAPTER_VERSION$1 = 7; // used to manage migrations\n\n// The object stores created for each database\n// DOC_STORE stores the document meta data, its revision history and state\nvar DOC_STORE$1 = quote('document-store');\n// BY_SEQ_STORE stores a particular version of a document, keyed by its\n// sequence id\nvar BY_SEQ_STORE$1 = quote('by-sequence');\n// Where we store attachments\nvar ATTACH_STORE$1 = quote('attach-store');\nvar LOCAL_STORE$1 = quote('local-store');\nvar META_STORE$1 = quote('metadata-store');\n// where we store many-to-many relations between attachment\n// digests and seqs\nvar ATTACH_AND_SEQ_STORE$1 = quote('attach-seq-store');\n\n// escapeBlob and unescapeBlob are workarounds for a websql bug:\n// https://code.google.com/p/chromium/issues/detail?id=422690\n// https://bugs.webkit.org/show_bug.cgi?id=137637\n// The goal is to never actually insert the \\u0000 character\n// in the database.\nfunction escapeBlob(str) {\n return str\n .replace(/\\u0002/g, '\\u0002\\u0002')\n .replace(/\\u0001/g, '\\u0001\\u0002')\n .replace(/\\u0000/g, '\\u0001\\u0001');\n}\n\nfunction unescapeBlob(str) {\n return str\n .replace(/\\u0001\\u0001/g, '\\u0000')\n .replace(/\\u0001\\u0002/g, '\\u0001')\n .replace(/\\u0002\\u0002/g, '\\u0002');\n}\n\nfunction stringifyDoc(doc) {\n // don't bother storing the id/rev. it uses lots of space,\n // in persistent map/reduce especially\n delete doc._id;\n delete doc._rev;\n return JSON.stringify(doc);\n}\n\nfunction unstringifyDoc(doc, id, rev) {\n doc = JSON.parse(doc);\n doc._id = id;\n doc._rev = rev;\n return doc;\n}\n\n// question mark groups IN queries, e.g. 3 -> '(?,?,?)'\nfunction qMarks(num) {\n var s = '(';\n while (num--) {\n s += '?';\n if (num) {\n s += ',';\n }\n }\n return s + ')';\n}\n\nfunction select(selector, table, joiner, where, orderBy) {\n return 'SELECT ' + selector + ' FROM ' +\n (typeof table === 'string' ? table : table.join(' JOIN ')) +\n (joiner ? (' ON ' + joiner) : '') +\n (where ? (' WHERE ' +\n (typeof where === 'string' ? where : where.join(' AND '))) : '') +\n (orderBy ? (' ORDER BY ' + orderBy) : '');\n}\n\nfunction compactRevs$1(revs, docId, tx) {\n\n if (!revs.length) {\n return;\n }\n\n var numDone = 0;\n var seqs = [];\n\n function checkDone() {\n if (++numDone === revs.length) { // done\n deleteOrphans();\n }\n }\n\n function deleteOrphans() {\n // find orphaned attachment digests\n\n if (!seqs.length) {\n return;\n }\n\n var sql = 'SELECT DISTINCT digest AS digest FROM ' +\n ATTACH_AND_SEQ_STORE$1 + ' WHERE seq IN ' + qMarks(seqs.length);\n\n tx.executeSql(sql, seqs, function (tx, res) {\n\n var digestsToCheck = [];\n for (var i = 0; i < res.rows.length; i++) {\n digestsToCheck.push(res.rows.item(i).digest);\n }\n if (!digestsToCheck.length) {\n return;\n }\n\n var sql = 'DELETE FROM ' + ATTACH_AND_SEQ_STORE$1 +\n ' WHERE seq IN (' +\n seqs.map(function () { return '?'; }).join(',') +\n ')';\n tx.executeSql(sql, seqs, function (tx) {\n\n var sql = 'SELECT digest FROM ' + ATTACH_AND_SEQ_STORE$1 +\n ' WHERE digest IN (' +\n digestsToCheck.map(function () { return '?'; }).join(',') +\n ')';\n tx.executeSql(sql, digestsToCheck, function (tx, res) {\n var nonOrphanedDigests = new _Set();\n for (var i = 0; i < res.rows.length; i++) {\n nonOrphanedDigests.add(res.rows.item(i).digest);\n }\n digestsToCheck.forEach(function (digest) {\n if (nonOrphanedDigests.has(digest)) {\n return;\n }\n tx.executeSql(\n 'DELETE FROM ' + ATTACH_AND_SEQ_STORE$1 + ' WHERE digest=?',\n [digest]);\n tx.executeSql(\n 'DELETE FROM ' + ATTACH_STORE$1 + ' WHERE digest=?', [digest]);\n });\n });\n });\n });\n }\n\n // update by-seq and attach stores in parallel\n revs.forEach(function (rev) {\n var sql = 'SELECT seq FROM ' + BY_SEQ_STORE$1 +\n ' WHERE doc_id=? AND rev=?';\n\n tx.executeSql(sql, [docId, rev], function (tx, res) {\n if (!res.rows.length) { // already deleted\n return checkDone();\n }\n var seq = res.rows.item(0).seq;\n seqs.push(seq);\n\n tx.executeSql(\n 'DELETE FROM ' + BY_SEQ_STORE$1 + ' WHERE seq=?', [seq], checkDone);\n });\n });\n}\n\nfunction websqlError(callback) {\n return function (event) {\n guardedConsole('error', 'WebSQL threw an error', event);\n // event may actually be a SQLError object, so report is as such\n var errorNameMatch = event && event.constructor.toString()\n .match(/function ([^\\(]+)/);\n var errorName = (errorNameMatch && errorNameMatch[1]) || event.type;\n var errorReason = event.target || event.message;\n callback(createError(WSQ_ERROR, errorReason, errorName));\n };\n}\n\nfunction getSize(opts) {\n if ('size' in opts) {\n // triggers immediate popup in iOS, fixes #2347\n // e.g. 5000001 asks for 5 MB, 10000001 asks for 10 MB,\n return opts.size * 1000000;\n }\n // In iOS, doesn't matter as long as it's <= 5000000.\n // Except that if you request too much, our tests fail\n // because of the native \"do you accept?\" popup.\n // In Android <=4.3, this value is actually used as an\n // honest-to-god ceiling for data, so we need to\n // set it to a decently high number.\n var isAndroid = typeof navigator !== 'undefined' &&\n /Android/.test(navigator.userAgent);\n return isAndroid ? 5000000 : 1; // in PhantomJS, if you use 0 it will crash\n}\n\nfunction websqlBulkDocs(dbOpts, req, opts, api, db, websqlChanges, callback) {\n var newEdits = opts.new_edits;\n var userDocs = req.docs;\n\n // Parse the docs, give them a sequence number for the result\n var docInfos = userDocs.map(function (doc) {\n if (doc._id && isLocalId(doc._id)) {\n return doc;\n }\n var newDoc = parseDoc(doc, newEdits);\n return newDoc;\n });\n\n var docInfoErrors = docInfos.filter(function (docInfo) {\n return docInfo.error;\n });\n if (docInfoErrors.length) {\n return callback(docInfoErrors[0]);\n }\n\n var tx;\n var results = new Array(docInfos.length);\n var fetchedDocs = new _Map();\n\n var preconditionErrored;\n function complete() {\n if (preconditionErrored) {\n return callback(preconditionErrored);\n }\n websqlChanges.notify(api._name);\n api._docCount = -1; // invalidate\n callback(null, results);\n }\n\n function verifyAttachment(digest, callback) {\n var sql = 'SELECT count(*) as cnt FROM ' + ATTACH_STORE$1 +\n ' WHERE digest=?';\n tx.executeSql(sql, [digest], function (tx, result) {\n if (result.rows.item(0).cnt === 0) {\n var err = createError(MISSING_STUB,\n 'unknown stub attachment with digest ' +\n digest);\n callback(err);\n } else {\n callback();\n }\n });\n }\n\n function verifyAttachments(finish) {\n var digests = [];\n docInfos.forEach(function (docInfo) {\n if (docInfo.data && docInfo.data._attachments) {\n Object.keys(docInfo.data._attachments).forEach(function (filename) {\n var att = docInfo.data._attachments[filename];\n if (att.stub) {\n digests.push(att.digest);\n }\n });\n }\n });\n if (!digests.length) {\n return finish();\n }\n var numDone = 0;\n var err;\n\n function checkDone() {\n if (++numDone === digests.length) {\n finish(err);\n }\n }\n digests.forEach(function (digest) {\n verifyAttachment(digest, function (attErr) {\n if (attErr && !err) {\n err = attErr;\n }\n checkDone();\n });\n });\n }\n\n function writeDoc(docInfo, winningRev, winningRevIsDeleted, newRevIsDeleted,\n isUpdate, delta, resultsIdx, callback) {\n\n function finish() {\n var data = docInfo.data;\n var deletedInt = newRevIsDeleted ? 1 : 0;\n\n var id = data._id;\n var rev = data._rev;\n var json = stringifyDoc(data);\n var sql = 'INSERT INTO ' + BY_SEQ_STORE$1 +\n ' (doc_id, rev, json, deleted) VALUES (?, ?, ?, ?);';\n var sqlArgs = [id, rev, json, deletedInt];\n\n // map seqs to attachment digests, which\n // we will need later during compaction\n function insertAttachmentMappings(seq, callback) {\n var attsAdded = 0;\n var attsToAdd = Object.keys(data._attachments || {});\n\n if (!attsToAdd.length) {\n return callback();\n }\n function checkDone() {\n if (++attsAdded === attsToAdd.length) {\n callback();\n }\n return false; // ack handling a constraint error\n }\n function add(att) {\n var sql = 'INSERT INTO ' + ATTACH_AND_SEQ_STORE$1 +\n ' (digest, seq) VALUES (?,?)';\n var sqlArgs = [data._attachments[att].digest, seq];\n tx.executeSql(sql, sqlArgs, checkDone, checkDone);\n // second callback is for a constaint error, which we ignore\n // because this docid/rev has already been associated with\n // the digest (e.g. when new_edits == false)\n }\n for (var i = 0; i < attsToAdd.length; i++) {\n add(attsToAdd[i]); // do in parallel\n }\n }\n\n tx.executeSql(sql, sqlArgs, function (tx, result) {\n var seq = result.insertId;\n insertAttachmentMappings(seq, function () {\n dataWritten(tx, seq);\n });\n }, function () {\n // constraint error, recover by updating instead (see #1638)\n var fetchSql = select('seq', BY_SEQ_STORE$1, null,\n 'doc_id=? AND rev=?');\n tx.executeSql(fetchSql, [id, rev], function (tx, res) {\n var seq = res.rows.item(0).seq;\n var sql = 'UPDATE ' + BY_SEQ_STORE$1 +\n ' SET json=?, deleted=? WHERE doc_id=? AND rev=?;';\n var sqlArgs = [json, deletedInt, id, rev];\n tx.executeSql(sql, sqlArgs, function (tx) {\n insertAttachmentMappings(seq, function () {\n dataWritten(tx, seq);\n });\n });\n });\n return false; // ack that we've handled the error\n });\n }\n\n function collectResults(attachmentErr) {\n if (!err) {\n if (attachmentErr) {\n err = attachmentErr;\n callback(err);\n } else if (recv === attachments.length) {\n finish();\n }\n }\n }\n\n var err = null;\n var recv = 0;\n\n docInfo.data._id = docInfo.metadata.id;\n docInfo.data._rev = docInfo.metadata.rev;\n var attachments = Object.keys(docInfo.data._attachments || {});\n\n\n if (newRevIsDeleted) {\n docInfo.data._deleted = true;\n }\n\n function attachmentSaved(err) {\n recv++;\n collectResults(err);\n }\n\n attachments.forEach(function (key) {\n var att = docInfo.data._attachments[key];\n if (!att.stub) {\n var data = att.data;\n delete att.data;\n att.revpos = parseInt(winningRev, 10);\n var digest = att.digest;\n saveAttachment(digest, data, attachmentSaved);\n } else {\n recv++;\n collectResults();\n }\n });\n\n if (!attachments.length) {\n finish();\n }\n\n function dataWritten(tx, seq) {\n var id = docInfo.metadata.id;\n\n var revsToCompact = docInfo.stemmedRevs || [];\n if (isUpdate && api.auto_compaction) {\n revsToCompact = compactTree(docInfo.metadata).concat(revsToCompact);\n }\n if (revsToCompact.length) {\n compactRevs$1(revsToCompact, id, tx);\n }\n\n docInfo.metadata.seq = seq;\n var rev = docInfo.metadata.rev;\n delete docInfo.metadata.rev;\n\n var sql = isUpdate ?\n 'UPDATE ' + DOC_STORE$1 +\n ' SET json=?, max_seq=?, winningseq=' +\n '(SELECT seq FROM ' + BY_SEQ_STORE$1 +\n ' WHERE doc_id=' + DOC_STORE$1 + '.id AND rev=?) WHERE id=?'\n : 'INSERT INTO ' + DOC_STORE$1 +\n ' (id, winningseq, max_seq, json) VALUES (?,?,?,?);';\n var metadataStr = safeJsonStringify(docInfo.metadata);\n var params = isUpdate ?\n [metadataStr, seq, winningRev, id] :\n [id, seq, seq, metadataStr];\n tx.executeSql(sql, params, function () {\n results[resultsIdx] = {\n ok: true,\n id: docInfo.metadata.id,\n rev: rev\n };\n fetchedDocs.set(id, docInfo.metadata);\n callback();\n });\n }\n }\n\n function websqlProcessDocs() {\n processDocs(dbOpts.revs_limit, docInfos, api, fetchedDocs, tx,\n results, writeDoc, opts);\n }\n\n function fetchExistingDocs(callback) {\n if (!docInfos.length) {\n return callback();\n }\n\n var numFetched = 0;\n\n function checkDone() {\n if (++numFetched === docInfos.length) {\n callback();\n }\n }\n\n docInfos.forEach(function (docInfo) {\n if (docInfo._id && isLocalId(docInfo._id)) {\n return checkDone(); // skip local docs\n }\n var id = docInfo.metadata.id;\n tx.executeSql('SELECT json FROM ' + DOC_STORE$1 +\n ' WHERE id = ?', [id], function (tx, result) {\n if (result.rows.length) {\n var metadata = safeJsonParse(result.rows.item(0).json);\n fetchedDocs.set(id, metadata);\n }\n checkDone();\n });\n });\n }\n\n function saveAttachment(digest, data, callback) {\n var sql = 'SELECT digest FROM ' + ATTACH_STORE$1 + ' WHERE digest=?';\n tx.executeSql(sql, [digest], function (tx, result) {\n if (result.rows.length) { // attachment already exists\n return callback();\n }\n // we could just insert before selecting and catch the error,\n // but my hunch is that it's cheaper not to serialize the blob\n // from JS to C if we don't have to (TODO: confirm this)\n sql = 'INSERT INTO ' + ATTACH_STORE$1 +\n ' (digest, body, escaped) VALUES (?,?,1)';\n tx.executeSql(sql, [digest, escapeBlob(data)], function () {\n callback();\n }, function () {\n // ignore constaint errors, means it already exists\n callback();\n return false; // ack we handled the error\n });\n });\n }\n\n preprocessAttachments(docInfos, 'binary', function (err) {\n if (err) {\n return callback(err);\n }\n db.transaction(function (txn) {\n tx = txn;\n verifyAttachments(function (err) {\n if (err) {\n preconditionErrored = err;\n } else {\n fetchExistingDocs(websqlProcessDocs);\n }\n });\n }, websqlError(callback), complete);\n });\n}\n\nvar cachedDatabases = new _Map();\n\n// openDatabase passed in through opts (e.g. for node-websql)\nfunction openDatabaseWithOpts(opts) {\n return opts.websql(opts.name, opts.version, opts.description, opts.size);\n}\n\nfunction openDBSafely(opts) {\n try {\n return {\n db: openDatabaseWithOpts(opts)\n };\n } catch (err) {\n return {\n error: err\n };\n }\n}\n\nfunction openDB$1(opts) {\n var cachedResult = cachedDatabases.get(opts.name);\n if (!cachedResult) {\n cachedResult = openDBSafely(opts);\n cachedDatabases.set(opts.name, cachedResult);\n }\n return cachedResult;\n}\n\nvar websqlChanges = new Changes();\n\nfunction fetchAttachmentsIfNecessary$1(doc, opts, api, txn, cb) {\n var attachments = Object.keys(doc._attachments || {});\n if (!attachments.length) {\n return cb && cb();\n }\n var numDone = 0;\n\n function checkDone() {\n if (++numDone === attachments.length && cb) {\n cb();\n }\n }\n\n function fetchAttachment(doc, att) {\n var attObj = doc._attachments[att];\n var attOpts = {binary: opts.binary, ctx: txn};\n api._getAttachment(doc._id, att, attObj, attOpts, function (_, data) {\n doc._attachments[att] = extend$1(\n pick(attObj, ['digest', 'content_type']),\n { data: data }\n );\n checkDone();\n });\n }\n\n attachments.forEach(function (att) {\n if (opts.attachments && opts.include_docs) {\n fetchAttachment(doc, att);\n } else {\n doc._attachments[att].stub = true;\n checkDone();\n }\n });\n}\n\nvar POUCH_VERSION = 1;\n\n// these indexes cover the ground for most allDocs queries\nvar BY_SEQ_STORE_DELETED_INDEX_SQL =\n 'CREATE INDEX IF NOT EXISTS \\'by-seq-deleted-idx\\' ON ' +\n BY_SEQ_STORE$1 + ' (seq, deleted)';\nvar BY_SEQ_STORE_DOC_ID_REV_INDEX_SQL =\n 'CREATE UNIQUE INDEX IF NOT EXISTS \\'by-seq-doc-id-rev\\' ON ' +\n BY_SEQ_STORE$1 + ' (doc_id, rev)';\nvar DOC_STORE_WINNINGSEQ_INDEX_SQL =\n 'CREATE INDEX IF NOT EXISTS \\'doc-winningseq-idx\\' ON ' +\n DOC_STORE$1 + ' (winningseq)';\nvar ATTACH_AND_SEQ_STORE_SEQ_INDEX_SQL =\n 'CREATE INDEX IF NOT EXISTS \\'attach-seq-seq-idx\\' ON ' +\n ATTACH_AND_SEQ_STORE$1 + ' (seq)';\nvar ATTACH_AND_SEQ_STORE_ATTACH_INDEX_SQL =\n 'CREATE UNIQUE INDEX IF NOT EXISTS \\'attach-seq-digest-idx\\' ON ' +\n ATTACH_AND_SEQ_STORE$1 + ' (digest, seq)';\n\nvar DOC_STORE_AND_BY_SEQ_JOINER = BY_SEQ_STORE$1 +\n '.seq = ' + DOC_STORE$1 + '.winningseq';\n\nvar SELECT_DOCS = BY_SEQ_STORE$1 + '.seq AS seq, ' +\n BY_SEQ_STORE$1 + '.deleted AS deleted, ' +\n BY_SEQ_STORE$1 + '.json AS data, ' +\n BY_SEQ_STORE$1 + '.rev AS rev, ' +\n DOC_STORE$1 + '.json AS metadata';\n\nfunction WebSqlPouch$1(opts, callback) {\n var api = this;\n var instanceId = null;\n var size = getSize(opts);\n var idRequests = [];\n var encoding;\n\n api._docCount = -1; // cache sqlite count(*) for performance\n api._name = opts.name;\n\n // extend the options here, because sqlite plugin has a ton of options\n // and they are constantly changing, so it's more prudent to allow anything\n var websqlOpts = extend$1({}, opts, {\n version: POUCH_VERSION,\n description: opts.name,\n size: size\n });\n var openDBResult = openDB$1(websqlOpts);\n if (openDBResult.error) {\n return websqlError(callback)(openDBResult.error);\n }\n var db = openDBResult.db;\n if (typeof db.readTransaction !== 'function') {\n // doesn't exist in sqlite plugin\n db.readTransaction = db.transaction;\n }\n\n function dbCreated() {\n // note the db name in case the browser upgrades to idb\n if (hasLocalStorage()) {\n window.localStorage['_pouch__websqldb_' + api._name] = true;\n }\n callback(null, api);\n }\n\n // In this migration, we added the 'deleted' and 'local' columns to the\n // by-seq and doc store tables.\n // To preserve existing user data, we re-process all the existing JSON\n // and add these values.\n // Called migration2 because it corresponds to adapter version (db_version) #2\n function runMigration2(tx, callback) {\n // index used for the join in the allDocs query\n tx.executeSql(DOC_STORE_WINNINGSEQ_INDEX_SQL);\n\n tx.executeSql('ALTER TABLE ' + BY_SEQ_STORE$1 +\n ' ADD COLUMN deleted TINYINT(1) DEFAULT 0', [], function () {\n tx.executeSql(BY_SEQ_STORE_DELETED_INDEX_SQL);\n tx.executeSql('ALTER TABLE ' + DOC_STORE$1 +\n ' ADD COLUMN local TINYINT(1) DEFAULT 0', [], function () {\n tx.executeSql('CREATE INDEX IF NOT EXISTS \\'doc-store-local-idx\\' ON ' +\n DOC_STORE$1 + ' (local, id)');\n\n var sql = 'SELECT ' + DOC_STORE$1 + '.winningseq AS seq, ' + DOC_STORE$1 +\n '.json AS metadata FROM ' + BY_SEQ_STORE$1 + ' JOIN ' + DOC_STORE$1 +\n ' ON ' + BY_SEQ_STORE$1 + '.seq = ' + DOC_STORE$1 + '.winningseq';\n\n tx.executeSql(sql, [], function (tx, result) {\n\n var deleted = [];\n var local = [];\n\n for (var i = 0; i < result.rows.length; i++) {\n var item = result.rows.item(i);\n var seq = item.seq;\n var metadata = JSON.parse(item.metadata);\n if (isDeleted(metadata)) {\n deleted.push(seq);\n }\n if (isLocalId(metadata.id)) {\n local.push(metadata.id);\n }\n }\n tx.executeSql('UPDATE ' + DOC_STORE$1 + 'SET local = 1 WHERE id IN ' +\n qMarks(local.length), local, function () {\n tx.executeSql('UPDATE ' + BY_SEQ_STORE$1 +\n ' SET deleted = 1 WHERE seq IN ' +\n qMarks(deleted.length), deleted, callback);\n });\n });\n });\n });\n }\n\n // in this migration, we make all the local docs unversioned\n function runMigration3(tx, callback) {\n var local = 'CREATE TABLE IF NOT EXISTS ' + LOCAL_STORE$1 +\n ' (id UNIQUE, rev, json)';\n tx.executeSql(local, [], function () {\n var sql = 'SELECT ' + DOC_STORE$1 + '.id AS id, ' +\n BY_SEQ_STORE$1 + '.json AS data ' +\n 'FROM ' + BY_SEQ_STORE$1 + ' JOIN ' +\n DOC_STORE$1 + ' ON ' + BY_SEQ_STORE$1 + '.seq = ' +\n DOC_STORE$1 + '.winningseq WHERE local = 1';\n tx.executeSql(sql, [], function (tx, res) {\n var rows = [];\n for (var i = 0; i < res.rows.length; i++) {\n rows.push(res.rows.item(i));\n }\n function doNext() {\n if (!rows.length) {\n return callback(tx);\n }\n var row = rows.shift();\n var rev = JSON.parse(row.data)._rev;\n tx.executeSql('INSERT INTO ' + LOCAL_STORE$1 +\n ' (id, rev, json) VALUES (?,?,?)',\n [row.id, rev, row.data], function (tx) {\n tx.executeSql('DELETE FROM ' + DOC_STORE$1 + ' WHERE id=?',\n [row.id], function (tx) {\n tx.executeSql('DELETE FROM ' + BY_SEQ_STORE$1 + ' WHERE seq=?',\n [row.seq], function () {\n doNext();\n });\n });\n });\n }\n doNext();\n });\n });\n }\n\n // in this migration, we remove doc_id_rev and just use rev\n function runMigration4(tx, callback) {\n\n function updateRows(rows) {\n function doNext() {\n if (!rows.length) {\n return callback(tx);\n }\n var row = rows.shift();\n var doc_id_rev = parseHexString(row.hex, encoding);\n var idx = doc_id_rev.lastIndexOf('::');\n var doc_id = doc_id_rev.substring(0, idx);\n var rev = doc_id_rev.substring(idx + 2);\n var sql = 'UPDATE ' + BY_SEQ_STORE$1 +\n ' SET doc_id=?, rev=? WHERE doc_id_rev=?';\n tx.executeSql(sql, [doc_id, rev, doc_id_rev], function () {\n doNext();\n });\n }\n doNext();\n }\n\n var sql = 'ALTER TABLE ' + BY_SEQ_STORE$1 + ' ADD COLUMN doc_id';\n tx.executeSql(sql, [], function (tx) {\n var sql = 'ALTER TABLE ' + BY_SEQ_STORE$1 + ' ADD COLUMN rev';\n tx.executeSql(sql, [], function (tx) {\n tx.executeSql(BY_SEQ_STORE_DOC_ID_REV_INDEX_SQL, [], function (tx) {\n var sql = 'SELECT hex(doc_id_rev) as hex FROM ' + BY_SEQ_STORE$1;\n tx.executeSql(sql, [], function (tx, res) {\n var rows = [];\n for (var i = 0; i < res.rows.length; i++) {\n rows.push(res.rows.item(i));\n }\n updateRows(rows);\n });\n });\n });\n });\n }\n\n // in this migration, we add the attach_and_seq table\n // for issue #2818\n function runMigration5(tx, callback) {\n\n function migrateAttsAndSeqs(tx) {\n // need to actually populate the table. this is the expensive part,\n // so as an optimization, check first that this database even\n // contains attachments\n var sql = 'SELECT COUNT(*) AS cnt FROM ' + ATTACH_STORE$1;\n tx.executeSql(sql, [], function (tx, res) {\n var count = res.rows.item(0).cnt;\n if (!count) {\n return callback(tx);\n }\n\n var offset = 0;\n var pageSize = 10;\n function nextPage() {\n var sql = select(\n SELECT_DOCS + ', ' + DOC_STORE$1 + '.id AS id',\n [DOC_STORE$1, BY_SEQ_STORE$1],\n DOC_STORE_AND_BY_SEQ_JOINER,\n null,\n DOC_STORE$1 + '.id '\n );\n sql += ' LIMIT ' + pageSize + ' OFFSET ' + offset;\n offset += pageSize;\n tx.executeSql(sql, [], function (tx, res) {\n if (!res.rows.length) {\n return callback(tx);\n }\n var digestSeqs = {};\n function addDigestSeq(digest, seq) {\n // uniq digest/seq pairs, just in case there are dups\n var seqs = digestSeqs[digest] = (digestSeqs[digest] || []);\n if (seqs.indexOf(seq) === -1) {\n seqs.push(seq);\n }\n }\n for (var i = 0; i < res.rows.length; i++) {\n var row = res.rows.item(i);\n var doc = unstringifyDoc(row.data, row.id, row.rev);\n var atts = Object.keys(doc._attachments || {});\n for (var j = 0; j < atts.length; j++) {\n var att = doc._attachments[atts[j]];\n addDigestSeq(att.digest, row.seq);\n }\n }\n var digestSeqPairs = [];\n Object.keys(digestSeqs).forEach(function (digest) {\n var seqs = digestSeqs[digest];\n seqs.forEach(function (seq) {\n digestSeqPairs.push([digest, seq]);\n });\n });\n if (!digestSeqPairs.length) {\n return nextPage();\n }\n var numDone = 0;\n digestSeqPairs.forEach(function (pair) {\n var sql = 'INSERT INTO ' + ATTACH_AND_SEQ_STORE$1 +\n ' (digest, seq) VALUES (?,?)';\n tx.executeSql(sql, pair, function () {\n if (++numDone === digestSeqPairs.length) {\n nextPage();\n }\n });\n });\n });\n }\n nextPage();\n });\n }\n\n var attachAndRev = 'CREATE TABLE IF NOT EXISTS ' +\n ATTACH_AND_SEQ_STORE$1 + ' (digest, seq INTEGER)';\n tx.executeSql(attachAndRev, [], function (tx) {\n tx.executeSql(\n ATTACH_AND_SEQ_STORE_ATTACH_INDEX_SQL, [], function (tx) {\n tx.executeSql(\n ATTACH_AND_SEQ_STORE_SEQ_INDEX_SQL, [],\n migrateAttsAndSeqs);\n });\n });\n }\n\n // in this migration, we use escapeBlob() and unescapeBlob()\n // instead of reading out the binary as HEX, which is slow\n function runMigration6(tx, callback) {\n var sql = 'ALTER TABLE ' + ATTACH_STORE$1 +\n ' ADD COLUMN escaped TINYINT(1) DEFAULT 0';\n tx.executeSql(sql, [], callback);\n }\n\n // issue #3136, in this migration we need a \"latest seq\" as well\n // as the \"winning seq\" in the doc store\n function runMigration7(tx, callback) {\n var sql = 'ALTER TABLE ' + DOC_STORE$1 +\n ' ADD COLUMN max_seq INTEGER';\n tx.executeSql(sql, [], function (tx) {\n var sql = 'UPDATE ' + DOC_STORE$1 + ' SET max_seq=(SELECT MAX(seq) FROM ' +\n BY_SEQ_STORE$1 + ' WHERE doc_id=id)';\n tx.executeSql(sql, [], function (tx) {\n // add unique index after filling, else we'll get a constraint\n // error when we do the ALTER TABLE\n var sql =\n 'CREATE UNIQUE INDEX IF NOT EXISTS \\'doc-max-seq-idx\\' ON ' +\n DOC_STORE$1 + ' (max_seq)';\n tx.executeSql(sql, [], callback);\n });\n });\n }\n\n function checkEncoding(tx, cb) {\n // UTF-8 on chrome/android, UTF-16 on safari < 7.1\n tx.executeSql('SELECT HEX(\"a\") AS hex', [], function (tx, res) {\n var hex = res.rows.item(0).hex;\n encoding = hex.length === 2 ? 'UTF-8' : 'UTF-16';\n cb();\n }\n );\n }\n\n function onGetInstanceId() {\n while (idRequests.length > 0) {\n var idCallback = idRequests.pop();\n idCallback(null, instanceId);\n }\n }\n\n function onGetVersion(tx, dbVersion) {\n if (dbVersion === 0) {\n // initial schema\n\n var meta = 'CREATE TABLE IF NOT EXISTS ' + META_STORE$1 +\n ' (dbid, db_version INTEGER)';\n var attach = 'CREATE TABLE IF NOT EXISTS ' + ATTACH_STORE$1 +\n ' (digest UNIQUE, escaped TINYINT(1), body BLOB)';\n var attachAndRev = 'CREATE TABLE IF NOT EXISTS ' +\n ATTACH_AND_SEQ_STORE$1 + ' (digest, seq INTEGER)';\n // TODO: migrate winningseq to INTEGER\n var doc = 'CREATE TABLE IF NOT EXISTS ' + DOC_STORE$1 +\n ' (id unique, json, winningseq, max_seq INTEGER UNIQUE)';\n var seq = 'CREATE TABLE IF NOT EXISTS ' + BY_SEQ_STORE$1 +\n ' (seq INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ' +\n 'json, deleted TINYINT(1), doc_id, rev)';\n var local = 'CREATE TABLE IF NOT EXISTS ' + LOCAL_STORE$1 +\n ' (id UNIQUE, rev, json)';\n\n // creates\n tx.executeSql(attach);\n tx.executeSql(local);\n tx.executeSql(attachAndRev, [], function () {\n tx.executeSql(ATTACH_AND_SEQ_STORE_SEQ_INDEX_SQL);\n tx.executeSql(ATTACH_AND_SEQ_STORE_ATTACH_INDEX_SQL);\n });\n tx.executeSql(doc, [], function () {\n tx.executeSql(DOC_STORE_WINNINGSEQ_INDEX_SQL);\n tx.executeSql(seq, [], function () {\n tx.executeSql(BY_SEQ_STORE_DELETED_INDEX_SQL);\n tx.executeSql(BY_SEQ_STORE_DOC_ID_REV_INDEX_SQL);\n tx.executeSql(meta, [], function () {\n // mark the db version, and new dbid\n var initSeq = 'INSERT INTO ' + META_STORE$1 +\n ' (db_version, dbid) VALUES (?,?)';\n instanceId = uuid();\n var initSeqArgs = [ADAPTER_VERSION$1, instanceId];\n tx.executeSql(initSeq, initSeqArgs, function () {\n onGetInstanceId();\n });\n });\n });\n });\n } else { // version > 0\n\n var setupDone = function () {\n var migrated = dbVersion < ADAPTER_VERSION$1;\n if (migrated) {\n // update the db version within this transaction\n tx.executeSql('UPDATE ' + META_STORE$1 + ' SET db_version = ' +\n ADAPTER_VERSION$1);\n }\n // notify db.id() callers\n var sql = 'SELECT dbid FROM ' + META_STORE$1;\n tx.executeSql(sql, [], function (tx, result) {\n instanceId = result.rows.item(0).dbid;\n onGetInstanceId();\n });\n };\n\n // would love to use promises here, but then websql\n // ends the transaction early\n var tasks = [\n runMigration2,\n runMigration3,\n runMigration4,\n runMigration5,\n runMigration6,\n runMigration7,\n setupDone\n ];\n\n // run each migration sequentially\n var i = dbVersion;\n var nextMigration = function (tx) {\n tasks[i - 1](tx, nextMigration);\n i++;\n };\n nextMigration(tx);\n }\n }\n\n function setup() {\n db.transaction(function (tx) {\n // first check the encoding\n checkEncoding(tx, function () {\n // then get the version\n fetchVersion(tx);\n });\n }, websqlError(callback), dbCreated);\n }\n\n function fetchVersion(tx) {\n var sql = 'SELECT sql FROM sqlite_master WHERE tbl_name = ' + META_STORE$1;\n tx.executeSql(sql, [], function (tx, result) {\n if (!result.rows.length) {\n // database hasn't even been created yet (version 0)\n onGetVersion(tx, 0);\n } else if (!/db_version/.test(result.rows.item(0).sql)) {\n // table was created, but without the new db_version column,\n // so add it.\n tx.executeSql('ALTER TABLE ' + META_STORE$1 +\n ' ADD COLUMN db_version INTEGER', [], function () {\n // before version 2, this column didn't even exist\n onGetVersion(tx, 1);\n });\n } else { // column exists, we can safely get it\n tx.executeSql('SELECT db_version FROM ' + META_STORE$1,\n [], function (tx, result) {\n var dbVersion = result.rows.item(0).db_version;\n onGetVersion(tx, dbVersion);\n });\n }\n });\n }\n\n setup();\n\n api.type = function () {\n return 'websql';\n };\n\n api._id = toPromise(function (callback) {\n callback(null, instanceId);\n });\n\n api._info = function (callback) {\n db.readTransaction(function (tx) {\n countDocs(tx, function (docCount) {\n var sql = 'SELECT MAX(seq) AS seq FROM ' + BY_SEQ_STORE$1;\n tx.executeSql(sql, [], function (tx, res) {\n var updateSeq = res.rows.item(0).seq || 0;\n callback(null, {\n doc_count: docCount,\n update_seq: updateSeq,\n websql_encoding: encoding\n });\n });\n });\n }, websqlError(callback));\n };\n\n api._bulkDocs = function (req, reqOpts, callback) {\n websqlBulkDocs(opts, req, reqOpts, api, db, websqlChanges, callback);\n };\n\n function latest$$(tx, id, rev, callback, finish) {\n var sql = select(\n SELECT_DOCS,\n [DOC_STORE$1, BY_SEQ_STORE$1],\n DOC_STORE_AND_BY_SEQ_JOINER,\n DOC_STORE$1 + '.id=?');\n var sqlArgs = [id];\n\n tx.executeSql(sql, sqlArgs, function (a, results) {\n if (!results.rows.length) {\n var err = createError(MISSING_DOC, 'missing');\n return finish(err);\n }\n var item = results.rows.item(0);\n var metadata = safeJsonParse(item.metadata);\n callback(latest(rev, metadata));\n });\n }\n\n api._get = function (id, opts, callback) {\n var doc;\n var metadata;\n var tx = opts.ctx;\n if (!tx) {\n return db.readTransaction(function (txn) {\n api._get(id, extend$1({ctx: txn}, opts), callback);\n });\n }\n\n function finish(err) {\n callback(err, {doc: doc, metadata: metadata, ctx: tx});\n }\n\n var sql;\n var sqlArgs;\n\n if(!opts.rev) {\n sql = select(\n SELECT_DOCS,\n [DOC_STORE$1, BY_SEQ_STORE$1],\n DOC_STORE_AND_BY_SEQ_JOINER,\n DOC_STORE$1 + '.id=?');\n sqlArgs = [id];\n } else if (opts.latest) {\n latest$$(tx, id, opts.rev, function (latestRev) {\n opts.latest = false;\n opts.rev = latestRev;\n api._get(id, opts, callback);\n }, finish);\n return;\n } else {\n sql = select(\n SELECT_DOCS,\n [DOC_STORE$1, BY_SEQ_STORE$1],\n DOC_STORE$1 + '.id=' + BY_SEQ_STORE$1 + '.doc_id',\n [BY_SEQ_STORE$1 + '.doc_id=?', BY_SEQ_STORE$1 + '.rev=?']);\n sqlArgs = [id, opts.rev];\n }\n\n tx.executeSql(sql, sqlArgs, function (a, results) {\n if (!results.rows.length) {\n var missingErr = createError(MISSING_DOC, 'missing');\n return finish(missingErr);\n }\n var item = results.rows.item(0);\n metadata = safeJsonParse(item.metadata);\n if (item.deleted && !opts.rev) {\n var deletedErr = createError(MISSING_DOC, 'deleted');\n return finish(deletedErr);\n }\n doc = unstringifyDoc(item.data, metadata.id, item.rev);\n finish();\n });\n };\n\n function countDocs(tx, callback) {\n\n if (api._docCount !== -1) {\n return callback(api._docCount);\n }\n\n // count the total rows\n var sql = select(\n 'COUNT(' + DOC_STORE$1 + '.id) AS \\'num\\'',\n [DOC_STORE$1, BY_SEQ_STORE$1],\n DOC_STORE_AND_BY_SEQ_JOINER,\n BY_SEQ_STORE$1 + '.deleted=0');\n\n tx.executeSql(sql, [], function (tx, result) {\n api._docCount = result.rows.item(0).num;\n callback(api._docCount);\n });\n }\n\n api._allDocs = function (opts, callback) {\n var results = [];\n var totalRows;\n\n var start = 'startkey' in opts ? opts.startkey : false;\n var end = 'endkey' in opts ? opts.endkey : false;\n var key = 'key' in opts ? opts.key : false;\n var descending = 'descending' in opts ? opts.descending : false;\n var limit = 'limit' in opts ? opts.limit : -1;\n var offset = 'skip' in opts ? opts.skip : 0;\n var inclusiveEnd = opts.inclusive_end !== false;\n\n var sqlArgs = [];\n var criteria = [];\n\n if (key !== false) {\n criteria.push(DOC_STORE$1 + '.id = ?');\n sqlArgs.push(key);\n } else if (start !== false || end !== false) {\n if (start !== false) {\n criteria.push(DOC_STORE$1 + '.id ' + (descending ? '<=' : '>=') + ' ?');\n sqlArgs.push(start);\n }\n if (end !== false) {\n var comparator = descending ? '>' : '<';\n if (inclusiveEnd) {\n comparator += '=';\n }\n criteria.push(DOC_STORE$1 + '.id ' + comparator + ' ?');\n sqlArgs.push(end);\n }\n if (key !== false) {\n criteria.push(DOC_STORE$1 + '.id = ?');\n sqlArgs.push(key);\n }\n }\n\n if (opts.deleted !== 'ok') {\n // report deleted if keys are specified\n criteria.push(BY_SEQ_STORE$1 + '.deleted = 0');\n }\n\n db.readTransaction(function (tx) {\n\n // first count up the total rows\n countDocs(tx, function (count) {\n totalRows = count;\n\n if (limit === 0) {\n return;\n }\n\n // then actually fetch the documents\n var sql = select(\n SELECT_DOCS,\n [DOC_STORE$1, BY_SEQ_STORE$1],\n DOC_STORE_AND_BY_SEQ_JOINER,\n criteria,\n DOC_STORE$1 + '.id ' + (descending ? 'DESC' : 'ASC')\n );\n sql += ' LIMIT ' + limit + ' OFFSET ' + offset;\n\n tx.executeSql(sql, sqlArgs, function (tx, result) {\n for (var i = 0, l = result.rows.length; i < l; i++) {\n var item = result.rows.item(i);\n var metadata = safeJsonParse(item.metadata);\n var id = metadata.id;\n var data = unstringifyDoc(item.data, id, item.rev);\n var winningRev = data._rev;\n var doc = {\n id: id,\n key: id,\n value: {rev: winningRev}\n };\n if (opts.include_docs) {\n doc.doc = data;\n doc.doc._rev = winningRev;\n if (opts.conflicts) {\n var conflicts = collectConflicts(metadata);\n if (conflicts.length) {\n doc.doc._conflicts = conflicts;\n }\n }\n fetchAttachmentsIfNecessary$1(doc.doc, opts, api, tx);\n }\n if (item.deleted) {\n if (opts.deleted === 'ok') {\n doc.value.deleted = true;\n doc.doc = null;\n } else {\n continue;\n }\n }\n results.push(doc);\n }\n });\n });\n }, websqlError(callback), function () {\n callback(null, {\n total_rows: totalRows,\n offset: opts.skip,\n rows: results\n });\n });\n };\n\n api._changes = function (opts) {\n opts = clone(opts);\n\n if (opts.continuous) {\n var id = api._name + ':' + uuid();\n websqlChanges.addListener(api._name, id, api, opts);\n websqlChanges.notify(api._name);\n return {\n cancel: function () {\n websqlChanges.removeListener(api._name, id);\n }\n };\n }\n\n var descending = opts.descending;\n\n // Ignore the `since` parameter when `descending` is true\n opts.since = opts.since && !descending ? opts.since : 0;\n\n var limit = 'limit' in opts ? opts.limit : -1;\n if (limit === 0) {\n limit = 1; // per CouchDB _changes spec\n }\n\n var returnDocs;\n if ('return_docs' in opts) {\n returnDocs = opts.return_docs;\n } else if ('returnDocs' in opts) {\n // TODO: Remove 'returnDocs' in favor of 'return_docs' in a future release\n returnDocs = opts.returnDocs;\n } else {\n returnDocs = true;\n }\n var results = [];\n var numResults = 0;\n\n function fetchChanges() {\n\n var selectStmt =\n DOC_STORE$1 + '.json AS metadata, ' +\n DOC_STORE$1 + '.max_seq AS maxSeq, ' +\n BY_SEQ_STORE$1 + '.json AS winningDoc, ' +\n BY_SEQ_STORE$1 + '.rev AS winningRev ';\n\n var from = DOC_STORE$1 + ' JOIN ' + BY_SEQ_STORE$1;\n\n var joiner = DOC_STORE$1 + '.id=' + BY_SEQ_STORE$1 + '.doc_id' +\n ' AND ' + DOC_STORE$1 + '.winningseq=' + BY_SEQ_STORE$1 + '.seq';\n\n var criteria = ['maxSeq > ?'];\n var sqlArgs = [opts.since];\n\n if (opts.doc_ids) {\n criteria.push(DOC_STORE$1 + '.id IN ' + qMarks(opts.doc_ids.length));\n sqlArgs = sqlArgs.concat(opts.doc_ids);\n }\n\n var orderBy = 'maxSeq ' + (descending ? 'DESC' : 'ASC');\n\n var sql = select(selectStmt, from, joiner, criteria, orderBy);\n\n var filter = filterChange(opts);\n if (!opts.view && !opts.filter) {\n // we can just limit in the query\n sql += ' LIMIT ' + limit;\n }\n\n var lastSeq = opts.since || 0;\n db.readTransaction(function (tx) {\n tx.executeSql(sql, sqlArgs, function (tx, result) {\n function reportChange(change) {\n return function () {\n opts.onChange(change);\n };\n }\n for (var i = 0, l = result.rows.length; i < l; i++) {\n var item = result.rows.item(i);\n var metadata = safeJsonParse(item.metadata);\n lastSeq = item.maxSeq;\n\n var doc = unstringifyDoc(item.winningDoc, metadata.id,\n item.winningRev);\n var change = opts.processChange(doc, metadata, opts);\n change.seq = item.maxSeq;\n\n var filtered = filter(change);\n if (typeof filtered === 'object') {\n return opts.complete(filtered);\n }\n\n if (filtered) {\n numResults++;\n if (returnDocs) {\n results.push(change);\n }\n // process the attachment immediately\n // for the benefit of live listeners\n if (opts.attachments && opts.include_docs) {\n fetchAttachmentsIfNecessary$1(doc, opts, api, tx,\n reportChange(change));\n } else {\n reportChange(change)();\n }\n }\n if (numResults === limit) {\n break;\n }\n }\n });\n }, websqlError(opts.complete), function () {\n if (!opts.continuous) {\n opts.complete(null, {\n results: results,\n last_seq: lastSeq\n });\n }\n });\n }\n\n fetchChanges();\n };\n\n api._close = function (callback) {\n //WebSQL databases do not need to be closed\n callback();\n };\n\n api._getAttachment = function (docId, attachId, attachment, opts, callback) {\n var res;\n var tx = opts.ctx;\n var digest = attachment.digest;\n var type = attachment.content_type;\n var sql = 'SELECT escaped, ' +\n 'CASE WHEN escaped = 1 THEN body ELSE HEX(body) END AS body FROM ' +\n ATTACH_STORE$1 + ' WHERE digest=?';\n tx.executeSql(sql, [digest], function (tx, result) {\n // websql has a bug where \\u0000 causes early truncation in strings\n // and blobs. to work around this, we used to use the hex() function,\n // but that's not performant. after migration 6, we remove \\u0000\n // and add it back in afterwards\n var item = result.rows.item(0);\n var data = item.escaped ? unescapeBlob(item.body) :\n parseHexString(item.body, encoding);\n if (opts.binary) {\n res = binStringToBluffer(data, type);\n } else {\n res = btoa$1(data);\n }\n callback(null, res);\n });\n };\n\n api._getRevisionTree = function (docId, callback) {\n db.readTransaction(function (tx) {\n var sql = 'SELECT json AS metadata FROM ' + DOC_STORE$1 + ' WHERE id = ?';\n tx.executeSql(sql, [docId], function (tx, result) {\n if (!result.rows.length) {\n callback(createError(MISSING_DOC));\n } else {\n var data = safeJsonParse(result.rows.item(0).metadata);\n callback(null, data.rev_tree);\n }\n });\n });\n };\n\n api._doCompaction = function (docId, revs, callback) {\n if (!revs.length) {\n return callback();\n }\n db.transaction(function (tx) {\n\n // update doc store\n var sql = 'SELECT json AS metadata FROM ' + DOC_STORE$1 + ' WHERE id = ?';\n tx.executeSql(sql, [docId], function (tx, result) {\n var metadata = safeJsonParse(result.rows.item(0).metadata);\n traverseRevTree(metadata.rev_tree, function (isLeaf, pos,\n revHash, ctx, opts) {\n var rev = pos + '-' + revHash;\n if (revs.indexOf(rev) !== -1) {\n opts.status = 'missing';\n }\n });\n\n var sql = 'UPDATE ' + DOC_STORE$1 + ' SET json = ? WHERE id = ?';\n tx.executeSql(sql, [safeJsonStringify(metadata), docId]);\n });\n\n compactRevs$1(revs, docId, tx);\n }, websqlError(callback), function () {\n callback();\n });\n };\n\n api._getLocal = function (id, callback) {\n db.readTransaction(function (tx) {\n var sql = 'SELECT json, rev FROM ' + LOCAL_STORE$1 + ' WHERE id=?';\n tx.executeSql(sql, [id], function (tx, res) {\n if (res.rows.length) {\n var item = res.rows.item(0);\n var doc = unstringifyDoc(item.json, id, item.rev);\n callback(null, doc);\n } else {\n callback(createError(MISSING_DOC));\n }\n });\n });\n };\n\n api._putLocal = function (doc, opts, callback) {\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n delete doc._revisions; // ignore this, trust the rev\n var oldRev = doc._rev;\n var id = doc._id;\n var newRev;\n if (!oldRev) {\n newRev = doc._rev = '0-1';\n } else {\n newRev = doc._rev = '0-' + (parseInt(oldRev.split('-')[1], 10) + 1);\n }\n var json = stringifyDoc(doc);\n\n var ret;\n function putLocal(tx) {\n var sql;\n var values;\n if (oldRev) {\n sql = 'UPDATE ' + LOCAL_STORE$1 + ' SET rev=?, json=? ' +\n 'WHERE id=? AND rev=?';\n values = [newRev, json, id, oldRev];\n } else {\n sql = 'INSERT INTO ' + LOCAL_STORE$1 + ' (id, rev, json) VALUES (?,?,?)';\n values = [id, newRev, json];\n }\n tx.executeSql(sql, values, function (tx, res) {\n if (res.rowsAffected) {\n ret = {ok: true, id: id, rev: newRev};\n if (opts.ctx) { // return immediately\n callback(null, ret);\n }\n } else {\n callback(createError(REV_CONFLICT));\n }\n }, function () {\n callback(createError(REV_CONFLICT));\n return false; // ack that we handled the error\n });\n }\n\n if (opts.ctx) {\n putLocal(opts.ctx);\n } else {\n db.transaction(putLocal, websqlError(callback), function () {\n if (ret) {\n callback(null, ret);\n }\n });\n }\n };\n\n api._removeLocal = function (doc, opts, callback) {\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n var ret;\n\n function removeLocal(tx) {\n var sql = 'DELETE FROM ' + LOCAL_STORE$1 + ' WHERE id=? AND rev=?';\n var params = [doc._id, doc._rev];\n tx.executeSql(sql, params, function (tx, res) {\n if (!res.rowsAffected) {\n return callback(createError(MISSING_DOC));\n }\n ret = {ok: true, id: doc._id, rev: '0-0'};\n if (opts.ctx) { // return immediately\n callback(null, ret);\n }\n });\n }\n\n if (opts.ctx) {\n removeLocal(opts.ctx);\n } else {\n db.transaction(removeLocal, websqlError(callback), function () {\n if (ret) {\n callback(null, ret);\n }\n });\n }\n };\n\n api._destroy = function (opts, callback) {\n websqlChanges.removeAllListeners(api._name);\n db.transaction(function (tx) {\n var stores = [DOC_STORE$1, BY_SEQ_STORE$1, ATTACH_STORE$1, META_STORE$1,\n LOCAL_STORE$1, ATTACH_AND_SEQ_STORE$1];\n stores.forEach(function (store) {\n tx.executeSql('DROP TABLE IF EXISTS ' + store, []);\n });\n }, websqlError(callback), function () {\n if (hasLocalStorage()) {\n delete window.localStorage['_pouch__websqldb_' + api._name];\n delete window.localStorage[api._name];\n }\n callback(null, {'ok': true});\n });\n };\n}\n\nfunction canOpenTestDB() {\n try {\n openDatabase('_pouch_validate_websql', 1, '', 1);\n return true;\n } catch (err) {\n return false;\n }\n}\n\n// WKWebView had a bug where WebSQL would throw a DOM Exception 18\n// (see https://bugs.webkit.org/show_bug.cgi?id=137760 and\n// https://github.com/pouchdb/pouchdb/issues/5079)\n// This has been fixed in latest WebKit, so we try to detect it here.\nfunction isValidWebSQL() {\n // WKWebView UA:\n // Mozilla/5.0 (iPhone; CPU iPhone OS 9_2 like Mac OS X)\n // AppleWebKit/601.1.46 (KHTML, like Gecko) Mobile/13C75\n // Chrome for iOS UA:\n // Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en)\n // AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60\n // Mobile/9B206 Safari/7534.48.3\n // Firefox for iOS UA:\n // Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4\n // (KHTML, like Gecko) FxiOS/1.0 Mobile/12F69 Safari/600.1.4\n\n // indexedDB is null on some UIWebViews and undefined in others\n // see: https://bugs.webkit.org/show_bug.cgi?id=137034\n if (typeof indexedDB === 'undefined' || indexedDB === null ||\n !/iP(hone|od|ad)/.test(navigator.userAgent)) {\n // definitely not WKWebView, avoid creating an unnecessary database\n return true;\n }\n // Cache the result in LocalStorage. Reason we do this is because if we\n // call openDatabase() too many times, Safari craps out in SauceLabs and\n // starts throwing DOM Exception 14s.\n var hasLS = hasLocalStorage();\n // Include user agent in the hash, so that if Safari is upgraded, we don't\n // continually think it's broken.\n var localStorageKey = '_pouch__websqldb_valid_' + navigator.userAgent;\n if (hasLS && localStorage[localStorageKey]) {\n return localStorage[localStorageKey] === '1';\n }\n var openedTestDB = canOpenTestDB();\n if (hasLS) {\n localStorage[localStorageKey] = openedTestDB ? '1' : '0';\n }\n return openedTestDB;\n}\n\nfunction valid() {\n if (typeof openDatabase !== 'function') {\n return false;\n }\n return isValidWebSQL();\n}\n\nfunction openDB(name, version, description, size) {\n // Traditional WebSQL API\n return openDatabase(name, version, description, size);\n}\n\nfunction WebSQLPouch(opts, callback) {\n var _opts = extend$1({\n websql: openDB\n }, opts);\n\n WebSqlPouch$1.call(this, _opts, callback);\n}\n\nWebSQLPouch.valid = valid;\n\nWebSQLPouch.use_prefix = true;\n\nfunction WebSqlPouch (PouchDB) {\n PouchDB.adapter('websql', WebSQLPouch, true);\n}\n\n/* global fetch */\n/* global Headers */\nfunction wrappedFetch() {\n var wrappedPromise = {};\n\n var promise = new PouchPromise(function (resolve, reject) {\n wrappedPromise.resolve = resolve;\n wrappedPromise.reject = reject;\n });\n\n var args = new Array(arguments.length);\n\n for (var i = 0; i < args.length; i++) {\n args[i] = arguments[i];\n }\n\n wrappedPromise.promise = promise;\n\n PouchPromise.resolve().then(function () {\n return fetch.apply(null, args);\n }).then(function (response) {\n wrappedPromise.resolve(response);\n }).catch(function (error) {\n wrappedPromise.reject(error);\n });\n\n return wrappedPromise;\n}\n\nfunction fetchRequest(options, callback) {\n var wrappedPromise, timer, response;\n\n var headers = new Headers();\n\n var fetchOptions = {\n method: options.method,\n credentials: 'include',\n headers: headers\n };\n\n if (options.json) {\n headers.set('Accept', 'application/json');\n headers.set('Content-Type', options.headers['Content-Type'] ||\n 'application/json');\n }\n\n if (options.body &&\n options.processData &&\n typeof options.body !== 'string') {\n fetchOptions.body = JSON.stringify(options.body);\n } else if ('body' in options) {\n fetchOptions.body = options.body;\n } else {\n fetchOptions.body = null;\n }\n\n Object.keys(options.headers).forEach(function (key) {\n if (options.headers.hasOwnProperty(key)) {\n headers.set(key, options.headers[key]);\n }\n });\n\n wrappedPromise = wrappedFetch(options.url, fetchOptions);\n\n if (options.timeout > 0) {\n timer = setTimeout(function () {\n wrappedPromise.reject(new Error('Load timeout for resource: ' +\n options.url));\n }, options.timeout);\n }\n\n wrappedPromise.promise.then(function (fetchResponse) {\n response = {\n statusCode: fetchResponse.status\n };\n\n if (options.timeout > 0) {\n clearTimeout(timer);\n }\n\n if (response.statusCode >= 200 && response.statusCode < 300) {\n return options.binary ? fetchResponse.blob() : fetchResponse.text();\n }\n\n return fetchResponse.json();\n }).then(function (result) {\n if (response.statusCode >= 200 && response.statusCode < 300) {\n callback(null, response, result);\n } else {\n result.status = response.statusCode;\n callback(result);\n }\n }).catch(function (error) {\n if (!error) {\n // this happens when the listener is canceled\n error = new Error('canceled');\n }\n callback(error);\n });\n\n return {abort: wrappedPromise.reject};\n}\n\nfunction xhRequest(options, callback) {\n\n var xhr, timer;\n var timedout = false;\n\n var abortReq = function () {\n xhr.abort();\n cleanUp();\n };\n\n var timeoutReq = function () {\n timedout = true;\n xhr.abort();\n cleanUp();\n };\n\n var ret = {abort: abortReq};\n\n var cleanUp = function () {\n clearTimeout(timer);\n ret.abort = function () {};\n if (xhr) {\n xhr.onprogress = undefined;\n if (xhr.upload) {\n xhr.upload.onprogress = undefined;\n }\n xhr.onreadystatechange = undefined;\n xhr = undefined;\n }\n };\n\n if (options.xhr) {\n xhr = new options.xhr();\n } else {\n xhr = new XMLHttpRequest();\n }\n\n try {\n xhr.open(options.method, options.url);\n } catch (exception) {\n return callback(new Error(exception.name || 'Url is invalid'));\n }\n\n xhr.withCredentials = ('withCredentials' in options) ?\n options.withCredentials : true;\n\n if (options.method === 'GET') {\n delete options.headers['Content-Type'];\n } else if (options.json) {\n options.headers.Accept = 'application/json';\n options.headers['Content-Type'] = options.headers['Content-Type'] ||\n 'application/json';\n if (options.body &&\n options.processData &&\n typeof options.body !== \"string\") {\n options.body = JSON.stringify(options.body);\n }\n }\n\n if (options.binary) {\n xhr.responseType = 'arraybuffer';\n }\n\n if (!('body' in options)) {\n options.body = null;\n }\n\n for (var key in options.headers) {\n if (options.headers.hasOwnProperty(key)) {\n xhr.setRequestHeader(key, options.headers[key]);\n }\n }\n\n if (options.timeout > 0) {\n timer = setTimeout(timeoutReq, options.timeout);\n xhr.onprogress = function () {\n clearTimeout(timer);\n if(xhr.readyState !== 4) {\n timer = setTimeout(timeoutReq, options.timeout);\n }\n };\n if (typeof xhr.upload !== 'undefined') { // does not exist in ie9\n xhr.upload.onprogress = xhr.onprogress;\n }\n }\n\n xhr.onreadystatechange = function () {\n if (xhr.readyState !== 4) {\n return;\n }\n\n var response = {\n statusCode: xhr.status\n };\n\n if (xhr.status >= 200 && xhr.status < 300) {\n var data;\n if (options.binary) {\n data = createBlob([xhr.response || ''], {\n type: xhr.getResponseHeader('Content-Type')\n });\n } else {\n data = xhr.responseText;\n }\n callback(null, response, data);\n } else {\n var err = {};\n if (timedout) {\n err = new Error('ETIMEDOUT');\n err.code = 'ETIMEDOUT';\n } else if (typeof xhr.response === 'string') {\n try {\n err = JSON.parse(xhr.response);\n } catch(e) {}\n }\n err.status = xhr.status;\n callback(err);\n }\n cleanUp();\n };\n\n if (options.body && (options.body instanceof Blob)) {\n readAsArrayBuffer(options.body, function (arrayBuffer) {\n xhr.send(arrayBuffer);\n });\n } else {\n xhr.send(options.body);\n }\n\n return ret;\n}\n\nfunction testXhr() {\n try {\n new XMLHttpRequest();\n return true;\n } catch (err) {\n return false;\n }\n}\n\nvar hasXhr = testXhr();\n\nfunction ajax$1(options, callback) {\n if (!false && (hasXhr || options.xhr)) {\n return xhRequest(options, callback);\n } else {\n return fetchRequest(options, callback);\n }\n}\n\n// the blob already has a type; do nothing\nvar res$2 = function () {};\n\nfunction defaultBody() {\n return '';\n}\n\nfunction ajaxCore(options, callback) {\n\n options = clone(options);\n\n var defaultOptions = {\n method : \"GET\",\n headers: {},\n json: true,\n processData: true,\n timeout: 10000,\n cache: false\n };\n\n options = extend$1(defaultOptions, options);\n\n function onSuccess(obj, resp, cb) {\n if (!options.binary && options.json && typeof obj === 'string') {\n /* istanbul ignore next */\n try {\n obj = JSON.parse(obj);\n } catch (e) {\n // Probably a malformed JSON from server\n return cb(e);\n }\n }\n if (Array.isArray(obj)) {\n obj = obj.map(function (v) {\n if (v.error || v.missing) {\n return generateErrorFromResponse(v);\n } else {\n return v;\n }\n });\n }\n if (options.binary) {\n res$2(obj, resp);\n }\n cb(null, obj, resp);\n }\n\n if (options.json) {\n if (!options.binary) {\n options.headers.Accept = 'application/json';\n }\n options.headers['Content-Type'] = options.headers['Content-Type'] ||\n 'application/json';\n }\n\n if (options.binary) {\n options.encoding = null;\n options.json = false;\n }\n\n if (!options.processData) {\n options.json = false;\n }\n\n return ajax$1(options, function (err, response, body) {\n\n if (err) {\n return callback(generateErrorFromResponse(err));\n }\n\n var error;\n var content_type = response.headers && response.headers['content-type'];\n var data = body || defaultBody();\n\n // CouchDB doesn't always return the right content-type for JSON data, so\n // we check for ^{ and }$ (ignoring leading/trailing whitespace)\n if (!options.binary && (options.json || !options.processData) &&\n typeof data !== 'object' &&\n (/json/.test(content_type) ||\n (/^[\\s]*\\{/.test(data) && /\\}[\\s]*$/.test(data)))) {\n try {\n data = JSON.parse(data.toString());\n } catch (e) {}\n }\n\n if (response.statusCode >= 200 && response.statusCode < 300) {\n onSuccess(data, response, callback);\n } else {\n error = generateErrorFromResponse(data);\n error.status = response.statusCode;\n callback(error);\n }\n });\n}\n\nfunction ajax(opts, callback) {\n\n // cache-buster, specifically designed to work around IE's aggressive caching\n // see http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/\n // Also Safari caches POSTs, so we need to cache-bust those too.\n var ua = (navigator && navigator.userAgent) ?\n navigator.userAgent.toLowerCase() : '';\n\n var isSafari = ua.indexOf('safari') !== -1 && ua.indexOf('chrome') === -1;\n var isIE = ua.indexOf('msie') !== -1;\n var isEdge = ua.indexOf('edge') !== -1;\n\n // it appears the new version of safari also caches GETs,\n // see https://github.com/pouchdb/pouchdb/issues/5010\n var shouldCacheBust = (isSafari ||\n ((isIE || isEdge) && opts.method === 'GET'));\n\n var cache = 'cache' in opts ? opts.cache : true;\n\n var isBlobUrl = /^blob:/.test(opts.url); // don't append nonces for blob URLs\n\n if (!isBlobUrl && (shouldCacheBust || !cache)) {\n var hasArgs = opts.url.indexOf('?') !== -1;\n opts.url += (hasArgs ? '&' : '?') + '_nonce=' + Date.now();\n }\n\n return ajaxCore(opts, callback);\n}\n\n// dead simple promise pool, inspired by https://github.com/timdp/es6-promise-pool\n// but much smaller in code size. limits the number of concurrent promises that are executed\n\nfunction pool(promiseFactories, limit) {\n return new PouchPromise(function (resolve, reject) {\n var running = 0;\n var current = 0;\n var done = 0;\n var len = promiseFactories.length;\n var err;\n\n function runNext() {\n running++;\n promiseFactories[current++]().then(onSuccess, onError);\n }\n\n function doNext() {\n if (++done === len) {\n /* istanbul ignore if */\n if (err) {\n reject(err);\n } else {\n resolve();\n }\n } else {\n runNextBatch();\n }\n }\n\n function onSuccess() {\n running--;\n doNext();\n }\n\n /* istanbul ignore next */\n function onError(thisErr) {\n running--;\n err = err || thisErr;\n doNext();\n }\n\n function runNextBatch() {\n while (running < limit && current < len) {\n runNext();\n }\n }\n\n runNextBatch();\n });\n}\n\nvar CHANGES_BATCH_SIZE = 25;\nvar MAX_SIMULTANEOUS_REVS = 50;\n\nvar supportsBulkGetMap = {};\n\nvar log$1 = debug('pouchdb:http');\n\nfunction readAttachmentsAsBlobOrBuffer(row) {\n var atts = row.doc && row.doc._attachments;\n if (!atts) {\n return;\n }\n Object.keys(atts).forEach(function (filename) {\n var att = atts[filename];\n att.data = b64ToBluffer(att.data, att.content_type);\n });\n}\n\nfunction encodeDocId(id) {\n if (/^_design/.test(id)) {\n return '_design/' + encodeURIComponent(id.slice(8));\n }\n if (/^_local/.test(id)) {\n return '_local/' + encodeURIComponent(id.slice(7));\n }\n return encodeURIComponent(id);\n}\n\nfunction preprocessAttachments$1(doc) {\n if (!doc._attachments || !Object.keys(doc._attachments)) {\n return PouchPromise.resolve();\n }\n\n return PouchPromise.all(Object.keys(doc._attachments).map(function (key) {\n var attachment = doc._attachments[key];\n if (attachment.data && typeof attachment.data !== 'string') {\n return new PouchPromise(function (resolve) {\n blobToBase64(attachment.data, resolve);\n }).then(function (b64) {\n attachment.data = b64;\n });\n }\n }));\n}\n\nfunction hasUrlPrefix(opts) {\n if (!opts.prefix) {\n return false;\n }\n\n var protocol = parseUri(opts.prefix).protocol;\n\n return protocol === 'http' || protocol === 'https';\n}\n\n// Get all the information you possibly can about the URI given by name and\n// return it as a suitable object.\nfunction getHost(name, opts) {\n\n // encode db name if opts.prefix is a url (#5574)\n if (hasUrlPrefix(opts)) {\n var dbName = opts.name.substr(opts.prefix.length);\n name = opts.prefix + encodeURIComponent(dbName);\n }\n\n // Prase the URI into all its little bits\n var uri = parseUri(name);\n\n // Store the user and password as a separate auth object\n if (uri.user || uri.password) {\n uri.auth = {username: uri.user, password: uri.password};\n }\n\n // Split the path part of the URI into parts using '/' as the delimiter\n // after removing any leading '/' and any trailing '/'\n var parts = uri.path.replace(/(^\\/|\\/$)/g, '').split('/');\n\n // Store the first part as the database name and remove it from the parts\n // array\n uri.db = parts.pop();\n // Prevent double encoding of URI component\n if (uri.db.indexOf('%') === -1) {\n uri.db = encodeURIComponent(uri.db);\n }\n\n // Restore the path by joining all the remaining parts (all the parts\n // except for the database name) with '/'s\n uri.path = parts.join('/');\n\n return uri;\n}\n\n// Generate a URL with the host data given by opts and the given path\nfunction genDBUrl(opts, path) {\n return genUrl(opts, opts.db + '/' + path);\n}\n\n// Generate a URL with the host data given by opts and the given path\nfunction genUrl(opts, path) {\n // If the host already has a path, then we need to have a path delimiter\n // Otherwise, the path delimiter is the empty string\n var pathDel = !opts.path ? '' : '/';\n\n // If the host already has a path, then we need to have a path delimiter\n // Otherwise, the path delimiter is the empty string\n return opts.protocol + '://' + opts.host +\n (opts.port ? (':' + opts.port) : '') +\n '/' + opts.path + pathDel + path;\n}\n\nfunction paramsToStr(params) {\n return '?' + Object.keys(params).map(function (k) {\n return k + '=' + encodeURIComponent(params[k]);\n }).join('&');\n}\n\n// Implements the PouchDB API for dealing with CouchDB instances over HTTP\nfunction HttpPouch(opts, callback) {\n\n // The functions that will be publicly available for HttpPouch\n var api = this;\n\n var host = getHost(opts.name, opts);\n var dbUrl = genDBUrl(host, '');\n\n opts = clone(opts);\n var ajaxOpts = opts.ajax || {};\n\n if (opts.auth || host.auth) {\n var nAuth = opts.auth || host.auth;\n var str = nAuth.username + ':' + nAuth.password;\n var token = btoa$1(unescape(encodeURIComponent(str)));\n ajaxOpts.headers = ajaxOpts.headers || {};\n ajaxOpts.headers.Authorization = 'Basic ' + token;\n }\n\n // Not strictly necessary, but we do this because numerous tests\n // rely on swapping ajax in and out.\n api._ajax = ajax;\n\n function ajax$$(userOpts, options, callback) {\n var reqAjax = userOpts.ajax || {};\n var reqOpts = extend$1(clone(ajaxOpts), reqAjax, options);\n log$1(reqOpts.method + ' ' + reqOpts.url);\n return api._ajax(reqOpts, callback);\n }\n\n function ajaxPromise(userOpts, opts) {\n return new PouchPromise(function (resolve, reject) {\n ajax$$(userOpts, opts, function (err, res) {\n /* istanbul ignore if */\n if (err) {\n return reject(err);\n }\n resolve(res);\n });\n });\n }\n\n function adapterFun$$(name, fun) {\n return adapterFun(name, getArguments(function (args) {\n setup().then(function () {\n return fun.apply(this, args);\n }).catch(function (e) {\n var callback = args.pop();\n callback(e);\n });\n }));\n }\n\n var setupPromise;\n\n function setup() {\n // TODO: Remove `skipSetup` in favor of `skip_setup` in a future release\n if (opts.skipSetup || opts.skip_setup) {\n return PouchPromise.resolve();\n }\n\n // If there is a setup in process or previous successful setup\n // done then we will use that\n // If previous setups have been rejected we will try again\n if (setupPromise) {\n return setupPromise;\n }\n\n var checkExists = {method: 'GET', url: dbUrl};\n setupPromise = ajaxPromise({}, checkExists).catch(function (err) {\n if (err && err.status && err.status === 404) {\n // Doesnt exist, create it\n explainError(404, 'PouchDB is just detecting if the remote exists.');\n return ajaxPromise({}, {method: 'PUT', url: dbUrl});\n } else {\n return PouchPromise.reject(err);\n }\n }).catch(function (err) {\n // If we try to create a database that already exists, skipped in\n // istanbul since its catching a race condition.\n /* istanbul ignore if */\n if (err && err.status && err.status === 412) {\n return true;\n }\n return PouchPromise.reject(err);\n });\n\n setupPromise.catch(function () {\n setupPromise = null;\n });\n\n return setupPromise;\n }\n\n immediate(function () {\n callback(null, api);\n });\n\n api.type = function () {\n return 'http';\n };\n\n api.id = adapterFun$$('id', function (callback) {\n ajax$$({}, {method: 'GET', url: genUrl(host, '')}, function (err, result) {\n var uuid = (result && result.uuid) ?\n (result.uuid + host.db) : genDBUrl(host, '');\n callback(null, uuid);\n });\n });\n\n api.request = adapterFun$$('request', function (options, callback) {\n options.url = genDBUrl(host, options.url);\n ajax$$({}, options, callback);\n });\n\n // Sends a POST request to the host calling the couchdb _compact function\n // version: The version of CouchDB it is running\n api.compact = adapterFun$$('compact', function (opts, callback) {\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n opts = clone(opts);\n ajax$$(opts, {\n url: genDBUrl(host, '_compact'),\n method: 'POST'\n }, function () {\n function ping() {\n api.info(function (err, res) {\n if (res && !res.compact_running) {\n callback(null, {ok: true});\n } else {\n setTimeout(ping, opts.interval || 200);\n }\n });\n }\n // Ping the http if it's finished compaction\n ping();\n });\n });\n\n api.bulkGet = adapterFun('bulkGet', function (opts, callback) {\n var self = this;\n\n function doBulkGet(cb) {\n var params = {};\n if (opts.revs) {\n params.revs = true;\n }\n if (opts.attachments) {\n /* istanbul ignore next */\n params.attachments = true;\n }\n if (opts.latest) {\n params.latest = true;\n }\n ajax$$(opts, {\n url: genDBUrl(host, '_bulk_get' + paramsToStr(params)),\n method: 'POST',\n body: { docs: opts.docs}\n }, cb);\n }\n\n function doBulkGetShim() {\n // avoid \"url too long error\" by splitting up into multiple requests\n var batchSize = MAX_SIMULTANEOUS_REVS;\n var numBatches = Math.ceil(opts.docs.length / batchSize);\n var numDone = 0;\n var results = new Array(numBatches);\n\n function onResult(batchNum) {\n return function (err, res) {\n // err is impossible because shim returns a list of errs in that case\n results[batchNum] = res.results;\n if (++numDone === numBatches) {\n callback(null, {results: flatten(results)});\n }\n };\n }\n\n for (var i = 0; i < numBatches; i++) {\n var subOpts = pick(opts, ['revs', 'attachments', 'latest']);\n subOpts.ajax = ajaxOpts;\n subOpts.docs = opts.docs.slice(i * batchSize,\n Math.min(opts.docs.length, (i + 1) * batchSize));\n bulkGet(self, subOpts, onResult(i));\n }\n }\n\n // mark the whole database as either supporting or not supporting _bulk_get\n var dbUrl = genUrl(host, '');\n var supportsBulkGet = supportsBulkGetMap[dbUrl];\n\n if (typeof supportsBulkGet !== 'boolean') {\n // check if this database supports _bulk_get\n doBulkGet(function (err, res) {\n /* istanbul ignore else */\n if (err) {\n var status = Math.floor(err.status / 100);\n /* istanbul ignore else */\n if (status === 4 || status === 5) { // 40x or 50x\n supportsBulkGetMap[dbUrl] = false;\n explainError(\n err.status,\n 'PouchDB is just detecting if the remote ' +\n 'supports the _bulk_get API.'\n );\n doBulkGetShim();\n } else {\n callback(err);\n }\n } else {\n supportsBulkGetMap[dbUrl] = true;\n callback(null, res);\n }\n });\n } else if (supportsBulkGet) {\n /* istanbul ignore next */\n doBulkGet(callback);\n } else {\n doBulkGetShim();\n }\n });\n\n // Calls GET on the host, which gets back a JSON string containing\n // couchdb: A welcome string\n // version: The version of CouchDB it is running\n api._info = function (callback) {\n setup().then(function () {\n ajax$$({}, {\n method: 'GET',\n url: genDBUrl(host, '')\n }, function (err, res) {\n /* istanbul ignore next */\n if (err) {\n return callback(err);\n }\n res.host = genDBUrl(host, '');\n callback(null, res);\n });\n }).catch(callback);\n };\n\n // Get the document with the given id from the database given by host.\n // The id could be solely the _id in the database, or it may be a\n // _design/ID or _local/ID path\n api.get = adapterFun$$('get', function (id, opts, callback) {\n // If no options were given, set the callback to the second parameter\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n opts = clone(opts);\n\n // List of parameters to add to the GET request\n var params = {};\n\n if (opts.revs) {\n params.revs = true;\n }\n\n if (opts.revs_info) {\n params.revs_info = true;\n }\n\n if (opts.latest) {\n params.latest = true;\n }\n\n if (opts.open_revs) {\n if (opts.open_revs !== \"all\") {\n opts.open_revs = JSON.stringify(opts.open_revs);\n }\n params.open_revs = opts.open_revs;\n }\n\n if (opts.rev) {\n params.rev = opts.rev;\n }\n\n if (opts.conflicts) {\n params.conflicts = opts.conflicts;\n }\n\n id = encodeDocId(id);\n\n // Set the options for the ajax call\n var options = {\n method: 'GET',\n url: genDBUrl(host, id + paramsToStr(params))\n };\n\n function fetchAttachments(doc) {\n var atts = doc._attachments;\n var filenames = atts && Object.keys(atts);\n if (!atts || !filenames.length) {\n return;\n }\n // we fetch these manually in separate XHRs, because\n // Sync Gateway would normally send it back as multipart/mixed,\n // which we cannot parse. Also, this is more efficient than\n // receiving attachments as base64-encoded strings.\n function fetch(filename) {\n var att = atts[filename];\n var path = encodeDocId(doc._id) + '/' + encodeAttachmentId(filename) +\n '?rev=' + doc._rev;\n return ajaxPromise(opts, {\n method: 'GET',\n url: genDBUrl(host, path),\n binary: true\n }).then(function (blob) {\n if (opts.binary) {\n return blob;\n }\n return new PouchPromise(function (resolve) {\n blobToBase64(blob, resolve);\n });\n }).then(function (data) {\n delete att.stub;\n delete att.length;\n att.data = data;\n });\n }\n\n var promiseFactories = filenames.map(function (filename) {\n return function () {\n return fetch(filename);\n };\n });\n\n // This limits the number of parallel xhr requests to 5 any time\n // to avoid issues with maximum browser request limits\n return pool(promiseFactories, 5);\n }\n\n function fetchAllAttachments(docOrDocs) {\n if (Array.isArray(docOrDocs)) {\n return PouchPromise.all(docOrDocs.map(function (doc) {\n if (doc.ok) {\n return fetchAttachments(doc.ok);\n }\n }));\n }\n return fetchAttachments(docOrDocs);\n }\n\n ajaxPromise(opts, options).then(function (res) {\n return PouchPromise.resolve().then(function () {\n if (opts.attachments) {\n return fetchAllAttachments(res);\n }\n }).then(function () {\n callback(null, res);\n });\n }).catch(callback);\n });\n\n // Delete the document given by doc from the database given by host.\n api.remove = adapterFun$$('remove',\n function (docOrId, optsOrRev, opts, callback) {\n var doc;\n if (typeof optsOrRev === 'string') {\n // id, rev, opts, callback style\n doc = {\n _id: docOrId,\n _rev: optsOrRev\n };\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n } else {\n // doc, opts, callback style\n doc = docOrId;\n if (typeof optsOrRev === 'function') {\n callback = optsOrRev;\n opts = {};\n } else {\n callback = opts;\n opts = optsOrRev;\n }\n }\n\n var rev = (doc._rev || opts.rev);\n\n // Delete the document\n ajax$$(opts, {\n method: 'DELETE',\n url: genDBUrl(host, encodeDocId(doc._id)) + '?rev=' + rev\n }, callback);\n });\n\n function encodeAttachmentId(attachmentId) {\n return attachmentId.split(\"/\").map(encodeURIComponent).join(\"/\");\n }\n\n // Get the attachment\n api.getAttachment =\n adapterFun$$('getAttachment', function (docId, attachmentId, opts,\n callback) {\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n var params = opts.rev ? ('?rev=' + opts.rev) : '';\n var url = genDBUrl(host, encodeDocId(docId)) + '/' +\n encodeAttachmentId(attachmentId) + params;\n ajax$$(opts, {\n method: 'GET',\n url: url,\n binary: true\n }, callback);\n });\n\n // Remove the attachment given by the id and rev\n api.removeAttachment =\n adapterFun$$('removeAttachment', function (docId, attachmentId, rev,\n callback) {\n\n var url = genDBUrl(host, encodeDocId(docId) + '/' +\n encodeAttachmentId(attachmentId)) + '?rev=' + rev;\n\n ajax$$({}, {\n method: 'DELETE',\n url: url\n }, callback);\n });\n\n // Add the attachment given by blob and its contentType property\n // to the document with the given id, the revision given by rev, and\n // add it to the database given by host.\n api.putAttachment =\n adapterFun$$('putAttachment', function (docId, attachmentId, rev, blob,\n type, callback) {\n if (typeof type === 'function') {\n callback = type;\n type = blob;\n blob = rev;\n rev = null;\n }\n var id = encodeDocId(docId) + '/' + encodeAttachmentId(attachmentId);\n var url = genDBUrl(host, id);\n if (rev) {\n url += '?rev=' + rev;\n }\n\n if (typeof blob === 'string') {\n // input is assumed to be a base64 string\n var binary;\n try {\n binary = atob$1(blob);\n } catch (err) {\n return callback(createError(BAD_ARG,\n 'Attachment is not a valid base64 string'));\n }\n blob = binary ? binStringToBluffer(binary, type) : '';\n }\n\n var opts = {\n headers: {'Content-Type': type},\n method: 'PUT',\n url: url,\n processData: false,\n body: blob,\n timeout: ajaxOpts.timeout || 60000\n };\n // Add the attachment\n ajax$$({}, opts, callback);\n });\n\n // Update/create multiple documents given by req in the database\n // given by host.\n api._bulkDocs = function (req, opts, callback) {\n // If new_edits=false then it prevents the database from creating\n // new revision numbers for the documents. Instead it just uses\n // the old ones. This is used in database replication.\n req.new_edits = opts.new_edits;\n\n setup().then(function () {\n return PouchPromise.all(req.docs.map(preprocessAttachments$1));\n }).then(function () {\n // Update/create the documents\n ajax$$(opts, {\n method: 'POST',\n url: genDBUrl(host, '_bulk_docs'),\n timeout: opts.timeout,\n body: req\n }, function (err, results) {\n if (err) {\n return callback(err);\n }\n results.forEach(function (result) {\n result.ok = true; // smooths out cloudant not adding this\n });\n callback(null, results);\n });\n }).catch(callback);\n };\n\n\n // Update/create document\n api._put = function (doc, opts, callback) {\n setup().then(function () {\n return preprocessAttachments$1(doc);\n }).then(function () {\n // Update/create the document\n ajax$$(opts, {\n method: 'PUT',\n url: genDBUrl(host, encodeDocId(doc._id)),\n body: doc\n }, function (err, result) {\n if (err) {\n return callback(err);\n }\n callback(null, result);\n });\n }).catch(callback);\n };\n\n\n // Get a listing of the documents in the database given\n // by host and ordered by increasing id.\n api.allDocs = adapterFun$$('allDocs', function (opts, callback) {\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n opts = clone(opts);\n\n // List of parameters to add to the GET request\n var params = {};\n var body;\n var method = 'GET';\n\n if (opts.conflicts) {\n params.conflicts = true;\n }\n\n if (opts.descending) {\n params.descending = true;\n }\n\n if (opts.include_docs) {\n params.include_docs = true;\n }\n\n // added in CouchDB 1.6.0\n if (opts.attachments) {\n params.attachments = true;\n }\n\n if (opts.key) {\n params.key = JSON.stringify(opts.key);\n }\n\n if (opts.start_key) {\n opts.startkey = opts.start_key;\n }\n\n if (opts.startkey) {\n params.startkey = JSON.stringify(opts.startkey);\n }\n\n if (opts.end_key) {\n opts.endkey = opts.end_key;\n }\n\n if (opts.endkey) {\n params.endkey = JSON.stringify(opts.endkey);\n }\n\n if (typeof opts.inclusive_end !== 'undefined') {\n params.inclusive_end = !!opts.inclusive_end;\n }\n\n if (typeof opts.limit !== 'undefined') {\n params.limit = opts.limit;\n }\n\n if (typeof opts.skip !== 'undefined') {\n params.skip = opts.skip;\n }\n\n var paramStr = paramsToStr(params);\n\n if (typeof opts.keys !== 'undefined') {\n method = 'POST';\n body = {keys: opts.keys};\n }\n\n // Get the document listing\n ajaxPromise(opts, {\n method: method,\n url: genDBUrl(host, '_all_docs' + paramStr),\n body: body\n }).then(function (res) {\n if (opts.include_docs && opts.attachments && opts.binary) {\n res.rows.forEach(readAttachmentsAsBlobOrBuffer);\n }\n callback(null, res);\n }).catch(callback);\n });\n\n // Get a list of changes made to documents in the database given by host.\n // TODO According to the README, there should be two other methods here,\n // api.changes.addListener and api.changes.removeListener.\n api._changes = function (opts) {\n\n // We internally page the results of a changes request, this means\n // if there is a large set of changes to be returned we can start\n // processing them quicker instead of waiting on the entire\n // set of changes to return and attempting to process them at once\n var batchSize = 'batch_size' in opts ? opts.batch_size : CHANGES_BATCH_SIZE;\n\n opts = clone(opts);\n opts.timeout = ('timeout' in opts) ? opts.timeout :\n ('timeout' in ajaxOpts) ? ajaxOpts.timeout :\n 30 * 1000;\n\n // We give a 5 second buffer for CouchDB changes to respond with\n // an ok timeout (if a timeout it set)\n var params = opts.timeout ? {timeout: opts.timeout - (5 * 1000)} : {};\n var limit = (typeof opts.limit !== 'undefined') ? opts.limit : false;\n var returnDocs;\n if ('return_docs' in opts) {\n returnDocs = opts.return_docs;\n } else if ('returnDocs' in opts) {\n // TODO: Remove 'returnDocs' in favor of 'return_docs' in a future release\n returnDocs = opts.returnDocs;\n } else {\n returnDocs = true;\n }\n //\n var leftToFetch = limit;\n\n if (opts.style) {\n params.style = opts.style;\n }\n\n if (opts.include_docs || opts.filter && typeof opts.filter === 'function') {\n params.include_docs = true;\n }\n\n if (opts.attachments) {\n params.attachments = true;\n }\n\n if (opts.continuous) {\n params.feed = 'longpoll';\n }\n\n if (opts.conflicts) {\n params.conflicts = true;\n }\n\n if (opts.descending) {\n params.descending = true;\n }\n\n if ('heartbeat' in opts) {\n // If the heartbeat value is false, it disables the default heartbeat\n if (opts.heartbeat) {\n params.heartbeat = opts.heartbeat;\n }\n } else {\n // Default heartbeat to 10 seconds\n params.heartbeat = 10000;\n }\n\n if (opts.filter && typeof opts.filter === 'string') {\n params.filter = opts.filter;\n }\n\n if (opts.view && typeof opts.view === 'string') {\n params.filter = '_view';\n params.view = opts.view;\n }\n\n // If opts.query_params exists, pass it through to the changes request.\n // These parameters may be used by the filter on the source database.\n if (opts.query_params && typeof opts.query_params === 'object') {\n for (var param_name in opts.query_params) {\n /* istanbul ignore else */\n if (opts.query_params.hasOwnProperty(param_name)) {\n params[param_name] = opts.query_params[param_name];\n }\n }\n }\n\n var method = 'GET';\n var body;\n\n if (opts.doc_ids) {\n // set this automagically for the user; it's annoying that couchdb\n // requires both a \"filter\" and a \"doc_ids\" param.\n params.filter = '_doc_ids';\n method = 'POST';\n body = {doc_ids: opts.doc_ids };\n }\n\n var xhr;\n var lastFetchedSeq;\n\n // Get all the changes starting wtih the one immediately after the\n // sequence number given by since.\n var fetch = function (since, callback) {\n if (opts.aborted) {\n return;\n }\n params.since = since;\n // \"since\" can be any kind of json object in Coudant/CouchDB 2.x\n /* istanbul ignore next */\n if (typeof params.since === \"object\") {\n params.since = JSON.stringify(params.since);\n }\n\n if (opts.descending) {\n if (limit) {\n params.limit = leftToFetch;\n }\n } else {\n params.limit = (!limit || leftToFetch > batchSize) ?\n batchSize : leftToFetch;\n }\n\n // Set the options for the ajax call\n var xhrOpts = {\n method: method,\n url: genDBUrl(host, '_changes' + paramsToStr(params)),\n timeout: opts.timeout,\n body: body\n };\n lastFetchedSeq = since;\n\n /* istanbul ignore if */\n if (opts.aborted) {\n return;\n }\n\n // Get the changes\n setup().then(function () {\n xhr = ajax$$(opts, xhrOpts, callback);\n }).catch(callback);\n };\n\n // If opts.since exists, get all the changes from the sequence\n // number given by opts.since. Otherwise, get all the changes\n // from the sequence number 0.\n var results = {results: []};\n\n var fetched = function (err, res) {\n if (opts.aborted) {\n return;\n }\n var raw_results_length = 0;\n // If the result of the ajax call (res) contains changes (res.results)\n if (res && res.results) {\n raw_results_length = res.results.length;\n results.last_seq = res.last_seq;\n // For each change\n var req = {};\n req.query = opts.query_params;\n res.results = res.results.filter(function (c) {\n leftToFetch--;\n var ret = filterChange(opts)(c);\n if (ret) {\n if (opts.include_docs && opts.attachments && opts.binary) {\n readAttachmentsAsBlobOrBuffer(c);\n }\n if (returnDocs) {\n results.results.push(c);\n }\n opts.onChange(c);\n }\n return ret;\n });\n } else if (err) {\n // In case of an error, stop listening for changes and call\n // opts.complete\n opts.aborted = true;\n opts.complete(err);\n return;\n }\n\n // The changes feed may have timed out with no results\n // if so reuse last update sequence\n if (res && res.last_seq) {\n lastFetchedSeq = res.last_seq;\n }\n\n var finished = (limit && leftToFetch <= 0) ||\n (res && raw_results_length < batchSize) ||\n (opts.descending);\n\n if ((opts.continuous && !(limit && leftToFetch <= 0)) || !finished) {\n // Queue a call to fetch again with the newest sequence number\n immediate(function () { fetch(lastFetchedSeq, fetched); });\n } else {\n // We're done, call the callback\n opts.complete(null, results);\n }\n };\n\n fetch(opts.since || 0, fetched);\n\n // Return a method to cancel this method from processing any more\n return {\n cancel: function () {\n opts.aborted = true;\n if (xhr) {\n xhr.abort();\n }\n }\n };\n };\n\n // Given a set of document/revision IDs (given by req), tets the subset of\n // those that do NOT correspond to revisions stored in the database.\n // See http://wiki.apache.org/couchdb/HttpPostRevsDiff\n api.revsDiff = adapterFun$$('revsDiff', function (req, opts, callback) {\n // If no options were given, set the callback to be the second parameter\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n\n // Get the missing document/revision IDs\n ajax$$(opts, {\n method: 'POST',\n url: genDBUrl(host, '_revs_diff'),\n body: req\n }, callback);\n });\n\n api._close = function (callback) {\n callback();\n };\n\n api._destroy = function (options, callback) {\n ajax$$(options, {\n url: genDBUrl(host, ''),\n method: 'DELETE'\n }, function (err, resp) {\n if (err && err.status && err.status !== 404) {\n return callback(err);\n }\n callback(null, resp);\n });\n };\n}\n\n// HttpPouch is a valid adapter.\nHttpPouch.valid = function () {\n return true;\n};\n\nfunction HttpPouch$1 (PouchDB) {\n PouchDB.adapter('http', HttpPouch, false);\n PouchDB.adapter('https', HttpPouch, false);\n}\n\nfunction pad(str, padWith, upToLength) {\n var padding = '';\n var targetLength = upToLength - str.length;\n /* istanbul ignore next */\n while (padding.length < targetLength) {\n padding += padWith;\n }\n return padding;\n}\n\nfunction padLeft(str, padWith, upToLength) {\n var padding = pad(str, padWith, upToLength);\n return padding + str;\n}\n\nvar MIN_MAGNITUDE = -324; // verified by -Number.MIN_VALUE\nvar MAGNITUDE_DIGITS = 3; // ditto\nvar SEP = ''; // set to '_' for easier debugging \n\nfunction collate(a, b) {\n\n if (a === b) {\n return 0;\n }\n\n a = normalizeKey(a);\n b = normalizeKey(b);\n\n var ai = collationIndex(a);\n var bi = collationIndex(b);\n if ((ai - bi) !== 0) {\n return ai - bi;\n }\n if (a === null) {\n return 0;\n }\n switch (typeof a) {\n case 'number':\n return a - b;\n case 'boolean':\n return a === b ? 0 : (a < b ? -1 : 1);\n case 'string':\n return stringCollate(a, b);\n }\n return Array.isArray(a) ? arrayCollate(a, b) : objectCollate(a, b);\n}\n\n// couch considers null/NaN/Infinity/-Infinity === undefined,\n// for the purposes of mapreduce indexes. also, dates get stringified.\nfunction normalizeKey(key) {\n switch (typeof key) {\n case 'undefined':\n return null;\n case 'number':\n if (key === Infinity || key === -Infinity || isNaN(key)) {\n return null;\n }\n return key;\n case 'object':\n var origKey = key;\n if (Array.isArray(key)) {\n var len = key.length;\n key = new Array(len);\n for (var i = 0; i < len; i++) {\n key[i] = normalizeKey(origKey[i]);\n }\n /* istanbul ignore next */\n } else if (key instanceof Date) {\n return key.toJSON();\n } else if (key !== null) { // generic object\n key = {};\n for (var k in origKey) {\n if (origKey.hasOwnProperty(k)) {\n var val = origKey[k];\n if (typeof val !== 'undefined') {\n key[k] = normalizeKey(val);\n }\n }\n }\n }\n }\n return key;\n}\n\nfunction indexify(key) {\n if (key !== null) {\n switch (typeof key) {\n case 'boolean':\n return key ? 1 : 0;\n case 'number':\n return numToIndexableString(key);\n case 'string':\n // We've to be sure that key does not contain \\u0000\n // Do order-preserving replacements:\n // 0 -> 1, 1\n // 1 -> 1, 2\n // 2 -> 2, 2\n return key\n .replace(/\\u0002/g, '\\u0002\\u0002')\n .replace(/\\u0001/g, '\\u0001\\u0002')\n .replace(/\\u0000/g, '\\u0001\\u0001');\n case 'object':\n var isArray = Array.isArray(key);\n var arr = isArray ? key : Object.keys(key);\n var i = -1;\n var len = arr.length;\n var result = '';\n if (isArray) {\n while (++i < len) {\n result += toIndexableString(arr[i]);\n }\n } else {\n while (++i < len) {\n var objKey = arr[i];\n result += toIndexableString(objKey) +\n toIndexableString(key[objKey]);\n }\n }\n return result;\n }\n }\n return '';\n}\n\n// convert the given key to a string that would be appropriate\n// for lexical sorting, e.g. within a database, where the\n// sorting is the same given by the collate() function.\nfunction toIndexableString(key) {\n var zero = '\\u0000';\n key = normalizeKey(key);\n return collationIndex(key) + SEP + indexify(key) + zero;\n}\n\nfunction parseNumber(str, i) {\n var originalIdx = i;\n var num;\n var zero = str[i] === '1';\n if (zero) {\n num = 0;\n i++;\n } else {\n var neg = str[i] === '0';\n i++;\n var numAsString = '';\n var magAsString = str.substring(i, i + MAGNITUDE_DIGITS);\n var magnitude = parseInt(magAsString, 10) + MIN_MAGNITUDE;\n /* istanbul ignore next */\n if (neg) {\n magnitude = -magnitude;\n }\n i += MAGNITUDE_DIGITS;\n while (true) {\n var ch = str[i];\n if (ch === '\\u0000') {\n break;\n } else {\n numAsString += ch;\n }\n i++;\n }\n numAsString = numAsString.split('.');\n if (numAsString.length === 1) {\n num = parseInt(numAsString, 10);\n } else {\n /* istanbul ignore next */\n num = parseFloat(numAsString[0] + '.' + numAsString[1]);\n }\n /* istanbul ignore next */\n if (neg) {\n num = num - 10;\n }\n /* istanbul ignore next */\n if (magnitude !== 0) {\n // parseFloat is more reliable than pow due to rounding errors\n // e.g. Number.MAX_VALUE would return Infinity if we did\n // num * Math.pow(10, magnitude);\n num = parseFloat(num + 'e' + magnitude);\n }\n }\n return {num: num, length : i - originalIdx};\n}\n\n// move up the stack while parsing\n// this function moved outside of parseIndexableString for performance\nfunction pop(stack, metaStack) {\n var obj = stack.pop();\n\n if (metaStack.length) {\n var lastMetaElement = metaStack[metaStack.length - 1];\n if (obj === lastMetaElement.element) {\n // popping a meta-element, e.g. an object whose value is another object\n metaStack.pop();\n lastMetaElement = metaStack[metaStack.length - 1];\n }\n var element = lastMetaElement.element;\n var lastElementIndex = lastMetaElement.index;\n if (Array.isArray(element)) {\n element.push(obj);\n } else if (lastElementIndex === stack.length - 2) { // obj with key+value\n var key = stack.pop();\n element[key] = obj;\n } else {\n stack.push(obj); // obj with key only\n }\n }\n}\n\nfunction parseIndexableString(str) {\n var stack = [];\n var metaStack = []; // stack for arrays and objects\n var i = 0;\n\n /*eslint no-constant-condition: [\"error\", { \"checkLoops\": false }]*/\n while (true) {\n var collationIndex = str[i++];\n if (collationIndex === '\\u0000') {\n if (stack.length === 1) {\n return stack.pop();\n } else {\n pop(stack, metaStack);\n continue;\n }\n }\n switch (collationIndex) {\n case '1':\n stack.push(null);\n break;\n case '2':\n stack.push(str[i] === '1');\n i++;\n break;\n case '3':\n var parsedNum = parseNumber(str, i);\n stack.push(parsedNum.num);\n i += parsedNum.length;\n break;\n case '4':\n var parsedStr = '';\n /*eslint no-constant-condition: [\"error\", { \"checkLoops\": false }]*/\n while (true) {\n var ch = str[i];\n if (ch === '\\u0000') {\n break;\n }\n parsedStr += ch;\n i++;\n }\n // perform the reverse of the order-preserving replacement\n // algorithm (see above)\n parsedStr = parsedStr.replace(/\\u0001\\u0001/g, '\\u0000')\n .replace(/\\u0001\\u0002/g, '\\u0001')\n .replace(/\\u0002\\u0002/g, '\\u0002');\n stack.push(parsedStr);\n break;\n case '5':\n var arrayElement = { element: [], index: stack.length };\n stack.push(arrayElement.element);\n metaStack.push(arrayElement);\n break;\n case '6':\n var objElement = { element: {}, index: stack.length };\n stack.push(objElement.element);\n metaStack.push(objElement);\n break;\n /* istanbul ignore next */\n default:\n throw new Error(\n 'bad collationIndex or unexpectedly reached end of input: ' +\n collationIndex);\n }\n }\n}\n\nfunction arrayCollate(a, b) {\n var len = Math.min(a.length, b.length);\n for (var i = 0; i < len; i++) {\n var sort = collate(a[i], b[i]);\n if (sort !== 0) {\n return sort;\n }\n }\n return (a.length === b.length) ? 0 :\n (a.length > b.length) ? 1 : -1;\n}\nfunction stringCollate(a, b) {\n // See: https://github.com/daleharvey/pouchdb/issues/40\n // This is incompatible with the CouchDB implementation, but its the\n // best we can do for now\n return (a === b) ? 0 : ((a > b) ? 1 : -1);\n}\nfunction objectCollate(a, b) {\n var ak = Object.keys(a), bk = Object.keys(b);\n var len = Math.min(ak.length, bk.length);\n for (var i = 0; i < len; i++) {\n // First sort the keys\n var sort = collate(ak[i], bk[i]);\n if (sort !== 0) {\n return sort;\n }\n // if the keys are equal sort the values\n sort = collate(a[ak[i]], b[bk[i]]);\n if (sort !== 0) {\n return sort;\n }\n\n }\n return (ak.length === bk.length) ? 0 :\n (ak.length > bk.length) ? 1 : -1;\n}\n// The collation is defined by erlangs ordered terms\n// the atoms null, true, false come first, then numbers, strings,\n// arrays, then objects\n// null/undefined/NaN/Infinity/-Infinity are all considered null\nfunction collationIndex(x) {\n var id = ['boolean', 'number', 'string', 'object'];\n var idx = id.indexOf(typeof x);\n //false if -1 otherwise true, but fast!!!!1\n if (~idx) {\n if (x === null) {\n return 1;\n }\n if (Array.isArray(x)) {\n return 5;\n }\n return idx < 3 ? (idx + 2) : (idx + 3);\n }\n /* istanbul ignore next */\n if (Array.isArray(x)) {\n return 5;\n }\n}\n\n// conversion:\n// x yyy zz...zz\n// x = 0 for negative, 1 for 0, 2 for positive\n// y = exponent (for negative numbers negated) moved so that it's >= 0\n// z = mantisse\nfunction numToIndexableString(num) {\n\n if (num === 0) {\n return '1';\n }\n\n // convert number to exponential format for easier and\n // more succinct string sorting\n var expFormat = num.toExponential().split(/e\\+?/);\n var magnitude = parseInt(expFormat[1], 10);\n\n var neg = num < 0;\n\n var result = neg ? '0' : '2';\n\n // first sort by magnitude\n // it's easier if all magnitudes are positive\n var magForComparison = ((neg ? -magnitude : magnitude) - MIN_MAGNITUDE);\n var magString = padLeft((magForComparison).toString(), '0', MAGNITUDE_DIGITS);\n\n result += SEP + magString;\n\n // then sort by the factor\n var factor = Math.abs(parseFloat(expFormat[0])); // [1..10)\n /* istanbul ignore next */\n if (neg) { // for negative reverse ordering\n factor = 10 - factor;\n }\n\n var factorStr = factor.toFixed(20);\n\n // strip zeros from the end\n factorStr = factorStr.replace(/\\.?0+$/, '');\n\n result += SEP + factorStr;\n\n return result;\n}\n\n/*\n * Simple task queue to sequentialize actions. Assumes\n * callbacks will eventually fire (once).\n */\n\nfunction TaskQueue$1() {\n this.promise = new PouchPromise(function (fulfill) {fulfill(); });\n}\nTaskQueue$1.prototype.add = function (promiseFactory) {\n this.promise = this.promise.catch(function () {\n // just recover\n }).then(function () {\n return promiseFactory();\n });\n return this.promise;\n};\nTaskQueue$1.prototype.finish = function () {\n return this.promise;\n};\n\nfunction createView(opts) {\n var sourceDB = opts.db;\n var viewName = opts.viewName;\n var mapFun = opts.map;\n var reduceFun = opts.reduce;\n var temporary = opts.temporary;\n\n // the \"undefined\" part is for backwards compatibility\n var viewSignature = mapFun.toString() + (reduceFun && reduceFun.toString()) +\n 'undefined';\n\n var cachedViews;\n if (!temporary) {\n // cache this to ensure we don't try to update the same view twice\n cachedViews = sourceDB._cachedViews = sourceDB._cachedViews || {};\n if (cachedViews[viewSignature]) {\n return cachedViews[viewSignature];\n }\n }\n\n var promiseForView = sourceDB.info().then(function (info) {\n\n var depDbName = info.db_name + '-mrview-' +\n (temporary ? 'temp' : stringMd5(viewSignature));\n\n // save the view name in the source db so it can be cleaned up if necessary\n // (e.g. when the _design doc is deleted, remove all associated view data)\n function diffFunction(doc) {\n doc.views = doc.views || {};\n var fullViewName = viewName;\n if (fullViewName.indexOf('/') === -1) {\n fullViewName = viewName + '/' + viewName;\n }\n var depDbs = doc.views[fullViewName] = doc.views[fullViewName] || {};\n /* istanbul ignore if */\n if (depDbs[depDbName]) {\n return; // no update necessary\n }\n depDbs[depDbName] = true;\n return doc;\n }\n return upsert(sourceDB, '_local/mrviews', diffFunction).then(function () {\n return sourceDB.registerDependentDatabase(depDbName).then(function (res) {\n var db = res.db;\n db.auto_compaction = true;\n var view = {\n name: depDbName,\n db: db,\n sourceDB: sourceDB,\n adapter: sourceDB.adapter,\n mapFun: mapFun,\n reduceFun: reduceFun\n };\n return view.db.get('_local/lastSeq').catch(function (err) {\n /* istanbul ignore if */\n if (err.status !== 404) {\n throw err;\n }\n }).then(function (lastSeqDoc) {\n view.seq = lastSeqDoc ? lastSeqDoc.seq : 0;\n if (cachedViews) {\n view.db.once('destroyed', function () {\n delete cachedViews[viewSignature];\n });\n }\n return view;\n });\n });\n });\n });\n\n if (cachedViews) {\n cachedViews[viewSignature] = promiseForView;\n }\n return promiseForView;\n}\n\nfunction QueryParseError(message) {\n this.status = 400;\n this.name = 'query_parse_error';\n this.message = message;\n this.error = true;\n try {\n Error.captureStackTrace(this, QueryParseError);\n } catch (e) {}\n}\n\ninherits(QueryParseError, Error);\n\nfunction NotFoundError(message) {\n this.status = 404;\n this.name = 'not_found';\n this.message = message;\n this.error = true;\n try {\n Error.captureStackTrace(this, NotFoundError);\n } catch (e) {}\n}\n\ninherits(NotFoundError, Error);\n\nfunction BuiltInError(message) {\n this.status = 500;\n this.name = 'invalid_value';\n this.message = message;\n this.error = true;\n try {\n Error.captureStackTrace(this, BuiltInError);\n } catch (e) {}\n}\n\ninherits(BuiltInError, Error);\n\nfunction createBuiltInError(name) {\n var message = 'builtin ' + name +\n ' function requires map values to be numbers' +\n ' or number arrays';\n return new BuiltInError(message);\n}\n\nfunction sum(values) {\n var result = 0;\n for (var i = 0, len = values.length; i < len; i++) {\n var num = values[i];\n if (typeof num !== 'number') {\n if (Array.isArray(num)) {\n // lists of numbers are also allowed, sum them separately\n result = typeof result === 'number' ? [result] : result;\n for (var j = 0, jLen = num.length; j < jLen; j++) {\n var jNum = num[j];\n if (typeof jNum !== 'number') {\n throw createBuiltInError('_sum');\n } else if (typeof result[j] === 'undefined') {\n result.push(jNum);\n } else {\n result[j] += jNum;\n }\n }\n } else { // not array/number\n throw createBuiltInError('_sum');\n }\n } else if (typeof result === 'number') {\n result += num;\n } else { // add number to array\n result[0] += num;\n }\n }\n return result;\n}\n\nvar log$2 = guardedConsole.bind(null, 'log');\nvar isArray = Array.isArray;\nvar toJSON = JSON.parse;\n\nfunction evalFunctionWithEval(func, emit) {\n return scopedEval(\n \"return (\" + func.replace(/;\\s*$/, \"\") + \");\",\n {\n emit: emit,\n sum: sum,\n log: log$2,\n isArray: isArray,\n toJSON: toJSON\n }\n );\n}\n\nvar promisedCallback = function (promise, callback) {\n if (callback) {\n promise.then(function (res) {\n immediate(function () {\n callback(null, res);\n });\n }, function (reason) {\n immediate(function () {\n callback(reason);\n });\n });\n }\n return promise;\n};\n\nvar callbackify = function (fun) {\n return getArguments(function (args) {\n var cb = args.pop();\n var promise = fun.apply(this, args);\n if (typeof cb === 'function') {\n promisedCallback(promise, cb);\n }\n return promise;\n });\n};\n\n// Promise finally util similar to Q.finally\nvar fin = function (promise, finalPromiseFactory) {\n return promise.then(function (res) {\n return finalPromiseFactory().then(function () {\n return res;\n });\n }, function (reason) {\n return finalPromiseFactory().then(function () {\n throw reason;\n });\n });\n};\n\nvar sequentialize = function (queue, promiseFactory) {\n return function () {\n var args = arguments;\n var that = this;\n return queue.add(function () {\n return promiseFactory.apply(that, args);\n });\n };\n};\n\n// uniq an array of strings, order not guaranteed\n// similar to underscore/lodash _.uniq\nvar uniq = function (arr) {\n var map = {};\n\n for (var i = 0, len = arr.length; i < len; i++) {\n map['$' + arr[i]] = true;\n }\n\n var keys = Object.keys(map);\n var output = new Array(keys.length);\n\n for (i = 0, len = keys.length; i < len; i++) {\n output[i] = keys[i].substring(1);\n }\n return output;\n};\n\nvar persistentQueues = {};\nvar tempViewQueue = new TaskQueue$1();\nvar CHANGES_BATCH_SIZE$1 = 50;\n\nfunction parseViewName(name) {\n // can be either 'ddocname/viewname' or just 'viewname'\n // (where the ddoc name is the same)\n return name.indexOf('/') === -1 ? [name, name] : name.split('/');\n}\n\nfunction isGenOne(changes) {\n // only return true if the current change is 1-\n // and there are no other leafs\n return changes.length === 1 && /^1-/.test(changes[0].rev);\n}\n\nfunction emitError(db, e) {\n try {\n db.emit('error', e);\n } catch (err) {\n guardedConsole('error',\n 'The user\\'s map/reduce function threw an uncaught error.\\n' +\n 'You can debug this error by doing:\\n' +\n 'myDatabase.on(\\'error\\', function (err) { debugger; });\\n' +\n 'Please double-check your map/reduce function.');\n guardedConsole('error', e);\n }\n}\n\nfunction tryCode$1(db, fun, args) {\n // emit an event if there was an error thrown by a map/reduce function.\n // putting try/catches in a single function also avoids deoptimizations.\n try {\n return {\n output : fun.apply(null, args)\n };\n } catch (e) {\n emitError(db, e);\n return {error: e};\n }\n}\n\nfunction sortByKeyThenValue(x, y) {\n var keyCompare = collate(x.key, y.key);\n return keyCompare !== 0 ? keyCompare : collate(x.value, y.value);\n}\n\nfunction sliceResults(results, limit, skip) {\n skip = skip || 0;\n if (typeof limit === 'number') {\n return results.slice(skip, limit + skip);\n } else if (skip > 0) {\n return results.slice(skip);\n }\n return results;\n}\n\nfunction rowToDocId(row) {\n var val = row.value;\n // Users can explicitly specify a joined doc _id, or it\n // defaults to the doc _id that emitted the key/value.\n var docId = (val && typeof val === 'object' && val._id) || row.id;\n return docId;\n}\n\nfunction readAttachmentsAsBlobOrBuffer$1(res) {\n res.rows.forEach(function (row) {\n var atts = row.doc && row.doc._attachments;\n if (!atts) {\n return;\n }\n Object.keys(atts).forEach(function (filename) {\n var att = atts[filename];\n atts[filename].data = b64ToBluffer(att.data, att.content_type);\n });\n });\n}\n\nfunction postprocessAttachments(opts) {\n return function (res) {\n if (opts.include_docs && opts.attachments && opts.binary) {\n readAttachmentsAsBlobOrBuffer$1(res);\n }\n return res;\n };\n}\n\nvar builtInReduce = {\n _sum: function (keys, values) {\n return sum(values);\n },\n\n _count: function (keys, values) {\n return values.length;\n },\n\n _stats: function (keys, values) {\n // no need to implement rereduce=true, because Pouch\n // will never call it\n function sumsqr(values) {\n var _sumsqr = 0;\n for (var i = 0, len = values.length; i < len; i++) {\n var num = values[i];\n _sumsqr += (num * num);\n }\n return _sumsqr;\n }\n return {\n sum : sum(values),\n min : Math.min.apply(null, values),\n max : Math.max.apply(null, values),\n count : values.length,\n sumsqr : sumsqr(values)\n };\n }\n};\n\nfunction addHttpParam(paramName, opts, params, asJson) {\n // add an http param from opts to params, optionally json-encoded\n var val = opts[paramName];\n if (typeof val !== 'undefined') {\n if (asJson) {\n val = encodeURIComponent(JSON.stringify(val));\n }\n params.push(paramName + '=' + val);\n }\n}\n\nfunction coerceInteger(integerCandidate) {\n if (typeof integerCandidate !== 'undefined') {\n var asNumber = Number(integerCandidate);\n // prevents e.g. '1foo' or '1.1' being coerced to 1\n if (!isNaN(asNumber) && asNumber === parseInt(integerCandidate, 10)) {\n return asNumber;\n } else {\n return integerCandidate;\n }\n }\n}\n\nfunction coerceOptions(opts) {\n opts.group_level = coerceInteger(opts.group_level);\n opts.limit = coerceInteger(opts.limit);\n opts.skip = coerceInteger(opts.skip);\n return opts;\n}\n\nfunction checkPositiveInteger(number) {\n if (number) {\n if (typeof number !== 'number') {\n return new QueryParseError('Invalid value for integer: \"' +\n number + '\"');\n }\n if (number < 0) {\n return new QueryParseError('Invalid value for positive integer: ' +\n '\"' + number + '\"');\n }\n }\n}\n\nfunction checkQueryParseError(options, fun) {\n var startkeyName = options.descending ? 'endkey' : 'startkey';\n var endkeyName = options.descending ? 'startkey' : 'endkey';\n\n if (typeof options[startkeyName] !== 'undefined' &&\n typeof options[endkeyName] !== 'undefined' &&\n collate(options[startkeyName], options[endkeyName]) > 0) {\n throw new QueryParseError('No rows can match your key range, ' +\n 'reverse your start_key and end_key or set {descending : true}');\n } else if (fun.reduce && options.reduce !== false) {\n if (options.include_docs) {\n throw new QueryParseError('{include_docs:true} is invalid for reduce');\n } else if (options.keys && options.keys.length > 1 &&\n !options.group && !options.group_level) {\n throw new QueryParseError('Multi-key fetches for reduce views must use ' +\n '{group: true}');\n }\n }\n ['group_level', 'limit', 'skip'].forEach(function (optionName) {\n var error = checkPositiveInteger(options[optionName]);\n if (error) {\n throw error;\n }\n });\n}\n\nfunction httpQuery(db, fun, opts) {\n // List of parameters to add to the PUT request\n var params = [];\n var body;\n var method = 'GET';\n\n // If opts.reduce exists and is defined, then add it to the list\n // of parameters.\n // If reduce=false then the results are that of only the map function\n // not the final result of map and reduce.\n addHttpParam('reduce', opts, params);\n addHttpParam('include_docs', opts, params);\n addHttpParam('attachments', opts, params);\n addHttpParam('limit', opts, params);\n addHttpParam('descending', opts, params);\n addHttpParam('group', opts, params);\n addHttpParam('group_level', opts, params);\n addHttpParam('skip', opts, params);\n addHttpParam('stale', opts, params);\n addHttpParam('conflicts', opts, params);\n addHttpParam('startkey', opts, params, true);\n addHttpParam('start_key', opts, params, true);\n addHttpParam('endkey', opts, params, true);\n addHttpParam('end_key', opts, params, true);\n addHttpParam('inclusive_end', opts, params);\n addHttpParam('key', opts, params, true);\n\n // Format the list of parameters into a valid URI query string\n params = params.join('&');\n params = params === '' ? '' : '?' + params;\n\n // If keys are supplied, issue a POST to circumvent GET query string limits\n // see http://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options\n if (typeof opts.keys !== 'undefined') {\n var MAX_URL_LENGTH = 2000;\n // according to http://stackoverflow.com/a/417184/680742,\n // the de facto URL length limit is 2000 characters\n\n var keysAsString =\n 'keys=' + encodeURIComponent(JSON.stringify(opts.keys));\n if (keysAsString.length + params.length + 1 <= MAX_URL_LENGTH) {\n // If the keys are short enough, do a GET. we do this to work around\n // Safari not understanding 304s on POSTs (see pouchdb/pouchdb#1239)\n params += (params[0] === '?' ? '&' : '?') + keysAsString;\n } else {\n method = 'POST';\n if (typeof fun === 'string') {\n body = {keys: opts.keys};\n } else { // fun is {map : mapfun}, so append to this\n fun.keys = opts.keys;\n }\n }\n }\n\n // We are referencing a query defined in the design doc\n if (typeof fun === 'string') {\n var parts = parseViewName(fun);\n return db.request({\n method: method,\n url: '_design/' + parts[0] + '/_view/' + parts[1] + params,\n body: body\n }).then(postprocessAttachments(opts));\n }\n\n // We are using a temporary view, terrible for performance, good for testing\n body = body || {};\n Object.keys(fun).forEach(function (key) {\n if (Array.isArray(fun[key])) {\n body[key] = fun[key];\n } else {\n body[key] = fun[key].toString();\n }\n });\n return db.request({\n method: 'POST',\n url: '_temp_view' + params,\n body: body\n }).then(postprocessAttachments(opts));\n}\n\n// custom adapters can define their own api._query\n// and override the default behavior\n/* istanbul ignore next */\nfunction customQuery(db, fun, opts) {\n return new PouchPromise(function (resolve, reject) {\n db._query(fun, opts, function (err, res) {\n if (err) {\n return reject(err);\n }\n resolve(res);\n });\n });\n}\n\n// custom adapters can define their own api._viewCleanup\n// and override the default behavior\n/* istanbul ignore next */\nfunction customViewCleanup(db) {\n return new PouchPromise(function (resolve, reject) {\n db._viewCleanup(function (err, res) {\n if (err) {\n return reject(err);\n }\n resolve(res);\n });\n });\n}\n\nfunction defaultsTo(value) {\n return function (reason) {\n /* istanbul ignore else */\n if (reason.status === 404) {\n return value;\n } else {\n throw reason;\n }\n };\n}\n\n// returns a promise for a list of docs to update, based on the input docId.\n// the order doesn't matter, because post-3.2.0, bulkDocs\n// is an atomic operation in all three adapters.\nfunction getDocsToPersist(docId, view, docIdsToChangesAndEmits) {\n var metaDocId = '_local/doc_' + docId;\n var defaultMetaDoc = {_id: metaDocId, keys: []};\n var docData = docIdsToChangesAndEmits[docId];\n var indexableKeysToKeyValues = docData.indexableKeysToKeyValues;\n var changes = docData.changes;\n\n function getMetaDoc() {\n if (isGenOne(changes)) {\n // generation 1, so we can safely assume initial state\n // for performance reasons (avoids unnecessary GETs)\n return PouchPromise.resolve(defaultMetaDoc);\n }\n return view.db.get(metaDocId).catch(defaultsTo(defaultMetaDoc));\n }\n\n function getKeyValueDocs(metaDoc) {\n if (!metaDoc.keys.length) {\n // no keys, no need for a lookup\n return PouchPromise.resolve({rows: []});\n }\n return view.db.allDocs({\n keys: metaDoc.keys,\n include_docs: true\n });\n }\n\n function processKvDocs(metaDoc, kvDocsRes) {\n var kvDocs = [];\n var oldKeysMap = {};\n\n for (var i = 0, len = kvDocsRes.rows.length; i < len; i++) {\n var row = kvDocsRes.rows[i];\n var doc = row.doc;\n if (!doc) { // deleted\n continue;\n }\n kvDocs.push(doc);\n oldKeysMap[doc._id] = true;\n doc._deleted = !indexableKeysToKeyValues[doc._id];\n if (!doc._deleted) {\n var keyValue = indexableKeysToKeyValues[doc._id];\n if ('value' in keyValue) {\n doc.value = keyValue.value;\n }\n }\n }\n\n var newKeys = Object.keys(indexableKeysToKeyValues);\n newKeys.forEach(function (key) {\n if (!oldKeysMap[key]) {\n // new doc\n var kvDoc = {\n _id: key\n };\n var keyValue = indexableKeysToKeyValues[key];\n if ('value' in keyValue) {\n kvDoc.value = keyValue.value;\n }\n kvDocs.push(kvDoc);\n }\n });\n metaDoc.keys = uniq(newKeys.concat(metaDoc.keys));\n kvDocs.push(metaDoc);\n\n return kvDocs;\n }\n\n return getMetaDoc().then(function (metaDoc) {\n return getKeyValueDocs(metaDoc).then(function (kvDocsRes) {\n return processKvDocs(metaDoc, kvDocsRes);\n });\n });\n}\n\n// updates all emitted key/value docs and metaDocs in the mrview database\n// for the given batch of documents from the source database\nfunction saveKeyValues(view, docIdsToChangesAndEmits, seq) {\n var seqDocId = '_local/lastSeq';\n return view.db.get(seqDocId)\n .catch(defaultsTo({_id: seqDocId, seq: 0}))\n .then(function (lastSeqDoc) {\n var docIds = Object.keys(docIdsToChangesAndEmits);\n return PouchPromise.all(docIds.map(function (docId) {\n return getDocsToPersist(docId, view, docIdsToChangesAndEmits);\n })).then(function (listOfDocsToPersist) {\n var docsToPersist = flatten(listOfDocsToPersist);\n lastSeqDoc.seq = seq;\n docsToPersist.push(lastSeqDoc);\n // write all docs in a single operation, update the seq once\n return view.db.bulkDocs({docs : docsToPersist});\n });\n });\n}\n\nfunction getQueue(view) {\n var viewName = typeof view === 'string' ? view : view.name;\n var queue = persistentQueues[viewName];\n if (!queue) {\n queue = persistentQueues[viewName] = new TaskQueue$1();\n }\n return queue;\n}\n\nfunction updateView(view) {\n return sequentialize(getQueue(view), function () {\n return updateViewInQueue(view);\n })();\n}\n\nfunction updateViewInQueue(view) {\n // bind the emit function once\n var mapResults;\n var doc;\n\n function emit(key, value) {\n var output = {id: doc._id, key: normalizeKey(key)};\n // Don't explicitly store the value unless it's defined and non-null.\n // This saves on storage space, because often people don't use it.\n if (typeof value !== 'undefined' && value !== null) {\n output.value = normalizeKey(value);\n }\n mapResults.push(output);\n }\n\n var mapFun;\n // for temp_views one can use emit(doc, emit), see #38\n if (typeof view.mapFun === \"function\" && view.mapFun.length === 2) {\n var origMap = view.mapFun;\n mapFun = function (doc) {\n return origMap(doc, emit);\n };\n } else {\n mapFun = evalFunctionWithEval(view.mapFun.toString(), emit);\n }\n\n var currentSeq = view.seq || 0;\n\n function processChange(docIdsToChangesAndEmits, seq) {\n return function () {\n return saveKeyValues(view, docIdsToChangesAndEmits, seq);\n };\n }\n\n var queue = new TaskQueue$1();\n // TODO(neojski): https://github.com/daleharvey/pouchdb/issues/1521\n\n return new PouchPromise(function (resolve, reject) {\n\n function complete() {\n queue.finish().then(function () {\n view.seq = currentSeq;\n resolve();\n });\n }\n\n function processNextBatch() {\n view.sourceDB.changes({\n conflicts: true,\n include_docs: true,\n style: 'all_docs',\n since: currentSeq,\n limit: CHANGES_BATCH_SIZE$1\n }).on('complete', function (response) {\n var results = response.results;\n if (!results.length) {\n return complete();\n }\n var docIdsToChangesAndEmits = {};\n for (var i = 0, l = results.length; i < l; i++) {\n var change = results[i];\n if (change.doc._id[0] !== '_') {\n mapResults = [];\n doc = change.doc;\n\n if (!doc._deleted) {\n tryCode$1(view.sourceDB, mapFun, [doc]);\n }\n mapResults.sort(sortByKeyThenValue);\n\n var indexableKeysToKeyValues = {};\n var lastKey;\n for (var j = 0, jl = mapResults.length; j < jl; j++) {\n var obj = mapResults[j];\n var complexKey = [obj.key, obj.id];\n if (collate(obj.key, lastKey) === 0) {\n complexKey.push(j); // dup key+id, so make it unique\n }\n var indexableKey = toIndexableString(complexKey);\n indexableKeysToKeyValues[indexableKey] = obj;\n lastKey = obj.key;\n }\n docIdsToChangesAndEmits[change.doc._id] = {\n indexableKeysToKeyValues: indexableKeysToKeyValues,\n changes: change.changes\n };\n }\n currentSeq = change.seq;\n }\n queue.add(processChange(docIdsToChangesAndEmits, currentSeq));\n if (results.length < CHANGES_BATCH_SIZE$1) {\n return complete();\n }\n return processNextBatch();\n }).on('error', onError);\n /* istanbul ignore next */\n function onError(err) {\n reject(err);\n }\n }\n\n processNextBatch();\n });\n}\n\nfunction reduceView(view, results, options) {\n if (options.group_level === 0) {\n delete options.group_level;\n }\n\n var shouldGroup = options.group || options.group_level;\n\n var reduceFun;\n if (builtInReduce[view.reduceFun]) {\n reduceFun = builtInReduce[view.reduceFun];\n } else {\n reduceFun = evalFunctionWithEval(view.reduceFun.toString());\n }\n\n var groups = [];\n var lvl = isNaN(options.group_level) ? Number.POSITIVE_INFINITY :\n options.group_level;\n results.forEach(function (e) {\n var last = groups[groups.length - 1];\n var groupKey = shouldGroup ? e.key : null;\n\n // only set group_level for array keys\n if (shouldGroup && Array.isArray(groupKey)) {\n groupKey = groupKey.slice(0, lvl);\n }\n\n if (last && collate(last.groupKey, groupKey) === 0) {\n last.keys.push([e.key, e.id]);\n last.values.push(e.value);\n return;\n }\n groups.push({\n keys: [[e.key, e.id]],\n values: [e.value],\n groupKey: groupKey\n });\n });\n results = [];\n for (var i = 0, len = groups.length; i < len; i++) {\n var e = groups[i];\n var reduceTry = tryCode$1(view.sourceDB, reduceFun,\n [e.keys, e.values, false]);\n if (reduceTry.error && reduceTry.error instanceof BuiltInError) {\n // CouchDB returns an error if a built-in errors out\n throw reduceTry.error;\n }\n results.push({\n // CouchDB just sets the value to null if a non-built-in errors out\n value: reduceTry.error ? null : reduceTry.output,\n key: e.groupKey\n });\n }\n // no total_rows/offset when reducing\n return {rows: sliceResults(results, options.limit, options.skip)};\n}\n\nfunction queryView(view, opts) {\n return sequentialize(getQueue(view), function () {\n return queryViewInQueue(view, opts);\n })();\n}\n\nfunction queryViewInQueue(view, opts) {\n var totalRows;\n var shouldReduce = view.reduceFun && opts.reduce !== false;\n var skip = opts.skip || 0;\n if (typeof opts.keys !== 'undefined' && !opts.keys.length) {\n // equivalent query\n opts.limit = 0;\n delete opts.keys;\n }\n\n function fetchFromView(viewOpts) {\n viewOpts.include_docs = true;\n return view.db.allDocs(viewOpts).then(function (res) {\n totalRows = res.total_rows;\n return res.rows.map(function (result) {\n\n // implicit migration - in older versions of PouchDB,\n // we explicitly stored the doc as {id: ..., key: ..., value: ...}\n // this is tested in a migration test\n /* istanbul ignore next */\n if ('value' in result.doc && typeof result.doc.value === 'object' &&\n result.doc.value !== null) {\n var keys = Object.keys(result.doc.value).sort();\n // this detection method is not perfect, but it's unlikely the user\n // emitted a value which was an object with these 3 exact keys\n var expectedKeys = ['id', 'key', 'value'];\n if (!(keys < expectedKeys || keys > expectedKeys)) {\n return result.doc.value;\n }\n }\n\n var parsedKeyAndDocId = parseIndexableString(result.doc._id);\n return {\n key: parsedKeyAndDocId[0],\n id: parsedKeyAndDocId[1],\n value: ('value' in result.doc ? result.doc.value : null)\n };\n });\n });\n }\n\n function onMapResultsReady(rows) {\n var finalResults;\n if (shouldReduce) {\n finalResults = reduceView(view, rows, opts);\n } else {\n finalResults = {\n total_rows: totalRows,\n offset: skip,\n rows: rows\n };\n }\n if (opts.include_docs) {\n var docIds = uniq(rows.map(rowToDocId));\n\n return view.sourceDB.allDocs({\n keys: docIds,\n include_docs: true,\n conflicts: opts.conflicts,\n attachments: opts.attachments,\n binary: opts.binary\n }).then(function (allDocsRes) {\n var docIdsToDocs = {};\n allDocsRes.rows.forEach(function (row) {\n if (row.doc) {\n docIdsToDocs['$' + row.id] = row.doc;\n }\n });\n rows.forEach(function (row) {\n var docId = rowToDocId(row);\n var doc = docIdsToDocs['$' + docId];\n if (doc) {\n row.doc = doc;\n }\n });\n return finalResults;\n });\n } else {\n return finalResults;\n }\n }\n\n if (typeof opts.keys !== 'undefined') {\n var keys = opts.keys;\n var fetchPromises = keys.map(function (key) {\n var viewOpts = {\n startkey : toIndexableString([key]),\n endkey : toIndexableString([key, {}])\n };\n return fetchFromView(viewOpts);\n });\n return PouchPromise.all(fetchPromises).then(flatten).then(onMapResultsReady);\n } else { // normal query, no 'keys'\n var viewOpts = {\n descending : opts.descending\n };\n if (opts.start_key) {\n opts.startkey = opts.start_key;\n }\n if (opts.end_key) {\n opts.endkey = opts.end_key;\n }\n if (typeof opts.startkey !== 'undefined') {\n viewOpts.startkey = opts.descending ?\n toIndexableString([opts.startkey, {}]) :\n toIndexableString([opts.startkey]);\n }\n if (typeof opts.endkey !== 'undefined') {\n var inclusiveEnd = opts.inclusive_end !== false;\n if (opts.descending) {\n inclusiveEnd = !inclusiveEnd;\n }\n\n viewOpts.endkey = toIndexableString(\n inclusiveEnd ? [opts.endkey, {}] : [opts.endkey]);\n }\n if (typeof opts.key !== 'undefined') {\n var keyStart = toIndexableString([opts.key]);\n var keyEnd = toIndexableString([opts.key, {}]);\n if (viewOpts.descending) {\n viewOpts.endkey = keyStart;\n viewOpts.startkey = keyEnd;\n } else {\n viewOpts.startkey = keyStart;\n viewOpts.endkey = keyEnd;\n }\n }\n if (!shouldReduce) {\n if (typeof opts.limit === 'number') {\n viewOpts.limit = opts.limit;\n }\n viewOpts.skip = skip;\n }\n return fetchFromView(viewOpts).then(onMapResultsReady);\n }\n}\n\nfunction httpViewCleanup(db) {\n return db.request({\n method: 'POST',\n url: '_view_cleanup'\n });\n}\n\nfunction localViewCleanup(db) {\n return db.get('_local/mrviews').then(function (metaDoc) {\n var docsToViews = {};\n Object.keys(metaDoc.views).forEach(function (fullViewName) {\n var parts = parseViewName(fullViewName);\n var designDocName = '_design/' + parts[0];\n var viewName = parts[1];\n docsToViews[designDocName] = docsToViews[designDocName] || {};\n docsToViews[designDocName][viewName] = true;\n });\n var opts = {\n keys : Object.keys(docsToViews),\n include_docs : true\n };\n return db.allDocs(opts).then(function (res) {\n var viewsToStatus = {};\n res.rows.forEach(function (row) {\n var ddocName = row.key.substring(8);\n Object.keys(docsToViews[row.key]).forEach(function (viewName) {\n var fullViewName = ddocName + '/' + viewName;\n /* istanbul ignore if */\n if (!metaDoc.views[fullViewName]) {\n // new format, without slashes, to support PouchDB 2.2.0\n // migration test in pouchdb's browser.migration.js verifies this\n fullViewName = viewName;\n }\n var viewDBNames = Object.keys(metaDoc.views[fullViewName]);\n // design doc deleted, or view function nonexistent\n var statusIsGood = row.doc && row.doc.views &&\n row.doc.views[viewName];\n viewDBNames.forEach(function (viewDBName) {\n viewsToStatus[viewDBName] =\n viewsToStatus[viewDBName] || statusIsGood;\n });\n });\n });\n var dbsToDelete = Object.keys(viewsToStatus).filter(\n function (viewDBName) { return !viewsToStatus[viewDBName]; });\n var destroyPromises = dbsToDelete.map(function (viewDBName) {\n return sequentialize(getQueue(viewDBName), function () {\n return new db.constructor(viewDBName, db.__opts).destroy();\n })();\n });\n return PouchPromise.all(destroyPromises).then(function () {\n return {ok: true};\n });\n });\n }, defaultsTo({ok: true}));\n}\n\nvar viewCleanup = callbackify(function () {\n var db = this;\n if (db.type() === 'http') {\n return httpViewCleanup(db);\n }\n /* istanbul ignore next */\n if (typeof db._viewCleanup === 'function') {\n return customViewCleanup(db);\n }\n return localViewCleanup(db);\n});\n\nfunction queryPromised(db, fun, opts) {\n if (db.type() === 'http') {\n return httpQuery(db, fun, opts);\n }\n\n /* istanbul ignore next */\n if (typeof db._query === 'function') {\n return customQuery(db, fun, opts);\n }\n\n if (typeof fun !== 'string') {\n // temp_view\n checkQueryParseError(opts, fun);\n\n var createViewOpts = {\n db : db,\n viewName : 'temp_view/temp_view',\n map : fun.map,\n reduce : fun.reduce,\n temporary : true\n };\n tempViewQueue.add(function () {\n return createView(createViewOpts).then(function (view) {\n function cleanup() {\n return view.db.destroy();\n }\n return fin(updateView(view).then(function () {\n return queryView(view, opts);\n }), cleanup);\n });\n });\n return tempViewQueue.finish();\n } else {\n // persistent view\n var fullViewName = fun;\n var parts = parseViewName(fullViewName);\n var designDocName = parts[0];\n var viewName = parts[1];\n return db.get('_design/' + designDocName).then(function (doc) {\n var fun = doc.views && doc.views[viewName];\n\n if (!fun || typeof fun.map !== 'string') {\n throw new NotFoundError('ddoc ' + designDocName +\n ' has no view named ' + viewName);\n }\n checkQueryParseError(opts, fun);\n\n var createViewOpts = {\n db : db,\n viewName : fullViewName,\n map : fun.map,\n reduce : fun.reduce\n };\n return createView(createViewOpts).then(function (view) {\n if (opts.stale === 'ok' || opts.stale === 'update_after') {\n if (opts.stale === 'update_after') {\n immediate(function () {\n updateView(view);\n });\n }\n return queryView(view, opts);\n } else { // stale not ok\n return updateView(view).then(function () {\n return queryView(view, opts);\n });\n }\n });\n });\n }\n}\n\nvar query = function (fun, opts, callback) {\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n opts = opts ? coerceOptions(opts) : {};\n\n if (typeof fun === 'function') {\n fun = {map : fun};\n }\n\n var db = this;\n var promise = PouchPromise.resolve().then(function () {\n return queryPromised(db, fun, opts);\n });\n promisedCallback(promise, callback);\n return promise;\n};\n\n\nvar mapreduce = {\n query: query,\n viewCleanup: viewCleanup\n};\n\nfunction isGenOne$1(rev) {\n return /^1-/.test(rev);\n}\n\nfunction fileHasChanged(localDoc, remoteDoc, filename) {\n return !localDoc._attachments ||\n !localDoc._attachments[filename] ||\n localDoc._attachments[filename].digest !== remoteDoc._attachments[filename].digest;\n}\n\nfunction getDocAttachments(db, doc) {\n var filenames = Object.keys(doc._attachments);\n return PouchPromise.all(filenames.map(function (filename) {\n return db.getAttachment(doc._id, filename, {rev: doc._rev});\n }));\n}\n\nfunction getDocAttachmentsFromTargetOrSource(target, src, doc) {\n var doCheckForLocalAttachments = src.type() === 'http' && target.type() !== 'http';\n var filenames = Object.keys(doc._attachments);\n\n if (!doCheckForLocalAttachments) {\n return getDocAttachments(src, doc);\n }\n\n return target.get(doc._id).then(function (localDoc) {\n return PouchPromise.all(filenames.map(function (filename) {\n if (fileHasChanged(localDoc, doc, filename)) {\n return src.getAttachment(doc._id, filename);\n }\n\n return target.getAttachment(localDoc._id, filename);\n }));\n }).catch(function (error) {\n /* istanbul ignore if */\n if (error.status !== 404) {\n throw error;\n }\n\n return getDocAttachments(src, doc);\n });\n}\n\nfunction createBulkGetOpts(diffs) {\n var requests = [];\n Object.keys(diffs).forEach(function (id) {\n var missingRevs = diffs[id].missing;\n missingRevs.forEach(function (missingRev) {\n requests.push({\n id: id,\n rev: missingRev\n });\n });\n });\n\n return {\n docs: requests,\n revs: true,\n latest: true\n };\n}\n\n//\n// Fetch all the documents from the src as described in the \"diffs\",\n// which is a mapping of docs IDs to revisions. If the state ever\n// changes to \"cancelled\", then the returned promise will be rejected.\n// Else it will be resolved with a list of fetched documents.\n//\nfunction getDocs(src, target, diffs, state) {\n diffs = clone(diffs); // we do not need to modify this\n\n var resultDocs = [],\n ok = true;\n\n function getAllDocs() {\n\n var bulkGetOpts = createBulkGetOpts(diffs);\n\n if (!bulkGetOpts.docs.length) { // optimization: skip empty requests\n return;\n }\n\n return src.bulkGet(bulkGetOpts).then(function (bulkGetResponse) {\n /* istanbul ignore if */\n if (state.cancelled) {\n throw new Error('cancelled');\n }\n return PouchPromise.all(bulkGetResponse.results.map(function (bulkGetInfo) {\n return PouchPromise.all(bulkGetInfo.docs.map(function (doc) {\n var remoteDoc = doc.ok;\n\n if (doc.error) {\n // when AUTO_COMPACTION is set, docs can be returned which look\n // like this: {\"missing\":\"1-7c3ac256b693c462af8442f992b83696\"}\n ok = false;\n }\n\n if (!remoteDoc || !remoteDoc._attachments) {\n return remoteDoc;\n }\n\n return getDocAttachmentsFromTargetOrSource(target, src, remoteDoc).then(function (attachments) {\n var filenames = Object.keys(remoteDoc._attachments);\n attachments.forEach(function (attachment, i) {\n var att = remoteDoc._attachments[filenames[i]];\n delete att.stub;\n delete att.length;\n att.data = attachment;\n });\n\n return remoteDoc;\n });\n }));\n }))\n\n .then(function (results) {\n resultDocs = resultDocs.concat(flatten(results).filter(Boolean));\n });\n });\n }\n\n function hasAttachments(doc) {\n return doc._attachments && Object.keys(doc._attachments).length > 0;\n }\n\n function hasConflicts(doc) {\n return doc._conflicts && doc._conflicts.length > 0;\n }\n\n function fetchRevisionOneDocs(ids) {\n // Optimization: fetch gen-1 docs and attachments in\n // a single request using _all_docs\n return src.allDocs({\n keys: ids,\n include_docs: true,\n conflicts: true\n }).then(function (res) {\n if (state.cancelled) {\n throw new Error('cancelled');\n }\n res.rows.forEach(function (row) {\n if (row.deleted || !row.doc || !isGenOne$1(row.value.rev) ||\n hasAttachments(row.doc) || hasConflicts(row.doc)) {\n // if any of these conditions apply, we need to fetch using get()\n return;\n }\n\n // strip _conflicts array to appease CSG (#5793)\n /* istanbul ignore if */\n if (row.doc._conflicts) {\n delete row.doc._conflicts;\n }\n\n // the doc we got back from allDocs() is sufficient\n resultDocs.push(row.doc);\n delete diffs[row.id];\n });\n });\n }\n\n function getRevisionOneDocs() {\n // filter out the generation 1 docs and get them\n // leaving the non-generation one docs to be got otherwise\n var ids = Object.keys(diffs).filter(function (id) {\n var missing = diffs[id].missing;\n return missing.length === 1 && isGenOne$1(missing[0]);\n });\n if (ids.length > 0) {\n return fetchRevisionOneDocs(ids);\n }\n }\n\n function returnResult() {\n return { ok:ok, docs:resultDocs };\n }\n\n return PouchPromise.resolve()\n .then(getRevisionOneDocs)\n .then(getAllDocs)\n .then(returnResult);\n}\n\nvar CHECKPOINT_VERSION = 1;\nvar REPLICATOR = \"pouchdb\";\n// This is an arbitrary number to limit the\n// amount of replication history we save in the checkpoint.\n// If we save too much, the checkpoing docs will become very big,\n// if we save fewer, we'll run a greater risk of having to\n// read all the changes from 0 when checkpoint PUTs fail\n// CouchDB 2.0 has a more involved history pruning,\n// but let's go for the simple version for now.\nvar CHECKPOINT_HISTORY_SIZE = 5;\nvar LOWEST_SEQ = 0;\n\nfunction updateCheckpoint(db, id, checkpoint, session, returnValue) {\n return db.get(id).catch(function (err) {\n if (err.status === 404) {\n if (db.type() === 'http') {\n explainError(\n 404, 'PouchDB is just checking if a remote checkpoint exists.'\n );\n }\n return {\n session_id: session,\n _id: id,\n history: [],\n replicator: REPLICATOR,\n version: CHECKPOINT_VERSION\n };\n }\n throw err;\n }).then(function (doc) {\n if (returnValue.cancelled) {\n return;\n }\n\n // if the checkpoint has not changed, do not update\n if (doc.last_seq === checkpoint) {\n return;\n }\n\n // Filter out current entry for this replication\n doc.history = (doc.history || []).filter(function (item) {\n return item.session_id !== session;\n });\n\n // Add the latest checkpoint to history\n doc.history.unshift({\n last_seq: checkpoint,\n session_id: session\n });\n\n // Just take the last pieces in history, to\n // avoid really big checkpoint docs.\n // see comment on history size above\n doc.history = doc.history.slice(0, CHECKPOINT_HISTORY_SIZE);\n\n doc.version = CHECKPOINT_VERSION;\n doc.replicator = REPLICATOR;\n\n doc.session_id = session;\n doc.last_seq = checkpoint;\n\n return db.put(doc).catch(function (err) {\n if (err.status === 409) {\n // retry; someone is trying to write a checkpoint simultaneously\n return updateCheckpoint(db, id, checkpoint, session, returnValue);\n }\n throw err;\n });\n });\n}\n\nfunction Checkpointer(src, target, id, returnValue) {\n this.src = src;\n this.target = target;\n this.id = id;\n this.returnValue = returnValue;\n}\n\nCheckpointer.prototype.writeCheckpoint = function (checkpoint, session) {\n var self = this;\n return this.updateTarget(checkpoint, session).then(function () {\n return self.updateSource(checkpoint, session);\n });\n};\n\nCheckpointer.prototype.updateTarget = function (checkpoint, session) {\n return updateCheckpoint(this.target, this.id, checkpoint,\n session, this.returnValue);\n};\n\nCheckpointer.prototype.updateSource = function (checkpoint, session) {\n var self = this;\n if (this.readOnlySource) {\n return PouchPromise.resolve(true);\n }\n return updateCheckpoint(this.src, this.id, checkpoint,\n session, this.returnValue)\n .catch(function (err) {\n if (isForbiddenError(err)) {\n self.readOnlySource = true;\n return true;\n }\n throw err;\n });\n};\n\nvar comparisons = {\n \"undefined\": function (targetDoc, sourceDoc) {\n // This is the previous comparison function\n if (collate(targetDoc.last_seq, sourceDoc.last_seq) === 0) {\n return sourceDoc.last_seq;\n }\n /* istanbul ignore next */\n return 0;\n },\n \"1\": function (targetDoc, sourceDoc) {\n // This is the comparison function ported from CouchDB\n return compareReplicationLogs(sourceDoc, targetDoc).last_seq;\n }\n};\n\nCheckpointer.prototype.getCheckpoint = function () {\n var self = this;\n return self.target.get(self.id).then(function (targetDoc) {\n if (self.readOnlySource) {\n return PouchPromise.resolve(targetDoc.last_seq);\n }\n\n return self.src.get(self.id).then(function (sourceDoc) {\n // Since we can't migrate an old version doc to a new one\n // (no session id), we just go with the lowest seq in this case\n /* istanbul ignore if */\n if (targetDoc.version !== sourceDoc.version) {\n return LOWEST_SEQ;\n }\n\n var version;\n if (targetDoc.version) {\n version = targetDoc.version.toString();\n } else {\n version = \"undefined\";\n }\n\n if (version in comparisons) {\n return comparisons[version](targetDoc, sourceDoc);\n }\n /* istanbul ignore next */\n return LOWEST_SEQ;\n }, function (err) {\n if (err.status === 404 && targetDoc.last_seq) {\n return self.src.put({\n _id: self.id,\n last_seq: LOWEST_SEQ\n }).then(function () {\n return LOWEST_SEQ;\n }, function (err) {\n if (isForbiddenError(err)) {\n self.readOnlySource = true;\n return targetDoc.last_seq;\n }\n /* istanbul ignore next */\n return LOWEST_SEQ;\n });\n }\n throw err;\n });\n }).catch(function (err) {\n if (err.status !== 404) {\n throw err;\n }\n return LOWEST_SEQ;\n });\n};\n// This checkpoint comparison is ported from CouchDBs source\n// they come from here:\n// https://github.com/apache/couchdb-couch-replicator/blob/master/src/couch_replicator.erl#L863-L906\n\nfunction compareReplicationLogs(srcDoc, tgtDoc) {\n if (srcDoc.session_id === tgtDoc.session_id) {\n return {\n last_seq: srcDoc.last_seq,\n history: srcDoc.history\n };\n }\n\n return compareReplicationHistory(srcDoc.history, tgtDoc.history);\n}\n\nfunction compareReplicationHistory(sourceHistory, targetHistory) {\n // the erlang loop via function arguments is not so easy to repeat in JS\n // therefore, doing this as recursion\n var S = sourceHistory[0];\n var sourceRest = sourceHistory.slice(1);\n var T = targetHistory[0];\n var targetRest = targetHistory.slice(1);\n\n if (!S || targetHistory.length === 0) {\n return {\n last_seq: LOWEST_SEQ,\n history: []\n };\n }\n\n var sourceId = S.session_id;\n /* istanbul ignore if */\n if (hasSessionId(sourceId, targetHistory)) {\n return {\n last_seq: S.last_seq,\n history: sourceHistory\n };\n }\n\n var targetId = T.session_id;\n if (hasSessionId(targetId, sourceRest)) {\n return {\n last_seq: T.last_seq,\n history: targetRest\n };\n }\n\n return compareReplicationHistory(sourceRest, targetRest);\n}\n\nfunction hasSessionId(sessionId, history) {\n var props = history[0];\n var rest = history.slice(1);\n\n if (!sessionId || history.length === 0) {\n return false;\n }\n\n if (sessionId === props.session_id) {\n return true;\n }\n\n return hasSessionId(sessionId, rest);\n}\n\nfunction isForbiddenError(err) {\n return typeof err.status === 'number' && Math.floor(err.status / 100) === 4;\n}\n\nvar STARTING_BACK_OFF = 0;\n\nfunction backOff(opts, returnValue, error, callback) {\n if (opts.retry === false) {\n returnValue.emit('error', error);\n returnValue.removeAllListeners();\n return;\n }\n if (typeof opts.back_off_function !== 'function') {\n opts.back_off_function = defaultBackOff;\n }\n returnValue.emit('requestError', error);\n if (returnValue.state === 'active' || returnValue.state === 'pending') {\n returnValue.emit('paused', error);\n returnValue.state = 'stopped';\n var backOffSet = function backoffTimeSet() {\n opts.current_back_off = STARTING_BACK_OFF;\n };\n var removeBackOffSetter = function removeBackOffTimeSet() {\n returnValue.removeListener('active', backOffSet);\n };\n returnValue.once('paused', removeBackOffSetter);\n returnValue.once('active', backOffSet);\n }\n\n opts.current_back_off = opts.current_back_off || STARTING_BACK_OFF;\n opts.current_back_off = opts.back_off_function(opts.current_back_off);\n setTimeout(callback, opts.current_back_off);\n}\n\nfunction sortObjectPropertiesByKey(queryParams) {\n return Object.keys(queryParams).sort(collate).reduce(function (result, key) {\n result[key] = queryParams[key];\n return result;\n }, {});\n}\n\n// Generate a unique id particular to this replication.\n// Not guaranteed to align perfectly with CouchDB's rep ids.\nfunction generateReplicationId(src, target, opts) {\n var docIds = opts.doc_ids ? opts.doc_ids.sort(collate) : '';\n var filterFun = opts.filter ? opts.filter.toString() : '';\n var queryParams = '';\n var filterViewName = '';\n\n if (opts.filter && opts.query_params) {\n queryParams = JSON.stringify(sortObjectPropertiesByKey(opts.query_params));\n }\n\n if (opts.filter && opts.filter === '_view') {\n filterViewName = opts.view.toString();\n }\n\n return PouchPromise.all([src.id(), target.id()]).then(function (res) {\n var queryData = res[0] + res[1] + filterFun + filterViewName +\n queryParams + docIds;\n return new PouchPromise(function (resolve) {\n binaryMd5(queryData, resolve);\n });\n }).then(function (md5sum) {\n // can't use straight-up md5 alphabet, because\n // the char '/' is interpreted as being for attachments,\n // and + is also not url-safe\n md5sum = md5sum.replace(/\\//g, '.').replace(/\\+/g, '_');\n return '_local/' + md5sum;\n });\n}\n\nfunction replicate$1(src, target, opts, returnValue, result) {\n var batches = []; // list of batches to be processed\n var currentBatch; // the batch currently being processed\n var pendingBatch = {\n seq: 0,\n changes: [],\n docs: []\n }; // next batch, not yet ready to be processed\n var writingCheckpoint = false; // true while checkpoint is being written\n var changesCompleted = false; // true when all changes received\n var replicationCompleted = false; // true when replication has completed\n var last_seq = 0;\n var continuous = opts.continuous || opts.live || false;\n var batch_size = opts.batch_size || 100;\n var batches_limit = opts.batches_limit || 10;\n var changesPending = false; // true while src.changes is running\n var doc_ids = opts.doc_ids;\n var repId;\n var checkpointer;\n var changedDocs = [];\n // Like couchdb, every replication gets a unique session id\n var session = uuid();\n\n result = result || {\n ok: true,\n start_time: new Date(),\n docs_read: 0,\n docs_written: 0,\n doc_write_failures: 0,\n errors: []\n };\n\n var changesOpts = {};\n returnValue.ready(src, target);\n\n function initCheckpointer() {\n if (checkpointer) {\n return PouchPromise.resolve();\n }\n return generateReplicationId(src, target, opts).then(function (res) {\n repId = res;\n checkpointer = new Checkpointer(src, target, repId, returnValue);\n });\n }\n\n function writeDocs() {\n changedDocs = [];\n\n if (currentBatch.docs.length === 0) {\n return;\n }\n var docs = currentBatch.docs;\n var bulkOpts = {timeout: opts.timeout};\n return target.bulkDocs({docs: docs, new_edits: false}, bulkOpts).then(function (res) {\n /* istanbul ignore if */\n if (returnValue.cancelled) {\n completeReplication();\n throw new Error('cancelled');\n }\n\n // `res` doesn't include full documents (which live in `docs`), so we create a map of \n // (id -> error), and check for errors while iterating over `docs`\n var errorsById = Object.create(null);\n res.forEach(function (res) {\n if (res.error) {\n errorsById[res.id] = res;\n }\n });\n\n var errorsNo = Object.keys(errorsById).length;\n result.doc_write_failures += errorsNo;\n result.docs_written += docs.length - errorsNo;\n\n docs.forEach(function (doc) {\n var error = errorsById[doc._id];\n if (error) {\n result.errors.push(error);\n if (error.name === 'unauthorized' || error.name === 'forbidden') {\n returnValue.emit('denied', clone(error));\n } else {\n throw error;\n }\n } else {\n changedDocs.push(doc);\n }\n });\n\n }, function (err) {\n result.doc_write_failures += docs.length;\n throw err;\n });\n }\n\n function finishBatch() {\n if (currentBatch.error) {\n throw new Error('There was a problem getting docs.');\n }\n result.last_seq = last_seq = currentBatch.seq;\n var outResult = clone(result);\n if (changedDocs.length) {\n outResult.docs = changedDocs;\n returnValue.emit('change', outResult);\n }\n writingCheckpoint = true;\n return checkpointer.writeCheckpoint(currentBatch.seq,\n session).then(function () {\n writingCheckpoint = false;\n /* istanbul ignore if */\n if (returnValue.cancelled) {\n completeReplication();\n throw new Error('cancelled');\n }\n currentBatch = undefined;\n getChanges();\n }).catch(function (err) {\n onCheckpointError(err);\n throw err;\n });\n }\n\n function getDiffs() {\n var diff = {};\n currentBatch.changes.forEach(function (change) {\n // Couchbase Sync Gateway emits these, but we can ignore them\n /* istanbul ignore if */\n if (change.id === \"_user/\") {\n return;\n }\n diff[change.id] = change.changes.map(function (x) {\n return x.rev;\n });\n });\n return target.revsDiff(diff).then(function (diffs) {\n /* istanbul ignore if */\n if (returnValue.cancelled) {\n completeReplication();\n throw new Error('cancelled');\n }\n // currentBatch.diffs elements are deleted as the documents are written\n currentBatch.diffs = diffs;\n });\n }\n\n function getBatchDocs() {\n return getDocs(src, target, currentBatch.diffs, returnValue).then(function (got) {\n currentBatch.error = !got.ok;\n got.docs.forEach(function (doc) {\n delete currentBatch.diffs[doc._id];\n result.docs_read++;\n currentBatch.docs.push(doc);\n });\n });\n }\n\n function startNextBatch() {\n if (returnValue.cancelled || currentBatch) {\n return;\n }\n if (batches.length === 0) {\n processPendingBatch(true);\n return;\n }\n currentBatch = batches.shift();\n getDiffs()\n .then(getBatchDocs)\n .then(writeDocs)\n .then(finishBatch)\n .then(startNextBatch)\n .catch(function (err) {\n abortReplication('batch processing terminated with error', err);\n });\n }\n\n\n function processPendingBatch(immediate) {\n if (pendingBatch.changes.length === 0) {\n if (batches.length === 0 && !currentBatch) {\n if ((continuous && changesOpts.live) || changesCompleted) {\n returnValue.state = 'pending';\n returnValue.emit('paused');\n }\n if (changesCompleted) {\n completeReplication();\n }\n }\n return;\n }\n if (\n immediate ||\n changesCompleted ||\n pendingBatch.changes.length >= batch_size\n ) {\n batches.push(pendingBatch);\n pendingBatch = {\n seq: 0,\n changes: [],\n docs: []\n };\n if (returnValue.state === 'pending' || returnValue.state === 'stopped') {\n returnValue.state = 'active';\n returnValue.emit('active');\n }\n startNextBatch();\n }\n }\n\n\n function abortReplication(reason, err) {\n if (replicationCompleted) {\n return;\n }\n if (!err.message) {\n err.message = reason;\n }\n result.ok = false;\n result.status = 'aborting';\n batches = [];\n pendingBatch = {\n seq: 0,\n changes: [],\n docs: []\n };\n completeReplication(err);\n }\n\n\n function completeReplication(fatalError) {\n if (replicationCompleted) {\n return;\n }\n /* istanbul ignore if */\n if (returnValue.cancelled) {\n result.status = 'cancelled';\n if (writingCheckpoint) {\n return;\n }\n }\n result.status = result.status || 'complete';\n result.end_time = new Date();\n result.last_seq = last_seq;\n replicationCompleted = true;\n\n if (fatalError) {\n fatalError.result = result;\n\n if (fatalError.name === 'unauthorized' || fatalError.name === 'forbidden') {\n returnValue.emit('error', fatalError);\n returnValue.removeAllListeners();\n } else {\n backOff(opts, returnValue, fatalError, function () {\n replicate$1(src, target, opts, returnValue);\n });\n }\n } else {\n returnValue.emit('complete', result);\n returnValue.removeAllListeners();\n }\n }\n\n\n function onChange(change) {\n /* istanbul ignore if */\n if (returnValue.cancelled) {\n return completeReplication();\n }\n var filter = filterChange(opts)(change);\n if (!filter) {\n return;\n }\n pendingBatch.seq = change.seq;\n pendingBatch.changes.push(change);\n processPendingBatch(batches.length === 0 && changesOpts.live);\n }\n\n\n function onChangesComplete(changes) {\n changesPending = false;\n /* istanbul ignore if */\n if (returnValue.cancelled) {\n return completeReplication();\n }\n\n // if no results were returned then we're done,\n // else fetch more\n if (changes.results.length > 0) {\n changesOpts.since = changes.last_seq;\n getChanges();\n processPendingBatch(true);\n } else {\n\n var complete = function () {\n if (continuous) {\n changesOpts.live = true;\n getChanges();\n } else {\n changesCompleted = true;\n }\n processPendingBatch(true);\n };\n\n // update the checkpoint so we start from the right seq next time\n if (!currentBatch && changes.results.length === 0) {\n writingCheckpoint = true;\n checkpointer.writeCheckpoint(changes.last_seq,\n session).then(function () {\n writingCheckpoint = false;\n result.last_seq = last_seq = changes.last_seq;\n complete();\n })\n .catch(onCheckpointError);\n } else {\n complete();\n }\n }\n }\n\n\n function onChangesError(err) {\n changesPending = false;\n /* istanbul ignore if */\n if (returnValue.cancelled) {\n return completeReplication();\n }\n abortReplication('changes rejected', err);\n }\n\n\n function getChanges() {\n if (!(\n !changesPending &&\n !changesCompleted &&\n batches.length < batches_limit\n )) {\n return;\n }\n changesPending = true;\n function abortChanges() {\n changes.cancel();\n }\n function removeListener() {\n returnValue.removeListener('cancel', abortChanges);\n }\n\n if (returnValue._changes) { // remove old changes() and listeners\n returnValue.removeListener('cancel', returnValue._abortChanges);\n returnValue._changes.cancel();\n }\n returnValue.once('cancel', abortChanges);\n\n var changes = src.changes(changesOpts)\n .on('change', onChange);\n changes.then(removeListener, removeListener);\n changes.then(onChangesComplete)\n .catch(onChangesError);\n\n if (opts.retry) {\n // save for later so we can cancel if necessary\n returnValue._changes = changes;\n returnValue._abortChanges = abortChanges;\n }\n }\n\n\n function startChanges() {\n initCheckpointer().then(function () {\n /* istanbul ignore if */\n if (returnValue.cancelled) {\n completeReplication();\n return;\n }\n return checkpointer.getCheckpoint().then(function (checkpoint) {\n last_seq = checkpoint;\n changesOpts = {\n since: last_seq,\n limit: batch_size,\n batch_size: batch_size,\n style: 'all_docs',\n doc_ids: doc_ids,\n return_docs: true // required so we know when we're done\n };\n if (opts.filter) {\n if (typeof opts.filter !== 'string') {\n // required for the client-side filter in onChange\n changesOpts.include_docs = true;\n } else { // ddoc filter\n changesOpts.filter = opts.filter;\n }\n }\n if ('heartbeat' in opts) {\n changesOpts.heartbeat = opts.heartbeat;\n }\n if ('timeout' in opts) {\n changesOpts.timeout = opts.timeout;\n }\n if (opts.query_params) {\n changesOpts.query_params = opts.query_params;\n }\n if (opts.view) {\n changesOpts.view = opts.view;\n }\n getChanges();\n });\n }).catch(function (err) {\n abortReplication('getCheckpoint rejected with ', err);\n });\n }\n\n /* istanbul ignore next */\n function onCheckpointError(err) {\n writingCheckpoint = false;\n abortReplication('writeCheckpoint completed with error', err);\n }\n\n /* istanbul ignore if */\n if (returnValue.cancelled) { // cancelled immediately\n completeReplication();\n return;\n }\n\n if (!returnValue._addedListeners) {\n returnValue.once('cancel', completeReplication);\n\n if (typeof opts.complete === 'function') {\n returnValue.once('error', opts.complete);\n returnValue.once('complete', function (result) {\n opts.complete(null, result);\n });\n }\n returnValue._addedListeners = true;\n }\n\n if (typeof opts.since === 'undefined') {\n startChanges();\n } else {\n initCheckpointer().then(function () {\n writingCheckpoint = true;\n return checkpointer.writeCheckpoint(opts.since, session);\n }).then(function () {\n writingCheckpoint = false;\n /* istanbul ignore if */\n if (returnValue.cancelled) {\n completeReplication();\n return;\n }\n last_seq = opts.since;\n startChanges();\n }).catch(onCheckpointError);\n }\n}\n\n// We create a basic promise so the caller can cancel the replication possibly\n// before we have actually started listening to changes etc\ninherits(Replication, events.EventEmitter);\nfunction Replication() {\n events.EventEmitter.call(this);\n this.cancelled = false;\n this.state = 'pending';\n var self = this;\n var promise = new PouchPromise(function (fulfill, reject) {\n self.once('complete', fulfill);\n self.once('error', reject);\n });\n self.then = function (resolve, reject) {\n return promise.then(resolve, reject);\n };\n self.catch = function (reject) {\n return promise.catch(reject);\n };\n // As we allow error handling via \"error\" event as well,\n // put a stub in here so that rejecting never throws UnhandledError.\n self.catch(function () {});\n}\n\nReplication.prototype.cancel = function () {\n this.cancelled = true;\n this.state = 'cancelled';\n this.emit('cancel');\n};\n\nReplication.prototype.ready = function (src, target) {\n var self = this;\n if (self._readyCalled) {\n return;\n }\n self._readyCalled = true;\n\n function onDestroy() {\n self.cancel();\n }\n src.once('destroyed', onDestroy);\n target.once('destroyed', onDestroy);\n function cleanup() {\n src.removeListener('destroyed', onDestroy);\n target.removeListener('destroyed', onDestroy);\n }\n self.once('complete', cleanup);\n};\n\nfunction toPouch(db, opts) {\n var PouchConstructor = opts.PouchConstructor;\n if (typeof db === 'string') {\n return new PouchConstructor(db, opts);\n } else {\n return db;\n }\n}\n\nfunction replicate(src, target, opts, callback) {\n\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n if (typeof opts === 'undefined') {\n opts = {};\n }\n\n if (opts.doc_ids && !Array.isArray(opts.doc_ids)) {\n throw createError(BAD_REQUEST,\n \"`doc_ids` filter parameter is not a list.\");\n }\n\n opts.complete = callback;\n opts = clone(opts);\n opts.continuous = opts.continuous || opts.live;\n opts.retry = ('retry' in opts) ? opts.retry : false;\n /*jshint validthis:true */\n opts.PouchConstructor = opts.PouchConstructor || this;\n var replicateRet = new Replication(opts);\n var srcPouch = toPouch(src, opts);\n var targetPouch = toPouch(target, opts);\n replicate$1(srcPouch, targetPouch, opts, replicateRet);\n return replicateRet;\n}\n\ninherits(Sync, events.EventEmitter);\nfunction sync(src, target, opts, callback) {\n if (typeof opts === 'function') {\n callback = opts;\n opts = {};\n }\n if (typeof opts === 'undefined') {\n opts = {};\n }\n opts = clone(opts);\n /*jshint validthis:true */\n opts.PouchConstructor = opts.PouchConstructor || this;\n src = toPouch(src, opts);\n target = toPouch(target, opts);\n return new Sync(src, target, opts, callback);\n}\n\nfunction Sync(src, target, opts, callback) {\n var self = this;\n this.canceled = false;\n\n var optsPush = opts.push ? extend$1({}, opts, opts.push) : opts;\n var optsPull = opts.pull ? extend$1({}, opts, opts.pull) : opts;\n\n this.push = replicate(src, target, optsPush);\n this.pull = replicate(target, src, optsPull);\n\n this.pushPaused = true;\n this.pullPaused = true;\n\n function pullChange(change) {\n self.emit('change', {\n direction: 'pull',\n change: change\n });\n }\n function pushChange(change) {\n self.emit('change', {\n direction: 'push',\n change: change\n });\n }\n function pushDenied(doc) {\n self.emit('denied', {\n direction: 'push',\n doc: doc\n });\n }\n function pullDenied(doc) {\n self.emit('denied', {\n direction: 'pull',\n doc: doc\n });\n }\n function pushPaused() {\n self.pushPaused = true;\n /* istanbul ignore if */\n if (self.pullPaused) {\n self.emit('paused');\n }\n }\n function pullPaused() {\n self.pullPaused = true;\n /* istanbul ignore if */\n if (self.pushPaused) {\n self.emit('paused');\n }\n }\n function pushActive() {\n self.pushPaused = false;\n /* istanbul ignore if */\n if (self.pullPaused) {\n self.emit('active', {\n direction: 'push'\n });\n }\n }\n function pullActive() {\n self.pullPaused = false;\n /* istanbul ignore if */\n if (self.pushPaused) {\n self.emit('active', {\n direction: 'pull'\n });\n }\n }\n\n var removed = {};\n\n function removeAll(type) { // type is 'push' or 'pull'\n return function (event, func) {\n var isChange = event === 'change' &&\n (func === pullChange || func === pushChange);\n var isDenied = event === 'denied' &&\n (func === pullDenied || func === pushDenied);\n var isPaused = event === 'paused' &&\n (func === pullPaused || func === pushPaused);\n var isActive = event === 'active' &&\n (func === pullActive || func === pushActive);\n\n if (isChange || isDenied || isPaused || isActive) {\n if (!(event in removed)) {\n removed[event] = {};\n }\n removed[event][type] = true;\n if (Object.keys(removed[event]).length === 2) {\n // both push and pull have asked to be removed\n self.removeAllListeners(event);\n }\n }\n };\n }\n\n if (opts.live) {\n this.push.on('complete', self.pull.cancel.bind(self.pull));\n this.pull.on('complete', self.push.cancel.bind(self.push));\n }\n\n function addOneListener(ee, event, listener) {\n if (ee.listeners(event).indexOf(listener) == -1) {\n ee.on(event, listener);\n }\n }\n\n this.on('newListener', function (event) {\n if (event === 'change') {\n addOneListener(self.pull, 'change', pullChange);\n addOneListener(self.push, 'change', pushChange);\n } else if (event === 'denied') {\n addOneListener(self.pull, 'denied', pullDenied);\n addOneListener(self.push, 'denied', pushDenied);\n } else if (event === 'active') {\n addOneListener(self.pull, 'active', pullActive);\n addOneListener(self.push, 'active', pushActive);\n } else if (event === 'paused') {\n addOneListener(self.pull, 'paused', pullPaused);\n addOneListener(self.push, 'paused', pushPaused);\n }\n });\n\n this.on('removeListener', function (event) {\n if (event === 'change') {\n self.pull.removeListener('change', pullChange);\n self.push.removeListener('change', pushChange);\n } else if (event === 'denied') {\n self.pull.removeListener('denied', pullDenied);\n self.push.removeListener('denied', pushDenied);\n } else if (event === 'active') {\n self.pull.removeListener('active', pullActive);\n self.push.removeListener('active', pushActive);\n } else if (event === 'paused') {\n self.pull.removeListener('paused', pullPaused);\n self.push.removeListener('paused', pushPaused);\n }\n });\n\n this.pull.on('removeListener', removeAll('pull'));\n this.push.on('removeListener', removeAll('push'));\n\n var promise = PouchPromise.all([\n this.push,\n this.pull\n ]).then(function (resp) {\n var out = {\n push: resp[0],\n pull: resp[1]\n };\n self.emit('complete', out);\n if (callback) {\n callback(null, out);\n }\n self.removeAllListeners();\n return out;\n }, function (err) {\n self.cancel();\n if (callback) {\n // if there's a callback, then the callback can receive\n // the error event\n callback(err);\n } else {\n // if there's no callback, then we're safe to emit an error\n // event, which would otherwise throw an unhandled error\n // due to 'error' being a special event in EventEmitters\n self.emit('error', err);\n }\n self.removeAllListeners();\n if (callback) {\n // no sense throwing if we're already emitting an 'error' event\n throw err;\n }\n });\n\n this.then = function (success, err) {\n return promise.then(success, err);\n };\n\n this.catch = function (err) {\n return promise.catch(err);\n };\n}\n\nSync.prototype.cancel = function () {\n if (!this.canceled) {\n this.canceled = true;\n this.push.cancel();\n this.pull.cancel();\n }\n};\n\nfunction replication(PouchDB) {\n PouchDB.replicate = replicate;\n PouchDB.sync = sync;\n\n Object.defineProperty(PouchDB.prototype, 'replicate', {\n get: function () {\n var self = this;\n return {\n from: function (other, opts, callback) {\n return self.constructor.replicate(other, self, opts, callback);\n },\n to: function (other, opts, callback) {\n return self.constructor.replicate(self, other, opts, callback);\n }\n };\n }\n });\n\n PouchDB.prototype.sync = function (dbName, opts, callback) {\n return this.constructor.sync(this, dbName, opts, callback);\n };\n}\n\nPouchDB.plugin(IDBPouch)\n .plugin(WebSqlPouch)\n .plugin(HttpPouch$1)\n .plugin(mapreduce)\n .plugin(replication);\n\n// Pull from src because pouchdb-node/pouchdb-browser themselves\n// are aggressively optimized and jsnext:main would normally give us this\n// aggressive bundle.\n\nmodule.exports = PouchDB;\n/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiODkuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L3BvdWNoZGIvbGliL2luZGV4LWJyb3dzZXIuanM/ZTk4MSJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wRGVmYXVsdCAoZXgpIHsgcmV0dXJuIChleCAmJiAodHlwZW9mIGV4ID09PSAnb2JqZWN0JykgJiYgJ2RlZmF1bHQnIGluIGV4KSA/IGV4WydkZWZhdWx0J10gOiBleDsgfVxuXG52YXIgbGllID0gX2ludGVyb3BEZWZhdWx0KHJlcXVpcmUoJ2xpZScpKTtcbnZhciBnZXRBcmd1bWVudHMgPSBfaW50ZXJvcERlZmF1bHQocmVxdWlyZSgnYXJnc2FycmF5JykpO1xudmFyIGRlYnVnID0gX2ludGVyb3BEZWZhdWx0KHJlcXVpcmUoJ2RlYnVnJykpO1xudmFyIGV2ZW50cyA9IHJlcXVpcmUoJ2V2ZW50cycpO1xudmFyIGluaGVyaXRzID0gX2ludGVyb3BEZWZhdWx0KHJlcXVpcmUoJ2luaGVyaXRzJykpO1xudmFyIGltbWVkaWF0ZSA9IF9pbnRlcm9wRGVmYXVsdChyZXF1aXJlKCdpbW1lZGlhdGUnKSk7XG52YXIgc2NvcGVkRXZhbCA9IF9pbnRlcm9wRGVmYXVsdChyZXF1aXJlKCdzY29wZS1ldmFsJykpO1xudmFyIE1kNSA9IF9pbnRlcm9wRGVmYXVsdChyZXF1aXJlKCdzcGFyay1tZDUnKSk7XG52YXIgdnV2dXplbGEgPSBfaW50ZXJvcERlZmF1bHQocmVxdWlyZSgndnV2dXplbGEnKSk7XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG52YXIgUG91Y2hQcm9taXNlID0gdHlwZW9mIFByb21pc2UgPT09ICdmdW5jdGlvbicgPyBQcm9taXNlIDogbGllO1xuXG5mdW5jdGlvbiBpc0JpbmFyeU9iamVjdChvYmplY3QpIHtcbiAgcmV0dXJuICh0eXBlb2YgQXJyYXlCdWZmZXIgIT09ICd1bmRlZmluZWQnICYmIG9iamVjdCBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSB8fFxuICAgICh0eXBlb2YgQmxvYiAhPT0gJ3VuZGVmaW5lZCcgJiYgb2JqZWN0IGluc3RhbmNlb2YgQmxvYik7XG59XG5cbmZ1bmN0aW9uIGNsb25lQXJyYXlCdWZmZXIoYnVmZikge1xuICBpZiAodHlwZW9mIGJ1ZmYuc2xpY2UgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gYnVmZi5zbGljZSgwKTtcbiAgfVxuICAvLyBJRTEwLTExIHNsaWNlKCkgcG9seWZpbGxcbiAgdmFyIHRhcmdldCA9IG5ldyBBcnJheUJ1ZmZlcihidWZmLmJ5dGVMZW5ndGgpO1xuICB2YXIgdGFyZ2V0QXJyYXkgPSBuZXcgVWludDhBcnJheSh0YXJnZXQpO1xuICB2YXIgc291cmNlQXJyYXkgPSBuZXcgVWludDhBcnJheShidWZmKTtcbiAgdGFyZ2V0QXJyYXkuc2V0KHNvdXJjZUFycmF5KTtcbiAgcmV0dXJuIHRhcmdldDtcbn1cblxuZnVuY3Rpb24gY2xvbmVCaW5hcnlPYmplY3Qob2JqZWN0KSB7XG4gIGlmIChvYmplY3QgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikge1xuICAgIHJldHVybiBjbG9uZUFycmF5QnVmZmVyKG9iamVjdCk7XG4gIH1cbiAgdmFyIHNpemUgPSBvYmplY3Quc2l6ZTtcbiAgdmFyIHR5cGUgPSBvYmplY3QudHlwZTtcbiAgLy8gQmxvYlxuICBpZiAodHlwZW9mIG9iamVjdC5zbGljZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHJldHVybiBvYmplY3Quc2xpY2UoMCwgc2l6ZSwgdHlwZSk7XG4gIH1cbiAgLy8gUGhhbnRvbUpTIHNsaWNlKCkgcmVwbGFjZW1lbnRcbiAgcmV0dXJuIG9iamVjdC53ZWJraXRTbGljZSgwLCBzaXplLCB0eXBlKTtcbn1cblxuLy8gbW9zdCBvZiB0aGlzIGlzIGJvcnJvd2VkIGZyb20gbG9kYXNoLmlzUGxhaW5PYmplY3Q6XG4vLyBodHRwczovL2dpdGh1Yi5jb20vZmlzLWNvbXBvbmVudHMvbG9kYXNoLmlzcGxhaW5vYmplY3QvXG4vLyBibG9iLzI5YzM1ODE0MGE3NGYyNTJhZWIwOGM5ZWIyOGJlZjg2ZjIyMTdkNGEvaW5kZXguanNcblxudmFyIGZ1bmNUb1N0cmluZyA9IEZ1bmN0aW9uLnByb3RvdHlwZS50b1N0cmluZztcbnZhciBvYmplY3RDdG9yU3RyaW5nID0gZnVuY1RvU3RyaW5nLmNhbGwoT2JqZWN0KTtcblxuZnVuY3Rpb24gaXNQbGFpbk9iamVjdCh2YWx1ZSkge1xuICB2YXIgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgaWYgKHByb3RvID09PSBudWxsKSB7IC8vIG5vdCBzdXJlIHdoZW4gdGhpcyBoYXBwZW5zLCBidXQgSSBndWVzcyBpdCBjYW5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICB2YXIgQ3RvciA9IHByb3RvLmNvbnN0cnVjdG9yO1xuICByZXR1cm4gKHR5cGVvZiBDdG9yID09ICdmdW5jdGlvbicgJiZcbiAgICBDdG9yIGluc3RhbmNlb2YgQ3RvciAmJiBmdW5jVG9TdHJpbmcuY2FsbChDdG9yKSA9PSBvYmplY3RDdG9yU3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gY2xvbmUob2JqZWN0KSB7XG4gIHZhciBuZXdPYmplY3Q7XG4gIHZhciBpO1xuICB2YXIgbGVuO1xuXG4gIGlmICghb2JqZWN0IHx8IHR5cGVvZiBvYmplY3QgIT09ICdvYmplY3QnKSB7XG4gICAgcmV0dXJuIG9iamVjdDtcbiAgfVxuXG4gIGlmIChBcnJheS5pc0FycmF5KG9iamVjdCkpIHtcbiAgICBuZXdPYmplY3QgPSBbXTtcbiAgICBmb3IgKGkgPSAwLCBsZW4gPSBvYmplY3QubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIG5ld09iamVjdFtpXSA9IGNsb25lKG9iamVjdFtpXSk7XG4gICAgfVxuICAgIHJldHVybiBuZXdPYmplY3Q7XG4gIH1cblxuICAvLyBzcGVjaWFsIGNhc2U6IHRvIGF2b2lkIGluY29uc2lzdGVuY2llcyBiZXR3ZWVuIEluZGV4ZWREQlxuICAvLyBhbmQgb3RoZXIgYmFja2VuZHMsIHdlIGF1dG9tYXRpY2FsbHkgc3RyaW5naWZ5IERhdGVzXG4gIGlmIChvYmplY3QgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgcmV0dXJuIG9iamVjdC50b0lTT1N0cmluZygpO1xuICB9XG5cbiAgaWYgKGlzQmluYXJ5T2JqZWN0KG9iamVjdCkpIHtcbiAgICByZXR1cm4gY2xvbmVCaW5hcnlPYmplY3Qob2JqZWN0KTtcbiAgfVxuXG4gIGlmICghaXNQbGFpbk9iamVjdChvYmplY3QpKSB7XG4gICAgcmV0dXJuIG9iamVjdDsgLy8gZG9uJ3QgY2xvbmUgb2JqZWN0cyBsaWtlIFdvcmtlcnNcbiAgfVxuXG4gIG5ld09iamVjdCA9IHt9O1xuICBmb3IgKGkgaW4gb2JqZWN0KSB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIGVsc2UgKi9cbiAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgaSkpIHtcbiAgICAgIHZhciB2YWx1ZSA9IGNsb25lKG9iamVjdFtpXSk7XG4gICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBuZXdPYmplY3RbaV0gPSB2YWx1ZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIG5ld09iamVjdDtcbn1cblxuZnVuY3Rpb24gb25jZShmdW4pIHtcbiAgdmFyIGNhbGxlZCA9IGZhbHNlO1xuICByZXR1cm4gZ2V0QXJndW1lbnRzKGZ1bmN0aW9uIChhcmdzKSB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgaWYgKGNhbGxlZCkge1xuICAgICAgLy8gdGhpcyBpcyBhIHNtb2tlIHRlc3QgYW5kIHNob3VsZCBuZXZlciBhY3R1YWxseSBoYXBwZW5cbiAgICAgIHRocm93IG5ldyBFcnJvcignb25jZSBjYWxsZWQgbW9yZSB0aGFuIG9uY2UnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY2FsbGVkID0gdHJ1ZTtcbiAgICAgIGZ1bi5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiB0b1Byb21pc2UoZnVuYykge1xuICAvL2NyZWF0ZSB0aGUgZnVuY3Rpb24gd2Ugd2lsbCBiZSByZXR1cm5pbmdcbiAgcmV0dXJuIGdldEFyZ3VtZW50cyhmdW5jdGlvbiAoYXJncykge1xuICAgIC8vIENsb25lIGFyZ3VtZW50c1xuICAgIGFyZ3MgPSBjbG9uZShhcmdzKTtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgLy8gaWYgdGhlIGxhc3QgYXJndW1lbnQgaXMgYSBmdW5jdGlvbiwgYXNzdW1lIGl0cyBhIGNhbGxiYWNrXG4gICAgdmFyIHVzZWRDQiA9ICh0eXBlb2YgYXJnc1thcmdzLmxlbmd0aCAtIDFdID09PSAnZnVuY3Rpb24nKSA/IGFyZ3MucG9wKCkgOiBmYWxzZTtcbiAgICB2YXIgcHJvbWlzZSA9IG5ldyBQb3VjaFByb21pc2UoZnVuY3Rpb24gKGZ1bGZpbGwsIHJlamVjdCkge1xuICAgICAgdmFyIHJlc3A7XG4gICAgICB0cnkge1xuICAgICAgICB2YXIgY2FsbGJhY2sgPSBvbmNlKGZ1bmN0aW9uIChlcnIsIG1lc2cpIHtcbiAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZnVsZmlsbChtZXNnKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBjcmVhdGUgYSBjYWxsYmFjayBmb3IgdGhpcyBpbnZvY2F0aW9uXG4gICAgICAgIC8vIGFwcGx5IHRoZSBmdW5jdGlvbiBpbiB0aGUgb3JpZyBjb250ZXh0XG4gICAgICAgIGFyZ3MucHVzaChjYWxsYmFjayk7XG4gICAgICAgIHJlc3AgPSBmdW5jLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICAgICAgICBpZiAocmVzcCAmJiB0eXBlb2YgcmVzcC50aGVuID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgZnVsZmlsbChyZXNwKTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZWplY3QoZSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgLy8gaWYgdGhlcmUgaXMgYSBjYWxsYmFjaywgY2FsbCBpdCBiYWNrXG4gICAgaWYgKHVzZWRDQikge1xuICAgICAgcHJvbWlzZS50aGVuKGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgdXNlZENCKG51bGwsIHJlc3VsdCk7XG4gICAgICB9LCB1c2VkQ0IpO1xuICAgIH1cbiAgICByZXR1cm4gcHJvbWlzZTtcbiAgfSk7XG59XG5cbnZhciBsb2cgPSBkZWJ1ZygncG91Y2hkYjphcGknKTtcblxuZnVuY3Rpb24gYWRhcHRlckZ1bihuYW1lLCBjYWxsYmFjaykge1xuICBmdW5jdGlvbiBsb2dBcGlDYWxsKHNlbGYsIG5hbWUsIGFyZ3MpIHtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICBpZiAobG9nLmVuYWJsZWQpIHtcbiAgICAgIHZhciBsb2dBcmdzID0gW3NlbGYubmFtZSwgbmFtZV07XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgIGxvZ0FyZ3MucHVzaChhcmdzW2ldKTtcbiAgICAgIH1cbiAgICAgIGxvZy5hcHBseShudWxsLCBsb2dBcmdzKTtcblxuICAgICAgLy8gb3ZlcnJpZGUgdGhlIGNhbGxiYWNrIGl0c2VsZiB0byBsb2cgdGhlIHJlc3BvbnNlXG4gICAgICB2YXIgb3JpZ0NhbGxiYWNrID0gYXJnc1thcmdzLmxlbmd0aCAtIDFdO1xuICAgICAgYXJnc1thcmdzLmxlbmd0aCAtIDFdID0gZnVuY3Rpb24gKGVyciwgcmVzKSB7XG4gICAgICAgIHZhciByZXNwb25zZUFyZ3MgPSBbc2VsZi5uYW1lLCBuYW1lXTtcbiAgICAgICAgcmVzcG9uc2VBcmdzID0gcmVzcG9uc2VBcmdzLmNvbmNhdChcbiAgICAgICAgICBlcnIgPyBbJ2Vycm9yJywgZXJyXSA6IFsnc3VjY2VzcycsIHJlc11cbiAgICAgICAgKTtcbiAgICAgICAgbG9nLmFwcGx5KG51bGwsIHJlc3BvbnNlQXJncyk7XG4gICAgICAgIG9yaWdDYWxsYmFjayhlcnIsIHJlcyk7XG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0b1Byb21pc2UoZ2V0QXJndW1lbnRzKGZ1bmN0aW9uIChhcmdzKSB7XG4gICAgaWYgKHRoaXMuX2Nsb3NlZCkge1xuICAgICAgcmV0dXJuIFBvdWNoUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCdkYXRhYmFzZSBpcyBjbG9zZWQnKSk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9kZXN0cm95ZWQpIHtcbiAgICAgIHJldHVybiBQb3VjaFByb21pc2UucmVqZWN0KG5ldyBFcnJvcignZGF0YWJhc2UgaXMgZGVzdHJveWVkJykpO1xuICAgIH1cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgbG9nQXBpQ2FsbChzZWxmLCBuYW1lLCBhcmdzKTtcbiAgICBpZiAoIXRoaXMudGFza3F1ZXVlLmlzUmVhZHkpIHtcbiAgICAgIHJldHVybiBuZXcgUG91Y2hQcm9taXNlKGZ1bmN0aW9uIChmdWxmaWxsLCByZWplY3QpIHtcbiAgICAgICAgc2VsZi50YXNrcXVldWUuYWRkVGFzayhmdW5jdGlvbiAoZmFpbGVkKSB7XG4gICAgICAgICAgaWYgKGZhaWxlZCkge1xuICAgICAgICAgICAgcmVqZWN0KGZhaWxlZCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZ1bGZpbGwoc2VsZltuYW1lXS5hcHBseShzZWxmLCBhcmdzKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gY2FsbGJhY2suYXBwbHkodGhpcywgYXJncyk7XG4gIH0pKTtcbn1cblxuLy8gbGlrZSB1bmRlcnNjb3JlL2xvZGFzaCBfLnBpY2soKVxuZnVuY3Rpb24gcGljayhvYmosIGFycikge1xuICB2YXIgcmVzID0ge307XG4gIGZvciAodmFyIGkgPSAwLCBsZW4gPSBhcnIubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICB2YXIgcHJvcCA9IGFycltpXTtcbiAgICBpZiAocHJvcCBpbiBvYmopIHtcbiAgICAgIHJlc1twcm9wXSA9IG9ialtwcm9wXTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlcztcbn1cblxuLy8gYmFzZWQgb24gaHR0cHM6Ly9naXRodWIuY29tL21vbnRhZ2Vqcy9jb2xsZWN0aW9uc1xuZnVuY3Rpb24gbWFuZ2xlKGtleSkge1xuICByZXR1cm4gJyQnICsga2V5O1xufVxuZnVuY3Rpb24gdW5tYW5nbGUoa2V5KSB7XG4gIHJldHVybiBrZXkuc3Vic3RyaW5nKDEpO1xufVxuZnVuY3Rpb24gX01hcCgpIHtcbiAgdGhpcy5fc3RvcmUgPSB7fTtcbn1cbl9NYXAucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgdmFyIG1hbmdsZWQgPSBtYW5nbGUoa2V5KTtcbiAgcmV0dXJuIHRoaXMuX3N0b3JlW21hbmdsZWRdO1xufTtcbl9NYXAucHJvdG90eXBlLnNldCA9IGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gIHZhciBtYW5nbGVkID0gbWFuZ2xlKGtleSk7XG4gIHRoaXMuX3N0b3JlW21hbmdsZWRdID0gdmFsdWU7XG4gIHJldHVybiB0cnVlO1xufTtcbl9NYXAucHJvdG90eXBlLmhhcyA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgdmFyIG1hbmdsZWQgPSBtYW5nbGUoa2V5KTtcbiAgcmV0dXJuIG1hbmdsZWQgaW4gdGhpcy5fc3RvcmU7XG59O1xuX01hcC5wcm90b3R5cGUuZGVsZXRlID0gZnVuY3Rpb24gKGtleSkge1xuICB2YXIgbWFuZ2xlZCA9IG1hbmdsZShrZXkpO1xuICB2YXIgcmVzID0gbWFuZ2xlZCBpbiB0aGlzLl9zdG9yZTtcbiAgZGVsZXRlIHRoaXMuX3N0b3JlW21hbmdsZWRdO1xuICByZXR1cm4gcmVzO1xufTtcbl9NYXAucHJvdG90eXBlLmZvckVhY2ggPSBmdW5jdGlvbiAoY2IpIHtcbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyh0aGlzLl9zdG9yZSk7XG4gIGZvciAodmFyIGkgPSAwLCBsZW4gPSBrZXlzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgdmFyIGtleSA9IGtleXNbaV07XG4gICAgdmFyIHZhbHVlID0gdGhpcy5fc3RvcmVba2V5XTtcbiAgICBrZXkgPSB1bm1hbmdsZShrZXkpO1xuICAgIGNiKHZhbHVlLCBrZXkpO1xuICB9XG59O1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KF9NYXAucHJvdG90eXBlLCAnc2l6ZScsIHtcbiAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHRoaXMuX3N0b3JlKS5sZW5ndGg7XG4gIH1cbn0pO1xuXG5mdW5jdGlvbiBfU2V0KGFycmF5KSB7XG4gIHRoaXMuX3N0b3JlID0gbmV3IF9NYXAoKTtcblxuICAvLyBpbml0IHdpdGggYW4gYXJyYXlcbiAgaWYgKGFycmF5ICYmIEFycmF5LmlzQXJyYXkoYXJyYXkpKSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGFycmF5Lmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICB0aGlzLmFkZChhcnJheVtpXSk7XG4gICAgfVxuICB9XG59XG5fU2V0LnByb3RvdHlwZS5hZGQgPSBmdW5jdGlvbiAoa2V5KSB7XG4gIHJldHVybiB0aGlzLl9zdG9yZS5zZXQoa2V5LCB0cnVlKTtcbn07XG5fU2V0LnByb3RvdHlwZS5oYXMgPSBmdW5jdGlvbiAoa2V5KSB7XG4gIHJldHVybiB0aGlzLl9zdG9yZS5oYXMoa2V5KTtcbn07XG5cbi8vIE1vc3QgYnJvd3NlcnMgdGhyb3R0bGUgY29uY3VycmVudCByZXF1ZXN0cyBhdCA2LCBzbyBpdCdzIHNpbGx5XG4vLyB0byBzaGltIF9idWxrX2dldCBieSB0cnlpbmcgdG8gbGF1bmNoIHBvdGVudGlhbGx5IGh1bmRyZWRzIG9mIHJlcXVlc3RzXG4vLyBhbmQgdGhlbiBsZXR0aW5nIHRoZSBtYWpvcml0eSB0aW1lIG91dC4gV2UgY2FuIGhhbmRsZSB0aGlzIG91cnNlbHZlcy5cbnZhciBNQVhfTlVNX0NPTkNVUlJFTlRfUkVRVUVTVFMgPSA2O1xuXG5mdW5jdGlvbiBpZGVudGl0eUZ1bmN0aW9uKHgpIHtcbiAgcmV0dXJuIHg7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdFJlc3VsdEZvck9wZW5SZXZzR2V0KHJlc3VsdCkge1xuICByZXR1cm4gW3tcbiAgICBvazogcmVzdWx0XG4gIH1dO1xufVxuXG4vLyBzaGltIGZvciBQL0NvdWNoREIgYWRhcHRlcnMgdGhhdCBkb24ndCBkaXJlY3RseSBpbXBsZW1lbnQgX2J1bGtfZ2V0XG5mdW5jdGlvbiBidWxrR2V0KGRiLCBvcHRzLCBjYWxsYmFjaykge1xuICB2YXIgcmVxdWVzdHMgPSBvcHRzLmRvY3M7XG5cbiAgLy8gY29uc29saWRhdGUgaW50byBvbmUgcmVxdWVzdCBwZXIgZG9jIGlmIHBvc3NpYmxlXG4gIHZhciByZXF1ZXN0c0J5SWQgPSBuZXcgX01hcCgpO1xuICByZXF1ZXN0cy5mb3JFYWNoKGZ1bmN0aW9uIChyZXF1ZXN0KSB7XG4gICAgaWYgKHJlcXVlc3RzQnlJZC5oYXMocmVxdWVzdC5pZCkpIHtcbiAgICAgIHJlcXVlc3RzQnlJZC5nZXQocmVxdWVzdC5pZCkucHVzaChyZXF1ZXN0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVxdWVzdHNCeUlkLnNldChyZXF1ZXN0LmlkLCBbcmVxdWVzdF0pO1xuICAgIH1cbiAgfSk7XG5cbiAgdmFyIG51bURvY3MgPSByZXF1ZXN0c0J5SWQuc2l6ZTtcbiAgdmFyIG51bURvbmUgPSAwO1xuICB2YXIgcGVyRG9jUmVzdWx0cyA9IG5ldyBBcnJheShudW1Eb2NzKTtcblxuICBmdW5jdGlvbiBjb2xsYXBzZVJlc3VsdHNBbmRGaW5pc2goKSB7XG4gICAgdmFyIHJlc3VsdHMgPSBbXTtcbiAgICBwZXJEb2NSZXN1bHRzLmZvckVhY2goZnVuY3Rpb24gKHJlcykge1xuICAgICAgcmVzLmRvY3MuZm9yRWFjaChmdW5jdGlvbiAoaW5mbykge1xuICAgICAgICByZXN1bHRzLnB1c2goe1xuICAgICAgICAgIGlkOiByZXMuaWQsXG4gICAgICAgICAgZG9jczogW2luZm9dXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG4gICAgY2FsbGJhY2sobnVsbCwge3Jlc3VsdHM6IHJlc3VsdHN9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNoZWNrRG9uZSgpIHtcbiAgICBpZiAoKytudW1Eb25lID09PSBudW1Eb2NzKSB7XG4gICAgICBjb2xsYXBzZVJlc3VsdHNBbmRGaW5pc2goKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBnb3RSZXN1bHQoZG9jSW5kZXgsIGlkLCBkb2NzKSB7XG4gICAgcGVyRG9jUmVzdWx0c1tkb2NJbmRleF0gPSB7aWQ6IGlkLCBkb2NzOiBkb2NzfTtcbiAgICBjaGVja0RvbmUoKTtcbiAgfVxuXG4gIHZhciBhbGxSZXF1ZXN0cyA9IFtdO1xuICByZXF1ZXN0c0J5SWQuZm9yRWFjaChmdW5jdGlvbiAodmFsdWUsIGtleSkge1xuICAgIGFsbFJlcXVlc3RzLnB1c2goa2V5KTtcbiAgfSk7XG5cbiAgdmFyIGkgPSAwO1xuXG4gIGZ1bmN0aW9uIG5leHRCYXRjaCgpIHtcblxuICAgIGlmIChpID49IGFsbFJlcXVlc3RzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciB1cFRvID0gTWF0aC5taW4oaSArIE1BWF9OVU1fQ09OQ1VSUkVOVF9SRVFVRVNUUywgYWxsUmVxdWVzdHMubGVuZ3RoKTtcbiAgICB2YXIgYmF0Y2ggPSBhbGxSZXF1ZXN0cy5zbGljZShpLCB1cFRvKTtcbiAgICBwcm9jZXNzQmF0Y2goYmF0Y2gsIGkpO1xuICAgIGkgKz0gYmF0Y2gubGVuZ3RoO1xuICB9XG5cbiAgZnVuY3Rpb24gcHJvY2Vzc0JhdGNoKGJhdGNoLCBvZmZzZXQpIHtcbiAgICBiYXRjaC5mb3JFYWNoKGZ1bmN0aW9uIChkb2NJZCwgaikge1xuICAgICAgdmFyIGRvY0lkeCA9IG9mZnNldCArIGo7XG4gICAgICB2YXIgZG9jUmVxdWVzdHMgPSByZXF1ZXN0c0J5SWQuZ2V0KGRvY0lkKTtcblxuICAgICAgLy8ganVzdCB1c2UgdGhlIGZpcnN0IHJlcXVlc3QgYXMgdGhlIFwidGVtcGxhdGVcIlxuICAgICAgLy8gVE9ETzogVGhlIF9idWxrX2dldCBBUEkgYWxsb3dzIGZvciBtb3JlIHN1YnRsZSB1c2UgY2FzZXMgdGhhbiB0aGlzLFxuICAgICAgLy8gYnV0IGZvciBub3cgaXQgaXMgdW5saWtlbHkgdGhhdCB0aGVyZSB3aWxsIGJlIGEgbWl4IG9mIGRpZmZlcmVudFxuICAgICAgLy8gXCJhdHRzX3NpbmNlXCIgb3IgXCJhdHRhY2htZW50c1wiIGluIHRoZSBzYW1lIHJlcXVlc3QsIHNpbmNlIGl0J3MganVzdFxuICAgICAgLy8gcmVwbGljYXRlLmpzIHRoYXQgaXMgdXNpbmcgdGhpcyBmb3IgdGhlIG1vbWVudC5cbiAgICAgIC8vIEFsc28sIGF0dHNfc2luY2UgaXMgYXNwaXJhdGlvbmFsLCBzaW5jZSB3ZSBkb24ndCBzdXBwb3J0IGl0IHlldC5cbiAgICAgIHZhciBkb2NPcHRzID0gcGljayhkb2NSZXF1ZXN0c1swXSwgWydhdHRzX3NpbmNlJywgJ2F0dGFjaG1lbnRzJ10pO1xuICAgICAgZG9jT3B0cy5vcGVuX3JldnMgPSBkb2NSZXF1ZXN0cy5tYXAoZnVuY3Rpb24gKHJlcXVlc3QpIHtcbiAgICAgICAgLy8gcmV2IGlzIG9wdGlvbmFsLCBvcGVuX3JldnMgZGlzYWxsb3dlZFxuICAgICAgICByZXR1cm4gcmVxdWVzdC5yZXY7XG4gICAgICB9KTtcblxuICAgICAgLy8gcmVtb3ZlIGZhbHNleSAvIHVuZGVmaW5lZCByZXZpc2lvbnNcbiAgICAgIGRvY09wdHMub3Blbl9yZXZzID0gZG9jT3B0cy5vcGVuX3JldnMuZmlsdGVyKGlkZW50aXR5RnVuY3Rpb24pO1xuXG4gICAgICB2YXIgZm9ybWF0UmVzdWx0ID0gaWRlbnRpdHlGdW5jdGlvbjtcblxuICAgICAgaWYgKGRvY09wdHMub3Blbl9yZXZzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBkZWxldGUgZG9jT3B0cy5vcGVuX3JldnM7XG5cbiAgICAgICAgLy8gd2hlbiBmZXRjaGluZyBvbmx5IHRoZSBcIndpbm5pbmdcIiBsZWFmLFxuICAgICAgICAvLyB0cmFuc2Zvcm0gdGhlIHJlc3VsdCBzbyBpdCBsb29rcyBsaWtlIGFuIG9wZW5fcmV2c1xuICAgICAgICAvLyByZXF1ZXN0XG4gICAgICAgIGZvcm1hdFJlc3VsdCA9IGZvcm1hdFJlc3VsdEZvck9wZW5SZXZzR2V0O1xuICAgICAgfVxuXG4gICAgICAvLyBnbG9iYWxseS1zdXBwbGllZCBvcHRpb25zXG4gICAgICBbJ3JldnMnLCAnYXR0YWNobWVudHMnLCAnYmluYXJ5JywgJ2FqYXgnLCAnbGF0ZXN0J10uZm9yRWFjaChmdW5jdGlvbiAocGFyYW0pIHtcbiAgICAgICAgaWYgKHBhcmFtIGluIG9wdHMpIHtcbiAgICAgICAgICBkb2NPcHRzW3BhcmFtXSA9IG9wdHNbcGFyYW1dO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGRiLmdldChkb2NJZCwgZG9jT3B0cywgZnVuY3Rpb24gKGVyciwgcmVzKSB7XG4gICAgICAgIHZhciByZXN1bHQ7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgcmVzdWx0ID0gW3tlcnJvcjogZXJyfV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzdWx0ID0gZm9ybWF0UmVzdWx0KHJlcyk7XG4gICAgICAgIH1cbiAgICAgICAgZ290UmVzdWx0KGRvY0lkeCwgZG9jSWQsIHJlc3VsdCk7XG4gICAgICAgIG5leHRCYXRjaCgpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBuZXh0QmF0Y2goKTtcblxufVxuXG5mdW5jdGlvbiBpc0Nocm9tZUFwcCgpIHtcbiAgcmV0dXJuICh0eXBlb2YgY2hyb21lICE9PSBcInVuZGVmaW5lZFwiICYmXG4gICAgdHlwZW9mIGNocm9tZS5zdG9yYWdlICE9PSBcInVuZGVmaW5lZFwiICYmXG4gICAgdHlwZW9mIGNocm9tZS5zdG9yYWdlLmxvY2FsICE9PSBcInVuZGVmaW5lZFwiKTtcbn1cblxudmFyIGhhc0xvY2FsO1xuXG5pZiAoaXNDaHJvbWVBcHAoKSkge1xuICBoYXNMb2NhbCA9IGZhbHNlO1xufSBlbHNlIHtcbiAgdHJ5IHtcbiAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSgnX3BvdWNoX2NoZWNrX2xvY2Fsc3RvcmFnZScsIDEpO1xuICAgIGhhc0xvY2FsID0gISFsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnX3BvdWNoX2NoZWNrX2xvY2Fsc3RvcmFnZScpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaGFzTG9jYWwgPSBmYWxzZTtcbiAgfVxufVxuXG5mdW5jdGlvbiBoYXNMb2NhbFN0b3JhZ2UoKSB7XG4gIHJldHVybiBoYXNMb2NhbDtcbn1cblxuaW5oZXJpdHMoQ2hhbmdlcywgZXZlbnRzLkV2ZW50RW1pdHRlcik7XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG5mdW5jdGlvbiBhdHRhY2hCcm93c2VyRXZlbnRzKHNlbGYpIHtcbiAgaWYgKGlzQ2hyb21lQXBwKCkpIHtcbiAgICBjaHJvbWUuc3RvcmFnZS5vbkNoYW5nZWQuYWRkTGlzdGVuZXIoZnVuY3Rpb24gKGUpIHtcbiAgICAgIC8vIG1ha2Ugc3VyZSBpdCdzIGV2ZW50IGFkZHJlc3NlZCB0byB1c1xuICAgICAgaWYgKGUuZGJfbmFtZSAhPSBudWxsKSB7XG4gICAgICAgIC8vb2JqZWN0IG9ubHkgaGFzIG9sZFZhbHVlLCBuZXdWYWx1ZSBtZW1iZXJzXG4gICAgICAgIHNlbGYuZW1pdChlLmRiTmFtZS5uZXdWYWx1ZSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0gZWxzZSBpZiAoaGFzTG9jYWxTdG9yYWdlKCkpIHtcbiAgICBpZiAodHlwZW9mIGFkZEV2ZW50TGlzdGVuZXIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBhZGRFdmVudExpc3RlbmVyKFwic3RvcmFnZVwiLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBzZWxmLmVtaXQoZS5rZXkpO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHsgLy8gb2xkIElFXG4gICAgICB3aW5kb3cuYXR0YWNoRXZlbnQoXCJzdG9yYWdlXCIsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHNlbGYuZW1pdChlLmtleSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gQ2hhbmdlcygpIHtcbiAgZXZlbnRzLkV2ZW50RW1pdHRlci5jYWxsKHRoaXMpO1xuICB0aGlzLl9saXN0ZW5lcnMgPSB7fTtcblxuICBhdHRhY2hCcm93c2VyRXZlbnRzKHRoaXMpO1xufVxuQ2hhbmdlcy5wcm90b3R5cGUuYWRkTGlzdGVuZXIgPSBmdW5jdGlvbiAoZGJOYW1lLCBpZCwgZGIsIG9wdHMpIHtcbiAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gIGlmICh0aGlzLl9saXN0ZW5lcnNbaWRdKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIGlucHJvZ3Jlc3MgPSBmYWxzZTtcbiAgZnVuY3Rpb24gZXZlbnRGdW5jdGlvbigpIHtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICBpZiAoIXNlbGYuX2xpc3RlbmVyc1tpZF0pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKGlucHJvZ3Jlc3MpIHtcbiAgICAgIGlucHJvZ3Jlc3MgPSAnd2FpdGluZyc7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlucHJvZ3Jlc3MgPSB0cnVlO1xuICAgIHZhciBjaGFuZ2VzT3B0cyA9IHBpY2sob3B0cywgW1xuICAgICAgJ3N0eWxlJywgJ2luY2x1ZGVfZG9jcycsICdhdHRhY2htZW50cycsICdjb25mbGljdHMnLCAnZmlsdGVyJyxcbiAgICAgICdkb2NfaWRzJywgJ3ZpZXcnLCAnc2luY2UnLCAncXVlcnlfcGFyYW1zJywgJ2JpbmFyeSdcbiAgICBdKTtcblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgZnVuY3Rpb24gb25FcnJvcigpIHtcbiAgICAgIGlucHJvZ3Jlc3MgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBkYi5jaGFuZ2VzKGNoYW5nZXNPcHRzKS5vbignY2hhbmdlJywgZnVuY3Rpb24gKGMpIHtcbiAgICAgIGlmIChjLnNlcSA+IG9wdHMuc2luY2UgJiYgIW9wdHMuY2FuY2VsbGVkKSB7XG4gICAgICAgIG9wdHMuc2luY2UgPSBjLnNlcTtcbiAgICAgICAgb3B0cy5vbkNoYW5nZShjKTtcbiAgICAgIH1cbiAgICB9KS5vbignY29tcGxldGUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBpZiAoaW5wcm9ncmVzcyA9PT0gJ3dhaXRpbmcnKSB7XG4gICAgICAgIGltbWVkaWF0ZShldmVudEZ1bmN0aW9uKTtcbiAgICAgIH1cbiAgICAgIGlucHJvZ3Jlc3MgPSBmYWxzZTtcbiAgICB9KS5vbignZXJyb3InLCBvbkVycm9yKTtcbiAgfVxuICB0aGlzLl9saXN0ZW5lcnNbaWRdID0gZXZlbnRGdW5jdGlvbjtcbiAgdGhpcy5vbihkYk5hbWUsIGV2ZW50RnVuY3Rpb24pO1xufTtcblxuQ2hhbmdlcy5wcm90b3R5cGUucmVtb3ZlTGlzdGVuZXIgPSBmdW5jdGlvbiAoZGJOYW1lLCBpZCkge1xuICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgaWYgKCEoaWQgaW4gdGhpcy5fbGlzdGVuZXJzKSkge1xuICAgIHJldHVybjtcbiAgfVxuICBldmVudHMuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lci5jYWxsKHRoaXMsIGRiTmFtZSxcbiAgICB0aGlzLl9saXN0ZW5lcnNbaWRdKTtcbiAgZGVsZXRlIHRoaXMuX2xpc3RlbmVyc1tpZF07XG59O1xuXG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG5DaGFuZ2VzLnByb3RvdHlwZS5ub3RpZnlMb2NhbFdpbmRvd3MgPSBmdW5jdGlvbiAoZGJOYW1lKSB7XG4gIC8vZG8gYSB1c2VsZXNzIGNoYW5nZSBvbiBhIHN0b3JhZ2UgdGhpbmdcbiAgLy9pbiBvcmRlciB0byBnZXQgb3RoZXIgd2luZG93cydzIGxpc3RlbmVycyB0byBhY3RpdmF0ZVxuICBpZiAoaXNDaHJvbWVBcHAoKSkge1xuICAgIGNocm9tZS5zdG9yYWdlLmxvY2FsLnNldCh7ZGJOYW1lOiBkYk5hbWV9KTtcbiAgfSBlbHNlIGlmIChoYXNMb2NhbFN0b3JhZ2UoKSkge1xuICAgIGxvY2FsU3RvcmFnZVtkYk5hbWVdID0gKGxvY2FsU3RvcmFnZVtkYk5hbWVdID09PSBcImFcIikgPyBcImJcIiA6IFwiYVwiO1xuICB9XG59O1xuXG5DaGFuZ2VzLnByb3RvdHlwZS5ub3RpZnkgPSBmdW5jdGlvbiAoZGJOYW1lKSB7XG4gIHRoaXMuZW1pdChkYk5hbWUpO1xuICB0aGlzLm5vdGlmeUxvY2FsV2luZG93cyhkYk5hbWUpO1xufTtcblxuZnVuY3Rpb24gZ3VhcmRlZENvbnNvbGUobWV0aG9kKSB7XG4gIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gIGlmIChjb25zb2xlICE9PSAndW5kZWZpbmVkJyAmJiBtZXRob2QgaW4gY29uc29sZSkge1xuICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICBjb25zb2xlW21ldGhvZF0uYXBwbHkoY29uc29sZSwgYXJncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gcmFuZG9tTnVtYmVyKG1pbiwgbWF4KSB7XG4gIHZhciBtYXhUaW1lb3V0ID0gNjAwMDAwOyAvLyBIYXJkLWNvZGVkIGRlZmF1bHQgb2YgMTAgbWludXRlc1xuICBtaW4gPSBwYXJzZUludChtaW4sIDEwKSB8fCAwO1xuICBtYXggPSBwYXJzZUludChtYXgsIDEwKTtcbiAgaWYgKG1heCAhPT0gbWF4IHx8IG1heCA8PSBtaW4pIHtcbiAgICBtYXggPSAobWluIHx8IDEpIDw8IDE7IC8vZG91YmxpbmdcbiAgfSBlbHNlIHtcbiAgICBtYXggPSBtYXggKyAxO1xuICB9XG4gIC8vIEluIG9yZGVyIHRvIG5vdCBleGNlZWQgbWF4VGltZW91dCwgcGljayBhIHJhbmRvbSB2YWx1ZSBiZXR3ZWVuIGhhbGYgb2YgbWF4VGltZW91dCBhbmQgbWF4VGltZW91dFxuICBpZihtYXggPiBtYXhUaW1lb3V0KSB7XG4gICAgbWluID0gbWF4VGltZW91dCA+PiAxOyAvLyBkaXZpZGUgYnkgdHdvXG4gICAgbWF4ID0gbWF4VGltZW91dDtcbiAgfVxuICB2YXIgcmF0aW8gPSBNYXRoLnJhbmRvbSgpO1xuICB2YXIgcmFuZ2UgPSBtYXggLSBtaW47XG5cbiAgcmV0dXJuIH5+KHJhbmdlICogcmF0aW8gKyBtaW4pOyAvLyB+fiBjb2VyY2VzIHRvIGFuIGludCwgYnV0IGZhc3QuXG59XG5cbmZ1bmN0aW9uIGRlZmF1bHRCYWNrT2ZmKG1pbikge1xuICB2YXIgbWF4ID0gMDtcbiAgaWYgKCFtaW4pIHtcbiAgICBtYXggPSAyMDAwO1xuICB9XG4gIHJldHVybiByYW5kb21OdW1iZXIobWluLCBtYXgpO1xufVxuXG4vLyBkZXNpZ25lZCB0byBnaXZlIGluZm8gdG8gYnJvd3NlciB1c2Vycywgd2hvIGFyZSBkaXN0dXJiZWRcbi8vIHdoZW4gdGhleSBzZWUgaHR0cCBlcnJvcnMgaW4gdGhlIGNvbnNvbGVcbmZ1bmN0aW9uIGV4cGxhaW5FcnJvcihzdGF0dXMsIHN0cikge1xuICBndWFyZGVkQ29uc29sZSgnaW5mbycsICdUaGUgYWJvdmUgJyArIHN0YXR1cyArICcgaXMgdG90YWxseSBub3JtYWwuICcgKyBzdHIpO1xufVxuXG4vLyBmb3JrZWQgZnJvbVxuLy8gaHR0cHM6Ly9naXRodWIuY29tL3ZtYXR0b3MvanMtZXh0ZW5kL2Jsb2IvNzAyM2ZkNjlhOWU5NTUyNjg4MDg2YjhiODAwNmIxZmNmOTE2YTMwNi9leHRlbmQuanNcbi8vIFRPRE86IEkgZG9uJ3Qga25vdyB3aHkgd2UgaGF2ZSB0d28gZGlmZmVyZW50IGV4dGVuZCgpIGZ1bmN0aW9ucyBpbiBQb3VjaERCXG5cbnZhciBzbGljZSA9IEFycmF5LnByb3RvdHlwZS5zbGljZTtcbnZhciBlYWNoID0gQXJyYXkucHJvdG90eXBlLmZvckVhY2g7XG5cbmZ1bmN0aW9uIGV4dGVuZCQxKG9iaikge1xuICBpZiAodHlwZW9mIG9iaiAhPT0gJ29iamVjdCcpIHtcbiAgICB0aHJvdyBvYmogKyAnIGlzIG5vdCBhbiBvYmplY3QnIDtcbiAgfVxuXG4gIHZhciBzb3VyY2VzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuXG4gIGVhY2guY2FsbChzb3VyY2VzLCBmdW5jdGlvbiAoc291cmNlKSB7XG4gICAgaWYgKHNvdXJjZSkge1xuICAgICAgZm9yICh2YXIgcHJvcCBpbiBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBzb3VyY2VbcHJvcF0gPT09ICdvYmplY3QnICYmIG9ialtwcm9wXSkge1xuICAgICAgICAgIGV4dGVuZCQxLmNhbGwob2JqLCBvYmpbcHJvcF0sIHNvdXJjZVtwcm9wXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgb2JqW3Byb3BdID0gc291cmNlW3Byb3BdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9KTtcblxuICByZXR1cm4gb2JqO1xufVxuXG5pbmhlcml0cyhQb3VjaEVycm9yLCBFcnJvcik7XG5cbmZ1bmN0aW9uIFBvdWNoRXJyb3Ioc3RhdHVzLCBlcnJvciwgcmVhc29uKSB7XG4gIEVycm9yLmNhbGwodGhpcywgcmVhc29uKTtcbiAgdGhpcy5zdGF0dXMgPSBzdGF0dXM7XG4gIHRoaXMubmFtZSA9IGVycm9yO1xuICB0aGlzLm1lc3NhZ2UgPSByZWFzb247XG4gIHRoaXMuZXJyb3IgPSB0cnVlO1xufVxuXG5Qb3VjaEVycm9yLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHtcbiAgICBzdGF0dXM6IHRoaXMuc3RhdHVzLFxuICAgIG5hbWU6IHRoaXMubmFtZSxcbiAgICBtZXNzYWdlOiB0aGlzLm1lc3NhZ2UsXG4gICAgcmVhc29uOiB0aGlzLnJlYXNvblxuICB9KTtcbn07XG5cbnZhciBVTkFVVEhPUklaRUQgPSBuZXcgUG91Y2hFcnJvcig0MDEsICd1bmF1dGhvcml6ZWQnLCBcIk5hbWUgb3IgcGFzc3dvcmQgaXMgaW5jb3JyZWN0LlwiKTtcbnZhciBNSVNTSU5HX0JVTEtfRE9DUyA9IG5ldyBQb3VjaEVycm9yKDQwMCwgJ2JhZF9yZXF1ZXN0JywgXCJNaXNzaW5nIEpTT04gbGlzdCBvZiAnZG9jcydcIik7XG52YXIgTUlTU0lOR19ET0MgPSBuZXcgUG91Y2hFcnJvcig0MDQsICdub3RfZm91bmQnLCAnbWlzc2luZycpO1xudmFyIFJFVl9DT05GTElDVCA9IG5ldyBQb3VjaEVycm9yKDQwOSwgJ2NvbmZsaWN0JywgJ0RvY3VtZW50IHVwZGF0ZSBjb25mbGljdCcpO1xudmFyIElOVkFMSURfSUQgPSBuZXcgUG91Y2hFcnJvcig0MDAsICdiYWRfcmVxdWVzdCcsICdfaWQgZmllbGQgbXVzdCBjb250YWluIGEgc3RyaW5nJyk7XG52YXIgTUlTU0lOR19JRCA9IG5ldyBQb3VjaEVycm9yKDQxMiwgJ21pc3NpbmdfaWQnLCAnX2lkIGlzIHJlcXVpcmVkIGZvciBwdXRzJyk7XG52YXIgUkVTRVJWRURfSUQgPSBuZXcgUG91Y2hFcnJvcig0MDAsICdiYWRfcmVxdWVzdCcsICdPbmx5IHJlc2VydmVkIGRvY3VtZW50IGlkcyBtYXkgc3RhcnQgd2l0aCB1bmRlcnNjb3JlLicpO1xudmFyIE5PVF9PUEVOID0gbmV3IFBvdWNoRXJyb3IoNDEyLCAncHJlY29uZGl0aW9uX2ZhaWxlZCcsICdEYXRhYmFzZSBub3Qgb3BlbicpO1xudmFyIFVOS05PV05fRVJST1IgPSBuZXcgUG91Y2hFcnJvcig1MDAsICd1bmtub3duX2Vycm9yJywgJ0RhdGFiYXNlIGVuY291bnRlcmVkIGFuIHVua25vd24gZXJyb3InKTtcbnZhciBCQURfQVJHID0gbmV3IFBvdWNoRXJyb3IoNTAwLCAnYmFkYXJnJywgJ1NvbWUgcXVlcnkgYXJndW1lbnQgaXMgaW52YWxpZCcpO1xudmFyIElOVkFMSURfUkVRVUVTVCA9IG5ldyBQb3VjaEVycm9yKDQwMCwgJ2ludmFsaWRfcmVxdWVzdCcsICdSZXF1ZXN0IHdhcyBpbnZhbGlkJyk7XG52YXIgUVVFUllfUEFSU0VfRVJST1IgPSBuZXcgUG91Y2hFcnJvcig0MDAsICdxdWVyeV9wYXJzZV9lcnJvcicsICdTb21lIHF1ZXJ5IHBhcmFtZXRlciBpcyBpbnZhbGlkJyk7XG52YXIgRE9DX1ZBTElEQVRJT04gPSBuZXcgUG91Y2hFcnJvcig1MDAsICdkb2NfdmFsaWRhdGlvbicsICdCYWQgc3BlY2lhbCBkb2N1bWVudCBtZW1iZXInKTtcbnZhciBCQURfUkVRVUVTVCA9IG5ldyBQb3VjaEVycm9yKDQwMCwgJ2JhZF9yZXF1ZXN0JywgJ1NvbWV0aGluZyB3cm9uZyB3aXRoIHRoZSByZXF1ZXN0Jyk7XG52YXIgTk9UX0FOX09CSkVDVCA9IG5ldyBQb3VjaEVycm9yKDQwMCwgJ2JhZF9yZXF1ZXN0JywgJ0RvY3VtZW50IG11c3QgYmUgYSBKU09OIG9iamVjdCcpO1xudmFyIERCX01JU1NJTkcgPSBuZXcgUG91Y2hFcnJvcig0MDQsICdub3RfZm91bmQnLCAnRGF0YWJhc2Ugbm90IGZvdW5kJyk7XG52YXIgSURCX0VSUk9SID0gbmV3IFBvdWNoRXJyb3IoNTAwLCAnaW5kZXhlZF9kYl93ZW50X2JhZCcsICd1bmtub3duJyk7XG52YXIgV1NRX0VSUk9SID0gbmV3IFBvdWNoRXJyb3IoNTAwLCAnd2ViX3NxbF93ZW50X2JhZCcsICd1bmtub3duJyk7XG52YXIgTERCX0VSUk9SID0gbmV3IFBvdWNoRXJyb3IoNTAwLCAnbGV2ZWxEQl93ZW50X3dlbnRfYmFkJywgJ3Vua25vd24nKTtcbnZhciBGT1JCSURERU4gPSBuZXcgUG91Y2hFcnJvcig0MDMsICdmb3JiaWRkZW4nLCAnRm9yYmlkZGVuIGJ5IGRlc2lnbiBkb2MgdmFsaWRhdGVfZG9jX3VwZGF0ZSBmdW5jdGlvbicpO1xudmFyIElOVkFMSURfUkVWID0gbmV3IFBvdWNoRXJyb3IoNDAwLCAnYmFkX3JlcXVlc3QnLCAnSW52YWxpZCByZXYgZm9ybWF0Jyk7XG52YXIgRklMRV9FWElTVFMgPSBuZXcgUG91Y2hFcnJvcig0MTIsICdmaWxlX2V4aXN0cycsICdUaGUgZGF0YWJhc2UgY291bGQgbm90IGJlIGNyZWF0ZWQsIHRoZSBmaWxlIGFscmVhZHkgZXhpc3RzLicpO1xudmFyIE1JU1NJTkdfU1RVQiA9IG5ldyBQb3VjaEVycm9yKDQxMiwgJ21pc3Npbmdfc3R1YicsICdBIHByZS1leGlzdGluZyBhdHRhY2htZW50IHN0dWIgd2FzblxcJ3QgZm91bmQnKTtcbnZhciBJTlZBTElEX1VSTCA9IG5ldyBQb3VjaEVycm9yKDQxMywgJ2ludmFsaWRfdXJsJywgJ1Byb3ZpZGVkIFVSTCBpcyBpbnZhbGlkJyk7XG5cbmZ1bmN0aW9uIGNyZWF0ZUVycm9yKGVycm9yLCByZWFzb24pIHtcbiAgZnVuY3Rpb24gQ3VzdG9tUG91Y2hFcnJvcihyZWFzb24pIHtcbiAgICAvLyBpbmhlcml0IGVycm9yIHByb3BlcnRpZXMgZnJvbSBvdXIgcGFyZW50IGVycm9yIG1hbnVhbGx5XG4gICAgLy8gc28gYXMgdG8gYWxsb3cgcHJvcGVyIEpTT04gcGFyc2luZy5cbiAgICAvKiBqc2hpbnQgaWdub3JlOnN0YXJ0ICovXG4gICAgZm9yICh2YXIgcCBpbiBlcnJvcikge1xuICAgICAgaWYgKHR5cGVvZiBlcnJvcltwXSAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aGlzW3BdID0gZXJyb3JbcF07XG4gICAgICB9XG4gICAgfVxuICAgIC8qIGpzaGludCBpZ25vcmU6ZW5kICovXG4gICAgaWYgKHJlYXNvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB9XG4gIH1cbiAgQ3VzdG9tUG91Y2hFcnJvci5wcm90b3R5cGUgPSBQb3VjaEVycm9yLnByb3RvdHlwZTtcbiAgcmV0dXJuIG5ldyBDdXN0b21Qb3VjaEVycm9yKHJlYXNvbik7XG59XG5cbmZ1bmN0aW9uIGdlbmVyYXRlRXJyb3JGcm9tUmVzcG9uc2UoZXJyKSB7XG5cbiAgaWYgKHR5cGVvZiBlcnIgIT09ICdvYmplY3QnKSB7XG4gICAgdmFyIGRhdGEgPSBlcnI7XG4gICAgZXJyID0gVU5LTk9XTl9FUlJPUjtcbiAgICBlcnIuZGF0YSA9IGRhdGE7XG4gIH1cblxuICBpZiAoJ2Vycm9yJyBpbiBlcnIgJiYgZXJyLmVycm9yID09PSAnY29uZmxpY3QnKSB7XG4gICAgZXJyLm5hbWUgPSAnY29uZmxpY3QnO1xuICAgIGVyci5zdGF0dXMgPSA0MDk7XG4gIH1cblxuICBpZiAoISgnbmFtZScgaW4gZXJyKSkge1xuICAgIGVyci5uYW1lID0gZXJyLmVycm9yIHx8ICd1bmtub3duJztcbiAgfVxuXG4gIGlmICghKCdzdGF0dXMnIGluIGVycikpIHtcbiAgICBlcnIuc3RhdHVzID0gNTAwO1xuICB9XG5cbiAgaWYgKCEoJ21lc3NhZ2UnIGluIGVycikpIHtcbiAgICBlcnIubWVzc2FnZSA9IGVyci5tZXNzYWdlIHx8IGVyci5yZWFzb247XG4gIH1cblxuICByZXR1cm4gZXJyO1xufVxuXG5mdW5jdGlvbiB0cnlGaWx0ZXIoZmlsdGVyLCBkb2MsIHJlcSkge1xuICB0cnkge1xuICAgIHJldHVybiAhZmlsdGVyKGRvYywgcmVxKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgdmFyIG1zZyA9ICdGaWx0ZXIgZnVuY3Rpb24gdGhyZXc6ICcgKyBlcnIudG9TdHJpbmcoKTtcbiAgICByZXR1cm4gY3JlYXRlRXJyb3IoQkFEX1JFUVVFU1QsIG1zZyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZmlsdGVyQ2hhbmdlKG9wdHMpIHtcbiAgdmFyIHJlcSA9IHt9O1xuICB2YXIgaGFzRmlsdGVyID0gb3B0cy5maWx0ZXIgJiYgdHlwZW9mIG9wdHMuZmlsdGVyID09PSAnZnVuY3Rpb24nO1xuICByZXEucXVlcnkgPSBvcHRzLnF1ZXJ5X3BhcmFtcztcblxuICByZXR1cm4gZnVuY3Rpb24gZmlsdGVyKGNoYW5nZSkge1xuICAgIGlmICghY2hhbmdlLmRvYykge1xuICAgICAgLy8gQ1NHIHNlbmRzIGV2ZW50cyBvbiB0aGUgY2hhbmdlcyBmZWVkIHRoYXQgZG9uJ3QgaGF2ZSBkb2N1bWVudHMsXG4gICAgICAvLyB0aGlzIGhhY2sgbWFrZXMgYSB3aG9sZSBsb3Qgb2YgZXhpc3RpbmcgY29kZSByb2J1c3QuXG4gICAgICBjaGFuZ2UuZG9jID0ge307XG4gICAgfVxuXG4gICAgdmFyIGZpbHRlclJldHVybiA9IGhhc0ZpbHRlciAmJiB0cnlGaWx0ZXIob3B0cy5maWx0ZXIsIGNoYW5nZS5kb2MsIHJlcSk7XG5cbiAgICBpZiAodHlwZW9mIGZpbHRlclJldHVybiA9PT0gJ29iamVjdCcpIHtcbiAgICAgIHJldHVybiBmaWx0ZXJSZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGZpbHRlclJldHVybikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmICghb3B0cy5pbmNsdWRlX2RvY3MpIHtcbiAgICAgIGRlbGV0ZSBjaGFuZ2UuZG9jO1xuICAgIH0gZWxzZSBpZiAoIW9wdHMuYXR0YWNobWVudHMpIHtcbiAgICAgIGZvciAodmFyIGF0dCBpbiBjaGFuZ2UuZG9jLl9hdHRhY2htZW50cykge1xuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgICAgICBpZiAoY2hhbmdlLmRvYy5fYXR0YWNobWVudHMuaGFzT3duUHJvcGVydHkoYXR0KSkge1xuICAgICAgICAgIGNoYW5nZS5kb2MuX2F0dGFjaG1lbnRzW2F0dF0uc3R1YiA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGZsYXR0ZW4oYXJycykge1xuICB2YXIgcmVzID0gW107XG4gIGZvciAodmFyIGkgPSAwLCBsZW4gPSBhcnJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgcmVzID0gcmVzLmNvbmNhdChhcnJzW2ldKTtcbiAgfVxuICByZXR1cm4gcmVzO1xufVxuXG4vLyBEZXRlcm1pbmUgaWQgYW4gSUQgaXMgdmFsaWRcbi8vICAgLSBpbnZhbGlkIElEcyBiZWdpbiB3aXRoIGFuIHVuZGVyZXNjb3JlIHRoYXQgZG9lcyBub3QgYmVnaW4gJ19kZXNpZ24nIG9yXG4vLyAgICAgJ19sb2NhbCdcbi8vICAgLSBhbnkgb3RoZXIgc3RyaW5nIHZhbHVlIGlzIGEgdmFsaWQgaWRcbi8vIFJldHVybnMgdGhlIHNwZWNpZmljIGVycm9yIG9iamVjdCBmb3IgZWFjaCBjYXNlXG5mdW5jdGlvbiBpbnZhbGlkSWRFcnJvcihpZCkge1xuICB2YXIgZXJyO1xuICBpZiAoIWlkKSB7XG4gICAgZXJyID0gY3JlYXRlRXJyb3IoTUlTU0lOR19JRCk7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGlkICE9PSAnc3RyaW5nJykge1xuICAgIGVyciA9IGNyZWF0ZUVycm9yKElOVkFMSURfSUQpO1xuICB9IGVsc2UgaWYgKC9eXy8udGVzdChpZCkgJiYgISgvXl8oZGVzaWdufGxvY2FsKS8pLnRlc3QoaWQpKSB7XG4gICAgZXJyID0gY3JlYXRlRXJyb3IoUkVTRVJWRURfSUQpO1xuICB9XG4gIGlmIChlcnIpIHtcbiAgICB0aHJvdyBlcnI7XG4gIH1cbn1cblxuZnVuY3Rpb24gbGlzdGVuZXJDb3VudChlZSwgdHlwZSkge1xuICByZXR1cm4gJ2xpc3RlbmVyQ291bnQnIGluIGVlID8gZWUubGlzdGVuZXJDb3VudCh0eXBlKSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudHMuRXZlbnRFbWl0dGVyLmxpc3RlbmVyQ291bnQoZWUsIHR5cGUpO1xufVxuXG4vLyBDdXN0b20gbmV4dFRpY2soKSBzaGltIGZvciBicm93c2Vycy4gSW4gbm9kZSwgdGhpcyB3aWxsIGp1c3QgYmUgcHJvY2Vzcy5uZXh0VGljaygpLiBXZVxuLy8gYXZvaWQgdXNpbmcgcHJvY2Vzcy5uZXh0VGljaygpIGRpcmVjdGx5IGJlY2F1c2UgdGhlIHBvbHlmaWxsIGlzIHZlcnkgbGFyZ2UgYW5kIHdlIGRvbid0XG4vLyBuZWVkIGFsbCBvZiBpdCAoc2VlOiBodHRwczovL2dpdGh1Yi5jb20vZGVmdW5jdHpvbWJpZS9ub2RlLXByb2Nlc3MpLlxuLy8gXCJpbW1lZGlhdGVcIiAzLjAuOCBpcyB1c2VkIGJ5IGxpZSwgYW5kIGl0J3MgYSBzbWFsbGVyIHZlcnNpb24gb2YgdGhlIGxhdGVzdCBcImltbWVkaWF0ZVwiXG4vLyBwYWNrYWdlLCBzbyBpdCdzIHRoZSBvbmUgd2UgdXNlLlxuLy8gV2hlbiB3ZSB1c2UgbmV4dFRpY2soKSBpbiBvdXIgY29kZWJhc2UsIHdlIG9ubHkgY2FyZSBhYm91dCBub3QgcmVsZWFzaW5nIFphbGdvXG4vLyAoc2VlOiBodHRwOi8vYmxvZy5penMubWUvcG9zdC81OTE0Mjc0MjE0My9kZXNpZ25pbmctYXBpcy1mb3ItYXN5bmNocm9ueSkuXG4vLyBNaWNyb3Rhc2sgdnMgbWFjcm90YXNrIGRvZXNuJ3QgbWF0dGVyIHRvIHVzLiBTbyB3ZSdyZSBmcmVlIHRvIHVzZSB0aGUgZmFzdGVzdFxuLy8gKGxlYXN0IGxhdGVuY3kpIG9wdGlvbiwgd2hpY2ggaXMgXCJpbW1lZGlhdGVcIiBkdWUgdG8gdXNlIG9mIG1pY3JvdGFza3MuXG4vLyBBbGwgb2Ygb3VyIG5leHRUaWNrcyBhcmUgaXNvbGF0ZWQgdG8gdGhpcyBvbmUgZnVuY3Rpb24gc28gd2UgY2FuIGVhc2lseSBzd2FwIG91dCBvbmVcbi8vIGltcGxlbWVudGF0aW9uIGZvciBhbm90aGVyLlxuXG5mdW5jdGlvbiBwYXJzZURlc2lnbkRvY0Z1bmN0aW9uTmFtZShzKSB7XG4gIGlmICghcykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIHZhciBwYXJ0cyA9IHMuc3BsaXQoJy8nKTtcbiAgaWYgKHBhcnRzLmxlbmd0aCA9PT0gMikge1xuICAgIHJldHVybiBwYXJ0cztcbiAgfVxuICBpZiAocGFydHMubGVuZ3RoID09PSAxKSB7XG4gICAgcmV0dXJuIFtzLCBzXTtcbiAgfVxuICByZXR1cm4gbnVsbDtcbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplRGVzaWduRG9jRnVuY3Rpb25OYW1lKHMpIHtcbiAgdmFyIG5vcm1hbGl6ZWQgPSBwYXJzZURlc2lnbkRvY0Z1bmN0aW9uTmFtZShzKTtcbiAgcmV0dXJuIG5vcm1hbGl6ZWQgPyBub3JtYWxpemVkLmpvaW4oJy8nKSA6IG51bGw7XG59XG5cbi8vIG9yaWdpbmFsbHkgcGFyc2VVcmkgMS4yLjIsIG5vdyBwYXRjaGVkIGJ5IHVzXG4vLyAoYykgU3RldmVuIExldml0aGFuIDxzdGV2ZW5sZXZpdGhhbi5jb20+XG4vLyBNSVQgTGljZW5zZVxudmFyIGtleXMgPSBbXCJzb3VyY2VcIiwgXCJwcm90b2NvbFwiLCBcImF1dGhvcml0eVwiLCBcInVzZXJJbmZvXCIsIFwidXNlclwiLCBcInBhc3N3b3JkXCIsXG4gICAgXCJob3N0XCIsIFwicG9ydFwiLCBcInJlbGF0aXZlXCIsIFwicGF0aFwiLCBcImRpcmVjdG9yeVwiLCBcImZpbGVcIiwgXCJxdWVyeVwiLCBcImFuY2hvclwiXTtcbnZhciBxTmFtZSA9XCJxdWVyeUtleVwiO1xudmFyIHFQYXJzZXIgPSAvKD86XnwmKShbXiY9XSopPT8oW14mXSopL2c7XG5cbi8vIHVzZSB0aGUgXCJsb29zZVwiIHBhcnNlclxuLyoganNoaW50IG1heGxlbjogZmFsc2UgKi9cbnZhciBwYXJzZXIgPSAvXig/Oig/IVteOkBdKzpbXjpAXFwvXSpAKShbXjpcXC8/Iy5dKyk6KT8oPzpcXC9cXC8pPygoPzooKFteOkBdKikoPzo6KFteOkBdKikpPyk/QCk/KFteOlxcLz8jXSopKD86OihcXGQqKSk/KSgoKFxcLyg/OltePyNdKD8hW14/I1xcL10qXFwuW14/I1xcLy5dKyg/Ols/I118JCkpKSpcXC8/KT8oW14/I1xcL10qKSkoPzpcXD8oW14jXSopKT8oPzojKC4qKSk/KS87XG5cbmZ1bmN0aW9uIHBhcnNlVXJpKHN0cikge1xuICB2YXIgbSA9IHBhcnNlci5leGVjKHN0cik7XG4gIHZhciB1cmkgPSB7fTtcbiAgdmFyIGkgPSAxNDtcblxuICB3aGlsZSAoaS0tKSB7XG4gICAgdmFyIGtleSA9IGtleXNbaV07XG4gICAgdmFyIHZhbHVlID0gbVtpXSB8fCBcIlwiO1xuICAgIHZhciBlbmNvZGVkID0gWyd1c2VyJywgJ3Bhc3N3b3JkJ10uaW5kZXhPZihrZXkpICE9PSAtMTtcbiAgICB1cmlba2V5XSA9IGVuY29kZWQgPyBkZWNvZGVVUklDb21wb25lbnQodmFsdWUpIDogdmFsdWU7XG4gIH1cblxuICB1cmlbcU5hbWVdID0ge307XG4gIHVyaVtrZXlzWzEyXV0ucmVwbGFjZShxUGFyc2VyLCBmdW5jdGlvbiAoJDAsICQxLCAkMikge1xuICAgIGlmICgkMSkge1xuICAgICAgdXJpW3FOYW1lXVskMV0gPSAkMjtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiB1cmk7XG59XG5cbi8vIHRoaXMgaXMgZXNzZW50aWFsbHkgdGhlIFwidXBkYXRlIHN1Z2FyXCIgZnVuY3Rpb24gZnJvbSBkYWxlaGFydmV5L3BvdWNoZGIjMTM4OFxuLy8gdGhlIGRpZmZGdW4gdGVsbHMgdXMgd2hhdCBkZWx0YSB0byBhcHBseSB0byB0aGUgZG9jLiAgaXQgZWl0aGVyIHJldHVybnNcbi8vIHRoZSBkb2MsIG9yIGZhbHNlIGlmIGl0IGRvZXNuJ3QgbmVlZCB0byBkbyBhbiB1cGRhdGUgYWZ0ZXIgYWxsXG5mdW5jdGlvbiB1cHNlcnQoZGIsIGRvY0lkLCBkaWZmRnVuKSB7XG4gIHJldHVybiBuZXcgUG91Y2hQcm9taXNlKGZ1bmN0aW9uIChmdWxmaWxsLCByZWplY3QpIHtcbiAgICBkYi5nZXQoZG9jSWQsIGZ1bmN0aW9uIChlcnIsIGRvYykge1xuICAgICAgaWYgKGVycikge1xuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgICBpZiAoZXJyLnN0YXR1cyAhPT0gNDA0KSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChlcnIpO1xuICAgICAgICB9XG4gICAgICAgIGRvYyA9IHt9O1xuICAgICAgfVxuXG4gICAgICAvLyB0aGUgdXNlciBtaWdodCBjaGFuZ2UgdGhlIF9yZXYsIHNvIHNhdmUgaXQgZm9yIHBvc3Rlcml0eVxuICAgICAgdmFyIGRvY1JldiA9IGRvYy5fcmV2O1xuICAgICAgdmFyIG5ld0RvYyA9IGRpZmZGdW4oZG9jKTtcblxuICAgICAgaWYgKCFuZXdEb2MpIHtcbiAgICAgICAgLy8gaWYgdGhlIGRpZmZGdW4gcmV0dXJucyBmYWxzeSwgd2Ugc2hvcnQtY2lyY3VpdCBhc1xuICAgICAgICAvLyBhbiBvcHRpbWl6YXRpb25cbiAgICAgICAgcmV0dXJuIGZ1bGZpbGwoe3VwZGF0ZWQ6IGZhbHNlLCByZXY6IGRvY1Jldn0pO1xuICAgICAgfVxuXG4gICAgICAvLyB1c2VycyBhcmVuJ3QgYWxsb3dlZCB0byBtb2RpZnkgdGhlc2UgdmFsdWVzLFxuICAgICAgLy8gc28gcmVzZXQgdGhlbSBoZXJlXG4gICAgICBuZXdEb2MuX2lkID0gZG9jSWQ7XG4gICAgICBuZXdEb2MuX3JldiA9IGRvY1JldjtcbiAgICAgIGZ1bGZpbGwodHJ5QW5kUHV0KGRiLCBuZXdEb2MsIGRpZmZGdW4pKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHRyeUFuZFB1dChkYiwgZG9jLCBkaWZmRnVuKSB7XG4gIHJldHVybiBkYi5wdXQoZG9jKS50aGVuKGZ1bmN0aW9uIChyZXMpIHtcbiAgICByZXR1cm4ge1xuICAgICAgdXBkYXRlZDogdHJ1ZSxcbiAgICAgIHJldjogcmVzLnJldlxuICAgIH07XG4gIH0sIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIGlmIChlcnIuc3RhdHVzICE9PSA0MDkpIHtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gICAgcmV0dXJuIHVwc2VydChkYiwgZG9jLl9pZCwgZGlmZkZ1bik7XG4gIH0pO1xufVxuXG4vLyBCRUdJTiBNYXRoLnV1aWQuanNcblxuLyohXG5NYXRoLnV1aWQuanMgKHYxLjQpXG5odHRwOi8vd3d3LmJyb29mYS5jb21cbm1haWx0bzpyb2JlcnRAYnJvb2ZhLmNvbVxuXG5Db3B5cmlnaHQgKGMpIDIwMTAgUm9iZXJ0IEtpZWZmZXJcbkR1YWwgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBhbmQgR1BMIGxpY2Vuc2VzLlxuKi9cblxuLypcbiAqIEdlbmVyYXRlIGEgcmFuZG9tIHV1aWQuXG4gKlxuICogVVNBR0U6IE1hdGgudXVpZChsZW5ndGgsIHJhZGl4KVxuICogICBsZW5ndGggLSB0aGUgZGVzaXJlZCBudW1iZXIgb2YgY2hhcmFjdGVyc1xuICogICByYWRpeCAgLSB0aGUgbnVtYmVyIG9mIGFsbG93YWJsZSB2YWx1ZXMgZm9yIGVhY2ggY2hhcmFjdGVyLlxuICpcbiAqIEVYQU1QTEVTOlxuICogICAvLyBObyBhcmd1bWVudHMgIC0gcmV0dXJucyBSRkM0MTIyLCB2ZXJzaW9uIDQgSURcbiAqICAgPj4+IE1hdGgudXVpZCgpXG4gKiAgIFwiOTIzMjlEMzktNkY1Qy00NTIwLUFCRkMtQUFCNjQ1NDRFMTcyXCJcbiAqXG4gKiAgIC8vIE9uZSBhcmd1bWVudCAtIHJldHVybnMgSUQgb2YgdGhlIHNwZWNpZmllZCBsZW5ndGhcbiAqICAgPj4+IE1hdGgudXVpZCgxNSkgICAgIC8vIDE1IGNoYXJhY3RlciBJRCAoZGVmYXVsdCBiYXNlPTYyKVxuICogICBcIlZjeWR4Z2x0eHJWWlNUVlwiXG4gKlxuICogICAvLyBUd28gYXJndW1lbnRzIC0gcmV0dXJucyBJRCBvZiB0aGUgc3BlY2lmaWVkIGxlbmd0aCwgYW5kIHJhZGl4LiBcbiAqICAgLy8gKFJhZGl4IG11c3QgYmUgPD0gNjIpXG4gKiAgID4+PiBNYXRoLnV1aWQoOCwgMikgIC8vIDggY2hhcmFjdGVyIElEIChiYXNlPTIpXG4gKiAgIFwiMDEwMDEwMTBcIlxuICogICA+Pj4gTWF0aC51dWlkKDgsIDEwKSAvLyA4IGNoYXJhY3RlciBJRCAoYmFzZT0xMClcbiAqICAgXCI0NzQ3MzA0NlwiXG4gKiAgID4+PiBNYXRoLnV1aWQoOCwgMTYpIC8vIDggY2hhcmFjdGVyIElEIChiYXNlPTE2KVxuICogICBcIjA5OEY0RDM1XCJcbiAqL1xudmFyIGNoYXJzID0gKFxuICAnMDEyMzQ1Njc4OUFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaJyArXG4gICdhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eidcbikuc3BsaXQoJycpO1xuZnVuY3Rpb24gZ2V0VmFsdWUocmFkaXgpIHtcbiAgcmV0dXJuIDAgfCBNYXRoLnJhbmRvbSgpICogcmFkaXg7XG59XG5mdW5jdGlvbiB1dWlkKGxlbiwgcmFkaXgpIHtcbiAgcmFkaXggPSByYWRpeCB8fCBjaGFycy5sZW5ndGg7XG4gIHZhciBvdXQgPSAnJztcbiAgdmFyIGkgPSAtMTtcblxuICBpZiAobGVuKSB7XG4gICAgLy8gQ29tcGFjdCBmb3JtXG4gICAgd2hpbGUgKCsraSA8IGxlbikge1xuICAgICAgb3V0ICs9IGNoYXJzW2dldFZhbHVlKHJhZGl4KV07XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG4gIH1cbiAgICAvLyByZmM0MTIyLCB2ZXJzaW9uIDQgZm9ybVxuICAgIC8vIEZpbGwgaW4gcmFuZG9tIGRhdGEuICBBdCBpPT0xOSBzZXQgdGhlIGhpZ2ggYml0cyBvZiBjbG9jayBzZXF1ZW5jZSBhc1xuICAgIC8vIHBlciByZmM0MTIyLCBzZWMuIDQuMS41XG4gIHdoaWxlICgrK2kgPCAzNikge1xuICAgIHN3aXRjaCAoaSkge1xuICAgICAgY2FzZSA4OlxuICAgICAgY2FzZSAxMzpcbiAgICAgIGNhc2UgMTg6XG4gICAgICBjYXNlIDIzOlxuICAgICAgICBvdXQgKz0gJy0nO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMTk6XG4gICAgICAgIG91dCArPSBjaGFyc1soZ2V0VmFsdWUoMTYpICYgMHgzKSB8IDB4OF07XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgb3V0ICs9IGNoYXJzW2dldFZhbHVlKDE2KV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG91dDtcbn1cblxuLy8gV2UgZmV0Y2ggYWxsIGxlYWZzIG9mIHRoZSByZXZpc2lvbiB0cmVlLCBhbmQgc29ydCB0aGVtIGJhc2VkIG9uIHRyZWUgbGVuZ3RoXG4vLyBhbmQgd2hldGhlciB0aGV5IHdlcmUgZGVsZXRlZCwgdW5kZWxldGVkIGRvY3VtZW50cyB3aXRoIHRoZSBsb25nZXN0IHJldmlzaW9uXG4vLyB0cmVlIChtb3N0IGVkaXRzKSB3aW5cbi8vIFRoZSBmaW5hbCBzb3J0IGFsZ29yaXRobSBpcyBzbGlnaHRseSBkb2N1bWVudGVkIGluIGEgc2lkZWJhciBoZXJlOlxuLy8gaHR0cDovL2d1aWRlLmNvdWNoZGIub3JnL2RyYWZ0L2NvbmZsaWN0cy5odG1sXG5mdW5jdGlvbiB3aW5uaW5nUmV2KG1ldGFkYXRhKSB7XG4gIHZhciB3aW5uaW5nSWQ7XG4gIHZhciB3aW5uaW5nUG9zO1xuICB2YXIgd2lubmluZ0RlbGV0ZWQ7XG4gIHZhciB0b1Zpc2l0ID0gbWV0YWRhdGEucmV2X3RyZWUuc2xpY2UoKTtcbiAgdmFyIG5vZGU7XG4gIHdoaWxlICgobm9kZSA9IHRvVmlzaXQucG9wKCkpKSB7XG4gICAgdmFyIHRyZWUgPSBub2RlLmlkcztcbiAgICB2YXIgYnJhbmNoZXMgPSB0cmVlWzJdO1xuICAgIHZhciBwb3MgPSBub2RlLnBvcztcbiAgICBpZiAoYnJhbmNoZXMubGVuZ3RoKSB7IC8vIG5vbi1sZWFmXG4gICAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gYnJhbmNoZXMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgdG9WaXNpdC5wdXNoKHtwb3M6IHBvcyArIDEsIGlkczogYnJhbmNoZXNbaV19KTtcbiAgICAgIH1cbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICB2YXIgZGVsZXRlZCA9ICEhdHJlZVsxXS5kZWxldGVkO1xuICAgIHZhciBpZCA9IHRyZWVbMF07XG4gICAgLy8gc29ydCBieSBkZWxldGVkLCB0aGVuIHBvcywgdGhlbiBpZFxuICAgIGlmICghd2lubmluZ0lkIHx8ICh3aW5uaW5nRGVsZXRlZCAhPT0gZGVsZXRlZCA/IHdpbm5pbmdEZWxldGVkIDpcbiAgICAgICAgd2lubmluZ1BvcyAhPT0gcG9zID8gd2lubmluZ1BvcyA8IHBvcyA6IHdpbm5pbmdJZCA8IGlkKSkge1xuICAgICAgd2lubmluZ0lkID0gaWQ7XG4gICAgICB3aW5uaW5nUG9zID0gcG9zO1xuICAgICAgd2lubmluZ0RlbGV0ZWQgPSBkZWxldGVkO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB3aW5uaW5nUG9zICsgJy0nICsgd2lubmluZ0lkO1xufVxuXG4vLyBQcmV0dHkgbXVjaCBhbGwgYmVsb3cgY2FuIGJlIGNvbWJpbmVkIGludG8gYSBoaWdoZXIgb3JkZXIgZnVuY3Rpb24gdG9cbi8vIHRyYXZlcnNlIHJldmlzaW9uc1xuLy8gVGhlIHJldHVybiB2YWx1ZSBmcm9tIHRoZSBjYWxsYmFjayB3aWxsIGJlIHBhc3NlZCBhcyBjb250ZXh0IHRvIGFsbFxuLy8gY2hpbGRyZW4gb2YgdGhhdCBub2RlXG5mdW5jdGlvbiB0cmF2ZXJzZVJldlRyZWUocmV2cywgY2FsbGJhY2spIHtcbiAgdmFyIHRvVmlzaXQgPSByZXZzLnNsaWNlKCk7XG5cbiAgdmFyIG5vZGU7XG4gIHdoaWxlICgobm9kZSA9IHRvVmlzaXQucG9wKCkpKSB7XG4gICAgdmFyIHBvcyA9IG5vZGUucG9zO1xuICAgIHZhciB0cmVlID0gbm9kZS5pZHM7XG4gICAgdmFyIGJyYW5jaGVzID0gdHJlZVsyXTtcbiAgICB2YXIgbmV3Q3R4ID1cbiAgICAgIGNhbGxiYWNrKGJyYW5jaGVzLmxlbmd0aCA9PT0gMCwgcG9zLCB0cmVlWzBdLCBub2RlLmN0eCwgdHJlZVsxXSk7XG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGJyYW5jaGVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICB0b1Zpc2l0LnB1c2goe3BvczogcG9zICsgMSwgaWRzOiBicmFuY2hlc1tpXSwgY3R4OiBuZXdDdHh9KTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gc29ydEJ5UG9zKGEsIGIpIHtcbiAgcmV0dXJuIGEucG9zIC0gYi5wb3M7XG59XG5cbmZ1bmN0aW9uIGNvbGxlY3RMZWF2ZXMocmV2cykge1xuICB2YXIgbGVhdmVzID0gW107XG4gIHRyYXZlcnNlUmV2VHJlZShyZXZzLCBmdW5jdGlvbiAoaXNMZWFmLCBwb3MsIGlkLCBhY2MsIG9wdHMpIHtcbiAgICBpZiAoaXNMZWFmKSB7XG4gICAgICBsZWF2ZXMucHVzaCh7cmV2OiBwb3MgKyBcIi1cIiArIGlkLCBwb3M6IHBvcywgb3B0czogb3B0c30pO1xuICAgIH1cbiAgfSk7XG4gIGxlYXZlcy5zb3J0KHNvcnRCeVBvcykucmV2ZXJzZSgpO1xuICBmb3IgKHZhciBpID0gMCwgbGVuID0gbGVhdmVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgZGVsZXRlIGxlYXZlc1tpXS5wb3M7XG4gIH1cbiAgcmV0dXJuIGxlYXZlcztcbn1cblxuLy8gcmV0dXJucyByZXZzIG9mIGFsbCBjb25mbGljdHMgdGhhdCBpcyBsZWF2ZXMgc3VjaCB0aGF0XG4vLyAxLiBhcmUgbm90IGRlbGV0ZWQgYW5kXG4vLyAyLiBhcmUgZGlmZmVyZW50IHRoYW4gd2lubmluZyByZXZpc2lvblxuZnVuY3Rpb24gY29sbGVjdENvbmZsaWN0cyhtZXRhZGF0YSkge1xuICB2YXIgd2luID0gd2lubmluZ1JldihtZXRhZGF0YSk7XG4gIHZhciBsZWF2ZXMgPSBjb2xsZWN0TGVhdmVzKG1ldGFkYXRhLnJldl90cmVlKTtcbiAgdmFyIGNvbmZsaWN0cyA9IFtdO1xuICBmb3IgKHZhciBpID0gMCwgbGVuID0gbGVhdmVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgdmFyIGxlYWYgPSBsZWF2ZXNbaV07XG4gICAgaWYgKGxlYWYucmV2ICE9PSB3aW4gJiYgIWxlYWYub3B0cy5kZWxldGVkKSB7XG4gICAgICBjb25mbGljdHMucHVzaChsZWFmLnJldik7XG4gICAgfVxuICB9XG4gIHJldHVybiBjb25mbGljdHM7XG59XG5cbi8vIGNvbXBhY3QgYSB0cmVlIGJ5IG1hcmtpbmcgaXRzIG5vbi1sZWFmcyBhcyBtaXNzaW5nLFxuLy8gYW5kIHJldHVybiBhIGxpc3Qgb2YgcmV2cyB0byBkZWxldGVcbmZ1bmN0aW9uIGNvbXBhY3RUcmVlKG1ldGFkYXRhKSB7XG4gIHZhciByZXZzID0gW107XG4gIHRyYXZlcnNlUmV2VHJlZShtZXRhZGF0YS5yZXZfdHJlZSwgZnVuY3Rpb24gKGlzTGVhZiwgcG9zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXZIYXNoLCBjdHgsIG9wdHMpIHtcbiAgICBpZiAob3B0cy5zdGF0dXMgPT09ICdhdmFpbGFibGUnICYmICFpc0xlYWYpIHtcbiAgICAgIHJldnMucHVzaChwb3MgKyAnLScgKyByZXZIYXNoKTtcbiAgICAgIG9wdHMuc3RhdHVzID0gJ21pc3NpbmcnO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiByZXZzO1xufVxuXG4vLyBidWlsZCB1cCBhIGxpc3Qgb2YgYWxsIHRoZSBwYXRocyB0byB0aGUgbGVhZnMgaW4gdGhpcyByZXZpc2lvbiB0cmVlXG5mdW5jdGlvbiByb290VG9MZWFmKHJldnMpIHtcbiAgdmFyIHBhdGhzID0gW107XG4gIHZhciB0b1Zpc2l0ID0gcmV2cy5zbGljZSgpO1xuICB2YXIgbm9kZTtcbiAgd2hpbGUgKChub2RlID0gdG9WaXNpdC5wb3AoKSkpIHtcbiAgICB2YXIgcG9zID0gbm9kZS5wb3M7XG4gICAgdmFyIHRyZWUgPSBub2RlLmlkcztcbiAgICB2YXIgaWQgPSB0cmVlWzBdO1xuICAgIHZhciBvcHRzID0gdHJlZVsxXTtcbiAgICB2YXIgYnJhbmNoZXMgPSB0cmVlWzJdO1xuICAgIHZhciBpc0xlYWYgPSBicmFuY2hlcy5sZW5ndGggPT09IDA7XG5cbiAgICB2YXIgaGlzdG9yeSA9IG5vZGUuaGlzdG9yeSA/IG5vZGUuaGlzdG9yeS5zbGljZSgpIDogW107XG4gICAgaGlzdG9yeS5wdXNoKHtpZDogaWQsIG9wdHM6IG9wdHN9KTtcbiAgICBpZiAoaXNMZWFmKSB7XG4gICAgICBwYXRocy5wdXNoKHtwb3M6IChwb3MgKyAxIC0gaGlzdG9yeS5sZW5ndGgpLCBpZHM6IGhpc3Rvcnl9KTtcbiAgICB9XG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGJyYW5jaGVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICB0b1Zpc2l0LnB1c2goe3BvczogcG9zICsgMSwgaWRzOiBicmFuY2hlc1tpXSwgaGlzdG9yeTogaGlzdG9yeX0pO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcGF0aHMucmV2ZXJzZSgpO1xufVxuXG4vLyBmb3IgYSBiZXR0ZXIgb3ZlcnZpZXcgb2Ygd2hhdCB0aGlzIGlzIGRvaW5nLCByZWFkOlxuLy8gaHR0cHM6Ly9naXRodWIuY29tL2FwYWNoZS9jb3VjaGRiLWNvdWNoL2Jsb2IvbWFzdGVyL3NyYy9jb3VjaF9rZXlfdHJlZS5lcmxcbi8vXG4vLyBCdXQgZm9yIGEgcXVpY2sgaW50cm8sIENvdWNoREIgdXNlcyBhIHJldmlzaW9uIHRyZWUgdG8gc3RvcmUgYSBkb2N1bWVudHNcbi8vIGhpc3RvcnksIEEgLT4gQiAtPiBDLCB3aGVuIGEgZG9jdW1lbnQgaGFzIGNvbmZsaWN0cywgdGhhdCBpcyBhIGJyYW5jaCBpbiB0aGVcbi8vIHRyZWUsIEEgLT4gKEIxIHwgQjIgLT4gQyksIFdlIHN0b3JlIHRoZXNlIGFzIGEgbmVzdGVkIGFycmF5IGluIHRoZSBmb3JtYXRcbi8vXG4vLyBLZXlUcmVlID0gW1BhdGggLi4uIF1cbi8vIFBhdGggPSB7cG9zOiBwb3NpdGlvbl9mcm9tX3Jvb3QsIGlkczogVHJlZX1cbi8vIFRyZWUgPSBbS2V5LCBPcHRzLCBbVHJlZSwgLi4uXV0sIGluIHBhcnRpY3VsYXIgc2luZ2xlIG5vZGU6IFtLZXksIFtdXVxuXG5mdW5jdGlvbiBzb3J0QnlQb3MkMShhLCBiKSB7XG4gIHJldHVybiBhLnBvcyAtIGIucG9zO1xufVxuXG4vLyBjbGFzc2ljIGJpbmFyeSBzZWFyY2hcbmZ1bmN0aW9uIGJpbmFyeVNlYXJjaChhcnIsIGl0ZW0sIGNvbXBhcmF0b3IpIHtcbiAgdmFyIGxvdyA9IDA7XG4gIHZhciBoaWdoID0gYXJyLmxlbmd0aDtcbiAgdmFyIG1pZDtcbiAgd2hpbGUgKGxvdyA8IGhpZ2gpIHtcbiAgICBtaWQgPSAobG93ICsgaGlnaCkgPj4+IDE7XG4gICAgaWYgKGNvbXBhcmF0b3IoYXJyW21pZF0sIGl0ZW0pIDwgMCkge1xuICAgICAgbG93ID0gbWlkICsgMTtcbiAgICB9IGVsc2Uge1xuICAgICAgaGlnaCA9IG1pZDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGxvdztcbn1cblxuLy8gYXNzdW1pbmcgdGhlIGFyciBpcyBzb3J0ZWQsIGluc2VydCB0aGUgaXRlbSBpbiB0aGUgcHJvcGVyIHBsYWNlXG5mdW5jdGlvbiBpbnNlcnRTb3J0ZWQoYXJyLCBpdGVtLCBjb21wYXJhdG9yKSB7XG4gIHZhciBpZHggPSBiaW5hcnlTZWFyY2goYXJyLCBpdGVtLCBjb21wYXJhdG9yKTtcbiAgYXJyLnNwbGljZShpZHgsIDAsIGl0ZW0pO1xufVxuXG4vLyBUdXJuIGEgcGF0aCBhcyBhIGZsYXQgYXJyYXkgaW50byBhIHRyZWUgd2l0aCBhIHNpbmdsZSBicmFuY2guXG4vLyBJZiBhbnkgc2hvdWxkIGJlIHN0ZW1tZWQgZnJvbSB0aGUgYmVnaW5uaW5nIG9mIHRoZSBhcnJheSwgdGhhdCdzIHBhc3NlZFxuLy8gaW4gYXMgdGhlIHNlY29uZCBhcmd1bWVudFxuZnVuY3Rpb24gcGF0aFRvVHJlZShwYXRoLCBudW1TdGVtbWVkKSB7XG4gIHZhciByb290O1xuICB2YXIgbGVhZjtcbiAgZm9yICh2YXIgaSA9IG51bVN0ZW1tZWQsIGxlbiA9IHBhdGgubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICB2YXIgbm9kZSA9IHBhdGhbaV07XG4gICAgdmFyIGN1cnJlbnRMZWFmID0gW25vZGUuaWQsIG5vZGUub3B0cywgW11dO1xuICAgIGlmIChsZWFmKSB7XG4gICAgICBsZWFmWzJdLnB1c2goY3VycmVudExlYWYpO1xuICAgICAgbGVhZiA9IGN1cnJlbnRMZWFmO1xuICAgIH0gZWxzZSB7XG4gICAgICByb290ID0gbGVhZiA9IGN1cnJlbnRMZWFmO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcm9vdDtcbn1cblxuLy8gY29tcGFyZSB0aGUgSURzIG9mIHR3byB0cmVlc1xuZnVuY3Rpb24gY29tcGFyZVRyZWUoYSwgYikge1xuICByZXR1cm4gYVswXSA8IGJbMF0gPyAtMSA6IDE7XG59XG5cbi8vIE1lcmdlIHR3byB0cmVlcyB0b2dldGhlclxuLy8gVGhlIHJvb3RzIG9mIHRyZWUxIGFuZCB0cmVlMiBtdXN0IGJlIHRoZSBzYW1lIHJldmlzaW9uXG5mdW5jdGlvbiBtZXJnZVRyZWUoaW5fdHJlZTEsIGluX3RyZWUyKSB7XG4gIHZhciBxdWV1ZSA9IFt7dHJlZTE6IGluX3RyZWUxLCB0cmVlMjogaW5fdHJlZTJ9XTtcbiAgdmFyIGNvbmZsaWN0cyA9IGZhbHNlO1xuICB3aGlsZSAocXVldWUubGVuZ3RoID4gMCkge1xuICAgIHZhciBpdGVtID0gcXVldWUucG9wKCk7XG4gICAgdmFyIHRyZWUxID0gaXRlbS50cmVlMTtcbiAgICB2YXIgdHJlZTIgPSBpdGVtLnRyZWUyO1xuXG4gICAgaWYgKHRyZWUxWzFdLnN0YXR1cyB8fCB0cmVlMlsxXS5zdGF0dXMpIHtcbiAgICAgIHRyZWUxWzFdLnN0YXR1cyA9XG4gICAgICAgICh0cmVlMVsxXS5zdGF0dXMgPT09ICAnYXZhaWxhYmxlJyB8fFxuICAgICAgICB0cmVlMlsxXS5zdGF0dXMgPT09ICdhdmFpbGFibGUnKSA/ICdhdmFpbGFibGUnIDogJ21pc3NpbmcnO1xuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHJlZTJbMl0ubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmICghdHJlZTFbMl1bMF0pIHtcbiAgICAgICAgY29uZmxpY3RzID0gJ25ld19sZWFmJztcbiAgICAgICAgdHJlZTFbMl1bMF0gPSB0cmVlMlsyXVtpXTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIHZhciBtZXJnZWQgPSBmYWxzZTtcbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgdHJlZTFbMl0ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgaWYgKHRyZWUxWzJdW2pdWzBdID09PSB0cmVlMlsyXVtpXVswXSkge1xuICAgICAgICAgIHF1ZXVlLnB1c2goe3RyZWUxOiB0cmVlMVsyXVtqXSwgdHJlZTI6IHRyZWUyWzJdW2ldfSk7XG4gICAgICAgICAgbWVyZ2VkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKCFtZXJnZWQpIHtcbiAgICAgICAgY29uZmxpY3RzID0gJ25ld19icmFuY2gnO1xuICAgICAgICBpbnNlcnRTb3J0ZWQodHJlZTFbMl0sIHRyZWUyWzJdW2ldLCBjb21wYXJlVHJlZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiB7Y29uZmxpY3RzOiBjb25mbGljdHMsIHRyZWU6IGluX3RyZWUxfTtcbn1cblxuZnVuY3Rpb24gZG9NZXJnZSh0cmVlLCBwYXRoLCBkb250RXhwYW5kKSB7XG4gIHZhciByZXN0cmVlID0gW107XG4gIHZhciBjb25mbGljdHMgPSBmYWxzZTtcbiAgdmFyIG1lcmdlZCA9IGZhbHNlO1xuICB2YXIgcmVzO1xuXG4gIGlmICghdHJlZS5sZW5ndGgpIHtcbiAgICByZXR1cm4ge3RyZWU6IFtwYXRoXSwgY29uZmxpY3RzOiAnbmV3X2xlYWYnfTtcbiAgfVxuXG4gIGZvciAodmFyIGkgPSAwLCBsZW4gPSB0cmVlLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgdmFyIGJyYW5jaCA9IHRyZWVbaV07XG4gICAgaWYgKGJyYW5jaC5wb3MgPT09IHBhdGgucG9zICYmIGJyYW5jaC5pZHNbMF0gPT09IHBhdGguaWRzWzBdKSB7XG4gICAgICAvLyBQYXRocyBzdGFydCBhdCB0aGUgc2FtZSBwb3NpdGlvbiBhbmQgaGF2ZSB0aGUgc2FtZSByb290LCBzbyB0aGV5IG5lZWRcbiAgICAgIC8vIG1lcmdlZFxuICAgICAgcmVzID0gbWVyZ2VUcmVlKGJyYW5jaC5pZHMsIHBhdGguaWRzKTtcbiAgICAgIHJlc3RyZWUucHVzaCh7cG9zOiBicmFuY2gucG9zLCBpZHM6IHJlcy50cmVlfSk7XG4gICAgICBjb25mbGljdHMgPSBjb25mbGljdHMgfHwgcmVzLmNvbmZsaWN0cztcbiAgICAgIG1lcmdlZCA9IHRydWU7XG4gICAgfSBlbHNlIGlmIChkb250RXhwYW5kICE9PSB0cnVlKSB7XG4gICAgICAvLyBUaGUgcGF0aHMgc3RhcnQgYXQgYSBkaWZmZXJlbnQgcG9zaXRpb24sIHRha2UgdGhlIGVhcmxpZXN0IHBhdGggYW5kXG4gICAgICAvLyB0cmF2ZXJzZSB1cCB1bnRpbCBpdCBhcyBhdCB0aGUgc2FtZSBwb2ludCBmcm9tIHJvb3QgYXMgdGhlIHBhdGggd2VcbiAgICAgIC8vIHdhbnQgdG8gbWVyZ2UuICBJZiB0aGUga2V5cyBtYXRjaCB3ZSByZXR1cm4gdGhlIGxvbmdlciBwYXRoIHdpdGggdGhlXG4gICAgICAvLyBvdGhlciBtZXJnZWQgQWZ0ZXIgc3RlbW1pbmcgd2UgZG9udCB3YW50IHRvIGV4cGFuZCB0aGUgdHJlZXNcblxuICAgICAgdmFyIHQxID0gYnJhbmNoLnBvcyA8IHBhdGgucG9zID8gYnJhbmNoIDogcGF0aDtcbiAgICAgIHZhciB0MiA9IGJyYW5jaC5wb3MgPCBwYXRoLnBvcyA/IHBhdGggOiBicmFuY2g7XG4gICAgICB2YXIgZGlmZiA9IHQyLnBvcyAtIHQxLnBvcztcblxuICAgICAgdmFyIGNhbmRpZGF0ZVBhcmVudHMgPSBbXTtcblxuICAgICAgdmFyIHRyZWVzID0gW107XG4gICAgICB0cmVlcy5wdXNoKHtpZHM6IHQxLmlkcywgZGlmZjogZGlmZiwgcGFyZW50OiBudWxsLCBwYXJlbnRJZHg6IG51bGx9KTtcbiAgICAgIHdoaWxlICh0cmVlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHZhciBpdGVtID0gdHJlZXMucG9wKCk7XG4gICAgICAgIGlmIChpdGVtLmRpZmYgPT09IDApIHtcbiAgICAgICAgICBpZiAoaXRlbS5pZHNbMF0gPT09IHQyLmlkc1swXSkge1xuICAgICAgICAgICAgY2FuZGlkYXRlUGFyZW50cy5wdXNoKGl0ZW0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZWxlbWVudHMgPSBpdGVtLmlkc1syXTtcbiAgICAgICAgZm9yICh2YXIgaiA9IDAsIGVsZW1lbnRzTGVuID0gZWxlbWVudHMubGVuZ3RoOyBqIDwgZWxlbWVudHNMZW47IGorKykge1xuICAgICAgICAgIHRyZWVzLnB1c2goe1xuICAgICAgICAgICAgaWRzOiBlbGVtZW50c1tqXSxcbiAgICAgICAgICAgIGRpZmY6IGl0ZW0uZGlmZiAtIDEsXG4gICAgICAgICAgICBwYXJlbnQ6IGl0ZW0uaWRzLFxuICAgICAgICAgICAgcGFyZW50SWR4OiBqXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdmFyIGVsID0gY2FuZGlkYXRlUGFyZW50c1swXTtcblxuICAgICAgaWYgKCFlbCkge1xuICAgICAgICByZXN0cmVlLnB1c2goYnJhbmNoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlcyA9IG1lcmdlVHJlZShlbC5pZHMsIHQyLmlkcyk7XG4gICAgICAgIGVsLnBhcmVudFsyXVtlbC5wYXJlbnRJZHhdID0gcmVzLnRyZWU7XG4gICAgICAgIHJlc3RyZWUucHVzaCh7cG9zOiB0MS5wb3MsIGlkczogdDEuaWRzfSk7XG4gICAgICAgIGNvbmZsaWN0cyA9IGNvbmZsaWN0cyB8fCByZXMuY29uZmxpY3RzO1xuICAgICAgICBtZXJnZWQgPSB0cnVlO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXN0cmVlLnB1c2goYnJhbmNoKTtcbiAgICB9XG4gIH1cblxuICAvLyBXZSBkaWRudCBmaW5kXG4gIGlmICghbWVyZ2VkKSB7XG4gICAgcmVzdHJlZS5wdXNoKHBhdGgpO1xuICB9XG5cbiAgcmVzdHJlZS5zb3J0KHNvcnRCeVBvcyQxKTtcblxuICByZXR1cm4ge1xuICAgIHRyZWU6IHJlc3RyZWUsXG4gICAgY29uZmxpY3RzOiBjb25mbGljdHMgfHwgJ2ludGVybmFsX25vZGUnXG4gIH07XG59XG5cbi8vIFRvIGVuc3VyZSB3ZSBkb250IGdyb3cgdGhlIHJldmlzaW9uIHRyZWUgaW5maW5pdGVseSwgd2Ugc3RlbSBvbGQgcmV2aXNpb25zXG5mdW5jdGlvbiBzdGVtKHRyZWUsIGRlcHRoKSB7XG4gIC8vIEZpcnN0IHdlIGJyZWFrIG91dCB0aGUgdHJlZSBpbnRvIGEgY29tcGxldGUgbGlzdCBvZiByb290IHRvIGxlYWYgcGF0aHNcbiAgdmFyIHBhdGhzID0gcm9vdFRvTGVhZih0cmVlKTtcbiAgdmFyIG1heWJlU3RlbSA9IHt9O1xuXG4gIHZhciByZXN1bHQ7XG4gIGZvciAodmFyIGkgPSAwLCBsZW4gPSBwYXRocy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgIC8vIFRoZW4gZm9yIGVhY2ggcGF0aCwgd2UgY3V0IG9mZiB0aGUgc3RhcnQgb2YgdGhlIHBhdGggYmFzZWQgb24gdGhlXG4gICAgLy8gYGRlcHRoYCB0byBzdGVtIHRvLCBhbmQgZ2VuZXJhdGUgYSBuZXcgc2V0IG9mIGZsYXQgdHJlZXNcbiAgICB2YXIgcGF0aCA9IHBhdGhzW2ldO1xuICAgIHZhciBzdGVtbWVkID0gcGF0aC5pZHM7XG4gICAgdmFyIG51bVN0ZW1tZWQgPSBNYXRoLm1heCgwLCBzdGVtbWVkLmxlbmd0aCAtIGRlcHRoKTtcbiAgICB2YXIgc3RlbW1lZE5vZGUgPSB7XG4gICAgICBwb3M6IHBhdGgucG9zICsgbnVtU3RlbW1lZCxcbiAgICAgIGlkczogcGF0aFRvVHJlZShzdGVtbWVkLCBudW1TdGVtbWVkKVxuICAgIH07XG5cbiAgICBmb3IgKHZhciBzID0gMDsgcyA8IG51bVN0ZW1tZWQ7IHMrKykge1xuICAgICAgdmFyIHJldiA9IChwYXRoLnBvcyArIHMpICsgJy0nICsgc3RlbW1lZFtzXS5pZDtcbiAgICAgIG1heWJlU3RlbVtyZXZdID0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBUaGVuIHdlIHJlbWVyZ2UgYWxsIHRob3NlIGZsYXQgdHJlZXMgdG9nZXRoZXIsIGVuc3VyaW5nIHRoYXQgd2UgZG9udFxuICAgIC8vIGNvbm5lY3QgdHJlZXMgdGhhdCB3b3VsZCBnbyBiZXlvbmQgdGhlIGRlcHRoIGxpbWl0XG4gICAgaWYgKHJlc3VsdCkge1xuICAgICAgcmVzdWx0ID0gZG9NZXJnZShyZXN1bHQsIHN0ZW1tZWROb2RlLCB0cnVlKS50cmVlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHQgPSBbc3RlbW1lZE5vZGVdO1xuICAgIH1cbiAgfVxuXG4gIHRyYXZlcnNlUmV2VHJlZShyZXN1bHQsIGZ1bmN0aW9uIChpc0xlYWYsIHBvcywgcmV2SGFzaCkge1xuICAgIC8vIHNvbWUgcmV2aXNpb25zIG1heSBoYXZlIGJlZW4gcmVtb3ZlZCBpbiBhIGJyYW5jaCBidXQgbm90IGluIGFub3RoZXJcbiAgICBkZWxldGUgbWF5YmVTdGVtW3BvcyArICctJyArIHJldkhhc2hdO1xuICB9KTtcblxuICByZXR1cm4ge1xuICAgIHRyZWU6IHJlc3VsdCxcbiAgICByZXZzOiBPYmplY3Qua2V5cyhtYXliZVN0ZW0pXG4gIH07XG59XG5cbmZ1bmN0aW9uIG1lcmdlKHRyZWUsIHBhdGgsIGRlcHRoKSB7XG4gIHZhciBuZXdUcmVlID0gZG9NZXJnZSh0cmVlLCBwYXRoKTtcbiAgdmFyIHN0ZW1tZWQgPSBzdGVtKG5ld1RyZWUudHJlZSwgZGVwdGgpO1xuICByZXR1cm4ge1xuICAgIHRyZWU6IHN0ZW1tZWQudHJlZSxcbiAgICBzdGVtbWVkUmV2czogc3RlbW1lZC5yZXZzLFxuICAgIGNvbmZsaWN0czogbmV3VHJlZS5jb25mbGljdHNcbiAgfTtcbn1cblxuLy8gcmV0dXJuIHRydWUgaWYgYSByZXYgZXhpc3RzIGluIHRoZSByZXYgdHJlZSwgZmFsc2Ugb3RoZXJ3aXNlXG5mdW5jdGlvbiByZXZFeGlzdHMocmV2cywgcmV2KSB7XG4gIHZhciB0b1Zpc2l0ID0gcmV2cy5zbGljZSgpO1xuICB2YXIgc3BsaXRSZXYgPSByZXYuc3BsaXQoJy0nKTtcbiAgdmFyIHRhcmdldFBvcyA9IHBhcnNlSW50KHNwbGl0UmV2WzBdLCAxMCk7XG4gIHZhciB0YXJnZXRJZCA9IHNwbGl0UmV2WzFdO1xuXG4gIHZhciBub2RlO1xuICB3aGlsZSAoKG5vZGUgPSB0b1Zpc2l0LnBvcCgpKSkge1xuICAgIGlmIChub2RlLnBvcyA9PT0gdGFyZ2V0UG9zICYmIG5vZGUuaWRzWzBdID09PSB0YXJnZXRJZCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHZhciBicmFuY2hlcyA9IG5vZGUuaWRzWzJdO1xuICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBicmFuY2hlcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgdG9WaXNpdC5wdXNoKHtwb3M6IG5vZGUucG9zICsgMSwgaWRzOiBicmFuY2hlc1tpXX0pO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGdldFRyZWVzKG5vZGUpIHtcbiAgcmV0dXJuIG5vZGUuaWRzO1xufVxuXG4vLyBjaGVjayBpZiBhIHNwZWNpZmljIHJldmlzaW9uIG9mIGEgZG9jIGhhcyBiZWVuIGRlbGV0ZWRcbi8vICAtIG1ldGFkYXRhOiB0aGUgbWV0YWRhdGEgb2JqZWN0IGZyb20gdGhlIGRvYyBzdG9yZVxuLy8gIC0gcmV2OiAob3B0aW9uYWwpIHRoZSByZXZpc2lvbiB0byBjaGVjay4gZGVmYXVsdHMgdG8gd2lubmluZyByZXZpc2lvblxuZnVuY3Rpb24gaXNEZWxldGVkKG1ldGFkYXRhLCByZXYpIHtcbiAgaWYgKCFyZXYpIHtcbiAgICByZXYgPSB3aW5uaW5nUmV2KG1ldGFkYXRhKTtcbiAgfVxuICB2YXIgaWQgPSByZXYuc3Vic3RyaW5nKHJldi5pbmRleE9mKCctJykgKyAxKTtcbiAgdmFyIHRvVmlzaXQgPSBtZXRhZGF0YS5yZXZfdHJlZS5tYXAoZ2V0VHJlZXMpO1xuXG4gIHZhciB0cmVlO1xuICB3aGlsZSAoKHRyZWUgPSB0b1Zpc2l0LnBvcCgpKSkge1xuICAgIGlmICh0cmVlWzBdID09PSBpZCkge1xuICAgICAgcmV0dXJuICEhdHJlZVsxXS5kZWxldGVkO1xuICAgIH1cbiAgICB0b1Zpc2l0ID0gdG9WaXNpdC5jb25jYXQodHJlZVsyXSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gaXNMb2NhbElkKGlkKSB7XG4gIHJldHVybiAoL15fbG9jYWwvKS50ZXN0KGlkKTtcbn1cblxuLy8gcmV0dXJucyB0aGUgY3VycmVudCBsZWFmIG5vZGUgZm9yIGEgZ2l2ZW4gcmV2aXNpb25cbmZ1bmN0aW9uIGxhdGVzdChyZXYsIG1ldGFkYXRhKSB7XG4gIHZhciB0b1Zpc2l0ID0gbWV0YWRhdGEucmV2X3RyZWUuc2xpY2UoKTtcbiAgdmFyIG5vZGU7XG4gIHdoaWxlICgobm9kZSA9IHRvVmlzaXQucG9wKCkpKSB7XG4gICAgdmFyIHBvcyA9IG5vZGUucG9zO1xuICAgIHZhciB0cmVlID0gbm9kZS5pZHM7XG4gICAgdmFyIGlkID0gdHJlZVswXTtcbiAgICB2YXIgb3B0cyA9IHRyZWVbMV07XG4gICAgdmFyIGJyYW5jaGVzID0gdHJlZVsyXTtcbiAgICB2YXIgaXNMZWFmID0gYnJhbmNoZXMubGVuZ3RoID09PSAwO1xuXG4gICAgdmFyIGhpc3RvcnkgPSBub2RlLmhpc3RvcnkgPyBub2RlLmhpc3Rvcnkuc2xpY2UoKSA6IFtdO1xuICAgIGhpc3RvcnkucHVzaCh7aWQ6IGlkLCBwb3M6IHBvcywgb3B0czogb3B0c30pO1xuXG4gICAgaWYgKGlzTGVhZikge1xuICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGhpc3RvcnkubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgdmFyIGhpc3RvcnlOb2RlID0gaGlzdG9yeVtpXTtcbiAgICAgICAgdmFyIGhpc3RvcnlSZXYgPSBoaXN0b3J5Tm9kZS5wb3MgKyAnLScgKyBoaXN0b3J5Tm9kZS5pZDtcblxuICAgICAgICBpZiAoaGlzdG9yeVJldiA9PT0gcmV2KSB7XG4gICAgICAgICAgLy8gcmV0dXJuIHRoZSByZXYgb2YgdGhpcyBsZWFmXG4gICAgICAgICAgcmV0dXJuIHBvcyArICctJyArIGlkO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaiA9IDAsIGwgPSBicmFuY2hlcy5sZW5ndGg7IGogPCBsOyBqKyspIHtcbiAgICAgIHRvVmlzaXQucHVzaCh7cG9zOiBwb3MgKyAxLCBpZHM6IGJyYW5jaGVzW2pdLCBoaXN0b3J5OiBoaXN0b3J5fSk7XG4gICAgfVxuICB9XG5cbiAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgdGhyb3cgbmV3IEVycm9yKCdVbmFibGUgdG8gcmVzb2x2ZSBsYXRlc3QgcmV2aXNpb24gZm9yIGlkICcgKyBtZXRhZGF0YS5pZCArICcsIHJldiAnICsgcmV2KTtcbn1cblxuZnVuY3Rpb24gZXZhbEZpbHRlcihpbnB1dCkge1xuICByZXR1cm4gc2NvcGVkRXZhbCgnXCJ1c2Ugc3RyaWN0XCI7XFxucmV0dXJuICcgKyBpbnB1dCArICc7Jywge30pO1xufVxuXG5mdW5jdGlvbiBldmFsVmlldyhpbnB1dCkge1xuICB2YXIgY29kZSA9IFtcbiAgICAncmV0dXJuIGZ1bmN0aW9uKGRvYykgeycsXG4gICAgJyAgXCJ1c2Ugc3RyaWN0XCI7JyxcbiAgICAnICB2YXIgZW1pdHRlZCA9IGZhbHNlOycsXG4gICAgJyAgdmFyIGVtaXQgPSBmdW5jdGlvbiAoYSwgYikgeycsXG4gICAgJyAgICBlbWl0dGVkID0gdHJ1ZTsnLFxuICAgICcgIH07JyxcbiAgICAnICB2YXIgdmlldyA9ICcgKyBpbnB1dCArICc7JyxcbiAgICAnICB2aWV3KGRvYyk7JyxcbiAgICAnICBpZiAoZW1pdHRlZCkgeycsXG4gICAgJyAgICByZXR1cm4gdHJ1ZTsnLFxuICAgICcgIH0nLFxuICAgICd9OydcbiAgXS5qb2luKCdcXG4nKTtcblxuICByZXR1cm4gc2NvcGVkRXZhbChjb2RlLCB7fSk7XG59XG5cbmluaGVyaXRzKENoYW5nZXMkMSwgZXZlbnRzLkV2ZW50RW1pdHRlcik7XG5cbmZ1bmN0aW9uIHRyeUNhdGNoSW5DaGFuZ2VMaXN0ZW5lcihzZWxmLCBjaGFuZ2UpIHtcbiAgLy8gaXNvbGF0ZSB0cnkvY2F0Y2hlcyB0byBhdm9pZCBWOCBkZW9wdGltaXphdGlvbnNcbiAgdHJ5IHtcbiAgICBzZWxmLmVtaXQoJ2NoYW5nZScsIGNoYW5nZSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBndWFyZGVkQ29uc29sZSgnZXJyb3InLCAnRXJyb3IgaW4gLm9uKFwiY2hhbmdlXCIsIGZ1bmN0aW9uKTonLCBlKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBDaGFuZ2VzJDEoZGIsIG9wdHMsIGNhbGxiYWNrKSB7XG4gIGV2ZW50cy5FdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICB0aGlzLmRiID0gZGI7XG4gIG9wdHMgPSBvcHRzID8gY2xvbmUob3B0cykgOiB7fTtcbiAgdmFyIGNvbXBsZXRlID0gb3B0cy5jb21wbGV0ZSA9IG9uY2UoZnVuY3Rpb24gKGVyciwgcmVzcCkge1xuICAgIGlmIChlcnIpIHtcbiAgICAgIGlmIChsaXN0ZW5lckNvdW50KHNlbGYsICdlcnJvcicpID4gMCkge1xuICAgICAgICBzZWxmLmVtaXQoJ2Vycm9yJywgZXJyKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgc2VsZi5lbWl0KCdjb21wbGV0ZScsIHJlc3ApO1xuICAgIH1cbiAgICBzZWxmLnJlbW92ZUFsbExpc3RlbmVycygpO1xuICAgIGRiLnJlbW92ZUxpc3RlbmVyKCdkZXN0cm95ZWQnLCBvbkRlc3Ryb3kpO1xuICB9KTtcbiAgaWYgKGNhbGxiYWNrKSB7XG4gICAgc2VsZi5vbignY29tcGxldGUnLCBmdW5jdGlvbiAocmVzcCkge1xuICAgICAgY2FsbGJhY2sobnVsbCwgcmVzcCk7XG4gICAgfSk7XG4gICAgc2VsZi5vbignZXJyb3InLCBjYWxsYmFjayk7XG4gIH1cbiAgZnVuY3Rpb24gb25EZXN0cm95KCkge1xuICAgIHNlbGYuY2FuY2VsKCk7XG4gIH1cbiAgZGIub25jZSgnZGVzdHJveWVkJywgb25EZXN0cm95KTtcblxuICBvcHRzLm9uQ2hhbmdlID0gZnVuY3Rpb24gKGNoYW5nZSkge1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgIGlmIChvcHRzLmlzQ2FuY2VsbGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRyeUNhdGNoSW5DaGFuZ2VMaXN0ZW5lcihzZWxmLCBjaGFuZ2UpO1xuICB9O1xuXG4gIHZhciBwcm9taXNlID0gbmV3IFBvdWNoUHJvbWlzZShmdW5jdGlvbiAoZnVsZmlsbCwgcmVqZWN0KSB7XG4gICAgb3B0cy5jb21wbGV0ZSA9IGZ1bmN0aW9uIChlcnIsIHJlcykge1xuICAgICAgaWYgKGVycikge1xuICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZ1bGZpbGwocmVzKTtcbiAgICAgIH1cbiAgICB9O1xuICB9KTtcbiAgc2VsZi5vbmNlKCdjYW5jZWwnLCBmdW5jdGlvbiAoKSB7XG4gICAgZGIucmVtb3ZlTGlzdGVuZXIoJ2Rlc3Ryb3llZCcsIG9uRGVzdHJveSk7XG4gICAgb3B0cy5jb21wbGV0ZShudWxsLCB7c3RhdHVzOiAnY2FuY2VsbGVkJ30pO1xuICB9KTtcbiAgdGhpcy50aGVuID0gcHJvbWlzZS50aGVuLmJpbmQocHJvbWlzZSk7XG4gIHRoaXNbJ2NhdGNoJ10gPSBwcm9taXNlWydjYXRjaCddLmJpbmQocHJvbWlzZSk7XG4gIHRoaXMudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgY29tcGxldGUobnVsbCwgcmVzdWx0KTtcbiAgfSwgY29tcGxldGUpO1xuXG5cblxuICBpZiAoIWRiLnRhc2txdWV1ZS5pc1JlYWR5KSB7XG4gICAgZGIudGFza3F1ZXVlLmFkZFRhc2soZnVuY3Rpb24gKGZhaWxlZCkge1xuICAgICAgaWYgKGZhaWxlZCkge1xuICAgICAgICBvcHRzLmNvbXBsZXRlKGZhaWxlZCk7XG4gICAgICB9IGVsc2UgaWYgKHNlbGYuaXNDYW5jZWxsZWQpIHtcbiAgICAgICAgc2VsZi5lbWl0KCdjYW5jZWwnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNlbGYuZG9DaGFuZ2VzKG9wdHMpO1xuICAgICAgfVxuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHNlbGYuZG9DaGFuZ2VzKG9wdHMpO1xuICB9XG59XG5DaGFuZ2VzJDEucHJvdG90eXBlLmNhbmNlbCA9IGZ1bmN0aW9uICgpIHtcbiAgdGhpcy5pc0NhbmNlbGxlZCA9IHRydWU7XG4gIGlmICh0aGlzLmRiLnRhc2txdWV1ZS5pc1JlYWR5KSB7XG4gICAgdGhpcy5lbWl0KCdjYW5jZWwnKTtcbiAgfVxufTtcbmZ1bmN0aW9uIHByb2Nlc3NDaGFuZ2UoZG9jLCBtZXRhZGF0YSwgb3B0cykge1xuICB2YXIgY2hhbmdlTGlzdCA9IFt7cmV2OiBkb2MuX3Jldn1dO1xuICBpZiAob3B0cy5zdHlsZSA9PT0gJ2FsbF9kb2NzJykge1xuICAgIGNoYW5nZUxpc3QgPSBjb2xsZWN0TGVhdmVzKG1ldGFkYXRhLnJldl90cmVlKVxuICAgIC5tYXAoZnVuY3Rpb24gKHgpIHsgcmV0dXJuIHtyZXY6IHgucmV2fTsgfSk7XG4gIH1cbiAgdmFyIGNoYW5nZSA9IHtcbiAgICBpZDogbWV0YWRhdGEuaWQsXG4gICAgY2hhbmdlczogY2hhbmdlTGlzdCxcbiAgICBkb2M6IGRvY1xuICB9O1xuXG4gIGlmIChpc0RlbGV0ZWQobWV0YWRhdGEsIGRvYy5fcmV2KSkge1xuICAgIGNoYW5nZS5kZWxldGVkID0gdHJ1ZTtcbiAgfVxuICBpZiAob3B0cy5jb25mbGljdHMpIHtcbiAgICBjaGFuZ2UuZG9jLl9jb25mbGljdHMgPSBjb2xsZWN0Q29uZmxpY3RzKG1ldGFkYXRhKTtcbiAgICBpZiAoIWNoYW5nZS5kb2MuX2NvbmZsaWN0cy5sZW5ndGgpIHtcbiAgICAgIGRlbGV0ZSBjaGFuZ2UuZG9jLl9jb25mbGljdHM7XG4gICAgfVxuICB9XG4gIHJldHVybiBjaGFuZ2U7XG59XG5cbkNoYW5nZXMkMS5wcm90b3R5cGUuZG9DaGFuZ2VzID0gZnVuY3Rpb24gKG9wdHMpIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICB2YXIgY2FsbGJhY2sgPSBvcHRzLmNvbXBsZXRlO1xuXG4gIG9wdHMgPSBjbG9uZShvcHRzKTtcbiAgaWYgKCdsaXZlJyBpbiBvcHRzICYmICEoJ2NvbnRpbnVvdXMnIGluIG9wdHMpKSB7XG4gICAgb3B0cy5jb250aW51b3VzID0gb3B0cy5saXZlO1xuICB9XG4gIG9wdHMucHJvY2Vzc0NoYW5nZSA9IHByb2Nlc3NDaGFuZ2U7XG5cbiAgaWYgKG9wdHMuc2luY2UgPT09ICdsYXRlc3QnKSB7XG4gICAgb3B0cy5zaW5jZSA9ICdub3cnO1xuICB9XG4gIGlmICghb3B0cy5zaW5jZSkge1xuICAgIG9wdHMuc2luY2UgPSAwO1xuICB9XG4gIGlmIChvcHRzLnNpbmNlID09PSAnbm93Jykge1xuICAgIHRoaXMuZGIuaW5mbygpLnRoZW4oZnVuY3Rpb24gKGluZm8pIHtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgICAgaWYgKHNlbGYuaXNDYW5jZWxsZWQpIHtcbiAgICAgICAgY2FsbGJhY2sobnVsbCwge3N0YXR1czogJ2NhbmNlbGxlZCd9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgb3B0cy5zaW5jZSA9IGluZm8udXBkYXRlX3NlcTtcbiAgICAgIHNlbGYuZG9DaGFuZ2VzKG9wdHMpO1xuICAgIH0sIGNhbGxiYWNrKTtcbiAgICByZXR1cm47XG4gIH1cblxuXG4gIGlmIChvcHRzLnZpZXcgJiYgIW9wdHMuZmlsdGVyKSB7XG4gICAgb3B0cy5maWx0ZXIgPSAnX3ZpZXcnO1xuICB9XG5cbiAgaWYgKG9wdHMuZmlsdGVyICYmIHR5cGVvZiBvcHRzLmZpbHRlciA9PT0gJ3N0cmluZycpIHtcbiAgICBpZiAob3B0cy5maWx0ZXIgPT09ICdfdmlldycpIHtcbiAgICAgIG9wdHMudmlldyA9IG5vcm1hbGl6ZURlc2lnbkRvY0Z1bmN0aW9uTmFtZShvcHRzLnZpZXcpO1xuICAgIH0gZWxzZSB7XG4gICAgICBvcHRzLmZpbHRlciA9IG5vcm1hbGl6ZURlc2lnbkRvY0Z1bmN0aW9uTmFtZShvcHRzLmZpbHRlcik7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZGIudHlwZSgpICE9PSAnaHR0cCcgJiYgIW9wdHMuZG9jX2lkcykge1xuICAgICAgcmV0dXJuIHRoaXMuZmlsdGVyQ2hhbmdlcyhvcHRzKTtcbiAgICB9XG4gIH1cblxuICBpZiAoISgnZGVzY2VuZGluZycgaW4gb3B0cykpIHtcbiAgICBvcHRzLmRlc2NlbmRpbmcgPSBmYWxzZTtcbiAgfVxuXG4gIC8vIDAgYW5kIDEgc2hvdWxkIHJldHVybiAxIGRvY3VtZW50XG4gIG9wdHMubGltaXQgPSBvcHRzLmxpbWl0ID09PSAwID8gMSA6IG9wdHMubGltaXQ7XG4gIG9wdHMuY29tcGxldGUgPSBjYWxsYmFjaztcbiAgdmFyIG5ld1Byb21pc2UgPSB0aGlzLmRiLl9jaGFuZ2VzKG9wdHMpO1xuICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICBpZiAobmV3UHJvbWlzZSAmJiB0eXBlb2YgbmV3UHJvbWlzZS5jYW5jZWwgPT09ICdmdW5jdGlvbicpIHtcbiAgICB2YXIgY2FuY2VsID0gc2VsZi5jYW5jZWw7XG4gICAgc2VsZi5jYW5jZWwgPSBnZXRBcmd1bWVudHMoZnVuY3Rpb24gKGFyZ3MpIHtcbiAgICAgIG5ld1Byb21pc2UuY2FuY2VsKCk7XG4gICAgICBjYW5jZWwuYXBwbHkodGhpcywgYXJncyk7XG4gICAgfSk7XG4gIH1cbn07XG5cbkNoYW5nZXMkMS5wcm90b3R5cGUuZmlsdGVyQ2hhbmdlcyA9IGZ1bmN0aW9uIChvcHRzKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIGNhbGxiYWNrID0gb3B0cy5jb21wbGV0ZTtcbiAgaWYgKG9wdHMuZmlsdGVyID09PSAnX3ZpZXcnKSB7XG4gICAgaWYgKCFvcHRzLnZpZXcgfHwgdHlwZW9mIG9wdHMudmlldyAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHZhciBlcnIgPSBjcmVhdGVFcnJvcihCQURfUkVRVUVTVCxcbiAgICAgICAgJ2B2aWV3YCBmaWx0ZXIgcGFyYW1ldGVyIG5vdCBmb3VuZCBvciBpbnZhbGlkLicpO1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKGVycik7XG4gICAgfVxuICAgIC8vIGZldGNoIGEgdmlldyBmcm9tIGEgZGVzaWduIGRvYywgbWFrZSBpdCBiZWhhdmUgbGlrZSBhIGZpbHRlclxuICAgIHZhciB2aWV3TmFtZSA9IHBhcnNlRGVzaWduRG9jRnVuY3Rpb25OYW1lKG9wdHMudmlldyk7XG4gICAgdGhpcy5kYi5nZXQoJ19kZXNpZ24vJyArIHZpZXdOYW1lWzBdLCBmdW5jdGlvbiAoZXJyLCBkZG9jKSB7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICAgIGlmIChzZWxmLmlzQ2FuY2VsbGVkKSB7XG4gICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCB7c3RhdHVzOiAnY2FuY2VsbGVkJ30pO1xuICAgICAgfVxuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGdlbmVyYXRlRXJyb3JGcm9tUmVzcG9uc2UoZXJyKSk7XG4gICAgICB9XG4gICAgICB2YXIgbWFwRnVuID0gZGRvYyAmJiBkZG9jLnZpZXdzICYmIGRkb2Mudmlld3Nbdmlld05hbWVbMV1dICYmXG4gICAgICAgIGRkb2Mudmlld3Nbdmlld05hbWVbMV1dLm1hcDtcbiAgICAgIGlmICghbWFwRnVuKSB7XG4gICAgICAgIHJldHVybiBjYWxsYmFjayhjcmVhdGVFcnJvcihNSVNTSU5HX0RPQyxcbiAgICAgICAgICAoZGRvYy52aWV3cyA/ICdtaXNzaW5nIGpzb24ga2V5OiAnICsgdmlld05hbWVbMV0gOlxuICAgICAgICAgICAgJ21pc3NpbmcganNvbiBrZXk6IHZpZXdzJykpKTtcbiAgICAgIH1cbiAgICAgIG9wdHMuZmlsdGVyID0gZXZhbFZpZXcobWFwRnVuKTtcbiAgICAgIHNlbGYuZG9DaGFuZ2VzKG9wdHMpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIC8vIGZldGNoIGEgZmlsdGVyIGZyb20gYSBkZXNpZ24gZG9jXG4gICAgdmFyIGZpbHRlck5hbWUgPSBwYXJzZURlc2lnbkRvY0Z1bmN0aW9uTmFtZShvcHRzLmZpbHRlcik7XG4gICAgaWYgKCFmaWx0ZXJOYW1lKSB7XG4gICAgICByZXR1cm4gc2VsZi5kb0NoYW5nZXMob3B0cyk7XG4gICAgfVxuICAgIHRoaXMuZGIuZ2V0KCdfZGVzaWduLycgKyBmaWx0ZXJOYW1lWzBdLCBmdW5jdGlvbiAoZXJyLCBkZG9jKSB7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICAgIGlmIChzZWxmLmlzQ2FuY2VsbGVkKSB7XG4gICAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCB7c3RhdHVzOiAnY2FuY2VsbGVkJ30pO1xuICAgICAgfVxuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGdlbmVyYXRlRXJyb3JGcm9tUmVzcG9uc2UoZXJyKSk7XG4gICAgICB9XG4gICAgICB2YXIgZmlsdGVyRnVuID0gZGRvYyAmJiBkZG9jLmZpbHRlcnMgJiYgZGRvYy5maWx0ZXJzW2ZpbHRlck5hbWVbMV1dO1xuICAgICAgaWYgKCFmaWx0ZXJGdW4pIHtcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGNyZWF0ZUVycm9yKE1JU1NJTkdfRE9DLFxuICAgICAgICAgICgoZGRvYyAmJiBkZG9jLmZpbHRlcnMpID8gJ21pc3NpbmcganNvbiBrZXk6ICcgKyBmaWx0ZXJOYW1lWzFdXG4gICAgICAgICAgICA6ICdtaXNzaW5nIGpzb24ga2V5OiBmaWx0ZXJzJykpKTtcbiAgICAgIH1cbiAgICAgIG9wdHMuZmlsdGVyID0gZXZhbEZpbHRlcihmaWx0ZXJGdW4pO1xuICAgICAgc2VsZi5kb0NoYW5nZXMob3B0cyk7XG4gICAgfSk7XG4gIH1cbn07XG5cbi8qXG4gKiBBIGdlbmVyaWMgcG91Y2ggYWRhcHRlclxuICovXG5cbmZ1bmN0aW9uIGNvbXBhcmUobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPCByaWdodCA/IC0xIDogbGVmdCA+IHJpZ2h0ID8gMSA6IDA7XG59XG5cbi8vIFdyYXBwZXIgZm9yIGZ1bmN0aW9ucyB0aGF0IGNhbGwgdGhlIGJ1bGtkb2NzIGFwaSB3aXRoIGEgc2luZ2xlIGRvYyxcbi8vIGlmIHRoZSBmaXJzdCByZXN1bHQgaXMgYW4gZXJyb3IsIHJldHVybiBhbiBlcnJvclxuZnVuY3Rpb24geWFua0Vycm9yKGNhbGxiYWNrKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoZXJyLCByZXN1bHRzKSB7XG4gICAgaWYgKGVyciB8fCAocmVzdWx0c1swXSAmJiByZXN1bHRzWzBdLmVycm9yKSkge1xuICAgICAgY2FsbGJhY2soZXJyIHx8IHJlc3VsdHNbMF0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBjYWxsYmFjayhudWxsLCByZXN1bHRzLmxlbmd0aCA/IHJlc3VsdHNbMF0gIDogcmVzdWx0cyk7XG4gICAgfVxuICB9O1xufVxuXG4vLyBjbGVhbiBkb2NzIGdpdmVuIHRvIHVzIGJ5IHRoZSB1c2VyXG5mdW5jdGlvbiBjbGVhbkRvY3MoZG9jcykge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGRvY3MubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgZG9jID0gZG9jc1tpXTtcbiAgICBpZiAoZG9jLl9kZWxldGVkKSB7XG4gICAgICBkZWxldGUgZG9jLl9hdHRhY2htZW50czsgLy8gaWdub3JlIGF0dHMgZm9yIGRlbGV0ZWQgZG9jc1xuICAgIH0gZWxzZSBpZiAoZG9jLl9hdHRhY2htZW50cykge1xuICAgICAgLy8gZmlsdGVyIG91dCBleHRyYW5lb3VzIGtleXMgZnJvbSBfYXR0YWNobWVudHNcbiAgICAgIHZhciBhdHRzID0gT2JqZWN0LmtleXMoZG9jLl9hdHRhY2htZW50cyk7XG4gICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGF0dHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgdmFyIGF0dCA9IGF0dHNbal07XG4gICAgICAgIGRvYy5fYXR0YWNobWVudHNbYXR0XSA9IHBpY2soZG9jLl9hdHRhY2htZW50c1thdHRdLFxuICAgICAgICAgIFsnZGF0YScsICdkaWdlc3QnLCAnY29udGVudF90eXBlJywgJ2xlbmd0aCcsICdyZXZwb3MnLCAnc3R1YiddKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuLy8gY29tcGFyZSB0d28gZG9jcywgZmlyc3QgYnkgX2lkIHRoZW4gYnkgX3JldlxuZnVuY3Rpb24gY29tcGFyZUJ5SWRUaGVuUmV2KGEsIGIpIHtcbiAgdmFyIGlkQ29tcGFyZSA9IGNvbXBhcmUoYS5faWQsIGIuX2lkKTtcbiAgaWYgKGlkQ29tcGFyZSAhPT0gMCkge1xuICAgIHJldHVybiBpZENvbXBhcmU7XG4gIH1cbiAgdmFyIGFTdGFydCA9IGEuX3JldmlzaW9ucyA/IGEuX3JldmlzaW9ucy5zdGFydCA6IDA7XG4gIHZhciBiU3RhcnQgPSBiLl9yZXZpc2lvbnMgPyBiLl9yZXZpc2lvbnMuc3RhcnQgOiAwO1xuICByZXR1cm4gY29tcGFyZShhU3RhcnQsIGJTdGFydCk7XG59XG5cbi8vIGZvciBldmVyeSBub2RlIGluIGEgcmV2aXNpb24gdHJlZSBjb21wdXRlcyBpdHMgZGlzdGFuY2UgZnJvbSB0aGUgY2xvc2VzdFxuLy8gbGVhZlxuZnVuY3Rpb24gY29tcHV0ZUhlaWdodChyZXZzKSB7XG4gIHZhciBoZWlnaHQgPSB7fTtcbiAgdmFyIGVkZ2VzID0gW107XG4gIHRyYXZlcnNlUmV2VHJlZShyZXZzLCBmdW5jdGlvbiAoaXNMZWFmLCBwb3MsIGlkLCBwcm50KSB7XG4gICAgdmFyIHJldiA9IHBvcyArIFwiLVwiICsgaWQ7XG4gICAgaWYgKGlzTGVhZikge1xuICAgICAgaGVpZ2h0W3Jldl0gPSAwO1xuICAgIH1cbiAgICBpZiAocHJudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBlZGdlcy5wdXNoKHtmcm9tOiBwcm50LCB0bzogcmV2fSk7XG4gICAgfVxuICAgIHJldHVybiByZXY7XG4gIH0pO1xuXG4gIGVkZ2VzLnJldmVyc2UoKTtcbiAgZWRnZXMuZm9yRWFjaChmdW5jdGlvbiAoZWRnZSkge1xuICAgIGlmIChoZWlnaHRbZWRnZS5mcm9tXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBoZWlnaHRbZWRnZS5mcm9tXSA9IDEgKyBoZWlnaHRbZWRnZS50b107XG4gICAgfSBlbHNlIHtcbiAgICAgIGhlaWdodFtlZGdlLmZyb21dID0gTWF0aC5taW4oaGVpZ2h0W2VkZ2UuZnJvbV0sIDEgKyBoZWlnaHRbZWRnZS50b10pO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBoZWlnaHQ7XG59XG5cbmZ1bmN0aW9uIGFsbERvY3NLZXlzUXVlcnkoYXBpLCBvcHRzLCBjYWxsYmFjaykge1xuICB2YXIga2V5cyA9ICAoJ2xpbWl0JyBpbiBvcHRzKSA/XG4gICAgICBvcHRzLmtleXMuc2xpY2Uob3B0cy5za2lwLCBvcHRzLmxpbWl0ICsgb3B0cy5za2lwKSA6XG4gICAgICAob3B0cy5za2lwID4gMCkgPyBvcHRzLmtleXMuc2xpY2Uob3B0cy5za2lwKSA6IG9wdHMua2V5cztcbiAgaWYgKG9wdHMuZGVzY2VuZGluZykge1xuICAgIGtleXMucmV2ZXJzZSgpO1xuICB9XG4gIGlmICgha2V5cy5sZW5ndGgpIHtcbiAgICByZXR1cm4gYXBpLl9hbGxEb2NzKHtsaW1pdDogMH0sIGNhbGxiYWNrKTtcbiAgfVxuICB2YXIgZmluYWxSZXN1bHRzID0ge1xuICAgIG9mZnNldDogb3B0cy5za2lwXG4gIH07XG4gIHJldHVybiBQb3VjaFByb21pc2UuYWxsKGtleXMubWFwKGZ1bmN0aW9uIChrZXkpIHtcbiAgICB2YXIgc3ViT3B0cyA9IGV4dGVuZCQxKHtrZXk6IGtleSwgZGVsZXRlZDogJ29rJ30sIG9wdHMpO1xuICAgIFsnbGltaXQnLCAnc2tpcCcsICdrZXlzJ10uZm9yRWFjaChmdW5jdGlvbiAob3B0S2V5KSB7XG4gICAgICBkZWxldGUgc3ViT3B0c1tvcHRLZXldO1xuICAgIH0pO1xuICAgIHJldHVybiBuZXcgUG91Y2hQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIGFwaS5fYWxsRG9jcyhzdWJPcHRzLCBmdW5jdGlvbiAoZXJyLCByZXMpIHtcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICAgIH1cbiAgICAgICAgZmluYWxSZXN1bHRzLnRvdGFsX3Jvd3MgPSByZXMudG90YWxfcm93cztcbiAgICAgICAgcmVzb2x2ZShyZXMucm93c1swXSB8fCB7a2V5OiBrZXksIGVycm9yOiAnbm90X2ZvdW5kJ30pO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pKS50aGVuKGZ1bmN0aW9uIChyZXN1bHRzKSB7XG4gICAgZmluYWxSZXN1bHRzLnJvd3MgPSByZXN1bHRzO1xuICAgIHJldHVybiBmaW5hbFJlc3VsdHM7XG4gIH0pO1xufVxuXG4vLyBhbGwgY29tcGFjdGlvbiBpcyBkb25lIGluIGEgcXVldWUsIHRvIGF2b2lkIGF0dGFjaGluZ1xuLy8gdG9vIG1hbnkgbGlzdGVuZXJzIGF0IG9uY2VcbmZ1bmN0aW9uIGRvTmV4dENvbXBhY3Rpb24oc2VsZikge1xuICB2YXIgdGFzayA9IHNlbGYuX2NvbXBhY3Rpb25RdWV1ZVswXTtcbiAgdmFyIG9wdHMgPSB0YXNrLm9wdHM7XG4gIHZhciBjYWxsYmFjayA9IHRhc2suY2FsbGJhY2s7XG4gIHNlbGYuZ2V0KCdfbG9jYWwvY29tcGFjdGlvbicpLmNhdGNoKGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH0pLnRoZW4oZnVuY3Rpb24gKGRvYykge1xuICAgIGlmIChkb2MgJiYgZG9jLmxhc3Rfc2VxKSB7XG4gICAgICBvcHRzLmxhc3Rfc2VxID0gZG9jLmxhc3Rfc2VxO1xuICAgIH1cbiAgICBzZWxmLl9jb21wYWN0KG9wdHMsIGZ1bmN0aW9uIChlcnIsIHJlcykge1xuICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgICBpZiAoZXJyKSB7XG4gICAgICAgIGNhbGxiYWNrKGVycik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjYWxsYmFjayhudWxsLCByZXMpO1xuICAgICAgfVxuICAgICAgaW1tZWRpYXRlKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgc2VsZi5fY29tcGFjdGlvblF1ZXVlLnNoaWZ0KCk7XG4gICAgICAgIGlmIChzZWxmLl9jb21wYWN0aW9uUXVldWUubGVuZ3RoKSB7XG4gICAgICAgICAgZG9OZXh0Q29tcGFjdGlvbihzZWxmKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBhdHRhY2htZW50TmFtZUVycm9yKG5hbWUpIHtcbiAgaWYgKG5hbWUuY2hhckF0KDApID09PSAnXycpIHtcbiAgICByZXR1cm4gbmFtZSArICdpcyBub3QgYSB2YWxpZCBhdHRhY2htZW50IG5hbWUsIGF0dGFjaG1lbnQgJyArXG4gICAgICAnbmFtZXMgY2Fubm90IHN0YXJ0IHdpdGggXFwnX1xcJyc7XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5pbmhlcml0cyhBYnN0cmFjdFBvdWNoREIsIGV2ZW50cy5FdmVudEVtaXR0ZXIpO1xuXG5mdW5jdGlvbiBBYnN0cmFjdFBvdWNoREIoKSB7XG4gIGV2ZW50cy5FdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcbn1cblxuQWJzdHJhY3RQb3VjaERCLnByb3RvdHlwZS5wb3N0ID1cbiAgYWRhcHRlckZ1bigncG9zdCcsIGZ1bmN0aW9uIChkb2MsIG9wdHMsIGNhbGxiYWNrKSB7XG4gIGlmICh0eXBlb2Ygb3B0cyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIGNhbGxiYWNrID0gb3B0cztcbiAgICBvcHRzID0ge307XG4gIH1cbiAgaWYgKHR5cGVvZiBkb2MgIT09ICdvYmplY3QnIHx8IEFycmF5LmlzQXJyYXkoZG9jKSkge1xuICAgIHJldHVybiBjYWxsYmFjayhjcmVhdGVFcnJvcihOT1RfQU5fT0JKRUNUKSk7XG4gIH1cbiAgdGhpcy5idWxrRG9jcyh7ZG9jczogW2RvY119LCBvcHRzLCB5YW5rRXJyb3IoY2FsbGJhY2spKTtcbn0pO1xuXG5BYnN0cmFjdFBvdWNoREIucHJvdG90eXBlLnB1dCA9IGFkYXB0ZXJGdW4oJ3B1dCcsIGZ1bmN0aW9uIChkb2MsIG9wdHMsIGNiKSB7XG4gIGlmICh0eXBlb2Ygb3B0cyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIGNiID0gb3B0cztcbiAgICBvcHRzID0ge307XG4gIH1cbiAgaWYgKHR5cGVvZiBkb2MgIT09ICdvYmplY3QnIHx8IEFycmF5LmlzQXJyYXkoZG9jKSkge1xuICAgIHJldHVybiBjYihjcmVhdGVFcnJvcihOT1RfQU5fT0JKRUNUKSk7XG4gIH1cbiAgaW52YWxpZElkRXJyb3IoZG9jLl9pZCk7XG4gIGlmIChpc0xvY2FsSWQoZG9jLl9pZCkgJiYgdHlwZW9mIHRoaXMuX3B1dExvY2FsID09PSAnZnVuY3Rpb24nKSB7XG4gICAgaWYgKGRvYy5fZGVsZXRlZCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3JlbW92ZUxvY2FsKGRvYywgY2IpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5fcHV0TG9jYWwoZG9jLCBjYik7XG4gICAgfVxuICB9XG4gIGlmICh0eXBlb2YgdGhpcy5fcHV0ID09PSAnZnVuY3Rpb24nICYmIG9wdHMubmV3X2VkaXRzICE9PSBmYWxzZSkge1xuICAgIHRoaXMuX3B1dChkb2MsIG9wdHMsIGNiKTtcbiAgfSBlbHNlIHtcbiAgICB0aGlzLmJ1bGtEb2NzKHtkb2NzOiBbZG9jXX0sIG9wdHMsIHlhbmtFcnJvcihjYikpO1xuICB9XG59KTtcblxuQWJzdHJhY3RQb3VjaERCLnByb3RvdHlwZS5wdXRBdHRhY2htZW50ID1cbiAgYWRhcHRlckZ1bigncHV0QXR0YWNobWVudCcsIGZ1bmN0aW9uIChkb2NJZCwgYXR0YWNobWVudElkLCByZXYsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmxvYiwgdHlwZSkge1xuICB2YXIgYXBpID0gdGhpcztcbiAgaWYgKHR5cGVvZiB0eXBlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgdHlwZSA9IGJsb2I7XG4gICAgYmxvYiA9IHJldjtcbiAgICByZXYgPSBudWxsO1xuICB9XG4gIC8vIExldHMgZml4IGluIGh0dHBzOi8vZ2l0aHViLmNvbS9wb3VjaGRiL3BvdWNoZGIvaXNzdWVzLzMyNjdcbiAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gIGlmICh0eXBlb2YgdHlwZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICB0eXBlID0gYmxvYjtcbiAgICBibG9iID0gcmV2O1xuICAgIHJldiA9IG51bGw7XG4gIH1cbiAgaWYgKCF0eXBlKSB7XG4gICAgZ3VhcmRlZENvbnNvbGUoJ3dhcm4nLCAnQXR0YWNobWVudCcsIGF0dGFjaG1lbnRJZCwgJ29uIGRvY3VtZW50JywgZG9jSWQsICdpcyBtaXNzaW5nIGNvbnRlbnRfdHlwZScpO1xuICB9XG5cbiAgZnVuY3Rpb24gY3JlYXRlQXR0YWNobWVudChkb2MpIHtcbiAgICB2YXIgcHJldnJldnBvcyA9ICdfcmV2JyBpbiBkb2MgPyBwYXJzZUludChkb2MuX3JldiwgMTApIDogMDtcbiAgICBkb2MuX2F0dGFjaG1lbnRzID0gZG9jLl9hdHRhY2htZW50cyB8fCB7fTtcbiAgICBkb2MuX2F0dGFjaG1lbnRzW2F0dGFjaG1lbnRJZF0gPSB7XG4gICAgICBjb250ZW50X3R5cGU6IHR5cGUsXG4gICAgICBkYXRhOiBibG9iLFxuICAgICAgcmV2cG9zOiArK3ByZXZyZXZwb3NcbiAgICB9O1xuICAgIHJldHVybiBhcGkucHV0KGRvYyk7XG4gIH1cblxuICByZXR1cm4gYXBpLmdldChkb2NJZCkudGhlbihmdW5jdGlvbiAoZG9jKSB7XG4gICAgaWYgKGRvYy5fcmV2ICE9PSByZXYpIHtcbiAgICAgIHRocm93IGNyZWF0ZUVycm9yKFJFVl9DT05GTElDVCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNyZWF0ZUF0dGFjaG1lbnQoZG9jKTtcbiAgfSwgZnVuY3Rpb24gKGVycikge1xuICAgICAvLyBjcmVhdGUgbmV3IGRvY1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgaWYgKGVyci5yZWFzb24gPT09IE1JU1NJTkdfRE9DLm1lc3NhZ2UpIHtcbiAgICAgIHJldHVybiBjcmVhdGVBdHRhY2htZW50KHtfaWQ6IGRvY0lkfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gIH0pO1xufSk7XG5cbkFic3RyYWN0UG91Y2hEQi5wcm90b3R5cGUucmVtb3ZlQXR0YWNobWVudCA9XG4gIGFkYXB0ZXJGdW4oJ3JlbW92ZUF0dGFjaG1lbnQnLCBmdW5jdGlvbiAoZG9jSWQsIGF0dGFjaG1lbnRJZCwgcmV2LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgc2VsZi5nZXQoZG9jSWQsIGZ1bmN0aW9uIChlcnIsIG9iaikge1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgIGlmIChlcnIpIHtcbiAgICAgIGNhbGxiYWNrKGVycik7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChvYmouX3JldiAhPT0gcmV2KSB7XG4gICAgICBjYWxsYmFjayhjcmVhdGVFcnJvcihSRVZfQ09ORkxJQ1QpKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgaWYgKCFvYmouX2F0dGFjaG1lbnRzKSB7XG4gICAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgICB9XG4gICAgZGVsZXRlIG9iai5fYXR0YWNobWVudHNbYXR0YWNobWVudElkXTtcbiAgICBpZiAoT2JqZWN0LmtleXMob2JqLl9hdHRhY2htZW50cykubGVuZ3RoID09PSAwKSB7XG4gICAgICBkZWxldGUgb2JqLl9hdHRhY2htZW50cztcbiAgICB9XG4gICAgc2VsZi5wdXQob2JqLCBjYWxsYmFjayk7XG4gIH0pO1xufSk7XG5cbkFic3RyYWN0UG91Y2hEQi5wcm90b3R5cGUucmVtb3ZlID1cbiAgYWRhcHRlckZ1bigncmVtb3ZlJywgZnVuY3Rpb24gKGRvY09ySWQsIG9wdHNPclJldiwgb3B0cywgY2FsbGJhY2spIHtcbiAgdmFyIGRvYztcbiAgaWYgKHR5cGVvZiBvcHRzT3JSZXYgPT09ICdzdHJpbmcnKSB7XG4gICAgLy8gaWQsIHJldiwgb3B0cywgY2FsbGJhY2sgc3R5bGVcbiAgICBkb2MgPSB7XG4gICAgICBfaWQ6IGRvY09ySWQsXG4gICAgICBfcmV2OiBvcHRzT3JSZXZcbiAgICB9O1xuICAgIGlmICh0eXBlb2Ygb3B0cyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgY2FsbGJhY2sgPSBvcHRzO1xuICAgICAgb3B0cyA9IHt9O1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBkb2MsIG9wdHMsIGNhbGxiYWNrIHN0eWxlXG4gICAgZG9jID0gZG9jT3JJZDtcbiAgICBpZiAodHlwZW9mIG9wdHNPclJldiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgY2FsbGJhY2sgPSBvcHRzT3JSZXY7XG4gICAgICBvcHRzID0ge307XG4gICAgfSBlbHNlIHtcbiAgICAgIGNhbGxiYWNrID0gb3B0cztcbiAgICAgIG9wdHMgPSBvcHRzT3JSZXY7XG4gICAgfVxuICB9XG4gIG9wdHMgPSBvcHRzIHx8IHt9O1xuICBvcHRzLndhc19kZWxldGUgPSB0cnVlO1xuICB2YXIgbmV3RG9jID0ge19pZDogZG9jLl9pZCwgX3JldjogKGRvYy5fcmV2IHx8IG9wdHMucmV2KX07XG4gIG5ld0RvYy5fZGVsZXRlZCA9IHRydWU7XG4gIGlmIChpc0xvY2FsSWQobmV3RG9jLl9pZCkgJiYgdHlwZW9mIHRoaXMuX3JlbW92ZUxvY2FsID09PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIHRoaXMuX3JlbW92ZUxvY2FsKGRvYywgY2FsbGJhY2spO1xuICB9XG4gIHRoaXMuYnVsa0RvY3Moe2RvY3M6IFtuZXdEb2NdfSwgb3B0cywgeWFua0Vycm9yKGNhbGxiYWNrKSk7XG59KTtcblxuQWJzdHJhY3RQb3VjaERCLnByb3RvdHlwZS5yZXZzRGlmZiA9XG4gIGFkYXB0ZXJGdW4oJ3JldnNEaWZmJywgZnVuY3Rpb24gKHJlcSwgb3B0cywgY2FsbGJhY2spIHtcbiAgaWYgKHR5cGVvZiBvcHRzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgY2FsbGJhY2sgPSBvcHRzO1xuICAgIG9wdHMgPSB7fTtcbiAgfVxuICB2YXIgaWRzID0gT2JqZWN0LmtleXMocmVxKTtcblxuICBpZiAoIWlkcy5sZW5ndGgpIHtcbiAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwge30pO1xuICB9XG5cbiAgdmFyIGNvdW50ID0gMDtcbiAgdmFyIG1pc3NpbmcgPSBuZXcgX01hcCgpO1xuXG4gIGZ1bmN0aW9uIGFkZFRvTWlzc2luZyhpZCwgcmV2SWQpIHtcbiAgICBpZiAoIW1pc3NpbmcuaGFzKGlkKSkge1xuICAgICAgbWlzc2luZy5zZXQoaWQsIHttaXNzaW5nOiBbXX0pO1xuICAgIH1cbiAgICBtaXNzaW5nLmdldChpZCkubWlzc2luZy5wdXNoKHJldklkKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHByb2Nlc3NEb2MoaWQsIHJldl90cmVlKSB7XG4gICAgLy8gSXMgdGhpcyBmYXN0IGVub3VnaD8gTWF5YmUgd2Ugc2hvdWxkIHN3aXRjaCB0byBhIHNldCBzaW11bGF0ZWQgYnkgYSBtYXBcbiAgICB2YXIgbWlzc2luZ0ZvcklkID0gcmVxW2lkXS5zbGljZSgwKTtcbiAgICB0cmF2ZXJzZVJldlRyZWUocmV2X3RyZWUsIGZ1bmN0aW9uIChpc0xlYWYsIHBvcywgcmV2SGFzaCwgY3R4LFxuICAgICAgb3B0cykge1xuICAgICAgICB2YXIgcmV2ID0gcG9zICsgJy0nICsgcmV2SGFzaDtcbiAgICAgICAgdmFyIGlkeCA9IG1pc3NpbmdGb3JJZC5pbmRleE9mKHJldik7XG4gICAgICAgIGlmIChpZHggPT09IC0xKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgbWlzc2luZ0ZvcklkLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICAgICAgaWYgKG9wdHMuc3RhdHVzICE9PSAnYXZhaWxhYmxlJykge1xuICAgICAgICAgIGFkZFRvTWlzc2luZyhpZCwgcmV2KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAvLyBUcmF2ZXJzaW5nIHRoZSB0cmVlIGlzIHN5bmNocm9ub3VzLCBzbyBub3cgYG1pc3NpbmdGb3JJZGAgY29udGFpbnNcbiAgICAvLyByZXZpc2lvbnMgdGhhdCB3ZXJlIG5vdCBmb3VuZCBpbiB0aGUgdHJlZVxuICAgIG1pc3NpbmdGb3JJZC5mb3JFYWNoKGZ1bmN0aW9uIChyZXYpIHtcbiAgICAgIGFkZFRvTWlzc2luZyhpZCwgcmV2KTtcbiAgICB9KTtcbiAgfVxuXG4gIGlkcy5tYXAoZnVuY3Rpb24gKGlkKSB7XG4gICAgdGhpcy5fZ2V0UmV2aXNpb25UcmVlKGlkLCBmdW5jdGlvbiAoZXJyLCByZXZfdHJlZSkge1xuICAgICAgaWYgKGVyciAmJiBlcnIuc3RhdHVzID09PSA0MDQgJiYgZXJyLm1lc3NhZ2UgPT09ICdtaXNzaW5nJykge1xuICAgICAgICBtaXNzaW5nLnNldChpZCwge21pc3Npbmc6IHJlcVtpZF19KTtcbiAgICAgIH0gZWxzZSBpZiAoZXJyKSB7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICAgIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcHJvY2Vzc0RvYyhpZCwgcmV2X3RyZWUpO1xuICAgICAgfVxuXG4gICAgICBpZiAoKytjb3VudCA9PT0gaWRzLmxlbmd0aCkge1xuICAgICAgICAvLyBjb252ZXJ0IExhenlNYXAgdG8gb2JqZWN0XG4gICAgICAgIHZhciBtaXNzaW5nT2JqID0ge307XG4gICAgICAgIG1pc3NpbmcuZm9yRWFjaChmdW5jdGlvbiAodmFsdWUsIGtleSkge1xuICAgICAgICAgIG1pc3NpbmdPYmpba2V5XSA9IHZhbHVlO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwsIG1pc3NpbmdPYmopO1xuICAgICAgfVxuICAgIH0pO1xuICB9LCB0aGlzKTtcbn0pO1xuXG4vLyBfYnVsa19nZXQgQVBJIGZvciBmYXN0ZXIgcmVwbGljYXRpb24sIGFzIGRlc2NyaWJlZCBpblxuLy8gaHR0cHM6Ly9naXRodWIuY29tL2FwYWNoZS9jb3VjaGRiLWNodHRwZC9wdWxsLzMzXG4vLyBBdCB0aGUgXCJhYnN0cmFjdFwiIGxldmVsLCBpdCB3aWxsIGp1c3QgcnVuIG11bHRpcGxlIGdldCgpcyBpblxuLy8gcGFyYWxsZWwsIGJlY2F1c2UgdGhpcyBpc24ndCBtdWNoIG9mIGEgcGVyZm9ybWFuY2UgY29zdFxuLy8gZm9yIGxvY2FsIGRhdGFiYXNlcyAoZXhjZXB0IHRoZSBjb3N0IG9mIG11bHRpcGxlIHRyYW5zYWN0aW9ucywgd2hpY2ggaXNcbi8vIHNtYWxsKS4gVGhlIGh0dHAgYWRhcHRlciBvdmVycmlkZXMgdGhpcyBpbiBvcmRlclxuLy8gdG8gZG8gYSBtb3JlIGVmZmljaWVudCBzaW5nbGUgSFRUUCByZXF1ZXN0LlxuQWJzdHJhY3RQb3VjaERCLnByb3RvdHlwZS5idWxrR2V0ID1cbiAgYWRhcHRlckZ1bignYnVsa0dldCcsIGZ1bmN0aW9uIChvcHRzLCBjYWxsYmFjaykge1xuICBidWxrR2V0KHRoaXMsIG9wdHMsIGNhbGxiYWNrKTtcbn0pO1xuXG4vLyBjb21wYWN0IG9uZSBkb2N1bWVudCBhbmQgZmlyZSBjYWxsYmFja1xuLy8gYnkgY29tcGFjdGluZyB3ZSBtZWFuIHJlbW92aW5nIGFsbCByZXZpc2lvbnMgd2hpY2hcbi8vIGFyZSBmdXJ0aGVyIGZyb20gdGhlIGxlYWYgaW4gcmV2aXNpb24gdHJlZSB0aGFuIG1heF9oZWlnaHRcbkFic3RyYWN0UG91Y2hEQi5wcm90b3R5cGUuY29tcGFjdERvY3VtZW50ID1cbiAgYWRhcHRlckZ1bignY29tcGFjdERvY3VtZW50JywgZnVuY3Rpb24gKGRvY0lkLCBtYXhIZWlnaHQsIGNhbGxiYWNrKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdGhpcy5fZ2V0UmV2aXNpb25UcmVlKGRvY0lkLCBmdW5jdGlvbiAoZXJyLCByZXZUcmVlKSB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgaWYgKGVycikge1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKGVycik7XG4gICAgfVxuICAgIHZhciBoZWlnaHQgPSBjb21wdXRlSGVpZ2h0KHJldlRyZWUpO1xuICAgIHZhciBjYW5kaWRhdGVzID0gW107XG4gICAgdmFyIHJldnMgPSBbXTtcbiAgICBPYmplY3Qua2V5cyhoZWlnaHQpLmZvckVhY2goZnVuY3Rpb24gKHJldikge1xuICAgICAgaWYgKGhlaWdodFtyZXZdID4gbWF4SGVpZ2h0KSB7XG4gICAgICAgIGNhbmRpZGF0ZXMucHVzaChyZXYpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdHJhdmVyc2VSZXZUcmVlKHJldlRyZWUsIGZ1bmN0aW9uIChpc0xlYWYsIHBvcywgcmV2SGFzaCwgY3R4LCBvcHRzKSB7XG4gICAgICB2YXIgcmV2ID0gcG9zICsgJy0nICsgcmV2SGFzaDtcbiAgICAgIGlmIChvcHRzLnN0YXR1cyA9PT0gJ2F2YWlsYWJsZScgJiYgY2FuZGlkYXRlcy5pbmRleE9mKHJldikgIT09IC0xKSB7XG4gICAgICAgIHJldnMucHVzaChyZXYpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHNlbGYuX2RvQ29tcGFjdGlvbihkb2NJZCwgcmV2cywgY2FsbGJhY2spO1xuICB9KTtcbn0pO1xuXG4vLyBjb21wYWN0IHRoZSB3aG9sZSBkYXRhYmFzZSB1c2luZyBzaW5nbGUgZG9jdW1lbnRcbi8vIGNvbXBhY3Rpb25cbkFic3RyYWN0UG91Y2hEQi5wcm90b3R5cGUuY29tcGFjdCA9XG4gIGFkYXB0ZXJGdW4oJ2NvbXBhY3QnLCBmdW5jdGlvbiAob3B0cywgY2FsbGJhY2spIHtcbiAgaWYgKHR5cGVvZiBvcHRzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgY2FsbGJhY2sgPSBvcHRzO1xuICAgIG9wdHMgPSB7fTtcbiAgfVxuXG4gIHZhciBzZWxmID0gdGhpcztcbiAgb3B0cyA9IG9wdHMgfHwge307XG5cbiAgc2VsZi5fY29tcGFjdGlvblF1ZXVlID0gc2VsZi5fY29tcGFjdGlvblF1ZXVlIHx8IFtdO1xuICBzZWxmLl9jb21wYWN0aW9uUXVldWUucHVzaCh7b3B0czogb3B0cywgY2FsbGJhY2s6IGNhbGxiYWNrfSk7XG4gIGlmIChzZWxmLl9jb21wYWN0aW9uUXVldWUubGVuZ3RoID09PSAxKSB7XG4gICAgZG9OZXh0Q29tcGFjdGlvbihzZWxmKTtcbiAgfVxufSk7XG5BYnN0cmFjdFBvdWNoREIucHJvdG90eXBlLl9jb21wYWN0ID0gZnVuY3Rpb24gKG9wdHMsIGNhbGxiYWNrKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIGNoYW5nZXNPcHRzID0ge1xuICAgIHJldHVybl9kb2NzOiBmYWxzZSxcbiAgICBsYXN0X3NlcTogb3B0cy5sYXN0X3NlcSB8fCAwXG4gIH07XG4gIHZhciBwcm9taXNlcyA9IFtdO1xuXG4gIGZ1bmN0aW9uIG9uQ2hhbmdlKHJvdykge1xuICAgIHByb21pc2VzLnB1c2goc2VsZi5jb21wYWN0RG9jdW1lbnQocm93LmlkLCAwKSk7XG4gIH1cbiAgZnVuY3Rpb24gb25Db21wbGV0ZShyZXNwKSB7XG4gICAgdmFyIGxhc3RTZXEgPSByZXNwLmxhc3Rfc2VxO1xuICAgIFBvdWNoUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHVwc2VydChzZWxmLCAnX2xvY2FsL2NvbXBhY3Rpb24nLCBmdW5jdGlvbiBkZWx0YUZ1bmMoZG9jKSB7XG4gICAgICAgIGlmICghZG9jLmxhc3Rfc2VxIHx8IGRvYy5sYXN0X3NlcSA8IGxhc3RTZXEpIHtcbiAgICAgICAgICBkb2MubGFzdF9zZXEgPSBsYXN0U2VxO1xuICAgICAgICAgIHJldHVybiBkb2M7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBzb21lYm9keSBlbHNlIGdvdCBoZXJlIGZpcnN0LCBkb24ndCB1cGRhdGVcbiAgICAgIH0pO1xuICAgIH0pLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgY2FsbGJhY2sobnVsbCwge29rOiB0cnVlfSk7XG4gICAgfSkuY2F0Y2goY2FsbGJhY2spO1xuICB9XG4gIHNlbGYuY2hhbmdlcyhjaGFuZ2VzT3B0cylcbiAgICAub24oJ2NoYW5nZScsIG9uQ2hhbmdlKVxuICAgIC5vbignY29tcGxldGUnLCBvbkNvbXBsZXRlKVxuICAgIC5vbignZXJyb3InLCBjYWxsYmFjayk7XG59O1xuXG4vKiBCZWdpbiBhcGkgd3JhcHBlcnMuIFNwZWNpZmljIGZ1bmN0aW9uYWxpdHkgdG8gc3RvcmFnZSBiZWxvbmdzIGluIHRoZVxuICAgX1ttZXRob2RdICovXG5BYnN0cmFjdFBvdWNoREIucHJvdG90eXBlLmdldCA9IGFkYXB0ZXJGdW4oJ2dldCcsIGZ1bmN0aW9uIChpZCwgb3B0cywgY2IpIHtcbiAgaWYgKHR5cGVvZiBvcHRzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgY2IgPSBvcHRzO1xuICAgIG9wdHMgPSB7fTtcbiAgfVxuICBpZiAodHlwZW9mIGlkICE9PSAnc3RyaW5nJykge1xuICAgIHJldHVybiBjYihjcmVhdGVFcnJvcihJTlZBTElEX0lEKSk7XG4gIH1cbiAgaWYgKGlzTG9jYWxJZChpZCkgJiYgdHlwZW9mIHRoaXMuX2dldExvY2FsID09PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIHRoaXMuX2dldExvY2FsKGlkLCBjYik7XG4gIH1cbiAgdmFyIGxlYXZlcyA9IFtdLCBzZWxmID0gdGhpcztcblxuICBmdW5jdGlvbiBmaW5pc2hPcGVuUmV2cygpIHtcbiAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgdmFyIGNvdW50ID0gbGVhdmVzLmxlbmd0aDtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICBpZiAoIWNvdW50KSB7XG4gICAgICByZXR1cm4gY2IobnVsbCwgcmVzdWx0KTtcbiAgICB9XG5cbiAgICAvLyBvcmRlciB3aXRoIG9wZW5fcmV2cyBpcyB1bnNwZWNpZmllZFxuICAgIGxlYXZlcy5mb3JFYWNoKGZ1bmN0aW9uIChsZWFmKSB7XG4gICAgICBzZWxmLmdldChpZCwge1xuICAgICAgICByZXY6IGxlYWYsXG4gICAgICAgIHJldnM6IG9wdHMucmV2cyxcbiAgICAgICAgbGF0ZXN0OiBvcHRzLmxhdGVzdCxcbiAgICAgICAgYXR0YWNobWVudHM6IG9wdHMuYXR0YWNobWVudHNcbiAgICAgIH0sIGZ1bmN0aW9uIChlcnIsIGRvYykge1xuICAgICAgICBpZiAoIWVycikge1xuICAgICAgICAgIC8vIHVzaW5nIGxhdGVzdD10cnVlIGNhbiBwcm9kdWNlIGR1cGxpY2F0ZXNcbiAgICAgICAgICB2YXIgZXhpc3Rpbmc7XG4gICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSByZXN1bHQubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAocmVzdWx0W2ldLm9rICYmIHJlc3VsdFtpXS5vay5fcmV2ID09PSBkb2MuX3Jldikge1xuICAgICAgICAgICAgICBleGlzdGluZyA9IHRydWU7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIWV4aXN0aW5nKSB7XG4gICAgICAgICAgICByZXN1bHQucHVzaCh7b2s6IGRvY30pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXN1bHQucHVzaCh7bWlzc2luZzogbGVhZn0pO1xuICAgICAgICB9XG4gICAgICAgIGNvdW50LS07XG4gICAgICAgIGlmICghY291bnQpIHtcbiAgICAgICAgICBjYihudWxsLCByZXN1bHQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIGlmIChvcHRzLm9wZW5fcmV2cykge1xuICAgIGlmIChvcHRzLm9wZW5fcmV2cyA9PT0gXCJhbGxcIikge1xuICAgICAgdGhpcy5fZ2V0UmV2aXNpb25UcmVlKGlkLCBmdW5jdGlvbiAoZXJyLCByZXZfdHJlZSkge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgcmV0dXJuIGNiKGVycik7XG4gICAgICAgIH1cbiAgICAgICAgbGVhdmVzID0gY29sbGVjdExlYXZlcyhyZXZfdHJlZSkubWFwKGZ1bmN0aW9uIChsZWFmKSB7XG4gICAgICAgICAgcmV0dXJuIGxlYWYucmV2O1xuICAgICAgICB9KTtcbiAgICAgICAgZmluaXNoT3BlblJldnMoKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShvcHRzLm9wZW5fcmV2cykpIHtcbiAgICAgICAgbGVhdmVzID0gb3B0cy5vcGVuX3JldnM7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVhdmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgdmFyIGwgPSBsZWF2ZXNbaV07XG4gICAgICAgICAgLy8gbG9va3MgbGlrZSBpdCdzIHRoZSBvbmx5IHRoaW5nIGNvdWNoZGIgY2hlY2tzXG4gICAgICAgICAgaWYgKCEodHlwZW9mIChsKSA9PT0gXCJzdHJpbmdcIiAmJiAvXlxcZCstLy50ZXN0KGwpKSkge1xuICAgICAgICAgICAgcmV0dXJuIGNiKGNyZWF0ZUVycm9yKElOVkFMSURfUkVWKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZpbmlzaE9wZW5SZXZzKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gY2IoY3JlYXRlRXJyb3IoVU5LTk9XTl9FUlJPUiwgJ2Z1bmN0aW9uX2NsYXVzZScpKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuOyAvLyBvcGVuX3JldnMgZG9lcyBub3QgbGlrZSBvdGhlciBvcHRpb25zXG4gIH1cblxuICByZXR1cm4gdGhpcy5fZ2V0KGlkLCBvcHRzLCBmdW5jdGlvbiAoZXJyLCByZXN1bHQpIHtcbiAgICBpZiAoZXJyKSB7XG4gICAgICByZXR1cm4gY2IoZXJyKTtcbiAgICB9XG5cbiAgICB2YXIgZG9jID0gcmVzdWx0LmRvYztcbiAgICB2YXIgbWV0YWRhdGEgPSByZXN1bHQubWV0YWRhdGE7XG4gICAgdmFyIGN0eCA9IHJlc3VsdC5jdHg7XG5cbiAgICBpZiAob3B0cy5jb25mbGljdHMpIHtcbiAgICAgIHZhciBjb25mbGljdHMgPSBjb2xsZWN0Q29uZmxpY3RzKG1ldGFkYXRhKTtcbiAgICAgIGlmIChjb25mbGljdHMubGVuZ3RoKSB7XG4gICAgICAgIGRvYy5fY29uZmxpY3RzID0gY29uZmxpY3RzO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChpc0RlbGV0ZWQobWV0YWRhdGEsIGRvYy5fcmV2KSkge1xuICAgICAgZG9jLl9kZWxldGVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAob3B0cy5yZXZzIHx8IG9wdHMucmV2c19pbmZvKSB7XG4gICAgICB2YXIgc3BsaXR0ZWRSZXYgPSBkb2MuX3Jldi5zcGxpdCgnLScpO1xuICAgICAgdmFyIHJldk5vICAgICAgID0gcGFyc2VJbnQoc3BsaXR0ZWRSZXZbMF0sIDEwKTtcbiAgICAgIHZhciByZXZIYXNoICAgICA9IHNwbGl0dGVkUmV2WzFdO1xuXG4gICAgICB2YXIgcGF0aHMgPSByb290VG9MZWFmKG1ldGFkYXRhLnJldl90cmVlKTtcbiAgICAgIHZhciBwYXRoID0gbnVsbDtcblxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXRocy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgY3VycmVudFBhdGggPSBwYXRoc1tpXTtcbiAgICAgICAgdmFyIGhhc2hJbmRleCA9IGN1cnJlbnRQYXRoLmlkcy5tYXAoZnVuY3Rpb24gKHgpIHsgcmV0dXJuIHguaWQ7IH0pXG4gICAgICAgICAgLmluZGV4T2YocmV2SGFzaCk7XG4gICAgICAgIHZhciBoYXNoRm91bmRBdFJldlBvcyA9IGhhc2hJbmRleCA9PT0gKHJldk5vIC0gMSk7XG5cbiAgICAgICAgaWYgKGhhc2hGb3VuZEF0UmV2UG9zIHx8ICghcGF0aCAmJiBoYXNoSW5kZXggIT09IC0xKSkge1xuICAgICAgICAgIHBhdGggPSBjdXJyZW50UGF0aDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB2YXIgaW5kZXhPZlJldiA9IHBhdGguaWRzLm1hcChmdW5jdGlvbiAoeCkgeyByZXR1cm4geC5pZDsgfSlcbiAgICAgICAgLmluZGV4T2YoZG9jLl9yZXYuc3BsaXQoJy0nKVsxXSkgKyAxO1xuICAgICAgdmFyIGhvd01hbnkgPSBwYXRoLmlkcy5sZW5ndGggLSBpbmRleE9mUmV2O1xuICAgICAgcGF0aC5pZHMuc3BsaWNlKGluZGV4T2ZSZXYsIGhvd01hbnkpO1xuICAgICAgcGF0aC5pZHMucmV2ZXJzZSgpO1xuXG4gICAgICBpZiAob3B0cy5yZXZzKSB7XG4gICAgICAgIGRvYy5fcmV2aXNpb25zID0ge1xuICAgICAgICAgIHN0YXJ0OiAocGF0aC5wb3MgKyBwYXRoLmlkcy5sZW5ndGgpIC0gMSxcbiAgICAgICAgICBpZHM6IHBhdGguaWRzLm1hcChmdW5jdGlvbiAocmV2KSB7XG4gICAgICAgICAgICByZXR1cm4gcmV2LmlkO1xuICAgICAgICAgIH0pXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBpZiAob3B0cy5yZXZzX2luZm8pIHtcbiAgICAgICAgdmFyIHBvcyA9ICBwYXRoLnBvcyArIHBhdGguaWRzLmxlbmd0aDtcbiAgICAgICAgZG9jLl9yZXZzX2luZm8gPSBwYXRoLmlkcy5tYXAoZnVuY3Rpb24gKHJldikge1xuICAgICAgICAgIHBvcy0tO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICByZXY6IHBvcyArICctJyArIHJldi5pZCxcbiAgICAgICAgICAgIHN0YXR1czogcmV2Lm9wdHMuc3RhdHVzXG4gICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKG9wdHMuYXR0YWNobWVudHMgJiYgZG9jLl9hdHRhY2htZW50cykge1xuICAgICAgdmFyIGF0dGFjaG1lbnRzID0gZG9jLl9hdHRhY2htZW50cztcbiAgICAgIHZhciBjb3VudCA9IE9iamVjdC5rZXlzKGF0dGFjaG1lbnRzKS5sZW5ndGg7XG4gICAgICBpZiAoY291bnQgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIGNiKG51bGwsIGRvYyk7XG4gICAgICB9XG4gICAgICBPYmplY3Qua2V5cyhhdHRhY2htZW50cykuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIHRoaXMuX2dldEF0dGFjaG1lbnQoZG9jLl9pZCwga2V5LCBhdHRhY2htZW50c1trZXldLCB7XG4gICAgICAgICAgLy8gUHJldmlvdXNseSB0aGUgcmV2aXNpb24gaGFuZGxpbmcgd2FzIGRvbmUgaW4gYWRhcHRlci5qc1xuICAgICAgICAgIC8vIGdldEF0dGFjaG1lbnQsIGhvd2V2ZXIgc2luY2UgaWRiLW5leHQgZG9lc250IHdlIG5lZWQgdG9cbiAgICAgICAgICAvLyBwYXNzIHRoZSByZXYgdGhyb3VnaFxuICAgICAgICAgIHJldjogZG9jLl9yZXYsXG4gICAgICAgICAgYmluYXJ5OiBvcHRzLmJpbmFyeSxcbiAgICAgICAgICBjdHg6IGN0eFxuICAgICAgICB9LCBmdW5jdGlvbiAoZXJyLCBkYXRhKSB7XG4gICAgICAgICAgdmFyIGF0dCA9IGRvYy5fYXR0YWNobWVudHNba2V5XTtcbiAgICAgICAgICBhdHQuZGF0YSA9IGRhdGE7XG4gICAgICAgICAgZGVsZXRlIGF0dC5zdHViO1xuICAgICAgICAgIGRlbGV0ZSBhdHQubGVuZ3RoO1xuICAgICAgICAgIGlmICghLS1jb3VudCkge1xuICAgICAgICAgICAgY2IobnVsbCwgZG9jKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSwgc2VsZik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChkb2MuX2F0dGFjaG1lbnRzKSB7XG4gICAgICAgIGZvciAodmFyIGtleSBpbiBkb2MuX2F0dGFjaG1lbnRzKSB7XG4gICAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIGVsc2UgKi9cbiAgICAgICAgICBpZiAoZG9jLl9hdHRhY2htZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICBkb2MuX2F0dGFjaG1lbnRzW2tleV0uc3R1YiA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjYihudWxsLCBkb2MpO1xuICAgIH1cbiAgfSk7XG59KTtcblxuLy8gVE9ETzogSSBkb250IGxpa2UgdGhpcywgaXQgZm9yY2VzIGFuIGV4dHJhIHJlYWQgZm9yIGV2ZXJ5XG4vLyBhdHRhY2htZW50IHJlYWQgYW5kIGVuZm9yY2VzIGEgY29uZnVzaW5nIGFwaSBiZXR3ZWVuXG4vLyBhZGFwdGVyLmpzIGFuZCB0aGUgYWRhcHRlciBpbXBsZW1lbnRhdGlvblxuQWJzdHJhY3RQb3VjaERCLnByb3RvdHlwZS5nZXRBdHRhY2htZW50ID1cbiAgYWRhcHRlckZ1bignZ2V0QXR0YWNobWVudCcsIGZ1bmN0aW9uIChkb2NJZCwgYXR0YWNobWVudElkLCBvcHRzLCBjYWxsYmFjaykge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIGlmIChvcHRzIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICBjYWxsYmFjayA9IG9wdHM7XG4gICAgb3B0cyA9IHt9O1xuICB9XG4gIHRoaXMuX2dldChkb2NJZCwgb3B0cywgZnVuY3Rpb24gKGVyciwgcmVzKSB7XG4gICAgaWYgKGVycikge1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKGVycik7XG4gICAgfVxuICAgIGlmIChyZXMuZG9jLl9hdHRhY2htZW50cyAmJiByZXMuZG9jLl9hdHRhY2htZW50c1thdHRhY2htZW50SWRdKSB7XG4gICAgICBvcHRzLmN0eCA9IHJlcy5jdHg7XG4gICAgICBvcHRzLmJpbmFyeSA9IHRydWU7XG4gICAgICBzZWxmLl9nZXRBdHRhY2htZW50KGRvY0lkLCBhdHRhY2htZW50SWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlcy5kb2MuX2F0dGFjaG1lbnRzW2F0dGFjaG1lbnRJZF0sIG9wdHMsIGNhbGxiYWNrKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKGNyZWF0ZUVycm9yKE1JU1NJTkdfRE9DKSk7XG4gICAgfVxuICB9KTtcbn0pO1xuXG5BYnN0cmFjdFBvdWNoREIucHJvdG90eXBlLmFsbERvY3MgPVxuICBhZGFwdGVyRnVuKCdhbGxEb2NzJywgZnVuY3Rpb24gKG9wdHMsIGNhbGxiYWNrKSB7XG4gIGlmICh0eXBlb2Ygb3B0cyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIGNhbGxiYWNrID0gb3B0cztcbiAgICBvcHRzID0ge307XG4gIH1cbiAgb3B0cy5za2lwID0gdHlwZW9mIG9wdHMuc2tpcCAhPT0gJ3VuZGVmaW5lZCcgPyBvcHRzLnNraXAgOiAwO1xuICBpZiAob3B0cy5zdGFydF9rZXkpIHtcbiAgICBvcHRzLnN0YXJ0a2V5ID0gb3B0cy5zdGFydF9rZXk7XG4gIH1cbiAgaWYgKG9wdHMuZW5kX2tleSkge1xuICAgIG9wdHMuZW5ka2V5ID0gb3B0cy5lbmRfa2V5O1xuICB9XG4gIGlmICgna2V5cycgaW4gb3B0cykge1xuICAgIGlmICghQXJyYXkuaXNBcnJheShvcHRzLmtleXMpKSB7XG4gICAgICByZXR1cm4gY2FsbGJhY2sobmV3IFR5cGVFcnJvcignb3B0aW9ucy5rZXlzIG11c3QgYmUgYW4gYXJyYXknKSk7XG4gICAgfVxuICAgIHZhciBpbmNvbXBhdGlibGVPcHQgPVxuICAgICAgWydzdGFydGtleScsICdlbmRrZXknLCAna2V5J10uZmlsdGVyKGZ1bmN0aW9uIChpbmNvbXBhdGlibGVPcHQpIHtcbiAgICAgIHJldHVybiBpbmNvbXBhdGlibGVPcHQgaW4gb3B0cztcbiAgICB9KVswXTtcbiAgICBpZiAoaW5jb21wYXRpYmxlT3B0KSB7XG4gICAgICBjYWxsYmFjayhjcmVhdGVFcnJvcihRVUVSWV9QQVJTRV9FUlJPUixcbiAgICAgICAgJ1F1ZXJ5IHBhcmFtZXRlciBgJyArIGluY29tcGF0aWJsZU9wdCArXG4gICAgICAgICdgIGlzIG5vdCBjb21wYXRpYmxlIHdpdGggbXVsdGktZ2V0J1xuICAgICAgKSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICh0aGlzLnR5cGUoKSAhPT0gJ2h0dHAnKSB7XG4gICAgICByZXR1cm4gYWxsRG9jc0tleXNRdWVyeSh0aGlzLCBvcHRzLCBjYWxsYmFjayk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoaXMuX2FsbERvY3Mob3B0cywgY2FsbGJhY2spO1xufSk7XG5cbkFic3RyYWN0UG91Y2hEQi5wcm90b3R5cGUuY2hhbmdlcyA9IGZ1bmN0aW9uIChvcHRzLCBjYWxsYmFjaykge1xuICBpZiAodHlwZW9mIG9wdHMgPT09ICdmdW5jdGlvbicpIHtcbiAgICBjYWxsYmFjayA9IG9wdHM7XG4gICAgb3B0cyA9IHt9O1xuICB9XG4gIHJldHVybiBuZXcgQ2hhbmdlcyQxKHRoaXMsIG9wdHMsIGNhbGxiYWNrKTtcbn07XG5cbkFic3RyYWN0UG91Y2hEQi5wcm90b3R5cGUuY2xvc2UgPSBhZGFwdGVyRnVuKCdjbG9zZScsIGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICB0aGlzLl9jbG9zZWQgPSB0cnVlO1xuICB0aGlzLmVtaXQoJ2Nsb3NlZCcpO1xuICByZXR1cm4gdGhpcy5fY2xvc2UoY2FsbGJhY2spO1xufSk7XG5cbkFic3RyYWN0UG91Y2hEQi5wcm90b3R5cGUuaW5mbyA9IGFkYXB0ZXJGdW4oJ2luZm8nLCBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICB0aGlzLl9pbmZvKGZ1bmN0aW9uIChlcnIsIGluZm8pIHtcbiAgICBpZiAoZXJyKSB7XG4gICAgICByZXR1cm4gY2FsbGJhY2soZXJyKTtcbiAgICB9XG4gICAgLy8gYXNzdW1lIHdlIGtub3cgYmV0dGVyIHRoYW4gdGhlIGFkYXB0ZXIsIHVubGVzcyBpdCBpbmZvcm1zIHVzXG4gICAgaW5mby5kYl9uYW1lID0gaW5mby5kYl9uYW1lIHx8IHNlbGYubmFtZTtcbiAgICBpbmZvLmF1dG9fY29tcGFjdGlvbiA9ICEhKHNlbGYuYXV0b19jb21wYWN0aW9uICYmIHNlbGYudHlwZSgpICE9PSAnaHR0cCcpO1xuICAgIGluZm8uYWRhcHRlciA9IHNlbGYudHlwZSgpO1xuICAgIGNhbGxiYWNrKG51bGwsIGluZm8pO1xuICB9KTtcbn0pO1xuXG5BYnN0cmFjdFBvdWNoREIucHJvdG90eXBlLmlkID0gYWRhcHRlckZ1bignaWQnLCBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgcmV0dXJuIHRoaXMuX2lkKGNhbGxiYWNrKTtcbn0pO1xuXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuQWJzdHJhY3RQb3VjaERCLnByb3RvdHlwZS50eXBlID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gKHR5cGVvZiB0aGlzLl90eXBlID09PSAnZnVuY3Rpb24nKSA/IHRoaXMuX3R5cGUoKSA6IHRoaXMuYWRhcHRlcjtcbn07XG5cbkFic3RyYWN0UG91Y2hEQi5wcm90b3R5cGUuYnVsa0RvY3MgPVxuICBhZGFwdGVyRnVuKCdidWxrRG9jcycsIGZ1bmN0aW9uIChyZXEsIG9wdHMsIGNhbGxiYWNrKSB7XG4gIGlmICh0eXBlb2Ygb3B0cyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIGNhbGxiYWNrID0gb3B0cztcbiAgICBvcHRzID0ge307XG4gIH1cblxuICBvcHRzID0gb3B0cyB8fCB7fTtcblxuICBpZiAoQXJyYXkuaXNBcnJheShyZXEpKSB7XG4gICAgcmVxID0ge1xuICAgICAgZG9jczogcmVxXG4gICAgfTtcbiAgfVxuXG4gIGlmICghcmVxIHx8ICFyZXEuZG9jcyB8fCAhQXJyYXkuaXNBcnJheShyZXEuZG9jcykpIHtcbiAgICByZXR1cm4gY2FsbGJhY2soY3JlYXRlRXJyb3IoTUlTU0lOR19CVUxLX0RPQ1MpKTtcbiAgfVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcmVxLmRvY3MubGVuZ3RoOyArK2kpIHtcbiAgICBpZiAodHlwZW9mIHJlcS5kb2NzW2ldICE9PSAnb2JqZWN0JyB8fCBBcnJheS5pc0FycmF5KHJlcS5kb2NzW2ldKSkge1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKGNyZWF0ZUVycm9yKE5PVF9BTl9PQkpFQ1QpKTtcbiAgICB9XG4gIH1cblxuICB2YXIgYXR0YWNobWVudEVycm9yO1xuICByZXEuZG9jcy5mb3JFYWNoKGZ1bmN0aW9uIChkb2MpIHtcbiAgICBpZiAoZG9jLl9hdHRhY2htZW50cykge1xuICAgICAgT2JqZWN0LmtleXMoZG9jLl9hdHRhY2htZW50cykuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICBhdHRhY2htZW50RXJyb3IgPSBhdHRhY2htZW50RXJyb3IgfHwgYXR0YWNobWVudE5hbWVFcnJvcihuYW1lKTtcbiAgICAgICAgaWYgKCFkb2MuX2F0dGFjaG1lbnRzW25hbWVdLmNvbnRlbnRfdHlwZSkge1xuICAgICAgICAgIGd1YXJkZWRDb25zb2xlKCd3YXJuJywgJ0F0dGFjaG1lbnQnLCBuYW1lLCAnb24gZG9jdW1lbnQnLCBkb2MuX2lkLCAnaXMgbWlzc2luZyBjb250ZW50X3R5cGUnKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9KTtcblxuICBpZiAoYXR0YWNobWVudEVycm9yKSB7XG4gICAgcmV0dXJuIGNhbGxiYWNrKGNyZWF0ZUVycm9yKEJBRF9SRVFVRVNULCBhdHRhY2htZW50RXJyb3IpKTtcbiAgfVxuXG4gIGlmICghKCduZXdfZWRpdHMnIGluIG9wdHMpKSB7XG4gICAgaWYgKCduZXdfZWRpdHMnIGluIHJlcSkge1xuICAgICAgb3B0cy5uZXdfZWRpdHMgPSByZXEubmV3X2VkaXRzO1xuICAgIH0gZWxzZSB7XG4gICAgICBvcHRzLm5ld19lZGl0cyA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFvcHRzLm5ld19lZGl0cyAmJiB0aGlzLnR5cGUoKSAhPT0gJ2h0dHAnKSB7XG4gICAgLy8gZW5zdXJlIHJldmlzaW9ucyBvZiB0aGUgc2FtZSBkb2MgYXJlIHNvcnRlZCwgc28gdGhhdFxuICAgIC8vIHRoZSBsb2NhbCBhZGFwdGVyIHByb2Nlc3NlcyB0aGVtIGNvcnJlY3RseSAoIzI5MzUpXG4gICAgcmVxLmRvY3Muc29ydChjb21wYXJlQnlJZFRoZW5SZXYpO1xuICB9XG5cbiAgY2xlYW5Eb2NzKHJlcS5kb2NzKTtcblxuICByZXR1cm4gdGhpcy5fYnVsa0RvY3MocmVxLCBvcHRzLCBmdW5jdGlvbiAoZXJyLCByZXMpIHtcbiAgICBpZiAoZXJyKSB7XG4gICAgICByZXR1cm4gY2FsbGJhY2soZXJyKTtcbiAgICB9XG4gICAgaWYgKCFvcHRzLm5ld19lZGl0cykge1xuICAgICAgLy8gdGhpcyBpcyB3aGF0IGNvdWNoIGRvZXMgd2hlbiBuZXdfZWRpdHMgaXMgZmFsc2VcbiAgICAgIHJlcyA9IHJlcy5maWx0ZXIoZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgcmV0dXJuIHguZXJyb3I7XG4gICAgICB9KTtcbiAgICB9XG4gICAgY2FsbGJhY2sobnVsbCwgcmVzKTtcbiAgfSk7XG59KTtcblxuQWJzdHJhY3RQb3VjaERCLnByb3RvdHlwZS5yZWdpc3RlckRlcGVuZGVudERhdGFiYXNlID1cbiAgYWRhcHRlckZ1bigncmVnaXN0ZXJEZXBlbmRlbnREYXRhYmFzZScsIGZ1bmN0aW9uIChkZXBlbmRlbnREYixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWxsYmFjaykge1xuICB2YXIgZGVwREIgPSBuZXcgdGhpcy5jb25zdHJ1Y3RvcihkZXBlbmRlbnREYiwgdGhpcy5fX29wdHMpO1xuXG4gIGZ1bmN0aW9uIGRpZmZGdW4oZG9jKSB7XG4gICAgZG9jLmRlcGVuZGVudERicyA9IGRvYy5kZXBlbmRlbnREYnMgfHwge307XG4gICAgaWYgKGRvYy5kZXBlbmRlbnREYnNbZGVwZW5kZW50RGJdKSB7XG4gICAgICByZXR1cm4gZmFsc2U7IC8vIG5vIHVwZGF0ZSByZXF1aXJlZFxuICAgIH1cbiAgICBkb2MuZGVwZW5kZW50RGJzW2RlcGVuZGVudERiXSA9IHRydWU7XG4gICAgcmV0dXJuIGRvYztcbiAgfVxuICB1cHNlcnQodGhpcywgJ19sb2NhbC9fcG91Y2hfZGVwZW5kZW50RGJzJywgZGlmZkZ1bilcbiAgICAudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICBjYWxsYmFjayhudWxsLCB7ZGI6IGRlcERCfSk7XG4gICAgfSkuY2F0Y2goY2FsbGJhY2spO1xufSk7XG5cbkFic3RyYWN0UG91Y2hEQi5wcm90b3R5cGUuZGVzdHJveSA9XG4gIGFkYXB0ZXJGdW4oJ2Rlc3Ryb3knLCBmdW5jdGlvbiAob3B0cywgY2FsbGJhY2spIHtcblxuICBpZiAodHlwZW9mIG9wdHMgPT09ICdmdW5jdGlvbicpIHtcbiAgICBjYWxsYmFjayA9IG9wdHM7XG4gICAgb3B0cyA9IHt9O1xuICB9XG5cbiAgdmFyIHNlbGYgPSB0aGlzO1xuICB2YXIgdXNlUHJlZml4ID0gJ3VzZV9wcmVmaXgnIGluIHNlbGYgPyBzZWxmLnVzZV9wcmVmaXggOiB0cnVlO1xuXG4gIGZ1bmN0aW9uIGRlc3Ryb3lEYigpIHtcbiAgICAvLyBjYWxsIGRlc3Ryb3kgbWV0aG9kIG9mIHRoZSBwYXJ0aWN1bGFyIGFkYXB0b3JcbiAgICBzZWxmLl9kZXN0cm95KG9wdHMsIGZ1bmN0aW9uIChlcnIsIHJlc3ApIHtcbiAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGVycik7XG4gICAgICB9XG4gICAgICBzZWxmLl9kZXN0cm95ZWQgPSB0cnVlO1xuICAgICAgc2VsZi5lbWl0KCdkZXN0cm95ZWQnKTtcbiAgICAgIGNhbGxiYWNrKG51bGwsIHJlc3AgfHwgeyAnb2snOiB0cnVlIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgaWYgKHNlbGYudHlwZSgpID09PSAnaHR0cCcpIHtcbiAgICAvLyBubyBuZWVkIHRvIGNoZWNrIGZvciBkZXBlbmRlbnQgREJzIGlmIGl0J3MgYSByZW1vdGUgREJcbiAgICByZXR1cm4gZGVzdHJveURiKCk7XG4gIH1cblxuICBzZWxmLmdldCgnX2xvY2FsL19wb3VjaF9kZXBlbmRlbnREYnMnLCBmdW5jdGlvbiAoZXJyLCBsb2NhbERvYykge1xuICAgIGlmIChlcnIpIHtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgICAgaWYgKGVyci5zdGF0dXMgIT09IDQwNCkge1xuICAgICAgICByZXR1cm4gY2FsbGJhY2soZXJyKTtcbiAgICAgIH0gZWxzZSB7IC8vIG5vIGRlcGVuZGVuY2llc1xuICAgICAgICByZXR1cm4gZGVzdHJveURiKCk7XG4gICAgICB9XG4gICAgfVxuICAgIHZhciBkZXBlbmRlbnREYnMgPSBsb2NhbERvYy5kZXBlbmRlbnREYnM7XG4gICAgdmFyIFBvdWNoREIgPSBzZWxmLmNvbnN0cnVjdG9yO1xuICAgIHZhciBkZWxldGVkTWFwID0gT2JqZWN0LmtleXMoZGVwZW5kZW50RGJzKS5tYXAoZnVuY3Rpb24gKG5hbWUpIHtcbiAgICAgIC8vIHVzZV9wcmVmaXggaXMgb25seSBmYWxzZSBpbiB0aGUgYnJvd3NlclxuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIHZhciB0cnVlTmFtZSA9IHVzZVByZWZpeCA/XG4gICAgICAgIG5hbWUucmVwbGFjZShuZXcgUmVnRXhwKCdeJyArIFBvdWNoREIucHJlZml4KSwgJycpIDogbmFtZTtcbiAgICAgIHJldHVybiBuZXcgUG91Y2hEQih0cnVlTmFtZSwgc2VsZi5fX29wdHMpLmRlc3Ryb3koKTtcbiAgICB9KTtcbiAgICBQb3VjaFByb21pc2UuYWxsKGRlbGV0ZWRNYXApLnRoZW4oZGVzdHJveURiLCBjYWxsYmFjayk7XG4gIH0pO1xufSk7XG5cbmZ1bmN0aW9uIFRhc2tRdWV1ZSgpIHtcbiAgdGhpcy5pc1JlYWR5ID0gZmFsc2U7XG4gIHRoaXMuZmFpbGVkID0gZmFsc2U7XG4gIHRoaXMucXVldWUgPSBbXTtcbn1cblxuVGFza1F1ZXVlLnByb3RvdHlwZS5leGVjdXRlID0gZnVuY3Rpb24gKCkge1xuICB2YXIgZnVuO1xuICBpZiAodGhpcy5mYWlsZWQpIHtcbiAgICB3aGlsZSAoKGZ1biA9IHRoaXMucXVldWUuc2hpZnQoKSkpIHtcbiAgICAgIGZ1bih0aGlzLmZhaWxlZCk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHdoaWxlICgoZnVuID0gdGhpcy5xdWV1ZS5zaGlmdCgpKSkge1xuICAgICAgZnVuKCk7XG4gICAgfVxuICB9XG59O1xuXG5UYXNrUXVldWUucHJvdG90eXBlLmZhaWwgPSBmdW5jdGlvbiAoZXJyKSB7XG4gIHRoaXMuZmFpbGVkID0gZXJyO1xuICB0aGlzLmV4ZWN1dGUoKTtcbn07XG5cblRhc2tRdWV1ZS5wcm90b3R5cGUucmVhZHkgPSBmdW5jdGlvbiAoZGIpIHtcbiAgdGhpcy5pc1JlYWR5ID0gdHJ1ZTtcbiAgdGhpcy5kYiA9IGRiO1xuICB0aGlzLmV4ZWN1dGUoKTtcbn07XG5cblRhc2tRdWV1ZS5wcm90b3R5cGUuYWRkVGFzayA9IGZ1bmN0aW9uIChmdW4pIHtcbiAgdGhpcy5xdWV1ZS5wdXNoKGZ1bik7XG4gIGlmICh0aGlzLmZhaWxlZCkge1xuICAgIHRoaXMuZXhlY3V0ZSgpO1xuICB9XG59O1xuXG5mdW5jdGlvbiBwYXJzZUFkYXB0ZXIobmFtZSwgb3B0cykge1xuICB2YXIgbWF0Y2ggPSBuYW1lLm1hdGNoKC8oW2EtelxcLV0qKTpcXC9cXC8oLiopLyk7XG4gIGlmIChtYXRjaCkge1xuICAgIC8vIHRoZSBodHRwIGFkYXB0ZXIgZXhwZWN0cyB0aGUgZnVsbHkgcXVhbGlmaWVkIG5hbWVcbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogL2h0dHBzPy8udGVzdChtYXRjaFsxXSkgPyBtYXRjaFsxXSArICc6Ly8nICsgbWF0Y2hbMl0gOiBtYXRjaFsyXSxcbiAgICAgIGFkYXB0ZXI6IG1hdGNoWzFdXG4gICAgfTtcbiAgfVxuXG4gIHZhciBhZGFwdGVycyA9IFBvdWNoREIuYWRhcHRlcnM7XG4gIHZhciBwcmVmZXJyZWRBZGFwdGVycyA9IFBvdWNoREIucHJlZmVycmVkQWRhcHRlcnM7XG4gIHZhciBwcmVmaXggPSBQb3VjaERCLnByZWZpeDtcbiAgdmFyIGFkYXB0ZXJOYW1lID0gb3B0cy5hZGFwdGVyO1xuXG4gIGlmICghYWRhcHRlck5hbWUpIHsgLy8gYXV0b21hdGljYWxseSBkZXRlcm1pbmUgYWRhcHRlclxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJlZmVycmVkQWRhcHRlcnMubGVuZ3RoOyArK2kpIHtcbiAgICAgIGFkYXB0ZXJOYW1lID0gcHJlZmVycmVkQWRhcHRlcnNbaV07XG4gICAgICAvLyBjaGVjayBmb3IgYnJvd3NlcnMgdGhhdCBoYXZlIGJlZW4gdXBncmFkZWQgZnJvbSB3ZWJzcWwtb25seSB0byB3ZWJzcWwraWRiXG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICAgIGlmIChhZGFwdGVyTmFtZSA9PT0gJ2lkYicgJiYgJ3dlYnNxbCcgaW4gYWRhcHRlcnMgJiZcbiAgICAgICAgICBoYXNMb2NhbFN0b3JhZ2UoKSAmJiBsb2NhbFN0b3JhZ2VbJ19wb3VjaF9fd2Vic3FsZGJfJyArIHByZWZpeCArIG5hbWVdKSB7XG4gICAgICAgIC8vIGxvZyBpdCwgYmVjYXVzZSB0aGlzIGNhbiBiZSBjb25mdXNpbmcgZHVyaW5nIGRldmVsb3BtZW50XG4gICAgICAgIGd1YXJkZWRDb25zb2xlKCdsb2cnLCAnUG91Y2hEQiBpcyBkb3duZ3JhZGluZyBcIicgKyBuYW1lICsgJ1wiIHRvIFdlYlNRTCB0bycgK1xuICAgICAgICAgICcgYXZvaWQgZGF0YSBsb3NzLCBiZWNhdXNlIGl0IHdhcyBhbHJlYWR5IG9wZW5lZCB3aXRoIFdlYlNRTC4nKTtcbiAgICAgICAgY29udGludWU7IC8vIGtlZXAgdXNpbmcgd2Vic3FsIHRvIGF2b2lkIHVzZXIgZGF0YSBsb3NzXG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICB2YXIgYWRhcHRlciA9IGFkYXB0ZXJzW2FkYXB0ZXJOYW1lXTtcblxuICAvLyBpZiBhZGFwdGVyIGlzIGludmFsaWQsIHRoZW4gYW4gZXJyb3Igd2lsbCBiZSB0aHJvd24gbGF0ZXJcbiAgdmFyIHVzZVByZWZpeCA9IChhZGFwdGVyICYmICd1c2VfcHJlZml4JyBpbiBhZGFwdGVyKSA/XG4gICAgYWRhcHRlci51c2VfcHJlZml4IDogdHJ1ZTtcblxuICByZXR1cm4ge1xuICAgIG5hbWU6IHVzZVByZWZpeCA/IChwcmVmaXggKyBuYW1lKSA6IG5hbWUsXG4gICAgYWRhcHRlcjogYWRhcHRlck5hbWVcbiAgfTtcbn1cblxuLy8gT0ssIHNvIGhlcmUncyB0aGUgZGVhbC4gQ29uc2lkZXIgdGhpcyBjb2RlOlxuLy8gICAgIHZhciBkYjEgPSBuZXcgUG91Y2hEQignZm9vJyk7XG4vLyAgICAgdmFyIGRiMiA9IG5ldyBQb3VjaERCKCdmb28nKTtcbi8vICAgICBkYjEuZGVzdHJveSgpO1xuLy8gXiB0aGVzZSB0d28gYm90aCBuZWVkIHRvIGVtaXQgJ2Rlc3Ryb3llZCcgZXZlbnRzLFxuLy8gYXMgd2VsbCBhcyB0aGUgUG91Y2hEQiBjb25zdHJ1Y3RvciBpdHNlbGYuXG4vLyBTbyB3ZSBoYXZlIG9uZSBkYiBvYmplY3QgKHdoaWNoZXZlciBvbmUgZ290IGRlc3Ryb3koKSBjYWxsZWQgb24gaXQpXG4vLyByZXNwb25zaWJsZSBmb3IgZW1pdHRpbmcgdGhlIGluaXRpYWwgZXZlbnQsIHdoaWNoIHRoZW4gZ2V0cyBlbWl0dGVkXG4vLyBieSB0aGUgY29uc3RydWN0b3IsIHdoaWNoIHRoZW4gYnJvYWRjYXN0cyBpdCB0byBhbnkgb3RoZXIgZGJzXG4vLyB0aGF0IG1heSBoYXZlIGJlZW4gY3JlYXRlZCB3aXRoIHRoZSBzYW1lIG5hbWUuXG5mdW5jdGlvbiBwcmVwYXJlRm9yRGVzdHJ1Y3Rpb24oc2VsZikge1xuXG4gIHZhciBkZXN0cnVjdGlvbkxpc3RlbmVycyA9IHNlbGYuY29uc3RydWN0b3IuX2Rlc3RydWN0aW9uTGlzdGVuZXJzO1xuXG4gIGZ1bmN0aW9uIG9uRGVzdHJveWVkKCkge1xuICAgIHNlbGYucmVtb3ZlTGlzdGVuZXIoJ2Nsb3NlZCcsIG9uQ2xvc2VkKTtcbiAgICBzZWxmLmNvbnN0cnVjdG9yLmVtaXQoJ2Rlc3Ryb3llZCcsIHNlbGYubmFtZSk7XG4gIH1cblxuICBmdW5jdGlvbiBvbkNvbnN0cnVjdG9yRGVzdHJveWVkKCkge1xuICAgIHNlbGYucmVtb3ZlTGlzdGVuZXIoJ2Rlc3Ryb3llZCcsIG9uRGVzdHJveWVkKTtcbiAgICBzZWxmLnJlbW92ZUxpc3RlbmVyKCdjbG9zZWQnLCBvbkNsb3NlZCk7XG4gICAgc2VsZi5lbWl0KCdkZXN0cm95ZWQnKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIG9uQ2xvc2VkKCkge1xuICAgIHNlbGYucmVtb3ZlTGlzdGVuZXIoJ2Rlc3Ryb3llZCcsIG9uRGVzdHJveWVkKTtcbiAgICBkZXN0cnVjdGlvbkxpc3RlbmVycy5kZWxldGUoc2VsZi5uYW1lKTtcbiAgfVxuXG4gIHNlbGYub25jZSgnZGVzdHJveWVkJywgb25EZXN0cm95ZWQpO1xuICBzZWxmLm9uY2UoJ2Nsb3NlZCcsIG9uQ2xvc2VkKTtcblxuICAvLyBpbiBzZXR1cC5qcywgdGhlIGNvbnN0cnVjdG9yIGlzIHByaW1lZCB0byBsaXN0ZW4gZm9yIGRlc3Ryb3kgZXZlbnRzXG4gIGlmICghZGVzdHJ1Y3Rpb25MaXN0ZW5lcnMuaGFzKHNlbGYubmFtZSkpIHtcbiAgICBkZXN0cnVjdGlvbkxpc3RlbmVycy5zZXQoc2VsZi5uYW1lLCBbXSk7XG4gIH1cbiAgZGVzdHJ1Y3Rpb25MaXN0ZW5lcnMuZ2V0KHNlbGYubmFtZSkucHVzaChvbkNvbnN0cnVjdG9yRGVzdHJveWVkKTtcbn1cblxuaW5oZXJpdHMoUG91Y2hEQiwgQWJzdHJhY3RQb3VjaERCKTtcbmZ1bmN0aW9uIFBvdWNoREIobmFtZSwgb3B0cykge1xuICAvLyBJbiBOb2RlIG91ciB0ZXN0IHN1aXRlIG9ubHkgdGVzdHMgdGhpcyBmb3IgUG91Y2hBbHQgdW5mb3J0dW5hdGVseVxuICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFBvdWNoREIpKSB7XG4gICAgcmV0dXJuIG5ldyBQb3VjaERCKG5hbWUsIG9wdHMpO1xuICB9XG5cbiAgdmFyIHNlbGYgPSB0aGlzO1xuICBvcHRzID0gb3B0cyB8fCB7fTtcblxuICBpZiAobmFtZSAmJiB0eXBlb2YgbmFtZSA9PT0gJ29iamVjdCcpIHtcbiAgICBvcHRzID0gbmFtZTtcbiAgICBuYW1lID0gb3B0cy5uYW1lO1xuICAgIGRlbGV0ZSBvcHRzLm5hbWU7XG4gIH1cblxuICB0aGlzLl9fb3B0cyA9IG9wdHMgPSBjbG9uZShvcHRzKTtcblxuICBzZWxmLmF1dG9fY29tcGFjdGlvbiA9IG9wdHMuYXV0b19jb21wYWN0aW9uO1xuICBzZWxmLnByZWZpeCA9IFBvdWNoREIucHJlZml4O1xuXG4gIGlmICh0eXBlb2YgbmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcvaW52YWxpZCBEQiBuYW1lJyk7XG4gIH1cblxuICB2YXIgcHJlZml4ZWROYW1lID0gKG9wdHMucHJlZml4IHx8ICcnKSArIG5hbWU7XG4gIHZhciBiYWNrZW5kID0gcGFyc2VBZGFwdGVyKHByZWZpeGVkTmFtZSwgb3B0cyk7XG5cbiAgb3B0cy5uYW1lID0gYmFja2VuZC5uYW1lO1xuICBvcHRzLmFkYXB0ZXIgPSBvcHRzLmFkYXB0ZXIgfHwgYmFja2VuZC5hZGFwdGVyO1xuXG4gIHNlbGYubmFtZSA9IG5hbWU7XG4gIHNlbGYuX2FkYXB0ZXIgPSBvcHRzLmFkYXB0ZXI7XG4gIGRlYnVnKCdwb3VjaGRiOmFkYXB0ZXInKSgnUGlja2VkIGFkYXB0ZXI6ICcgKyBvcHRzLmFkYXB0ZXIpO1xuXG4gIGlmICghUG91Y2hEQi5hZGFwdGVyc1tvcHRzLmFkYXB0ZXJdIHx8XG4gICAgICAhUG91Y2hEQi5hZGFwdGVyc1tvcHRzLmFkYXB0ZXJdLnZhbGlkKCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgQWRhcHRlcjogJyArIG9wdHMuYWRhcHRlcik7XG4gIH1cblxuICBBYnN0cmFjdFBvdWNoREIuY2FsbChzZWxmKTtcbiAgc2VsZi50YXNrcXVldWUgPSBuZXcgVGFza1F1ZXVlKCk7XG5cbiAgc2VsZi5hZGFwdGVyID0gb3B0cy5hZGFwdGVyO1xuXG4gIFBvdWNoREIuYWRhcHRlcnNbb3B0cy5hZGFwdGVyXS5jYWxsKHNlbGYsIG9wdHMsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICBpZiAoZXJyKSB7XG4gICAgICByZXR1cm4gc2VsZi50YXNrcXVldWUuZmFpbChlcnIpO1xuICAgIH1cbiAgICBwcmVwYXJlRm9yRGVzdHJ1Y3Rpb24oc2VsZik7XG5cbiAgICBzZWxmLmVtaXQoJ2NyZWF0ZWQnLCBzZWxmKTtcbiAgICBQb3VjaERCLmVtaXQoJ2NyZWF0ZWQnLCBzZWxmLm5hbWUpO1xuICAgIHNlbGYudGFza3F1ZXVlLnJlYWR5KHNlbGYpO1xuICB9KTtcblxufVxuXG5Qb3VjaERCLmRlYnVnID0gZGVidWc7XG5cblBvdWNoREIuYWRhcHRlcnMgPSB7fTtcblBvdWNoREIucHJlZmVycmVkQWRhcHRlcnMgPSBbXTtcblxuUG91Y2hEQi5wcmVmaXggPSAnX3BvdWNoXyc7XG5cbnZhciBldmVudEVtaXR0ZXIgPSBuZXcgZXZlbnRzLkV2ZW50RW1pdHRlcigpO1xuXG5mdW5jdGlvbiBzZXRVcEV2ZW50RW1pdHRlcihQb3VjaCkge1xuICBPYmplY3Qua2V5cyhldmVudHMuRXZlbnRFbWl0dGVyLnByb3RvdHlwZSkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgaWYgKHR5cGVvZiBldmVudHMuRXZlbnRFbWl0dGVyLnByb3RvdHlwZVtrZXldID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBQb3VjaFtrZXldID0gZXZlbnRFbWl0dGVyW2tleV0uYmluZChldmVudEVtaXR0ZXIpO1xuICAgIH1cbiAgfSk7XG5cbiAgLy8gdGhlc2UgYXJlIGNyZWF0ZWQgaW4gY29uc3RydWN0b3IuanMsIGFuZCBhbGxvdyB1cyB0byBub3RpZnkgZWFjaCBEQiB3aXRoXG4gIC8vIHRoZSBzYW1lIG5hbWUgdGhhdCBpdCB3YXMgZGVzdHJveWVkLCB2aWEgdGhlIGNvbnN0cnVjdG9yIG9iamVjdFxuICB2YXIgZGVzdHJ1Y3RMaXN0ZW5lcnMgPSBQb3VjaC5fZGVzdHJ1Y3Rpb25MaXN0ZW5lcnMgPSBuZXcgX01hcCgpO1xuICBQb3VjaC5vbignZGVzdHJveWVkJywgZnVuY3Rpb24gb25Db25zdHJ1Y3RvckRlc3Ryb3llZChuYW1lKSB7XG4gICAgZGVzdHJ1Y3RMaXN0ZW5lcnMuZ2V0KG5hbWUpLmZvckVhY2goZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgICBjYWxsYmFjaygpO1xuICAgIH0pO1xuICAgIGRlc3RydWN0TGlzdGVuZXJzLmRlbGV0ZShuYW1lKTtcbiAgfSk7XG59XG5cbnNldFVwRXZlbnRFbWl0dGVyKFBvdWNoREIpO1xuXG5Qb3VjaERCLmFkYXB0ZXIgPSBmdW5jdGlvbiAoaWQsIG9iaiwgYWRkVG9QcmVmZXJyZWRBZGFwdGVycykge1xuICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICBpZiAob2JqLnZhbGlkKCkpIHtcbiAgICBQb3VjaERCLmFkYXB0ZXJzW2lkXSA9IG9iajtcbiAgICBpZiAoYWRkVG9QcmVmZXJyZWRBZGFwdGVycykge1xuICAgICAgUG91Y2hEQi5wcmVmZXJyZWRBZGFwdGVycy5wdXNoKGlkKTtcbiAgICB9XG4gIH1cbn07XG5cblBvdWNoREIucGx1Z2luID0gZnVuY3Rpb24gKG9iaikge1xuICBpZiAodHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJykgeyAvLyBmdW5jdGlvbiBzdHlsZSBmb3IgcGx1Z2luc1xuICAgIG9iaihQb3VjaERCKTtcbiAgfSBlbHNlIGlmICh0eXBlb2Ygb2JqICE9PSAnb2JqZWN0JyB8fCBPYmplY3Qua2V5cyhvYmopLmxlbmd0aCA9PT0gMCl7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHBsdWdpbjogZ290IFxcXCInICsgb2JqICsgJ1xcXCIsIGV4cGVjdGVkIGFuIG9iamVjdCBvciBhIGZ1bmN0aW9uJyk7XG4gIH0gZWxzZSB7XG4gICAgT2JqZWN0LmtleXMob2JqKS5mb3JFYWNoKGZ1bmN0aW9uIChpZCkgeyAvLyBvYmplY3Qgc3R5bGUgZm9yIHBsdWdpbnNcbiAgICAgIFBvdWNoREIucHJvdG90eXBlW2lkXSA9IG9ialtpZF07XG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIFBvdWNoREI7XG59O1xuXG5Qb3VjaERCLmRlZmF1bHRzID0gZnVuY3Rpb24gKGRlZmF1bHRPcHRzKSB7XG4gIGZ1bmN0aW9uIFBvdWNoQWx0KG5hbWUsIG9wdHMpIHtcbiAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgUG91Y2hBbHQpKSB7XG4gICAgICByZXR1cm4gbmV3IFBvdWNoQWx0KG5hbWUsIG9wdHMpO1xuICAgIH1cblxuICAgIG9wdHMgPSBvcHRzIHx8IHt9O1xuXG4gICAgaWYgKG5hbWUgJiYgdHlwZW9mIG5hbWUgPT09ICdvYmplY3QnKSB7XG4gICAgICBvcHRzID0gbmFtZTtcbiAgICAgIG5hbWUgPSBvcHRzLm5hbWU7XG4gICAgICBkZWxldGUgb3B0cy5uYW1lO1xuICAgIH1cblxuICAgIG9wdHMgPSBleHRlbmQkMSh7fSwgUG91Y2hBbHQuX19kZWZhdWx0cywgb3B0cyk7XG4gICAgUG91Y2hEQi5jYWxsKHRoaXMsIG5hbWUsIG9wdHMpO1xuICB9XG5cbiAgaW5oZXJpdHMoUG91Y2hBbHQsIFBvdWNoREIpO1xuXG4gIFBvdWNoQWx0LnByZWZlcnJlZEFkYXB0ZXJzID0gUG91Y2hEQi5wcmVmZXJyZWRBZGFwdGVycy5zbGljZSgpO1xuICBPYmplY3Qua2V5cyhQb3VjaERCKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICBpZiAoIShrZXkgaW4gUG91Y2hBbHQpKSB7XG4gICAgICBQb3VjaEFsdFtrZXldID0gUG91Y2hEQltrZXldO1xuICAgIH1cbiAgfSk7XG5cbiAgLy8gbWFrZSBkZWZhdWx0IG9wdGlvbnMgdHJhbnNpdGl2ZVxuICAvLyBodHRwczovL2dpdGh1Yi5jb20vcG91Y2hkYi9wb3VjaGRiL2lzc3Vlcy81OTIyXG4gIFBvdWNoQWx0Ll9fZGVmYXVsdHMgPSBleHRlbmQkMSh7fSwgdGhpcy5fX2RlZmF1bHRzLCBkZWZhdWx0T3B0cyk7XG5cbiAgcmV0dXJuIFBvdWNoQWx0O1xufTtcblxuLy8gbWFuYWdlZCBhdXRvbWF0aWNhbGx5IGJ5IHNldC12ZXJzaW9uLmpzXG52YXIgdmVyc2lvbiA9IFwiNi4xLjBcIjtcblxuUG91Y2hEQi52ZXJzaW9uID0gdmVyc2lvbjtcblxuZnVuY3Rpb24gdG9PYmplY3QoYXJyYXkpIHtcbiAgcmV0dXJuIGFycmF5LnJlZHVjZShmdW5jdGlvbiAob2JqLCBpdGVtKSB7XG4gICAgb2JqW2l0ZW1dID0gdHJ1ZTtcbiAgICByZXR1cm4gb2JqO1xuICB9LCB7fSk7XG59XG4vLyBMaXN0IG9mIHRvcCBsZXZlbCByZXNlcnZlZCB3b3JkcyBmb3IgZG9jXG52YXIgcmVzZXJ2ZWRXb3JkcyA9IHRvT2JqZWN0KFtcbiAgJ19pZCcsXG4gICdfcmV2JyxcbiAgJ19hdHRhY2htZW50cycsXG4gICdfZGVsZXRlZCcsXG4gICdfcmV2aXNpb25zJyxcbiAgJ19yZXZzX2luZm8nLFxuICAnX2NvbmZsaWN0cycsXG4gICdfZGVsZXRlZF9jb25mbGljdHMnLFxuICAnX2xvY2FsX3NlcScsXG4gICdfcmV2X3RyZWUnLFxuICAvL3JlcGxpY2F0aW9uIGRvY3VtZW50c1xuICAnX3JlcGxpY2F0aW9uX2lkJyxcbiAgJ19yZXBsaWNhdGlvbl9zdGF0ZScsXG4gICdfcmVwbGljYXRpb25fc3RhdGVfdGltZScsXG4gICdfcmVwbGljYXRpb25fc3RhdGVfcmVhc29uJyxcbiAgJ19yZXBsaWNhdGlvbl9zdGF0cycsXG4gIC8vIFNwZWNpZmljIHRvIENvdWNoYmFzZSBTeW5jIEdhdGV3YXlcbiAgJ19yZW1vdmVkJ1xuXSk7XG5cbi8vIExpc3Qgb2YgcmVzZXJ2ZWQgd29yZHMgdGhhdCBzaG91bGQgZW5kIHVwIHRoZSBkb2N1bWVudFxudmFyIGRhdGFXb3JkcyA9IHRvT2JqZWN0KFtcbiAgJ19hdHRhY2htZW50cycsXG4gIC8vcmVwbGljYXRpb24gZG9jdW1lbnRzXG4gICdfcmVwbGljYXRpb25faWQnLFxuICAnX3JlcGxpY2F0aW9uX3N0YXRlJyxcbiAgJ19yZXBsaWNhdGlvbl9zdGF0ZV90aW1lJyxcbiAgJ19yZXBsaWNhdGlvbl9zdGF0ZV9yZWFzb24nLFxuICAnX3JlcGxpY2F0aW9uX3N0YXRzJ1xuXSk7XG5cbmZ1bmN0aW9uIHBhcnNlUmV2aXNpb25JbmZvKHJldikge1xuICBpZiAoIS9eXFxkK1xcLS4vLnRlc3QocmV2KSkge1xuICAgIHJldHVybiBjcmVhdGVFcnJvcihJTlZBTElEX1JFVik7XG4gIH1cbiAgdmFyIGlkeCA9IHJldi5pbmRleE9mKCctJyk7XG4gIHZhciBsZWZ0ID0gcmV2LnN1YnN0cmluZygwLCBpZHgpO1xuICB2YXIgcmlnaHQgPSByZXYuc3Vic3RyaW5nKGlkeCArIDEpO1xuICByZXR1cm4ge1xuICAgIHByZWZpeDogcGFyc2VJbnQobGVmdCwgMTApLFxuICAgIGlkOiByaWdodFxuICB9O1xufVxuXG5mdW5jdGlvbiBtYWtlUmV2VHJlZUZyb21SZXZpc2lvbnMocmV2aXNpb25zLCBvcHRzKSB7XG4gIHZhciBwb3MgPSByZXZpc2lvbnMuc3RhcnQgLSByZXZpc2lvbnMuaWRzLmxlbmd0aCArIDE7XG5cbiAgdmFyIHJldmlzaW9uSWRzID0gcmV2aXNpb25zLmlkcztcbiAgdmFyIGlkcyA9IFtyZXZpc2lvbklkc1swXSwgb3B0cywgW11dO1xuXG4gIGZvciAodmFyIGkgPSAxLCBsZW4gPSByZXZpc2lvbklkcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgIGlkcyA9IFtyZXZpc2lvbklkc1tpXSwge3N0YXR1czogJ21pc3NpbmcnfSwgW2lkc11dO1xuICB9XG5cbiAgcmV0dXJuIFt7XG4gICAgcG9zOiBwb3MsXG4gICAgaWRzOiBpZHNcbiAgfV07XG59XG5cbi8vIFByZXByb2Nlc3MgZG9jdW1lbnRzLCBwYXJzZSB0aGVpciByZXZpc2lvbnMsIGFzc2lnbiBhbiBpZCBhbmQgYVxuLy8gcmV2aXNpb24gZm9yIG5ldyB3cml0ZXMgdGhhdCBhcmUgbWlzc2luZyB0aGVtLCBldGNcbmZ1bmN0aW9uIHBhcnNlRG9jKGRvYywgbmV3RWRpdHMpIHtcblxuICB2YXIgblJldk51bTtcbiAgdmFyIG5ld1JldklkO1xuICB2YXIgcmV2SW5mbztcbiAgdmFyIG9wdHMgPSB7c3RhdHVzOiAnYXZhaWxhYmxlJ307XG4gIGlmIChkb2MuX2RlbGV0ZWQpIHtcbiAgICBvcHRzLmRlbGV0ZWQgPSB0cnVlO1xuICB9XG5cbiAgaWYgKG5ld0VkaXRzKSB7XG4gICAgaWYgKCFkb2MuX2lkKSB7XG4gICAgICBkb2MuX2lkID0gdXVpZCgpO1xuICAgIH1cbiAgICBuZXdSZXZJZCA9IHV1aWQoMzIsIDE2KS50b0xvd2VyQ2FzZSgpO1xuICAgIGlmIChkb2MuX3Jldikge1xuICAgICAgcmV2SW5mbyA9IHBhcnNlUmV2aXNpb25JbmZvKGRvYy5fcmV2KTtcbiAgICAgIGlmIChyZXZJbmZvLmVycm9yKSB7XG4gICAgICAgIHJldHVybiByZXZJbmZvO1xuICAgICAgfVxuICAgICAgZG9jLl9yZXZfdHJlZSA9IFt7XG4gICAgICAgIHBvczogcmV2SW5mby5wcmVmaXgsXG4gICAgICAgIGlkczogW3JldkluZm8uaWQsIHtzdGF0dXM6ICdtaXNzaW5nJ30sIFtbbmV3UmV2SWQsIG9wdHMsIFtdXV1dXG4gICAgICB9XTtcbiAgICAgIG5SZXZOdW0gPSByZXZJbmZvLnByZWZpeCArIDE7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRvYy5fcmV2X3RyZWUgPSBbe1xuICAgICAgICBwb3M6IDEsXG4gICAgICAgIGlkcyA6IFtuZXdSZXZJZCwgb3B0cywgW11dXG4gICAgICB9XTtcbiAgICAgIG5SZXZOdW0gPSAxO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBpZiAoZG9jLl9yZXZpc2lvbnMpIHtcbiAgICAgIGRvYy5fcmV2X3RyZWUgPSBtYWtlUmV2VHJlZUZyb21SZXZpc2lvbnMoZG9jLl9yZXZpc2lvbnMsIG9wdHMpO1xuICAgICAgblJldk51bSA9IGRvYy5fcmV2aXNpb25zLnN0YXJ0O1xuICAgICAgbmV3UmV2SWQgPSBkb2MuX3JldmlzaW9ucy5pZHNbMF07XG4gICAgfVxuICAgIGlmICghZG9jLl9yZXZfdHJlZSkge1xuICAgICAgcmV2SW5mbyA9IHBhcnNlUmV2aXNpb25JbmZvKGRvYy5fcmV2KTtcbiAgICAgIGlmIChyZXZJbmZvLmVycm9yKSB7XG4gICAgICAgIHJldHVybiByZXZJbmZvO1xuICAgICAgfVxuICAgICAgblJldk51bSA9IHJldkluZm8ucHJlZml4O1xuICAgICAgbmV3UmV2SWQgPSByZXZJbmZvLmlkO1xuICAgICAgZG9jLl9yZXZfdHJlZSA9IFt7XG4gICAgICAgIHBvczogblJldk51bSxcbiAgICAgICAgaWRzOiBbbmV3UmV2SWQsIG9wdHMsIFtdXVxuICAgICAgfV07XG4gICAgfVxuICB9XG5cbiAgaW52YWxpZElkRXJyb3IoZG9jLl9pZCk7XG5cbiAgZG9jLl9yZXYgPSBuUmV2TnVtICsgJy0nICsgbmV3UmV2SWQ7XG5cbiAgdmFyIHJlc3VsdCA9IHttZXRhZGF0YSA6IHt9LCBkYXRhIDoge319O1xuICBmb3IgKHZhciBrZXkgaW4gZG9jKSB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIGVsc2UgKi9cbiAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGRvYywga2V5KSkge1xuICAgICAgdmFyIHNwZWNpYWxLZXkgPSBrZXlbMF0gPT09ICdfJztcbiAgICAgIGlmIChzcGVjaWFsS2V5ICYmICFyZXNlcnZlZFdvcmRzW2tleV0pIHtcbiAgICAgICAgdmFyIGVycm9yID0gY3JlYXRlRXJyb3IoRE9DX1ZBTElEQVRJT04sIGtleSk7XG4gICAgICAgIGVycm9yLm1lc3NhZ2UgPSBET0NfVkFMSURBVElPTi5tZXNzYWdlICsgJzogJyArIGtleTtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9IGVsc2UgaWYgKHNwZWNpYWxLZXkgJiYgIWRhdGFXb3Jkc1trZXldKSB7XG4gICAgICAgIHJlc3VsdC5tZXRhZGF0YVtrZXkuc2xpY2UoMSldID0gZG9jW2tleV07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXN1bHQuZGF0YVtrZXldID0gZG9jW2tleV07XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbnZhciBhdG9iJDEgPSBmdW5jdGlvbiAoc3RyKSB7XG4gIHJldHVybiBhdG9iKHN0cik7XG59O1xuXG52YXIgYnRvYSQxID0gZnVuY3Rpb24gKHN0cikge1xuICByZXR1cm4gYnRvYShzdHIpO1xufTtcblxuLy8gQWJzdHJhY3RzIGNvbnN0cnVjdGluZyBhIEJsb2Igb2JqZWN0LCBzbyBpdCBhbHNvIHdvcmtzIGluIG9sZGVyXG4vLyBicm93c2VycyB0aGF0IGRvbid0IHN1cHBvcnQgdGhlIG5hdGl2ZSBCbG9iIGNvbnN0cnVjdG9yIChlLmcuXG4vLyBvbGQgUXRXZWJLaXQgdmVyc2lvbnMsIEFuZHJvaWQgPCA0LjQpLlxuZnVuY3Rpb24gY3JlYXRlQmxvYihwYXJ0cywgcHJvcGVydGllcykge1xuICAvKiBnbG9iYWwgQmxvYkJ1aWxkZXIsTVNCbG9iQnVpbGRlcixNb3pCbG9iQnVpbGRlcixXZWJLaXRCbG9iQnVpbGRlciAqL1xuICBwYXJ0cyA9IHBhcnRzIHx8IFtdO1xuICBwcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCB7fTtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbmV3IEJsb2IocGFydHMsIHByb3BlcnRpZXMpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUubmFtZSAhPT0gXCJUeXBlRXJyb3JcIikge1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gICAgdmFyIEJ1aWxkZXIgPSB0eXBlb2YgQmxvYkJ1aWxkZXIgIT09ICd1bmRlZmluZWQnID8gQmxvYkJ1aWxkZXIgOlxuICAgICAgICAgICAgICAgICAgdHlwZW9mIE1TQmxvYkJ1aWxkZXIgIT09ICd1bmRlZmluZWQnID8gTVNCbG9iQnVpbGRlciA6XG4gICAgICAgICAgICAgICAgICB0eXBlb2YgTW96QmxvYkJ1aWxkZXIgIT09ICd1bmRlZmluZWQnID8gTW96QmxvYkJ1aWxkZXIgOlxuICAgICAgICAgICAgICAgICAgV2ViS2l0QmxvYkJ1aWxkZXI7XG4gICAgdmFyIGJ1aWxkZXIgPSBuZXcgQnVpbGRlcigpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgIGJ1aWxkZXIuYXBwZW5kKHBhcnRzW2ldKTtcbiAgICB9XG4gICAgcmV0dXJuIGJ1aWxkZXIuZ2V0QmxvYihwcm9wZXJ0aWVzLnR5cGUpO1xuICB9XG59XG5cbi8vIEZyb20gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8xNDk2NzY0Ny8gKGNvbnRpbnVlcyBvbiBuZXh0IGxpbmUpXG4vLyBlbmNvZGUtZGVjb2RlLWltYWdlLXdpdGgtYmFzZTY0LWJyZWFrcy1pbWFnZSAoMjAxMy0wNC0yMSlcbmZ1bmN0aW9uIGJpbmFyeVN0cmluZ1RvQXJyYXlCdWZmZXIoYmluKSB7XG4gIHZhciBsZW5ndGggPSBiaW4ubGVuZ3RoO1xuICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKGxlbmd0aCk7XG4gIHZhciBhcnIgPSBuZXcgVWludDhBcnJheShidWYpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgYXJyW2ldID0gYmluLmNoYXJDb2RlQXQoaSk7XG4gIH1cbiAgcmV0dXJuIGJ1Zjtcbn1cblxuZnVuY3Rpb24gYmluU3RyaW5nVG9CbHVmZmVyKGJpblN0cmluZywgdHlwZSkge1xuICByZXR1cm4gY3JlYXRlQmxvYihbYmluYXJ5U3RyaW5nVG9BcnJheUJ1ZmZlcihiaW5TdHJpbmcpXSwge3R5cGU6IHR5cGV9KTtcbn1cblxuZnVuY3Rpb24gYjY0VG9CbHVmZmVyKGI2NCwgdHlwZSkge1xuICByZXR1cm4gYmluU3RyaW5nVG9CbHVmZmVyKGF0b2IkMShiNjQpLCB0eXBlKTtcbn1cblxuLy9DYW4ndCBmaW5kIG9yaWdpbmFsIHBvc3QsIGJ1dCB0aGlzIGlzIGNsb3NlXG4vL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNjk2NTEwNy8gKGNvbnRpbnVlcyBvbiBuZXh0IGxpbmUpXG4vL2NvbnZlcnRpbmctYmV0d2Vlbi1zdHJpbmdzLWFuZC1hcnJheWJ1ZmZlcnNcbmZ1bmN0aW9uIGFycmF5QnVmZmVyVG9CaW5hcnlTdHJpbmcoYnVmZmVyKSB7XG4gIHZhciBiaW5hcnkgPSAnJztcbiAgdmFyIGJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoYnVmZmVyKTtcbiAgdmFyIGxlbmd0aCA9IGJ5dGVzLmJ5dGVMZW5ndGg7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICBiaW5hcnkgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShieXRlc1tpXSk7XG4gIH1cbiAgcmV0dXJuIGJpbmFyeTtcbn1cblxuLy8gc2hpbSBmb3IgYnJvd3NlcnMgdGhhdCBkb24ndCBzdXBwb3J0IGl0XG5mdW5jdGlvbiByZWFkQXNCaW5hcnlTdHJpbmcoYmxvYiwgY2FsbGJhY2spIHtcbiAgaWYgKHR5cGVvZiBGaWxlUmVhZGVyID09PSAndW5kZWZpbmVkJykge1xuICAgIC8vIGZpeCBmb3IgRmlyZWZveCBpbiBhIHdlYiB3b3JrZXJcbiAgICAvLyBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD05MDEwOTdcbiAgICByZXR1cm4gY2FsbGJhY2soYXJyYXlCdWZmZXJUb0JpbmFyeVN0cmluZyhcbiAgICAgIG5ldyBGaWxlUmVhZGVyU3luYygpLnJlYWRBc0FycmF5QnVmZmVyKGJsb2IpKSk7XG4gIH1cblxuICB2YXIgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTtcbiAgdmFyIGhhc0JpbmFyeVN0cmluZyA9IHR5cGVvZiByZWFkZXIucmVhZEFzQmluYXJ5U3RyaW5nID09PSAnZnVuY3Rpb24nO1xuICByZWFkZXIub25sb2FkZW5kID0gZnVuY3Rpb24gKGUpIHtcbiAgICB2YXIgcmVzdWx0ID0gZS50YXJnZXQucmVzdWx0IHx8ICcnO1xuICAgIGlmIChoYXNCaW5hcnlTdHJpbmcpIHtcbiAgICAgIHJldHVybiBjYWxsYmFjayhyZXN1bHQpO1xuICAgIH1cbiAgICBjYWxsYmFjayhhcnJheUJ1ZmZlclRvQmluYXJ5U3RyaW5nKHJlc3VsdCkpO1xuICB9O1xuICBpZiAoaGFzQmluYXJ5U3RyaW5nKSB7XG4gICAgcmVhZGVyLnJlYWRBc0JpbmFyeVN0cmluZyhibG9iKTtcbiAgfSBlbHNlIHtcbiAgICByZWFkZXIucmVhZEFzQXJyYXlCdWZmZXIoYmxvYik7XG4gIH1cbn1cblxuZnVuY3Rpb24gYmxvYlRvQmluYXJ5U3RyaW5nKGJsb2JPckJ1ZmZlciwgY2FsbGJhY2spIHtcbiAgcmVhZEFzQmluYXJ5U3RyaW5nKGJsb2JPckJ1ZmZlciwgZnVuY3Rpb24gKGJpbikge1xuICAgIGNhbGxiYWNrKGJpbik7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBibG9iVG9CYXNlNjQoYmxvYk9yQnVmZmVyLCBjYWxsYmFjaykge1xuICBibG9iVG9CaW5hcnlTdHJpbmcoYmxvYk9yQnVmZmVyLCBmdW5jdGlvbiAoYmFzZTY0KSB7XG4gICAgY2FsbGJhY2soYnRvYSQxKGJhc2U2NCkpO1xuICB9KTtcbn1cblxuLy8gc2ltcGxpZmllZCBBUEkuIHVuaXZlcnNhbCBicm93c2VyIHN1cHBvcnQgaXMgYXNzdW1lZFxuZnVuY3Rpb24gcmVhZEFzQXJyYXlCdWZmZXIoYmxvYiwgY2FsbGJhY2spIHtcbiAgaWYgKHR5cGVvZiBGaWxlUmVhZGVyID09PSAndW5kZWZpbmVkJykge1xuICAgIC8vIGZpeCBmb3IgRmlyZWZveCBpbiBhIHdlYiB3b3JrZXI6XG4gICAgLy8gaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9OTAxMDk3XG4gICAgcmV0dXJuIGNhbGxiYWNrKG5ldyBGaWxlUmVhZGVyU3luYygpLnJlYWRBc0FycmF5QnVmZmVyKGJsb2IpKTtcbiAgfVxuXG4gIHZhciByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xuICByZWFkZXIub25sb2FkZW5kID0gZnVuY3Rpb24gKGUpIHtcbiAgICB2YXIgcmVzdWx0ID0gZS50YXJnZXQucmVzdWx0IHx8IG5ldyBBcnJheUJ1ZmZlcigwKTtcbiAgICBjYWxsYmFjayhyZXN1bHQpO1xuICB9O1xuICByZWFkZXIucmVhZEFzQXJyYXlCdWZmZXIoYmxvYik7XG59XG5cbnZhciBzZXRJbW1lZGlhdGVTaGltID0gZ2xvYmFsLnNldEltbWVkaWF0ZSB8fCBnbG9iYWwuc2V0VGltZW91dDtcbnZhciBNRDVfQ0hVTktfU0laRSA9IDMyNzY4O1xuXG5mdW5jdGlvbiByYXdUb0Jhc2U2NChyYXcpIHtcbiAgcmV0dXJuIGJ0b2EkMShyYXcpO1xufVxuXG5mdW5jdGlvbiBzbGljZUJsb2IoYmxvYiwgc3RhcnQsIGVuZCkge1xuICBpZiAoYmxvYi53ZWJraXRTbGljZSkge1xuICAgIHJldHVybiBibG9iLndlYmtpdFNsaWNlKHN0YXJ0LCBlbmQpO1xuICB9XG4gIHJldHVybiBibG9iLnNsaWNlKHN0YXJ0LCBlbmQpO1xufVxuXG5mdW5jdGlvbiBhcHBlbmRCbG9iKGJ1ZmZlciwgYmxvYiwgc3RhcnQsIGVuZCwgY2FsbGJhY2spIHtcbiAgaWYgKHN0YXJ0ID4gMCB8fCBlbmQgPCBibG9iLnNpemUpIHtcbiAgICAvLyBvbmx5IHNsaWNlIGJsb2IgaWYgd2UgcmVhbGx5IG5lZWQgdG9cbiAgICBibG9iID0gc2xpY2VCbG9iKGJsb2IsIHN0YXJ0LCBlbmQpO1xuICB9XG4gIHJlYWRBc0FycmF5QnVmZmVyKGJsb2IsIGZ1bmN0aW9uIChhcnJheUJ1ZmZlcikge1xuICAgIGJ1ZmZlci5hcHBlbmQoYXJyYXlCdWZmZXIpO1xuICAgIGNhbGxiYWNrKCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBhcHBlbmRTdHJpbmcoYnVmZmVyLCBzdHJpbmcsIHN0YXJ0LCBlbmQsIGNhbGxiYWNrKSB7XG4gIGlmIChzdGFydCA+IDAgfHwgZW5kIDwgc3RyaW5nLmxlbmd0aCkge1xuICAgIC8vIG9ubHkgY3JlYXRlIGEgc3Vic3RyaW5nIGlmIHdlIHJlYWxseSBuZWVkIHRvXG4gICAgc3RyaW5nID0gc3RyaW5nLnN1YnN0cmluZyhzdGFydCwgZW5kKTtcbiAgfVxuICBidWZmZXIuYXBwZW5kQmluYXJ5KHN0cmluZyk7XG4gIGNhbGxiYWNrKCk7XG59XG5cbmZ1bmN0aW9uIGJpbmFyeU1kNShkYXRhLCBjYWxsYmFjaykge1xuICB2YXIgaW5wdXRJc1N0cmluZyA9IHR5cGVvZiBkYXRhID09PSAnc3RyaW5nJztcbiAgdmFyIGxlbiA9IGlucHV0SXNTdHJpbmcgPyBkYXRhLmxlbmd0aCA6IGRhdGEuc2l6ZTtcbiAgdmFyIGNodW5rU2l6ZSA9IE1hdGgubWluKE1ENV9DSFVOS19TSVpFLCBsZW4pO1xuICB2YXIgY2h1bmtzID0gTWF0aC5jZWlsKGxlbiAvIGNodW5rU2l6ZSk7XG4gIHZhciBjdXJyZW50Q2h1bmsgPSAwO1xuICB2YXIgYnVmZmVyID0gaW5wdXRJc1N0cmluZyA/IG5ldyBNZDUoKSA6IG5ldyBNZDUuQXJyYXlCdWZmZXIoKTtcblxuICB2YXIgYXBwZW5kID0gaW5wdXRJc1N0cmluZyA/IGFwcGVuZFN0cmluZyA6IGFwcGVuZEJsb2I7XG5cbiAgZnVuY3Rpb24gbmV4dCgpIHtcbiAgICBzZXRJbW1lZGlhdGVTaGltKGxvYWROZXh0Q2h1bmspO1xuICB9XG5cbiAgZnVuY3Rpb24gZG9uZSgpIHtcbiAgICB2YXIgcmF3ID0gYnVmZmVyLmVuZCh0cnVlKTtcbiAgICB2YXIgYmFzZTY0ID0gcmF3VG9CYXNlNjQocmF3KTtcbiAgICBjYWxsYmFjayhiYXNlNjQpO1xuICAgIGJ1ZmZlci5kZXN0cm95KCk7XG4gIH1cblxuICBmdW5jdGlvbiBsb2FkTmV4dENodW5rKCkge1xuICAgIHZhciBzdGFydCA9IGN1cnJlbnRDaHVuayAqIGNodW5rU2l6ZTtcbiAgICB2YXIgZW5kID0gc3RhcnQgKyBjaHVua1NpemU7XG4gICAgY3VycmVudENodW5rKys7XG4gICAgaWYgKGN1cnJlbnRDaHVuayA8IGNodW5rcykge1xuICAgICAgYXBwZW5kKGJ1ZmZlciwgZGF0YSwgc3RhcnQsIGVuZCwgbmV4dCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFwcGVuZChidWZmZXIsIGRhdGEsIHN0YXJ0LCBlbmQsIGRvbmUpO1xuICAgIH1cbiAgfVxuICBsb2FkTmV4dENodW5rKCk7XG59XG5cbmZ1bmN0aW9uIHN0cmluZ01kNShzdHJpbmcpIHtcbiAgcmV0dXJuIE1kNS5oYXNoKHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHBhcnNlQmFzZTY0KGRhdGEpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXRvYiQxKGRhdGEpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdmFyIGVyciA9IGNyZWF0ZUVycm9yKEJBRF9BUkcsXG4gICAgICAnQXR0YWNobWVudCBpcyBub3QgYSB2YWxpZCBiYXNlNjQgc3RyaW5nJyk7XG4gICAgcmV0dXJuIHtlcnJvcjogZXJyfTtcbiAgfVxufVxuXG5mdW5jdGlvbiBwcmVwcm9jZXNzU3RyaW5nKGF0dCwgYmxvYlR5cGUsIGNhbGxiYWNrKSB7XG4gIHZhciBhc0JpbmFyeSA9IHBhcnNlQmFzZTY0KGF0dC5kYXRhKTtcbiAgaWYgKGFzQmluYXJ5LmVycm9yKSB7XG4gICAgcmV0dXJuIGNhbGxiYWNrKGFzQmluYXJ5LmVycm9yKTtcbiAgfVxuXG4gIGF0dC5sZW5ndGggPSBhc0JpbmFyeS5sZW5ndGg7XG4gIGlmIChibG9iVHlwZSA9PT0gJ2Jsb2InKSB7XG4gICAgYXR0LmRhdGEgPSBiaW5TdHJpbmdUb0JsdWZmZXIoYXNCaW5hcnksIGF0dC5jb250ZW50X3R5cGUpO1xuICB9IGVsc2UgaWYgKGJsb2JUeXBlID09PSAnYmFzZTY0Jykge1xuICAgIGF0dC5kYXRhID0gYnRvYSQxKGFzQmluYXJ5KTtcbiAgfSBlbHNlIHsgLy8gYmluYXJ5XG4gICAgYXR0LmRhdGEgPSBhc0JpbmFyeTtcbiAgfVxuICBiaW5hcnlNZDUoYXNCaW5hcnksIGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICBhdHQuZGlnZXN0ID0gJ21kNS0nICsgcmVzdWx0O1xuICAgIGNhbGxiYWNrKCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBwcmVwcm9jZXNzQmxvYihhdHQsIGJsb2JUeXBlLCBjYWxsYmFjaykge1xuICBiaW5hcnlNZDUoYXR0LmRhdGEsIGZ1bmN0aW9uIChtZDUpIHtcbiAgICBhdHQuZGlnZXN0ID0gJ21kNS0nICsgbWQ1O1xuICAgIC8vIHNpemUgaXMgZm9yIGJsb2JzIChicm93c2VyKSwgbGVuZ3RoIGlzIGZvciBidWZmZXJzIChub2RlKVxuICAgIGF0dC5sZW5ndGggPSBhdHQuZGF0YS5zaXplIHx8IGF0dC5kYXRhLmxlbmd0aCB8fCAwO1xuICAgIGlmIChibG9iVHlwZSA9PT0gJ2JpbmFyeScpIHtcbiAgICAgIGJsb2JUb0JpbmFyeVN0cmluZyhhdHQuZGF0YSwgZnVuY3Rpb24gKGJpblN0cmluZykge1xuICAgICAgICBhdHQuZGF0YSA9IGJpblN0cmluZztcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSBpZiAoYmxvYlR5cGUgPT09ICdiYXNlNjQnKSB7XG4gICAgICBibG9iVG9CYXNlNjQoYXR0LmRhdGEsIGZ1bmN0aW9uIChiNjQpIHtcbiAgICAgICAgYXR0LmRhdGEgPSBiNjQ7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgY2FsbGJhY2soKTtcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBwcmVwcm9jZXNzQXR0YWNobWVudChhdHQsIGJsb2JUeXBlLCBjYWxsYmFjaykge1xuICBpZiAoYXR0LnN0dWIpIHtcbiAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgfVxuICBpZiAodHlwZW9mIGF0dC5kYXRhID09PSAnc3RyaW5nJykgeyAvLyBpbnB1dCBpcyBhIGJhc2U2NCBzdHJpbmdcbiAgICBwcmVwcm9jZXNzU3RyaW5nKGF0dCwgYmxvYlR5cGUsIGNhbGxiYWNrKTtcbiAgfSBlbHNlIHsgLy8gaW5wdXQgaXMgYSBibG9iXG4gICAgcHJlcHJvY2Vzc0Jsb2IoYXR0LCBibG9iVHlwZSwgY2FsbGJhY2spO1xuICB9XG59XG5cbmZ1bmN0aW9uIHByZXByb2Nlc3NBdHRhY2htZW50cyhkb2NJbmZvcywgYmxvYlR5cGUsIGNhbGxiYWNrKSB7XG5cbiAgaWYgKCFkb2NJbmZvcy5sZW5ndGgpIHtcbiAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgfVxuXG4gIHZhciBkb2N2ID0gMDtcbiAgdmFyIG92ZXJhbGxFcnI7XG5cbiAgZG9jSW5mb3MuZm9yRWFjaChmdW5jdGlvbiAoZG9jSW5mbykge1xuICAgIHZhciBhdHRhY2htZW50cyA9IGRvY0luZm8uZGF0YSAmJiBkb2NJbmZvLmRhdGEuX2F0dGFjaG1lbnRzID9cbiAgICAgIE9iamVjdC5rZXlzKGRvY0luZm8uZGF0YS5fYXR0YWNobWVudHMpIDogW107XG4gICAgdmFyIHJlY3YgPSAwO1xuXG4gICAgaWYgKCFhdHRhY2htZW50cy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBkb25lKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc2VkQXR0YWNobWVudChlcnIpIHtcbiAgICAgIG92ZXJhbGxFcnIgPSBlcnI7XG4gICAgICByZWN2Kys7XG4gICAgICBpZiAocmVjdiA9PT0gYXR0YWNobWVudHMubGVuZ3RoKSB7XG4gICAgICAgIGRvbmUoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKHZhciBrZXkgaW4gZG9jSW5mby5kYXRhLl9hdHRhY2htZW50cykge1xuICAgICAgaWYgKGRvY0luZm8uZGF0YS5fYXR0YWNobWVudHMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICBwcmVwcm9jZXNzQXR0YWNobWVudChkb2NJbmZvLmRhdGEuX2F0dGFjaG1lbnRzW2tleV0sXG4gICAgICAgICAgYmxvYlR5cGUsIHByb2Nlc3NlZEF0dGFjaG1lbnQpO1xuICAgICAgfVxuICAgIH1cbiAgfSk7XG5cbiAgZnVuY3Rpb24gZG9uZSgpIHtcbiAgICBkb2N2Kys7XG4gICAgaWYgKGRvY0luZm9zLmxlbmd0aCA9PT0gZG9jdikge1xuICAgICAgaWYgKG92ZXJhbGxFcnIpIHtcbiAgICAgICAgY2FsbGJhY2sob3ZlcmFsbEVycik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiB1cGRhdGVEb2MocmV2TGltaXQsIHByZXYsIGRvY0luZm8sIHJlc3VsdHMsXG4gICAgICAgICAgICAgICAgICAgaSwgY2IsIHdyaXRlRG9jLCBuZXdFZGl0cykge1xuXG4gIGlmIChyZXZFeGlzdHMocHJldi5yZXZfdHJlZSwgZG9jSW5mby5tZXRhZGF0YS5yZXYpKSB7XG4gICAgcmVzdWx0c1tpXSA9IGRvY0luZm87XG4gICAgcmV0dXJuIGNiKCk7XG4gIH1cblxuICAvLyBzb21ldGltZXMgdGhpcyBpcyBwcmUtY2FsY3VsYXRlZC4gaGlzdG9yaWNhbGx5IG5vdCBhbHdheXNcbiAgdmFyIHByZXZpb3VzV2lubmluZ1JldiA9IHByZXYud2lubmluZ1JldiB8fCB3aW5uaW5nUmV2KHByZXYpO1xuICB2YXIgcHJldmlvdXNseURlbGV0ZWQgPSAnZGVsZXRlZCcgaW4gcHJldiA/IHByZXYuZGVsZXRlZCA6XG4gICAgaXNEZWxldGVkKHByZXYsIHByZXZpb3VzV2lubmluZ1Jldik7XG4gIHZhciBkZWxldGVkID0gJ2RlbGV0ZWQnIGluIGRvY0luZm8ubWV0YWRhdGEgPyBkb2NJbmZvLm1ldGFkYXRhLmRlbGV0ZWQgOlxuICAgIGlzRGVsZXRlZChkb2NJbmZvLm1ldGFkYXRhKTtcbiAgdmFyIGlzUm9vdCA9IC9eMS0vLnRlc3QoZG9jSW5mby5tZXRhZGF0YS5yZXYpO1xuXG4gIGlmIChwcmV2aW91c2x5RGVsZXRlZCAmJiAhZGVsZXRlZCAmJiBuZXdFZGl0cyAmJiBpc1Jvb3QpIHtcbiAgICB2YXIgbmV3RG9jID0gZG9jSW5mby5kYXRhO1xuICAgIG5ld0RvYy5fcmV2ID0gcHJldmlvdXNXaW5uaW5nUmV2O1xuICAgIG5ld0RvYy5faWQgPSBkb2NJbmZvLm1ldGFkYXRhLmlkO1xuICAgIGRvY0luZm8gPSBwYXJzZURvYyhuZXdEb2MsIG5ld0VkaXRzKTtcbiAgfVxuXG4gIHZhciBtZXJnZWQgPSBtZXJnZShwcmV2LnJldl90cmVlLCBkb2NJbmZvLm1ldGFkYXRhLnJldl90cmVlWzBdLCByZXZMaW1pdCk7XG5cbiAgdmFyIGluQ29uZmxpY3QgPSBuZXdFZGl0cyAmJiAoKChwcmV2aW91c2x5RGVsZXRlZCAmJiBkZWxldGVkKSB8fFxuICAgICghcHJldmlvdXNseURlbGV0ZWQgJiYgbWVyZ2VkLmNvbmZsaWN0cyAhPT0gJ25ld19sZWFmJykgfHxcbiAgICAocHJldmlvdXNseURlbGV0ZWQgJiYgIWRlbGV0ZWQgJiYgbWVyZ2VkLmNvbmZsaWN0cyA9PT0gJ25ld19icmFuY2gnKSkpO1xuXG4gIGlmIChpbkNvbmZsaWN0KSB7XG4gICAgdmFyIGVyciA9IGNyZWF0ZUVycm9yKFJFVl9DT05GTElDVCk7XG4gICAgcmVzdWx0c1tpXSA9IGVycjtcbiAgICByZXR1cm4gY2IoKTtcbiAgfVxuXG4gIHZhciBuZXdSZXYgPSBkb2NJbmZvLm1ldGFkYXRhLnJldjtcbiAgZG9jSW5mby5tZXRhZGF0YS5yZXZfdHJlZSA9IG1lcmdlZC50cmVlO1xuICBkb2NJbmZvLnN0ZW1tZWRSZXZzID0gbWVyZ2VkLnN0ZW1tZWRSZXZzIHx8IFtdO1xuICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICBpZiAocHJldi5yZXZfbWFwKSB7XG4gICAgZG9jSW5mby5tZXRhZGF0YS5yZXZfbWFwID0gcHJldi5yZXZfbWFwOyAvLyB1c2VkIG9ubHkgYnkgbGV2ZWxkYlxuICB9XG5cbiAgLy8gcmVjYWxjdWxhdGVcbiAgdmFyIHdpbm5pbmdSZXYkJCA9IHdpbm5pbmdSZXYoZG9jSW5mby5tZXRhZGF0YSk7XG4gIHZhciB3aW5uaW5nUmV2SXNEZWxldGVkID0gaXNEZWxldGVkKGRvY0luZm8ubWV0YWRhdGEsIHdpbm5pbmdSZXYkJCk7XG5cbiAgLy8gY2FsY3VsYXRlIHRoZSB0b3RhbCBudW1iZXIgb2YgZG9jdW1lbnRzIHRoYXQgd2VyZSBhZGRlZC9yZW1vdmVkLFxuICAvLyBmcm9tIHRoZSBwZXJzcGVjdGl2ZSBvZiB0b3RhbF9yb3dzL2RvY19jb3VudFxuICB2YXIgZGVsdGEgPSAocHJldmlvdXNseURlbGV0ZWQgPT09IHdpbm5pbmdSZXZJc0RlbGV0ZWQpID8gMCA6XG4gICAgcHJldmlvdXNseURlbGV0ZWQgPCB3aW5uaW5nUmV2SXNEZWxldGVkID8gLTEgOiAxO1xuXG4gIHZhciBuZXdSZXZJc0RlbGV0ZWQ7XG4gIGlmIChuZXdSZXYgPT09IHdpbm5pbmdSZXYkJCkge1xuICAgIC8vIGlmIHRoZSBuZXcgcmV2IGlzIHRoZSBzYW1lIGFzIHRoZSB3aW5uaW5nIHJldiwgd2UgY2FuIHJldXNlIHRoYXQgdmFsdWVcbiAgICBuZXdSZXZJc0RlbGV0ZWQgPSB3aW5uaW5nUmV2SXNEZWxldGVkO1xuICB9IGVsc2Uge1xuICAgIC8vIGlmIHRoZXkncmUgbm90IHRoZSBzYW1lLCB0aGVuIHdlIG5lZWQgdG8gcmVjYWxjdWxhdGVcbiAgICBuZXdSZXZJc0RlbGV0ZWQgPSBpc0RlbGV0ZWQoZG9jSW5mby5tZXRhZGF0YSwgbmV3UmV2KTtcbiAgfVxuXG4gIHdyaXRlRG9jKGRvY0luZm8sIHdpbm5pbmdSZXYkJCwgd2lubmluZ1JldklzRGVsZXRlZCwgbmV3UmV2SXNEZWxldGVkLFxuICAgIHRydWUsIGRlbHRhLCBpLCBjYik7XG59XG5cbmZ1bmN0aW9uIHJvb3RJc01pc3NpbmcoZG9jSW5mbykge1xuICByZXR1cm4gZG9jSW5mby5tZXRhZGF0YS5yZXZfdHJlZVswXS5pZHNbMV0uc3RhdHVzID09PSAnbWlzc2luZyc7XG59XG5cbmZ1bmN0aW9uIHByb2Nlc3NEb2NzKHJldkxpbWl0LCBkb2NJbmZvcywgYXBpLCBmZXRjaGVkRG9jcywgdHgsIHJlc3VsdHMsXG4gICAgICAgICAgICAgICAgICAgICB3cml0ZURvYywgb3B0cywgb3ZlcmFsbENhbGxiYWNrKSB7XG5cbiAgLy8gRGVmYXVsdCB0byAxMDAwIGxvY2FsbHlcbiAgcmV2TGltaXQgPSByZXZMaW1pdCB8fCAxMDAwO1xuXG4gIGZ1bmN0aW9uIGluc2VydERvYyhkb2NJbmZvLCByZXN1bHRzSWR4LCBjYWxsYmFjaykge1xuICAgIC8vIENhbnQgaW5zZXJ0IG5ldyBkZWxldGVkIGRvY3VtZW50c1xuICAgIHZhciB3aW5uaW5nUmV2JCQgPSB3aW5uaW5nUmV2KGRvY0luZm8ubWV0YWRhdGEpO1xuICAgIHZhciBkZWxldGVkID0gaXNEZWxldGVkKGRvY0luZm8ubWV0YWRhdGEsIHdpbm5pbmdSZXYkJCk7XG4gICAgaWYgKCd3YXNfZGVsZXRlJyBpbiBvcHRzICYmIGRlbGV0ZWQpIHtcbiAgICAgIHJlc3VsdHNbcmVzdWx0c0lkeF0gPSBjcmVhdGVFcnJvcihNSVNTSU5HX0RPQywgJ2RlbGV0ZWQnKTtcbiAgICAgIHJldHVybiBjYWxsYmFjaygpO1xuICAgIH1cblxuICAgIC8vIDQ3MTIgLSBkZXRlY3Qgd2hldGhlciBhIG5ldyBkb2N1bWVudCB3YXMgaW5zZXJ0ZWQgd2l0aCBhIF9yZXZcbiAgICB2YXIgaW5Db25mbGljdCA9IG5ld0VkaXRzICYmIHJvb3RJc01pc3NpbmcoZG9jSW5mbyk7XG5cbiAgICBpZiAoaW5Db25mbGljdCkge1xuICAgICAgdmFyIGVyciA9IGNyZWF0ZUVycm9yKFJFVl9DT05GTElDVCk7XG4gICAgICByZXN1bHRzW3Jlc3VsdHNJZHhdID0gZXJyO1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKCk7XG4gICAgfVxuXG4gICAgdmFyIGRlbHRhID0gZGVsZXRlZCA/IDAgOiAxO1xuXG4gICAgd3JpdGVEb2MoZG9jSW5mbywgd2lubmluZ1JldiQkLCBkZWxldGVkLCBkZWxldGVkLCBmYWxzZSxcbiAgICAgIGRlbHRhLCByZXN1bHRzSWR4LCBjYWxsYmFjayk7XG4gIH1cblxuICB2YXIgbmV3RWRpdHMgPSBvcHRzLm5ld19lZGl0cztcbiAgdmFyIGlkc1RvRG9jcyA9IG5ldyBfTWFwKCk7XG5cbiAgdmFyIGRvY3NEb25lID0gMDtcbiAgdmFyIGRvY3NUb0RvID0gZG9jSW5mb3MubGVuZ3RoO1xuXG4gIGZ1bmN0aW9uIGNoZWNrQWxsRG9jc0RvbmUoKSB7XG4gICAgaWYgKCsrZG9jc0RvbmUgPT09IGRvY3NUb0RvICYmIG92ZXJhbGxDYWxsYmFjaykge1xuICAgICAgb3ZlcmFsbENhbGxiYWNrKCk7XG4gICAgfVxuICB9XG5cbiAgZG9jSW5mb3MuZm9yRWFjaChmdW5jdGlvbiAoY3VycmVudERvYywgcmVzdWx0c0lkeCkge1xuXG4gICAgaWYgKGN1cnJlbnREb2MuX2lkICYmIGlzTG9jYWxJZChjdXJyZW50RG9jLl9pZCkpIHtcbiAgICAgIHZhciBmdW4gPSBjdXJyZW50RG9jLl9kZWxldGVkID8gJ19yZW1vdmVMb2NhbCcgOiAnX3B1dExvY2FsJztcbiAgICAgIGFwaVtmdW5dKGN1cnJlbnREb2MsIHtjdHg6IHR4fSwgZnVuY3Rpb24gKGVyciwgcmVzKSB7XG4gICAgICAgIHJlc3VsdHNbcmVzdWx0c0lkeF0gPSBlcnIgfHwgcmVzO1xuICAgICAgICBjaGVja0FsbERvY3NEb25lKCk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgaWQgPSBjdXJyZW50RG9jLm1ldGFkYXRhLmlkO1xuICAgIGlmIChpZHNUb0RvY3MuaGFzKGlkKSkge1xuICAgICAgZG9jc1RvRG8tLTsgLy8gZHVwbGljYXRlXG4gICAgICBpZHNUb0RvY3MuZ2V0KGlkKS5wdXNoKFtjdXJyZW50RG9jLCByZXN1bHRzSWR4XSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlkc1RvRG9jcy5zZXQoaWQsIFtbY3VycmVudERvYywgcmVzdWx0c0lkeF1dKTtcbiAgICB9XG4gIH0pO1xuXG4gIC8vIGluIHRoZSBjYXNlIG9mIG5ld19lZGl0cywgdGhlIHVzZXIgY2FuIHByb3ZpZGUgbXVsdGlwbGUgZG9jc1xuICAvLyB3aXRoIHRoZSBzYW1lIGlkLiB0aGVzZSBuZWVkIHRvIGJlIHByb2Nlc3NlZCBzZXF1ZW50aWFsbHlcbiAgaWRzVG9Eb2NzLmZvckVhY2goZnVuY3Rpb24gKGRvY3MsIGlkKSB7XG4gICAgdmFyIG51bURvbmUgPSAwO1xuXG4gICAgZnVuY3Rpb24gZG9jV3JpdHRlbigpIHtcbiAgICAgIGlmICgrK251bURvbmUgPCBkb2NzLmxlbmd0aCkge1xuICAgICAgICBuZXh0RG9jKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjaGVja0FsbERvY3NEb25lKCk7XG4gICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIG5leHREb2MoKSB7XG4gICAgICB2YXIgdmFsdWUgPSBkb2NzW251bURvbmVdO1xuICAgICAgdmFyIGN1cnJlbnREb2MgPSB2YWx1ZVswXTtcbiAgICAgIHZhciByZXN1bHRzSWR4ID0gdmFsdWVbMV07XG5cbiAgICAgIGlmIChmZXRjaGVkRG9jcy5oYXMoaWQpKSB7XG4gICAgICAgIHVwZGF0ZURvYyhyZXZMaW1pdCwgZmV0Y2hlZERvY3MuZ2V0KGlkKSwgY3VycmVudERvYywgcmVzdWx0cyxcbiAgICAgICAgICByZXN1bHRzSWR4LCBkb2NXcml0dGVuLCB3cml0ZURvYywgbmV3RWRpdHMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gRW5zdXJlIHN0ZW1taW5nIGFwcGxpZXMgdG8gbmV3IHdyaXRlcyBhcyB3ZWxsXG4gICAgICAgIHZhciBtZXJnZWQgPSBtZXJnZShbXSwgY3VycmVudERvYy5tZXRhZGF0YS5yZXZfdHJlZVswXSwgcmV2TGltaXQpO1xuICAgICAgICBjdXJyZW50RG9jLm1ldGFkYXRhLnJldl90cmVlID0gbWVyZ2VkLnRyZWU7XG4gICAgICAgIGN1cnJlbnREb2Muc3RlbW1lZFJldnMgPSBtZXJnZWQuc3RlbW1lZFJldnMgfHwgW107XG4gICAgICAgIGluc2VydERvYyhjdXJyZW50RG9jLCByZXN1bHRzSWR4LCBkb2NXcml0dGVuKTtcbiAgICAgIH1cbiAgICB9XG4gICAgbmV4dERvYygpO1xuICB9KTtcbn1cblxuLy8gSW5kZXhlZERCIHJlcXVpcmVzIGEgdmVyc2lvbmVkIGRhdGFiYXNlIHN0cnVjdHVyZSwgc28gd2UgdXNlIHRoZVxuLy8gdmVyc2lvbiBoZXJlIHRvIG1hbmFnZSBtaWdyYXRpb25zLlxudmFyIEFEQVBURVJfVkVSU0lPTiA9IDU7XG5cbi8vIFRoZSBvYmplY3Qgc3RvcmVzIGNyZWF0ZWQgZm9yIGVhY2ggZGF0YWJhc2Vcbi8vIERPQ19TVE9SRSBzdG9yZXMgdGhlIGRvY3VtZW50IG1ldGEgZGF0YSwgaXRzIHJldmlzaW9uIGhpc3RvcnkgYW5kIHN0YXRlXG4vLyBLZXllZCBieSBkb2N1bWVudCBpZFxudmFyIERPQ19TVE9SRSA9ICdkb2N1bWVudC1zdG9yZSc7XG4vLyBCWV9TRVFfU1RPUkUgc3RvcmVzIGEgcGFydGljdWxhciB2ZXJzaW9uIG9mIGEgZG9jdW1lbnQsIGtleWVkIGJ5IGl0c1xuLy8gc2VxdWVuY2UgaWRcbnZhciBCWV9TRVFfU1RPUkUgPSAnYnktc2VxdWVuY2UnO1xuLy8gV2hlcmUgd2Ugc3RvcmUgYXR0YWNobWVudHNcbnZhciBBVFRBQ0hfU1RPUkUgPSAnYXR0YWNoLXN0b3JlJztcbi8vIFdoZXJlIHdlIHN0b3JlIG1hbnktdG8tbWFueSByZWxhdGlvbnNcbi8vIGJldHdlZW4gYXR0YWNobWVudCBkaWdlc3RzIGFuZCBzZXFzXG52YXIgQVRUQUNIX0FORF9TRVFfU1RPUkUgPSAnYXR0YWNoLXNlcS1zdG9yZSc7XG5cbi8vIFdoZXJlIHdlIHN0b3JlIGRhdGFiYXNlLXdpZGUgbWV0YSBkYXRhIGluIGEgc2luZ2xlIHJlY29yZFxuLy8ga2V5ZWQgYnkgaWQ6IE1FVEFfU1RPUkVcbnZhciBNRVRBX1NUT1JFID0gJ21ldGEtc3RvcmUnO1xuLy8gV2hlcmUgd2Ugc3RvcmUgbG9jYWwgZG9jdW1lbnRzXG52YXIgTE9DQUxfU1RPUkUgPSAnbG9jYWwtc3RvcmUnO1xuLy8gV2hlcmUgd2UgZGV0ZWN0IGJsb2Igc3VwcG9ydFxudmFyIERFVEVDVF9CTE9CX1NVUFBPUlRfU1RPUkUgPSAnZGV0ZWN0LWJsb2Itc3VwcG9ydCc7XG5cbmZ1bmN0aW9uIHNhZmVKc29uUGFyc2Uoc3RyKSB7XG4gIC8vIFRoaXMgdHJ5L2NhdGNoIGd1YXJkcyBhZ2FpbnN0IHN0YWNrIG92ZXJmbG93IGVycm9ycy5cbiAgLy8gSlNPTi5wYXJzZSgpIGlzIGZhc3RlciB0aGFuIHZ1dnV6ZWxhLnBhcnNlKCkgYnV0IHZ1dnV6ZWxhXG4gIC8vIGNhbm5vdCBvdmVyZmxvdy5cbiAgdHJ5IHtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShzdHIpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICByZXR1cm4gdnV2dXplbGEucGFyc2Uoc3RyKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBzYWZlSnNvblN0cmluZ2lmeShqc29uKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGpzb24pO1xuICB9IGNhdGNoIChlKSB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICByZXR1cm4gdnV2dXplbGEuc3RyaW5naWZ5KGpzb24pO1xuICB9XG59XG5cbmZ1bmN0aW9uIGlkYkVycm9yKGNhbGxiYWNrKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoZXZ0KSB7XG4gICAgdmFyIG1lc3NhZ2UgPSAndW5rbm93bl9lcnJvcic7XG4gICAgaWYgKGV2dC50YXJnZXQgJiYgZXZ0LnRhcmdldC5lcnJvcikge1xuICAgICAgbWVzc2FnZSA9IGV2dC50YXJnZXQuZXJyb3IubmFtZSB8fCBldnQudGFyZ2V0LmVycm9yLm1lc3NhZ2U7XG4gICAgfVxuICAgIGNhbGxiYWNrKGNyZWF0ZUVycm9yKElEQl9FUlJPUiwgbWVzc2FnZSwgZXZ0LnR5cGUpKTtcbiAgfTtcbn1cblxuLy8gVW5mb3J0dW5hdGVseSwgdGhlIG1ldGFkYXRhIGhhcyB0byBiZSBzdHJpbmdpZmllZFxuLy8gd2hlbiBpdCBpcyBwdXQgaW50byB0aGUgZGF0YWJhc2UsIGJlY2F1c2Ugb3RoZXJ3aXNlXG4vLyBJbmRleGVkREIgY2FuIHRocm93IGVycm9ycyBmb3IgZGVlcGx5LW5lc3RlZCBvYmplY3RzLlxuLy8gT3JpZ2luYWxseSB3ZSBqdXN0IHVzZWQgSlNPTi5wYXJzZS9KU09OLnN0cmluZ2lmeTsgbm93XG4vLyB3ZSB1c2UgdGhpcyBjdXN0b20gdnV2dXplbGEgbGlicmFyeSB0aGF0IGF2b2lkcyByZWN1cnNpb24uXG4vLyBJZiB3ZSBjb3VsZCBkbyBpdCBhbGwgb3ZlciBhZ2Fpbiwgd2UnZCBwcm9iYWJseSB1c2UgYVxuLy8gZm9ybWF0IGZvciB0aGUgcmV2aXNpb24gdHJlZXMgb3RoZXIgdGhhbiBKU09OLlxuZnVuY3Rpb24gZW5jb2RlTWV0YWRhdGEobWV0YWRhdGEsIHdpbm5pbmdSZXYsIGRlbGV0ZWQpIHtcbiAgcmV0dXJuIHtcbiAgICBkYXRhOiBzYWZlSnNvblN0cmluZ2lmeShtZXRhZGF0YSksXG4gICAgd2lubmluZ1Jldjogd2lubmluZ1JldixcbiAgICBkZWxldGVkT3JMb2NhbDogZGVsZXRlZCA/ICcxJyA6ICcwJyxcbiAgICBzZXE6IG1ldGFkYXRhLnNlcSwgLy8gaGlnaGVzdCBzZXEgZm9yIHRoaXMgZG9jXG4gICAgaWQ6IG1ldGFkYXRhLmlkXG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlY29kZU1ldGFkYXRhKHN0b3JlZE9iamVjdCkge1xuICBpZiAoIXN0b3JlZE9iamVjdCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIHZhciBtZXRhZGF0YSA9IHNhZmVKc29uUGFyc2Uoc3RvcmVkT2JqZWN0LmRhdGEpO1xuICBtZXRhZGF0YS53aW5uaW5nUmV2ID0gc3RvcmVkT2JqZWN0Lndpbm5pbmdSZXY7XG4gIG1ldGFkYXRhLmRlbGV0ZWQgPSBzdG9yZWRPYmplY3QuZGVsZXRlZE9yTG9jYWwgPT09ICcxJztcbiAgbWV0YWRhdGEuc2VxID0gc3RvcmVkT2JqZWN0LnNlcTtcbiAgcmV0dXJuIG1ldGFkYXRhO1xufVxuXG4vLyByZWFkIHRoZSBkb2MgYmFjayBvdXQgZnJvbSB0aGUgZGF0YWJhc2UuIHdlIGRvbid0IHN0b3JlIHRoZVxuLy8gX2lkIG9yIF9yZXYgYmVjYXVzZSB3ZSBhbHJlYWR5IGhhdmUgX2RvY19pZF9yZXYuXG5mdW5jdGlvbiBkZWNvZGVEb2MoZG9jKSB7XG4gIGlmICghZG9jKSB7XG4gICAgcmV0dXJuIGRvYztcbiAgfVxuICB2YXIgaWR4ID0gZG9jLl9kb2NfaWRfcmV2Lmxhc3RJbmRleE9mKCc6Jyk7XG4gIGRvYy5faWQgPSBkb2MuX2RvY19pZF9yZXYuc3Vic3RyaW5nKDAsIGlkeCAtIDEpO1xuICBkb2MuX3JldiA9IGRvYy5fZG9jX2lkX3Jldi5zdWJzdHJpbmcoaWR4ICsgMSk7XG4gIGRlbGV0ZSBkb2MuX2RvY19pZF9yZXY7XG4gIHJldHVybiBkb2M7XG59XG5cbi8vIFJlYWQgYSBibG9iIGZyb20gdGhlIGRhdGFiYXNlLCBlbmNvZGluZyBhcyBuZWNlc3Nhcnlcbi8vIGFuZCB0cmFuc2xhdGluZyBmcm9tIGJhc2U2NCBpZiB0aGUgSURCIGRvZXNuJ3Qgc3VwcG9ydFxuLy8gbmF0aXZlIEJsb2JzXG5mdW5jdGlvbiByZWFkQmxvYkRhdGEoYm9keSwgdHlwZSwgYXNCbG9iLCBjYWxsYmFjaykge1xuICBpZiAoYXNCbG9iKSB7XG4gICAgaWYgKCFib2R5KSB7XG4gICAgICBjYWxsYmFjayhjcmVhdGVCbG9iKFsnJ10sIHt0eXBlOiB0eXBlfSkpO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGJvZHkgIT09ICdzdHJpbmcnKSB7IC8vIHdlIGhhdmUgYmxvYiBzdXBwb3J0XG4gICAgICBjYWxsYmFjayhib2R5KTtcbiAgICB9IGVsc2UgeyAvLyBubyBibG9iIHN1cHBvcnRcbiAgICAgIGNhbGxiYWNrKGI2NFRvQmx1ZmZlcihib2R5LCB0eXBlKSk7XG4gICAgfVxuICB9IGVsc2UgeyAvLyBhcyBiYXNlNjQgc3RyaW5nXG4gICAgaWYgKCFib2R5KSB7XG4gICAgICBjYWxsYmFjaygnJyk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgYm9keSAhPT0gJ3N0cmluZycpIHsgLy8gd2UgaGF2ZSBibG9iIHN1cHBvcnRcbiAgICAgIHJlYWRBc0JpbmFyeVN0cmluZyhib2R5LCBmdW5jdGlvbiAoYmluYXJ5KSB7XG4gICAgICAgIGNhbGxiYWNrKGJ0b2EkMShiaW5hcnkpKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7IC8vIG5vIGJsb2Igc3VwcG9ydFxuICAgICAgY2FsbGJhY2soYm9keSk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGZldGNoQXR0YWNobWVudHNJZk5lY2Vzc2FyeShkb2MsIG9wdHMsIHR4biwgY2IpIHtcbiAgdmFyIGF0dGFjaG1lbnRzID0gT2JqZWN0LmtleXMoZG9jLl9hdHRhY2htZW50cyB8fCB7fSk7XG4gIGlmICghYXR0YWNobWVudHMubGVuZ3RoKSB7XG4gICAgcmV0dXJuIGNiICYmIGNiKCk7XG4gIH1cbiAgdmFyIG51bURvbmUgPSAwO1xuXG4gIGZ1bmN0aW9uIGNoZWNrRG9uZSgpIHtcbiAgICBpZiAoKytudW1Eb25lID09PSBhdHRhY2htZW50cy5sZW5ndGggJiYgY2IpIHtcbiAgICAgIGNiKCk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gZmV0Y2hBdHRhY2htZW50KGRvYywgYXR0KSB7XG4gICAgdmFyIGF0dE9iaiA9IGRvYy5fYXR0YWNobWVudHNbYXR0XTtcbiAgICB2YXIgZGlnZXN0ID0gYXR0T2JqLmRpZ2VzdDtcbiAgICB2YXIgcmVxID0gdHhuLm9iamVjdFN0b3JlKEFUVEFDSF9TVE9SRSkuZ2V0KGRpZ2VzdCk7XG4gICAgcmVxLm9uc3VjY2VzcyA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICBhdHRPYmouYm9keSA9IGUudGFyZ2V0LnJlc3VsdC5ib2R5O1xuICAgICAgY2hlY2tEb25lKCk7XG4gICAgfTtcbiAgfVxuXG4gIGF0dGFjaG1lbnRzLmZvckVhY2goZnVuY3Rpb24gKGF0dCkge1xuICAgIGlmIChvcHRzLmF0dGFjaG1lbnRzICYmIG9wdHMuaW5jbHVkZV9kb2NzKSB7XG4gICAgICBmZXRjaEF0dGFjaG1lbnQoZG9jLCBhdHQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBkb2MuX2F0dGFjaG1lbnRzW2F0dF0uc3R1YiA9IHRydWU7XG4gICAgICBjaGVja0RvbmUoKTtcbiAgICB9XG4gIH0pO1xufVxuXG4vLyBJREItc3BlY2lmaWMgcG9zdHByb2Nlc3NpbmcgbmVjZXNzYXJ5IGJlY2F1c2Vcbi8vIHdlIGRvbid0IGtub3cgd2hldGhlciB3ZSBzdG9yZWQgYSB0cnVlIEJsb2Igb3Jcbi8vIGEgYmFzZTY0LWVuY29kZWQgc3RyaW5nLCBhbmQgaWYgaXQncyBhIEJsb2IgaXRcbi8vIG5lZWRzIHRvIGJlIHJlYWQgb3V0c2lkZSBvZiB0aGUgdHJhbnNhY3Rpb24gY29udGV4dFxuZnVuY3Rpb24gcG9zdFByb2Nlc3NBdHRhY2htZW50cyhyZXN1bHRzLCBhc0Jsb2IpIHtcbiAgcmV0dXJuIFBvdWNoUHJvbWlzZS5hbGwocmVzdWx0cy5tYXAoZnVuY3Rpb24gKHJvdykge1xuICAgIGlmIChyb3cuZG9jICYmIHJvdy5kb2MuX2F0dGFjaG1lbnRzKSB7XG4gICAgICB2YXIgYXR0TmFtZXMgPSBPYmplY3Qua2V5cyhyb3cuZG9jLl9hdHRhY2htZW50cyk7XG4gICAgICByZXR1cm4gUG91Y2hQcm9taXNlLmFsbChhdHROYW1lcy5tYXAoZnVuY3Rpb24gKGF0dCkge1xuICAgICAgICB2YXIgYXR0T2JqID0gcm93LmRvYy5fYXR0YWNobWVudHNbYXR0XTtcbiAgICAgICAgaWYgKCEoJ2JvZHknIGluIGF0dE9iaikpIHsgLy8gYWxyZWFkeSBwcm9jZXNzZWRcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGJvZHkgPSBhdHRPYmouYm9keTtcbiAgICAgICAgdmFyIHR5cGUgPSBhdHRPYmouY29udGVudF90eXBlO1xuICAgICAgICByZXR1cm4gbmV3IFBvdWNoUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSkge1xuICAgICAgICAgIHJlYWRCbG9iRGF0YShib2R5LCB0eXBlLCBhc0Jsb2IsIGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgICAgICByb3cuZG9jLl9hdHRhY2htZW50c1thdHRdID0gZXh0ZW5kJDEoXG4gICAgICAgICAgICAgIHBpY2soYXR0T2JqLCBbJ2RpZ2VzdCcsICdjb250ZW50X3R5cGUnXSksXG4gICAgICAgICAgICAgIHtkYXRhOiBkYXRhfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KSk7XG4gICAgfVxuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGNvbXBhY3RSZXZzKHJldnMsIGRvY0lkLCB0eG4pIHtcblxuICB2YXIgcG9zc2libHlPcnBoYW5lZERpZ2VzdHMgPSBbXTtcbiAgdmFyIHNlcVN0b3JlID0gdHhuLm9iamVjdFN0b3JlKEJZX1NFUV9TVE9SRSk7XG4gIHZhciBhdHRTdG9yZSA9IHR4bi5vYmplY3RTdG9yZShBVFRBQ0hfU1RPUkUpO1xuICB2YXIgYXR0QW5kU2VxU3RvcmUgPSB0eG4ub2JqZWN0U3RvcmUoQVRUQUNIX0FORF9TRVFfU1RPUkUpO1xuICB2YXIgY291bnQgPSByZXZzLmxlbmd0aDtcblxuICBmdW5jdGlvbiBjaGVja0RvbmUoKSB7XG4gICAgY291bnQtLTtcbiAgICBpZiAoIWNvdW50KSB7IC8vIGRvbmUgcHJvY2Vzc2luZyBhbGwgcmV2c1xuICAgICAgZGVsZXRlT3JwaGFuZWRBdHRhY2htZW50cygpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGRlbGV0ZU9ycGhhbmVkQXR0YWNobWVudHMoKSB7XG4gICAgaWYgKCFwb3NzaWJseU9ycGhhbmVkRGlnZXN0cy5sZW5ndGgpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgcG9zc2libHlPcnBoYW5lZERpZ2VzdHMuZm9yRWFjaChmdW5jdGlvbiAoZGlnZXN0KSB7XG4gICAgICB2YXIgY291bnRSZXEgPSBhdHRBbmRTZXFTdG9yZS5pbmRleCgnZGlnZXN0U2VxJykuY291bnQoXG4gICAgICAgIElEQktleVJhbmdlLmJvdW5kKFxuICAgICAgICAgIGRpZ2VzdCArICc6OicsIGRpZ2VzdCArICc6OlxcdWZmZmYnLCBmYWxzZSwgZmFsc2UpKTtcbiAgICAgIGNvdW50UmVxLm9uc3VjY2VzcyA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHZhciBjb3VudCA9IGUudGFyZ2V0LnJlc3VsdDtcbiAgICAgICAgaWYgKCFjb3VudCkge1xuICAgICAgICAgIC8vIG9ycGhhbmVkXG4gICAgICAgICAgYXR0U3RvcmUuZGVsZXRlKGRpZ2VzdCk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfSk7XG4gIH1cblxuICByZXZzLmZvckVhY2goZnVuY3Rpb24gKHJldikge1xuICAgIHZhciBpbmRleCA9IHNlcVN0b3JlLmluZGV4KCdfZG9jX2lkX3JldicpO1xuICAgIHZhciBrZXkgPSBkb2NJZCArIFwiOjpcIiArIHJldjtcbiAgICBpbmRleC5nZXRLZXkoa2V5KS5vbnN1Y2Nlc3MgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgdmFyIHNlcSA9IGUudGFyZ2V0LnJlc3VsdDtcbiAgICAgIGlmICh0eXBlb2Ygc2VxICE9PSAnbnVtYmVyJykge1xuICAgICAgICByZXR1cm4gY2hlY2tEb25lKCk7XG4gICAgICB9XG4gICAgICBzZXFTdG9yZS5kZWxldGUoc2VxKTtcblxuICAgICAgdmFyIGN1cnNvciA9IGF0dEFuZFNlcVN0b3JlLmluZGV4KCdzZXEnKVxuICAgICAgICAub3BlbkN1cnNvcihJREJLZXlSYW5nZS5vbmx5KHNlcSkpO1xuXG4gICAgICBjdXJzb3Iub25zdWNjZXNzID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHZhciBjdXJzb3IgPSBldmVudC50YXJnZXQucmVzdWx0O1xuICAgICAgICBpZiAoY3Vyc29yKSB7XG4gICAgICAgICAgdmFyIGRpZ2VzdCA9IGN1cnNvci52YWx1ZS5kaWdlc3RTZXEuc3BsaXQoJzo6JylbMF07XG4gICAgICAgICAgcG9zc2libHlPcnBoYW5lZERpZ2VzdHMucHVzaChkaWdlc3QpO1xuICAgICAgICAgIGF0dEFuZFNlcVN0b3JlLmRlbGV0ZShjdXJzb3IucHJpbWFyeUtleSk7XG4gICAgICAgICAgY3Vyc29yLmNvbnRpbnVlKCk7XG4gICAgICAgIH0gZWxzZSB7IC8vIGRvbmVcbiAgICAgICAgICBjaGVja0RvbmUoKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9O1xuICB9KTtcbn1cblxuZnVuY3Rpb24gb3BlblRyYW5zYWN0aW9uU2FmZWx5KGlkYiwgc3RvcmVzLCBtb2RlKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHR4bjogaWRiLnRyYW5zYWN0aW9uKHN0b3JlcywgbW9kZSlcbiAgICB9O1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICByZXR1cm4ge1xuICAgICAgZXJyb3I6IGVyclxuICAgIH07XG4gIH1cbn1cblxuZnVuY3Rpb24gaWRiQnVsa0RvY3MoZGJPcHRzLCByZXEsIG9wdHMsIGFwaSwgaWRiLCBpZGJDaGFuZ2VzLCBjYWxsYmFjaykge1xuICB2YXIgZG9jSW5mb3MgPSByZXEuZG9jcztcbiAgdmFyIHR4bjtcbiAgdmFyIGRvY1N0b3JlO1xuICB2YXIgYnlTZXFTdG9yZTtcbiAgdmFyIGF0dGFjaFN0b3JlO1xuICB2YXIgYXR0YWNoQW5kU2VxU3RvcmU7XG4gIHZhciBkb2NJbmZvRXJyb3I7XG4gIHZhciBkb2NDb3VudERlbHRhID0gMDtcblxuICBmb3IgKHZhciBpID0gMCwgbGVuID0gZG9jSW5mb3MubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICB2YXIgZG9jID0gZG9jSW5mb3NbaV07XG4gICAgaWYgKGRvYy5faWQgJiYgaXNMb2NhbElkKGRvYy5faWQpKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgZG9jID0gZG9jSW5mb3NbaV0gPSBwYXJzZURvYyhkb2MsIG9wdHMubmV3X2VkaXRzKTtcbiAgICBpZiAoZG9jLmVycm9yICYmICFkb2NJbmZvRXJyb3IpIHtcbiAgICAgIGRvY0luZm9FcnJvciA9IGRvYztcbiAgICB9XG4gIH1cblxuICBpZiAoZG9jSW5mb0Vycm9yKSB7XG4gICAgcmV0dXJuIGNhbGxiYWNrKGRvY0luZm9FcnJvcik7XG4gIH1cblxuICB2YXIgcmVzdWx0cyA9IG5ldyBBcnJheShkb2NJbmZvcy5sZW5ndGgpO1xuICB2YXIgZmV0Y2hlZERvY3MgPSBuZXcgX01hcCgpO1xuICB2YXIgcHJlY29uZGl0aW9uRXJyb3JlZCA9IGZhbHNlO1xuICB2YXIgYmxvYlR5cGUgPSBhcGkuX21ldGEuYmxvYlN1cHBvcnQgPyAnYmxvYicgOiAnYmFzZTY0JztcblxuICBwcmVwcm9jZXNzQXR0YWNobWVudHMoZG9jSW5mb3MsIGJsb2JUeXBlLCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgaWYgKGVycikge1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKGVycik7XG4gICAgfVxuICAgIHN0YXJ0VHJhbnNhY3Rpb24oKTtcbiAgfSk7XG5cbiAgZnVuY3Rpb24gc3RhcnRUcmFuc2FjdGlvbigpIHtcblxuICAgIHZhciBzdG9yZXMgPSBbXG4gICAgICBET0NfU1RPUkUsIEJZX1NFUV9TVE9SRSxcbiAgICAgIEFUVEFDSF9TVE9SRSxcbiAgICAgIExPQ0FMX1NUT1JFLCBBVFRBQ0hfQU5EX1NFUV9TVE9SRVxuICAgIF07XG4gICAgdmFyIHR4blJlc3VsdCA9IG9wZW5UcmFuc2FjdGlvblNhZmVseShpZGIsIHN0b3JlcywgJ3JlYWR3cml0ZScpO1xuICAgIGlmICh0eG5SZXN1bHQuZXJyb3IpIHtcbiAgICAgIHJldHVybiBjYWxsYmFjayh0eG5SZXN1bHQuZXJyb3IpO1xuICAgIH1cbiAgICB0eG4gPSB0eG5SZXN1bHQudHhuO1xuICAgIHR4bi5vbmFib3J0ID0gaWRiRXJyb3IoY2FsbGJhY2spO1xuICAgIHR4bi5vbnRpbWVvdXQgPSBpZGJFcnJvcihjYWxsYmFjayk7XG4gICAgdHhuLm9uY29tcGxldGUgPSBjb21wbGV0ZTtcbiAgICBkb2NTdG9yZSA9IHR4bi5vYmplY3RTdG9yZShET0NfU1RPUkUpO1xuICAgIGJ5U2VxU3RvcmUgPSB0eG4ub2JqZWN0U3RvcmUoQllfU0VRX1NUT1JFKTtcbiAgICBhdHRhY2hTdG9yZSA9IHR4bi5vYmplY3RTdG9yZShBVFRBQ0hfU1RPUkUpO1xuICAgIGF0dGFjaEFuZFNlcVN0b3JlID0gdHhuLm9iamVjdFN0b3JlKEFUVEFDSF9BTkRfU0VRX1NUT1JFKTtcblxuICAgIHZlcmlmeUF0dGFjaG1lbnRzKGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgcHJlY29uZGl0aW9uRXJyb3JlZCA9IHRydWU7XG4gICAgICAgIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgICAgfVxuICAgICAgZmV0Y2hFeGlzdGluZ0RvY3MoKTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGlkYlByb2Nlc3NEb2NzKCkge1xuICAgIHByb2Nlc3NEb2NzKGRiT3B0cy5yZXZzX2xpbWl0LCBkb2NJbmZvcywgYXBpLCBmZXRjaGVkRG9jcyxcbiAgICAgICAgICAgICAgICB0eG4sIHJlc3VsdHMsIHdyaXRlRG9jLCBvcHRzKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZldGNoRXhpc3RpbmdEb2NzKCkge1xuXG4gICAgaWYgKCFkb2NJbmZvcy5sZW5ndGgpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgbnVtRmV0Y2hlZCA9IDA7XG5cbiAgICBmdW5jdGlvbiBjaGVja0RvbmUoKSB7XG4gICAgICBpZiAoKytudW1GZXRjaGVkID09PSBkb2NJbmZvcy5sZW5ndGgpIHtcbiAgICAgICAgaWRiUHJvY2Vzc0RvY3MoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZWFkTWV0YWRhdGEoZXZlbnQpIHtcbiAgICAgIHZhciBtZXRhZGF0YSA9IGRlY29kZU1ldGFkYXRhKGV2ZW50LnRhcmdldC5yZXN1bHQpO1xuXG4gICAgICBpZiAobWV0YWRhdGEpIHtcbiAgICAgICAgZmV0Y2hlZERvY3Muc2V0KG1ldGFkYXRhLmlkLCBtZXRhZGF0YSk7XG4gICAgICB9XG4gICAgICBjaGVja0RvbmUoKTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gZG9jSW5mb3MubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIHZhciBkb2NJbmZvID0gZG9jSW5mb3NbaV07XG4gICAgICBpZiAoZG9jSW5mby5faWQgJiYgaXNMb2NhbElkKGRvY0luZm8uX2lkKSkge1xuICAgICAgICBjaGVja0RvbmUoKTsgLy8gc2tpcCBsb2NhbCBkb2NzXG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgdmFyIHJlcSA9IGRvY1N0b3JlLmdldChkb2NJbmZvLm1ldGFkYXRhLmlkKTtcbiAgICAgIHJlcS5vbnN1Y2Nlc3MgPSByZWFkTWV0YWRhdGE7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gY29tcGxldGUoKSB7XG4gICAgaWYgKHByZWNvbmRpdGlvbkVycm9yZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZGJDaGFuZ2VzLm5vdGlmeShhcGkuX21ldGEubmFtZSk7XG4gICAgYXBpLl9tZXRhLmRvY0NvdW50ICs9IGRvY0NvdW50RGVsdGE7XG4gICAgY2FsbGJhY2sobnVsbCwgcmVzdWx0cyk7XG4gIH1cblxuICBmdW5jdGlvbiB2ZXJpZnlBdHRhY2htZW50KGRpZ2VzdCwgY2FsbGJhY2spIHtcblxuICAgIHZhciByZXEgPSBhdHRhY2hTdG9yZS5nZXQoZGlnZXN0KTtcbiAgICByZXEub25zdWNjZXNzID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgIGlmICghZS50YXJnZXQucmVzdWx0KSB7XG4gICAgICAgIHZhciBlcnIgPSBjcmVhdGVFcnJvcihNSVNTSU5HX1NUVUIsXG4gICAgICAgICAgJ3Vua25vd24gc3R1YiBhdHRhY2htZW50IHdpdGggZGlnZXN0ICcgK1xuICAgICAgICAgIGRpZ2VzdCk7XG4gICAgICAgIGVyci5zdGF0dXMgPSA0MTI7XG4gICAgICAgIGNhbGxiYWNrKGVycik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgfVxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiB2ZXJpZnlBdHRhY2htZW50cyhmaW5pc2gpIHtcblxuXG4gICAgdmFyIGRpZ2VzdHMgPSBbXTtcbiAgICBkb2NJbmZvcy5mb3JFYWNoKGZ1bmN0aW9uIChkb2NJbmZvKSB7XG4gICAgICBpZiAoZG9jSW5mby5kYXRhICYmIGRvY0luZm8uZGF0YS5fYXR0YWNobWVudHMpIHtcbiAgICAgICAgT2JqZWN0LmtleXMoZG9jSW5mby5kYXRhLl9hdHRhY2htZW50cykuZm9yRWFjaChmdW5jdGlvbiAoZmlsZW5hbWUpIHtcbiAgICAgICAgICB2YXIgYXR0ID0gZG9jSW5mby5kYXRhLl9hdHRhY2htZW50c1tmaWxlbmFtZV07XG4gICAgICAgICAgaWYgKGF0dC5zdHViKSB7XG4gICAgICAgICAgICBkaWdlc3RzLnB1c2goYXR0LmRpZ2VzdCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBpZiAoIWRpZ2VzdHMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmluaXNoKCk7XG4gICAgfVxuICAgIHZhciBudW1Eb25lID0gMDtcbiAgICB2YXIgZXJyO1xuXG4gICAgZnVuY3Rpb24gY2hlY2tEb25lKCkge1xuICAgICAgaWYgKCsrbnVtRG9uZSA9PT0gZGlnZXN0cy5sZW5ndGgpIHtcbiAgICAgICAgZmluaXNoKGVycik7XG4gICAgICB9XG4gICAgfVxuICAgIGRpZ2VzdHMuZm9yRWFjaChmdW5jdGlvbiAoZGlnZXN0KSB7XG4gICAgICB2ZXJpZnlBdHRhY2htZW50KGRpZ2VzdCwgZnVuY3Rpb24gKGF0dEVycikge1xuICAgICAgICBpZiAoYXR0RXJyICYmICFlcnIpIHtcbiAgICAgICAgICBlcnIgPSBhdHRFcnI7XG4gICAgICAgIH1cbiAgICAgICAgY2hlY2tEb25lKCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHdyaXRlRG9jKGRvY0luZm8sIHdpbm5pbmdSZXYsIHdpbm5pbmdSZXZJc0RlbGV0ZWQsIG5ld1JldklzRGVsZXRlZCxcbiAgICAgICAgICAgICAgICAgICAgaXNVcGRhdGUsIGRlbHRhLCByZXN1bHRzSWR4LCBjYWxsYmFjaykge1xuXG4gICAgZG9jQ291bnREZWx0YSArPSBkZWx0YTtcblxuICAgIGRvY0luZm8ubWV0YWRhdGEud2lubmluZ1JldiA9IHdpbm5pbmdSZXY7XG4gICAgZG9jSW5mby5tZXRhZGF0YS5kZWxldGVkID0gd2lubmluZ1JldklzRGVsZXRlZDtcblxuICAgIHZhciBkb2MgPSBkb2NJbmZvLmRhdGE7XG4gICAgZG9jLl9pZCA9IGRvY0luZm8ubWV0YWRhdGEuaWQ7XG4gICAgZG9jLl9yZXYgPSBkb2NJbmZvLm1ldGFkYXRhLnJldjtcblxuICAgIGlmIChuZXdSZXZJc0RlbGV0ZWQpIHtcbiAgICAgIGRvYy5fZGVsZXRlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgdmFyIGhhc0F0dGFjaG1lbnRzID0gZG9jLl9hdHRhY2htZW50cyAmJlxuICAgICAgT2JqZWN0LmtleXMoZG9jLl9hdHRhY2htZW50cykubGVuZ3RoO1xuICAgIGlmIChoYXNBdHRhY2htZW50cykge1xuICAgICAgcmV0dXJuIHdyaXRlQXR0YWNobWVudHMoZG9jSW5mbywgd2lubmluZ1Jldiwgd2lubmluZ1JldklzRGVsZXRlZCxcbiAgICAgICAgaXNVcGRhdGUsIHJlc3VsdHNJZHgsIGNhbGxiYWNrKTtcbiAgICB9XG5cbiAgICBmaW5pc2hEb2MoZG9jSW5mbywgd2lubmluZ1Jldiwgd2lubmluZ1JldklzRGVsZXRlZCxcbiAgICAgIGlzVXBkYXRlLCByZXN1bHRzSWR4LCBjYWxsYmFjayk7XG4gIH1cblxuICBmdW5jdGlvbiBmaW5pc2hEb2MoZG9jSW5mbywgd2lubmluZ1Jldiwgd2lubmluZ1JldklzRGVsZXRlZCxcbiAgICAgICAgICAgICAgICAgICAgIGlzVXBkYXRlLCByZXN1bHRzSWR4LCBjYWxsYmFjaykge1xuXG4gICAgdmFyIGRvYyA9IGRvY0luZm8uZGF0YTtcbiAgICB2YXIgbWV0YWRhdGEgPSBkb2NJbmZvLm1ldGFkYXRhO1xuXG4gICAgZG9jLl9kb2NfaWRfcmV2ID0gbWV0YWRhdGEuaWQgKyAnOjonICsgbWV0YWRhdGEucmV2O1xuICAgIGRlbGV0ZSBkb2MuX2lkO1xuICAgIGRlbGV0ZSBkb2MuX3JldjtcblxuICAgIGZ1bmN0aW9uIGFmdGVyUHV0RG9jKGUpIHtcbiAgICAgIHZhciByZXZzVG9EZWxldGUgPSBkb2NJbmZvLnN0ZW1tZWRSZXZzIHx8IFtdO1xuXG4gICAgICBpZiAoaXNVcGRhdGUgJiYgYXBpLmF1dG9fY29tcGFjdGlvbikge1xuICAgICAgICByZXZzVG9EZWxldGUgPSByZXZzVG9EZWxldGUuY29uY2F0KGNvbXBhY3RUcmVlKGRvY0luZm8ubWV0YWRhdGEpKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHJldnNUb0RlbGV0ZSAmJiByZXZzVG9EZWxldGUubGVuZ3RoKSB7XG4gICAgICAgIGNvbXBhY3RSZXZzKHJldnNUb0RlbGV0ZSwgZG9jSW5mby5tZXRhZGF0YS5pZCwgdHhuKTtcbiAgICAgIH1cblxuICAgICAgbWV0YWRhdGEuc2VxID0gZS50YXJnZXQucmVzdWx0O1xuICAgICAgLy8gQ3VycmVudCBfcmV2IGlzIGNhbGN1bGF0ZWQgZnJvbSBfcmV2X3RyZWUgb24gcmVhZFxuICAgICAgLy8gZGVsZXRlIG1ldGFkYXRhLnJldjtcbiAgICAgIHZhciBtZXRhZGF0YVRvU3RvcmUgPSBlbmNvZGVNZXRhZGF0YShtZXRhZGF0YSwgd2lubmluZ1JldixcbiAgICAgICAgd2lubmluZ1JldklzRGVsZXRlZCk7XG4gICAgICB2YXIgbWV0YURhdGFSZXEgPSBkb2NTdG9yZS5wdXQobWV0YWRhdGFUb1N0b3JlKTtcbiAgICAgIG1ldGFEYXRhUmVxLm9uc3VjY2VzcyA9IGFmdGVyUHV0TWV0YWRhdGE7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYWZ0ZXJQdXREb2NFcnJvcihlKSB7XG4gICAgICAvLyBDb25zdHJhaW50RXJyb3IsIG5lZWQgdG8gdXBkYXRlLCBub3QgcHV0IChzZWUgIzE2MzggZm9yIGRldGFpbHMpXG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7IC8vIGF2b2lkIHRyYW5zYWN0aW9uIGFib3J0XG4gICAgICBlLnN0b3BQcm9wYWdhdGlvbigpOyAvLyBhdm9pZCB0cmFuc2FjdGlvbiBvbmVycm9yXG4gICAgICB2YXIgaW5kZXggPSBieVNlcVN0b3JlLmluZGV4KCdfZG9jX2lkX3JldicpO1xuICAgICAgdmFyIGdldEtleVJlcSA9IGluZGV4LmdldEtleShkb2MuX2RvY19pZF9yZXYpO1xuICAgICAgZ2V0S2V5UmVxLm9uc3VjY2VzcyA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHZhciBwdXRSZXEgPSBieVNlcVN0b3JlLnB1dChkb2MsIGUudGFyZ2V0LnJlc3VsdCk7XG4gICAgICAgIHB1dFJlcS5vbnN1Y2Nlc3MgPSBhZnRlclB1dERvYztcbiAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYWZ0ZXJQdXRNZXRhZGF0YSgpIHtcbiAgICAgIHJlc3VsdHNbcmVzdWx0c0lkeF0gPSB7XG4gICAgICAgIG9rOiB0cnVlLFxuICAgICAgICBpZDogbWV0YWRhdGEuaWQsXG4gICAgICAgIHJldjogbWV0YWRhdGEucmV2XG4gICAgICB9O1xuICAgICAgZmV0Y2hlZERvY3Muc2V0KGRvY0luZm8ubWV0YWRhdGEuaWQsIGRvY0luZm8ubWV0YWRhdGEpO1xuICAgICAgaW5zZXJ0QXR0YWNobWVudE1hcHBpbmdzKGRvY0luZm8sIG1ldGFkYXRhLnNlcSwgY2FsbGJhY2spO1xuICAgIH1cblxuICAgIHZhciBwdXRSZXEgPSBieVNlcVN0b3JlLnB1dChkb2MpO1xuXG4gICAgcHV0UmVxLm9uc3VjY2VzcyA9IGFmdGVyUHV0RG9jO1xuICAgIHB1dFJlcS5vbmVycm9yID0gYWZ0ZXJQdXREb2NFcnJvcjtcbiAgfVxuXG4gIGZ1bmN0aW9uIHdyaXRlQXR0YWNobWVudHMoZG9jSW5mbywgd2lubmluZ1Jldiwgd2lubmluZ1JldklzRGVsZXRlZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1VwZGF0ZSwgcmVzdWx0c0lkeCwgY2FsbGJhY2spIHtcblxuXG4gICAgdmFyIGRvYyA9IGRvY0luZm8uZGF0YTtcblxuICAgIHZhciBudW1Eb25lID0gMDtcbiAgICB2YXIgYXR0YWNobWVudHMgPSBPYmplY3Qua2V5cyhkb2MuX2F0dGFjaG1lbnRzKTtcblxuICAgIGZ1bmN0aW9uIGNvbGxlY3RSZXN1bHRzKCkge1xuICAgICAgaWYgKG51bURvbmUgPT09IGF0dGFjaG1lbnRzLmxlbmd0aCkge1xuICAgICAgICBmaW5pc2hEb2MoZG9jSW5mbywgd2lubmluZ1Jldiwgd2lubmluZ1JldklzRGVsZXRlZCxcbiAgICAgICAgICBpc1VwZGF0ZSwgcmVzdWx0c0lkeCwgY2FsbGJhY2spO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGF0dGFjaG1lbnRTYXZlZCgpIHtcbiAgICAgIG51bURvbmUrKztcbiAgICAgIGNvbGxlY3RSZXN1bHRzKCk7XG4gICAgfVxuXG4gICAgYXR0YWNobWVudHMuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICB2YXIgYXR0ID0gZG9jSW5mby5kYXRhLl9hdHRhY2htZW50c1trZXldO1xuICAgICAgaWYgKCFhdHQuc3R1Yikge1xuICAgICAgICB2YXIgZGF0YSA9IGF0dC5kYXRhO1xuICAgICAgICBkZWxldGUgYXR0LmRhdGE7XG4gICAgICAgIGF0dC5yZXZwb3MgPSBwYXJzZUludCh3aW5uaW5nUmV2LCAxMCk7XG4gICAgICAgIHZhciBkaWdlc3QgPSBhdHQuZGlnZXN0O1xuICAgICAgICBzYXZlQXR0YWNobWVudChkaWdlc3QsIGRhdGEsIGF0dGFjaG1lbnRTYXZlZCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBudW1Eb25lKys7XG4gICAgICAgIGNvbGxlY3RSZXN1bHRzKCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBtYXAgc2VxcyB0byBhdHRhY2htZW50IGRpZ2VzdHMsIHdoaWNoXG4gIC8vIHdlIHdpbGwgbmVlZCBsYXRlciBkdXJpbmcgY29tcGFjdGlvblxuICBmdW5jdGlvbiBpbnNlcnRBdHRhY2htZW50TWFwcGluZ3MoZG9jSW5mbywgc2VxLCBjYWxsYmFjaykge1xuXG4gICAgdmFyIGF0dHNBZGRlZCA9IDA7XG4gICAgdmFyIGF0dHNUb0FkZCA9IE9iamVjdC5rZXlzKGRvY0luZm8uZGF0YS5fYXR0YWNobWVudHMgfHwge30pO1xuXG4gICAgaWYgKCFhdHRzVG9BZGQubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjaGVja0RvbmUoKSB7XG4gICAgICBpZiAoKythdHRzQWRkZWQgPT09IGF0dHNUb0FkZC5sZW5ndGgpIHtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhZGQoYXR0KSB7XG4gICAgICB2YXIgZGlnZXN0ID0gZG9jSW5mby5kYXRhLl9hdHRhY2htZW50c1thdHRdLmRpZ2VzdDtcbiAgICAgIHZhciByZXEgPSBhdHRhY2hBbmRTZXFTdG9yZS5wdXQoe1xuICAgICAgICBzZXE6IHNlcSxcbiAgICAgICAgZGlnZXN0U2VxOiBkaWdlc3QgKyAnOjonICsgc2VxXG4gICAgICB9KTtcblxuICAgICAgcmVxLm9uc3VjY2VzcyA9IGNoZWNrRG9uZTtcbiAgICAgIHJlcS5vbmVycm9yID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgLy8gdGhpcyBjYWxsYmFjayBpcyBmb3IgYSBjb25zdGFpbnQgZXJyb3IsIHdoaWNoIHdlIGlnbm9yZVxuICAgICAgICAvLyBiZWNhdXNlIHRoaXMgZG9jaWQvcmV2IGhhcyBhbHJlYWR5IGJlZW4gYXNzb2NpYXRlZCB3aXRoXG4gICAgICAgIC8vIHRoZSBkaWdlc3QgKGUuZy4gd2hlbiBuZXdfZWRpdHMgPT0gZmFsc2UpXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTsgLy8gYXZvaWQgdHJhbnNhY3Rpb24gYWJvcnRcbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTsgLy8gYXZvaWQgdHJhbnNhY3Rpb24gb25lcnJvclxuICAgICAgICBjaGVja0RvbmUoKTtcbiAgICAgIH07XG4gICAgfVxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXR0c1RvQWRkLmxlbmd0aDsgaSsrKSB7XG4gICAgICBhZGQoYXR0c1RvQWRkW2ldKTsgLy8gZG8gaW4gcGFyYWxsZWxcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBzYXZlQXR0YWNobWVudChkaWdlc3QsIGRhdGEsIGNhbGxiYWNrKSB7XG5cblxuICAgIHZhciBnZXRLZXlSZXEgPSBhdHRhY2hTdG9yZS5jb3VudChkaWdlc3QpO1xuICAgIGdldEtleVJlcS5vbnN1Y2Nlc3MgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgdmFyIGNvdW50ID0gZS50YXJnZXQucmVzdWx0O1xuICAgICAgaWYgKGNvdW50KSB7XG4gICAgICAgIHJldHVybiBjYWxsYmFjaygpOyAvLyBhbHJlYWR5IGV4aXN0c1xuICAgICAgfVxuICAgICAgdmFyIG5ld0F0dCA9IHtcbiAgICAgICAgZGlnZXN0OiBkaWdlc3QsXG4gICAgICAgIGJvZHk6IGRhdGFcbiAgICAgIH07XG4gICAgICB2YXIgcHV0UmVxID0gYXR0YWNoU3RvcmUucHV0KG5ld0F0dCk7XG4gICAgICBwdXRSZXEub25zdWNjZXNzID0gY2FsbGJhY2s7XG4gICAgfTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjcmVhdGVLZXlSYW5nZShzdGFydCwgZW5kLCBpbmNsdXNpdmVFbmQsIGtleSwgZGVzY2VuZGluZykge1xuICB0cnkge1xuICAgIGlmIChzdGFydCAmJiBlbmQpIHtcbiAgICAgIGlmIChkZXNjZW5kaW5nKSB7XG4gICAgICAgIHJldHVybiBJREJLZXlSYW5nZS5ib3VuZChlbmQsIHN0YXJ0LCAhaW5jbHVzaXZlRW5kLCBmYWxzZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gSURCS2V5UmFuZ2UuYm91bmQoc3RhcnQsIGVuZCwgZmFsc2UsICFpbmNsdXNpdmVFbmQpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoc3RhcnQpIHtcbiAgICAgIGlmIChkZXNjZW5kaW5nKSB7XG4gICAgICAgIHJldHVybiBJREJLZXlSYW5nZS51cHBlckJvdW5kKHN0YXJ0KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBJREJLZXlSYW5nZS5sb3dlckJvdW5kKHN0YXJ0KTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGVuZCkge1xuICAgICAgaWYgKGRlc2NlbmRpbmcpIHtcbiAgICAgICAgcmV0dXJuIElEQktleVJhbmdlLmxvd2VyQm91bmQoZW5kLCAhaW5jbHVzaXZlRW5kKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBJREJLZXlSYW5nZS51cHBlckJvdW5kKGVuZCwgIWluY2x1c2l2ZUVuZCk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChrZXkpIHtcbiAgICAgIHJldHVybiBJREJLZXlSYW5nZS5vbmx5KGtleSk7XG4gICAgfVxuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIHtlcnJvcjogZX07XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59XG5cbmZ1bmN0aW9uIGhhbmRsZUtleVJhbmdlRXJyb3IoYXBpLCBvcHRzLCBlcnIsIGNhbGxiYWNrKSB7XG4gIGlmIChlcnIubmFtZSA9PT0gXCJEYXRhRXJyb3JcIiAmJiBlcnIuY29kZSA9PT0gMCkge1xuICAgIC8vIGRhdGEgZXJyb3IsIHN0YXJ0IGlzIGxlc3MgdGhhbiBlbmRcbiAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwge1xuICAgICAgdG90YWxfcm93czogYXBpLl9tZXRhLmRvY0NvdW50LFxuICAgICAgb2Zmc2V0OiBvcHRzLnNraXAsXG4gICAgICByb3dzOiBbXVxuICAgIH0pO1xuICB9XG4gIGNhbGxiYWNrKGNyZWF0ZUVycm9yKElEQl9FUlJPUiwgZXJyLm5hbWUsIGVyci5tZXNzYWdlKSk7XG59XG5cbmZ1bmN0aW9uIGlkYkFsbERvY3Mob3B0cywgYXBpLCBpZGIsIGNhbGxiYWNrKSB7XG5cbiAgZnVuY3Rpb24gYWxsRG9jc1F1ZXJ5KG9wdHMsIGNhbGxiYWNrKSB7XG4gICAgdmFyIHN0YXJ0ID0gJ3N0YXJ0a2V5JyBpbiBvcHRzID8gb3B0cy5zdGFydGtleSA6IGZhbHNlO1xuICAgIHZhciBlbmQgPSAnZW5ka2V5JyBpbiBvcHRzID8gb3B0cy5lbmRrZXkgOiBmYWxzZTtcbiAgICB2YXIga2V5ID0gJ2tleScgaW4gb3B0cyA/IG9wdHMua2V5IDogZmFsc2U7XG4gICAgdmFyIHNraXAgPSBvcHRzLnNraXAgfHwgMDtcbiAgICB2YXIgbGltaXQgPSB0eXBlb2Ygb3B0cy5saW1pdCA9PT0gJ251bWJlcicgPyBvcHRzLmxpbWl0IDogLTE7XG4gICAgdmFyIGluY2x1c2l2ZUVuZCA9IG9wdHMuaW5jbHVzaXZlX2VuZCAhPT0gZmFsc2U7XG4gICAgdmFyIGRlc2NlbmRpbmcgPSAnZGVzY2VuZGluZycgaW4gb3B0cyAmJiBvcHRzLmRlc2NlbmRpbmcgPyAncHJldicgOiBudWxsO1xuXG4gICAgdmFyIGtleVJhbmdlID0gY3JlYXRlS2V5UmFuZ2Uoc3RhcnQsIGVuZCwgaW5jbHVzaXZlRW5kLCBrZXksIGRlc2NlbmRpbmcpO1xuICAgIGlmIChrZXlSYW5nZSAmJiBrZXlSYW5nZS5lcnJvcikge1xuICAgICAgcmV0dXJuIGhhbmRsZUtleVJhbmdlRXJyb3IoYXBpLCBvcHRzLCBrZXlSYW5nZS5lcnJvciwgY2FsbGJhY2spO1xuICAgIH1cblxuICAgIHZhciBzdG9yZXMgPSBbRE9DX1NUT1JFLCBCWV9TRVFfU1RPUkVdO1xuXG4gICAgaWYgKG9wdHMuYXR0YWNobWVudHMpIHtcbiAgICAgIHN0b3Jlcy5wdXNoKEFUVEFDSF9TVE9SRSk7XG4gICAgfVxuICAgIHZhciB0eG5SZXN1bHQgPSBvcGVuVHJhbnNhY3Rpb25TYWZlbHkoaWRiLCBzdG9yZXMsICdyZWFkb25seScpO1xuICAgIGlmICh0eG5SZXN1bHQuZXJyb3IpIHtcbiAgICAgIHJldHVybiBjYWxsYmFjayh0eG5SZXN1bHQuZXJyb3IpO1xuICAgIH1cbiAgICB2YXIgdHhuID0gdHhuUmVzdWx0LnR4bjtcbiAgICB2YXIgZG9jU3RvcmUgPSB0eG4ub2JqZWN0U3RvcmUoRE9DX1NUT1JFKTtcbiAgICB2YXIgc2VxU3RvcmUgPSB0eG4ub2JqZWN0U3RvcmUoQllfU0VRX1NUT1JFKTtcbiAgICB2YXIgY3Vyc29yID0gZGVzY2VuZGluZyA/XG4gICAgICBkb2NTdG9yZS5vcGVuQ3Vyc29yKGtleVJhbmdlLCBkZXNjZW5kaW5nKSA6XG4gICAgICBkb2NTdG9yZS5vcGVuQ3Vyc29yKGtleVJhbmdlKTtcbiAgICB2YXIgZG9jSWRSZXZJbmRleCA9IHNlcVN0b3JlLmluZGV4KCdfZG9jX2lkX3JldicpO1xuICAgIHZhciByZXN1bHRzID0gW107XG4gICAgdmFyIGRvY0NvdW50ID0gMDtcblxuICAgIC8vIGlmIHRoZSB1c2VyIHNwZWNpZmllcyBpbmNsdWRlX2RvY3M9dHJ1ZSwgdGhlbiB3ZSBkb24ndFxuICAgIC8vIHdhbnQgdG8gYmxvY2sgdGhlIG1haW4gY3Vyc29yIHdoaWxlIHdlJ3JlIGZldGNoaW5nIHRoZSBkb2NcbiAgICBmdW5jdGlvbiBmZXRjaERvY0FzeW5jaHJvbm91c2x5KG1ldGFkYXRhLCByb3csIHdpbm5pbmdSZXYpIHtcbiAgICAgIHZhciBrZXkgPSBtZXRhZGF0YS5pZCArIFwiOjpcIiArIHdpbm5pbmdSZXY7XG4gICAgICBkb2NJZFJldkluZGV4LmdldChrZXkpLm9uc3VjY2VzcyA9ICBmdW5jdGlvbiBvbkdldERvYyhlKSB7XG4gICAgICAgIHJvdy5kb2MgPSBkZWNvZGVEb2MoZS50YXJnZXQucmVzdWx0KTtcbiAgICAgICAgaWYgKG9wdHMuY29uZmxpY3RzKSB7XG4gICAgICAgICAgdmFyIGNvbmZsaWN0cyA9IGNvbGxlY3RDb25mbGljdHMobWV0YWRhdGEpO1xuICAgICAgICAgIGlmIChjb25mbGljdHMubGVuZ3RoKSB7XG4gICAgICAgICAgICByb3cuZG9jLl9jb25mbGljdHMgPSBjb25mbGljdHM7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZldGNoQXR0YWNobWVudHNJZk5lY2Vzc2FyeShyb3cuZG9jLCBvcHRzLCB0eG4pO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhbGxEb2NzSW5uZXIoY3Vyc29yLCB3aW5uaW5nUmV2LCBtZXRhZGF0YSkge1xuICAgICAgdmFyIHJvdyA9IHtcbiAgICAgICAgaWQ6IG1ldGFkYXRhLmlkLFxuICAgICAgICBrZXk6IG1ldGFkYXRhLmlkLFxuICAgICAgICB2YWx1ZToge1xuICAgICAgICAgIHJldjogd2lubmluZ1JldlxuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgdmFyIGRlbGV0ZWQgPSBtZXRhZGF0YS5kZWxldGVkO1xuICAgICAgaWYgKG9wdHMuZGVsZXRlZCA9PT0gJ29rJykge1xuICAgICAgICByZXN1bHRzLnB1c2gocm93KTtcbiAgICAgICAgLy8gZGVsZXRlZCBkb2NzIGFyZSBva2F5IHdpdGggXCJrZXlzXCIgcmVxdWVzdHNcbiAgICAgICAgaWYgKGRlbGV0ZWQpIHtcbiAgICAgICAgICByb3cudmFsdWUuZGVsZXRlZCA9IHRydWU7XG4gICAgICAgICAgcm93LmRvYyA9IG51bGw7XG4gICAgICAgIH0gZWxzZSBpZiAob3B0cy5pbmNsdWRlX2RvY3MpIHtcbiAgICAgICAgICBmZXRjaERvY0FzeW5jaHJvbm91c2x5KG1ldGFkYXRhLCByb3csIHdpbm5pbmdSZXYpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKCFkZWxldGVkICYmIHNraXAtLSA8PSAwKSB7XG4gICAgICAgIHJlc3VsdHMucHVzaChyb3cpO1xuICAgICAgICBpZiAob3B0cy5pbmNsdWRlX2RvY3MpIHtcbiAgICAgICAgICBmZXRjaERvY0FzeW5jaHJvbm91c2x5KG1ldGFkYXRhLCByb3csIHdpbm5pbmdSZXYpO1xuICAgICAgICB9XG4gICAgICAgIGlmICgtLWxpbWl0ID09PSAwKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjdXJzb3IuY29udGludWUoKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBvbkdldEN1cnNvcihlKSB7XG4gICAgICBkb2NDb3VudCA9IGFwaS5fbWV0YS5kb2NDb3VudDsgLy8gZG8gdGhpcyB3aXRoaW4gdGhlIHR4biBmb3IgY29uc2lzdGVuY3lcbiAgICAgIHZhciBjdXJzb3IgPSBlLnRhcmdldC5yZXN1bHQ7XG4gICAgICBpZiAoIWN1cnNvcikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB2YXIgbWV0YWRhdGEgPSBkZWNvZGVNZXRhZGF0YShjdXJzb3IudmFsdWUpO1xuICAgICAgdmFyIHdpbm5pbmdSZXYgPSBtZXRhZGF0YS53aW5uaW5nUmV2O1xuXG4gICAgICBhbGxEb2NzSW5uZXIoY3Vyc29yLCB3aW5uaW5nUmV2LCBtZXRhZGF0YSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25SZXN1bHRzUmVhZHkoKSB7XG4gICAgICBjYWxsYmFjayhudWxsLCB7XG4gICAgICAgIHRvdGFsX3Jvd3M6IGRvY0NvdW50LFxuICAgICAgICBvZmZzZXQ6IG9wdHMuc2tpcCxcbiAgICAgICAgcm93czogcmVzdWx0c1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25UeG5Db21wbGV0ZSgpIHtcbiAgICAgIGlmIChvcHRzLmF0dGFjaG1lbnRzKSB7XG4gICAgICAgIHBvc3RQcm9jZXNzQXR0YWNobWVudHMocmVzdWx0cywgb3B0cy5iaW5hcnkpLnRoZW4ob25SZXN1bHRzUmVhZHkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb25SZXN1bHRzUmVhZHkoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0eG4ub25jb21wbGV0ZSA9IG9uVHhuQ29tcGxldGU7XG4gICAgY3Vyc29yLm9uc3VjY2VzcyA9IG9uR2V0Q3Vyc29yO1xuICB9XG5cbiAgZnVuY3Rpb24gYWxsRG9jcyhvcHRzLCBjYWxsYmFjaykge1xuXG4gICAgaWYgKG9wdHMubGltaXQgPT09IDApIHtcbiAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCB7XG4gICAgICAgIHRvdGFsX3Jvd3M6IGFwaS5fbWV0YS5kb2NDb3VudCxcbiAgICAgICAgb2Zmc2V0OiBvcHRzLnNraXAsXG4gICAgICAgIHJvd3M6IFtdXG4gICAgICB9KTtcbiAgICB9XG4gICAgYWxsRG9jc1F1ZXJ5KG9wdHMsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIGFsbERvY3Mob3B0cywgY2FsbGJhY2spO1xufVxuXG4vL1xuLy8gQmxvYnMgYXJlIG5vdCBzdXBwb3J0ZWQgaW4gYWxsIHZlcnNpb25zIG9mIEluZGV4ZWREQiwgbm90YWJseVxuLy8gQ2hyb21lIDwzNyBhbmQgQW5kcm9pZCA8NS4gSW4gdGhvc2UgdmVyc2lvbnMsIHN0b3JpbmcgYSBibG9iIHdpbGwgdGhyb3cuXG4vL1xuLy8gVmFyaW91cyBvdGhlciBibG9iIGJ1Z3MgZXhpc3QgaW4gQ2hyb21lIHYzNy00MiAoaW5jbHVzaXZlKS5cbi8vIERldGVjdGluZyB0aGVtIGlzIGV4cGVuc2l2ZSBhbmQgY29uZnVzaW5nIHRvIHVzZXJzLCBhbmQgQ2hyb21lIDM3LTQyXG4vLyBpcyBhdCB2ZXJ5IGxvdyB1c2FnZSB3b3JsZHdpZGUsIHNvIHdlIGRvIGEgaGFja3kgdXNlckFnZW50IGNoZWNrIGluc3RlYWQuXG4vL1xuLy8gY29udGVudC10eXBlIGJ1ZzogaHR0cHM6Ly9jb2RlLmdvb2dsZS5jb20vcC9jaHJvbWl1bS9pc3N1ZXMvZGV0YWlsP2lkPTQwODEyMFxuLy8gNDA0IGJ1ZzogaHR0cHM6Ly9jb2RlLmdvb2dsZS5jb20vcC9jaHJvbWl1bS9pc3N1ZXMvZGV0YWlsP2lkPTQ0NzkxNlxuLy8gRmlsZVJlYWRlciBidWc6IGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD00NDc4MzZcbi8vXG5mdW5jdGlvbiBjaGVja0Jsb2JTdXBwb3J0KHR4bikge1xuICByZXR1cm4gbmV3IFBvdWNoUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSkge1xuICAgIHZhciBibG9iID0gY3JlYXRlQmxvYihbJyddKTtcbiAgICB0eG4ub2JqZWN0U3RvcmUoREVURUNUX0JMT0JfU1VQUE9SVF9TVE9SRSkucHV0KGJsb2IsICdrZXknKTtcblxuICAgIHR4bi5vbmFib3J0ID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgIC8vIElmIHRoZSB0cmFuc2FjdGlvbiBhYm9ydHMgbm93IGl0cyBkdWUgdG8gbm90IGJlaW5nIGFibGUgdG9cbiAgICAgIC8vIHdyaXRlIHRvIHRoZSBkYXRhYmFzZSwgbGlrZWx5IGR1ZSB0byB0aGUgZGlzayBiZWluZyBmdWxsXG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgcmVzb2x2ZShmYWxzZSk7XG4gICAgfTtcblxuICAgIHR4bi5vbmNvbXBsZXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIG1hdGNoZWRDaHJvbWUgPSBuYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKC9DaHJvbWVcXC8oXFxkKykvKTtcbiAgICAgIHZhciBtYXRjaGVkRWRnZSA9IG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goL0VkZ2VcXC8vKTtcbiAgICAgIC8vIE1TIEVkZ2UgcHJldGVuZHMgdG8gYmUgQ2hyb21lIDQyOlxuICAgICAgLy8gaHR0cHM6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9oaDg2OTMwMSUyOHY9dnMuODUlMjkuYXNweFxuICAgICAgcmVzb2x2ZShtYXRjaGVkRWRnZSB8fCAhbWF0Y2hlZENocm9tZSB8fFxuICAgICAgICBwYXJzZUludChtYXRjaGVkQ2hyb21lWzFdLCAxMCkgPj0gNDMpO1xuICAgIH07XG4gIH0pLmNhdGNoKGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZmFsc2U7IC8vIGVycm9yLCBzbyBhc3N1bWUgdW5zdXBwb3J0ZWRcbiAgfSk7XG59XG5cbi8vIFRoaXMgdGFzayBxdWV1ZSBlbnN1cmVzIHRoYXQgSURCIG9wZW4gY2FsbHMgYXJlIGRvbmUgaW4gdGhlaXIgb3duIHRpY2tcbi8vIGFuZCBzZXF1ZW50aWFsbHkgLSBpLmUuIHdlIHdhaXQgZm9yIHRoZSBhc3luYyBJREIgb3BlbiB0byAqZnVsbHkqIGNvbXBsZXRlXG4vLyBiZWZvcmUgY2FsbGluZyB0aGUgbmV4dCBvbmUuIFRoaXMgd29ya3MgYXJvdW5kIElFL0VkZ2UgcmFjZSBjb25kaXRpb25zIGluIElEQi5cblxudmFyIHJ1bm5pbmcgPSBmYWxzZTtcbnZhciBxdWV1ZSA9IFtdO1xuXG5mdW5jdGlvbiB0cnlDb2RlKGZ1biwgZXJyLCByZXMsIFBvdWNoREIpIHtcbiAgdHJ5IHtcbiAgICBmdW4oZXJyLCByZXMpO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICAvLyBTaG91bGRuJ3QgaGFwcGVuLCBidXQgaW4gc29tZSBvZGQgY2FzZXNcbiAgICAvLyBJbmRleGVkREIgaW1wbGVtZW50YXRpb25zIG1pZ2h0IHRocm93IGEgc3luY1xuICAgIC8vIGVycm9yLCBpbiB3aGljaCBjYXNlIHRoaXMgd2lsbCBhdCBsZWFzdCBsb2cgaXQuXG4gICAgUG91Y2hEQi5lbWl0KCdlcnJvcicsIGVycik7XG4gIH1cbn1cblxuZnVuY3Rpb24gYXBwbHlOZXh0KCkge1xuICBpZiAocnVubmluZyB8fCAhcXVldWUubGVuZ3RoKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHJ1bm5pbmcgPSB0cnVlO1xuICBxdWV1ZS5zaGlmdCgpKCk7XG59XG5cbmZ1bmN0aW9uIGVucXVldWVUYXNrKGFjdGlvbiwgY2FsbGJhY2ssIFBvdWNoREIpIHtcbiAgcXVldWUucHVzaChmdW5jdGlvbiBydW5BY3Rpb24oKSB7XG4gICAgYWN0aW9uKGZ1bmN0aW9uIHJ1bkNhbGxiYWNrKGVyciwgcmVzKSB7XG4gICAgICB0cnlDb2RlKGNhbGxiYWNrLCBlcnIsIHJlcywgUG91Y2hEQik7XG4gICAgICBydW5uaW5nID0gZmFsc2U7XG4gICAgICBpbW1lZGlhdGUoZnVuY3Rpb24gcnVuTmV4dCgpIHtcbiAgICAgICAgYXBwbHlOZXh0KFBvdWNoREIpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuICBhcHBseU5leHQoKTtcbn1cblxudmFyIGNhY2hlZERCcyA9IG5ldyBfTWFwKCk7XG52YXIgYmxvYlN1cHBvcnRQcm9taXNlO1xudmFyIGlkYkNoYW5nZXMgPSBuZXcgQ2hhbmdlcygpO1xudmFyIG9wZW5SZXFMaXN0ID0gbmV3IF9NYXAoKTtcblxuZnVuY3Rpb24gSWRiUG91Y2gob3B0cywgY2FsbGJhY2spIHtcbiAgdmFyIGFwaSA9IHRoaXM7XG5cbiAgZW5xdWV1ZVRhc2soZnVuY3Rpb24gKHRoaXNDYWxsYmFjaykge1xuICAgIGluaXQoYXBpLCBvcHRzLCB0aGlzQ2FsbGJhY2spO1xuICB9LCBjYWxsYmFjaywgYXBpLmNvbnN0cnVjdG9yKTtcbn1cblxuZnVuY3Rpb24gaW5pdChhcGksIG9wdHMsIGNhbGxiYWNrKSB7XG5cbiAgdmFyIGRiTmFtZSA9IG9wdHMubmFtZTtcblxuICB2YXIgaWRiID0gbnVsbDtcbiAgYXBpLl9tZXRhID0gbnVsbDtcblxuICAvLyBjYWxsZWQgd2hlbiBjcmVhdGluZyBhIGZyZXNoIG5ldyBkYXRhYmFzZVxuICBmdW5jdGlvbiBjcmVhdGVTY2hlbWEoZGIpIHtcbiAgICB2YXIgZG9jU3RvcmUgPSBkYi5jcmVhdGVPYmplY3RTdG9yZShET0NfU1RPUkUsIHtrZXlQYXRoIDogJ2lkJ30pO1xuICAgIGRiLmNyZWF0ZU9iamVjdFN0b3JlKEJZX1NFUV9TVE9SRSwge2F1dG9JbmNyZW1lbnQ6IHRydWV9KVxuICAgICAgLmNyZWF0ZUluZGV4KCdfZG9jX2lkX3JldicsICdfZG9jX2lkX3JldicsIHt1bmlxdWU6IHRydWV9KTtcbiAgICBkYi5jcmVhdGVPYmplY3RTdG9yZShBVFRBQ0hfU1RPUkUsIHtrZXlQYXRoOiAnZGlnZXN0J30pO1xuICAgIGRiLmNyZWF0ZU9iamVjdFN0b3JlKE1FVEFfU1RPUkUsIHtrZXlQYXRoOiAnaWQnLCBhdXRvSW5jcmVtZW50OiBmYWxzZX0pO1xuICAgIGRiLmNyZWF0ZU9iamVjdFN0b3JlKERFVEVDVF9CTE9CX1NVUFBPUlRfU1RPUkUpO1xuXG4gICAgLy8gYWRkZWQgaW4gdjJcbiAgICBkb2NTdG9yZS5jcmVhdGVJbmRleCgnZGVsZXRlZE9yTG9jYWwnLCAnZGVsZXRlZE9yTG9jYWwnLCB7dW5pcXVlIDogZmFsc2V9KTtcblxuICAgIC8vIGFkZGVkIGluIHYzXG4gICAgZGIuY3JlYXRlT2JqZWN0U3RvcmUoTE9DQUxfU1RPUkUsIHtrZXlQYXRoOiAnX2lkJ30pO1xuXG4gICAgLy8gYWRkZWQgaW4gdjRcbiAgICB2YXIgYXR0QW5kU2VxU3RvcmUgPSBkYi5jcmVhdGVPYmplY3RTdG9yZShBVFRBQ0hfQU5EX1NFUV9TVE9SRSxcbiAgICAgIHthdXRvSW5jcmVtZW50OiB0cnVlfSk7XG4gICAgYXR0QW5kU2VxU3RvcmUuY3JlYXRlSW5kZXgoJ3NlcScsICdzZXEnKTtcbiAgICBhdHRBbmRTZXFTdG9yZS5jcmVhdGVJbmRleCgnZGlnZXN0U2VxJywgJ2RpZ2VzdFNlcScsIHt1bmlxdWU6IHRydWV9KTtcbiAgfVxuXG4gIC8vIG1pZ3JhdGlvbiB0byB2ZXJzaW9uIDJcbiAgLy8gdW5mb3J0dW5hdGVseSBcImRlbGV0ZWRPckxvY2FsXCIgaXMgYSBtaXNub21lciBub3cgdGhhdCB3ZSBubyBsb25nZXJcbiAgLy8gc3RvcmUgbG9jYWwgZG9jcyBpbiB0aGUgbWFpbiBkb2Mtc3RvcmUsIGJ1dCB3aGFkZHlhZ29ubmFkb1xuICBmdW5jdGlvbiBhZGREZWxldGVkT3JMb2NhbEluZGV4KHR4biwgY2FsbGJhY2spIHtcbiAgICB2YXIgZG9jU3RvcmUgPSB0eG4ub2JqZWN0U3RvcmUoRE9DX1NUT1JFKTtcbiAgICBkb2NTdG9yZS5jcmVhdGVJbmRleCgnZGVsZXRlZE9yTG9jYWwnLCAnZGVsZXRlZE9yTG9jYWwnLCB7dW5pcXVlIDogZmFsc2V9KTtcblxuICAgIGRvY1N0b3JlLm9wZW5DdXJzb3IoKS5vbnN1Y2Nlc3MgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgIHZhciBjdXJzb3IgPSBldmVudC50YXJnZXQucmVzdWx0O1xuICAgICAgaWYgKGN1cnNvcikge1xuICAgICAgICB2YXIgbWV0YWRhdGEgPSBjdXJzb3IudmFsdWU7XG4gICAgICAgIHZhciBkZWxldGVkID0gaXNEZWxldGVkKG1ldGFkYXRhKTtcbiAgICAgICAgbWV0YWRhdGEuZGVsZXRlZE9yTG9jYWwgPSBkZWxldGVkID8gXCIxXCIgOiBcIjBcIjtcbiAgICAgICAgZG9jU3RvcmUucHV0KG1ldGFkYXRhKTtcbiAgICAgICAgY3Vyc29yLmNvbnRpbnVlKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgfVxuICAgIH07XG4gIH1cblxuICAvLyBtaWdyYXRpb24gdG8gdmVyc2lvbiAzIChwYXJ0IDEpXG4gIGZ1bmN0aW9uIGNyZWF0ZUxvY2FsU3RvcmVTY2hlbWEoZGIpIHtcbiAgICBkYi5jcmVhdGVPYmplY3RTdG9yZShMT0NBTF9TVE9SRSwge2tleVBhdGg6ICdfaWQnfSlcbiAgICAgIC5jcmVhdGVJbmRleCgnX2RvY19pZF9yZXYnLCAnX2RvY19pZF9yZXYnLCB7dW5pcXVlOiB0cnVlfSk7XG4gIH1cblxuICAvLyBtaWdyYXRpb24gdG8gdmVyc2lvbiAzIChwYXJ0IDIpXG4gIGZ1bmN0aW9uIG1pZ3JhdGVMb2NhbFN0b3JlKHR4biwgY2IpIHtcbiAgICB2YXIgbG9jYWxTdG9yZSA9IHR4bi5vYmplY3RTdG9yZShMT0NBTF9TVE9SRSk7XG4gICAgdmFyIGRvY1N0b3JlID0gdHhuLm9iamVjdFN0b3JlKERPQ19TVE9SRSk7XG4gICAgdmFyIHNlcVN0b3JlID0gdHhuLm9iamVjdFN0b3JlKEJZX1NFUV9TVE9SRSk7XG5cbiAgICB2YXIgY3Vyc29yID0gZG9jU3RvcmUub3BlbkN1cnNvcigpO1xuICAgIGN1cnNvci5vbnN1Y2Nlc3MgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgIHZhciBjdXJzb3IgPSBldmVudC50YXJnZXQucmVzdWx0O1xuICAgICAgaWYgKGN1cnNvcikge1xuICAgICAgICB2YXIgbWV0YWRhdGEgPSBjdXJzb3IudmFsdWU7XG4gICAgICAgIHZhciBkb2NJZCA9IG1ldGFkYXRhLmlkO1xuICAgICAgICB2YXIgbG9jYWwgPSBpc0xvY2FsSWQoZG9jSWQpO1xuICAgICAgICB2YXIgcmV2ID0gd2lubmluZ1JldihtZXRhZGF0YSk7XG4gICAgICAgIGlmIChsb2NhbCkge1xuICAgICAgICAgIHZhciBkb2NJZFJldiA9IGRvY0lkICsgXCI6OlwiICsgcmV2O1xuICAgICAgICAgIC8vIHJlbW92ZSBhbGwgc2VxIGVudHJpZXNcbiAgICAgICAgICAvLyBhc3NvY2lhdGVkIHdpdGggdGhpcyBkb2NJZFxuICAgICAgICAgIHZhciBzdGFydCA9IGRvY0lkICsgXCI6OlwiO1xuICAgICAgICAgIHZhciBlbmQgPSBkb2NJZCArIFwiOjp+XCI7XG4gICAgICAgICAgdmFyIGluZGV4ID0gc2VxU3RvcmUuaW5kZXgoJ19kb2NfaWRfcmV2Jyk7XG4gICAgICAgICAgdmFyIHJhbmdlID0gSURCS2V5UmFuZ2UuYm91bmQoc3RhcnQsIGVuZCwgZmFsc2UsIGZhbHNlKTtcbiAgICAgICAgICB2YXIgc2VxQ3Vyc29yID0gaW5kZXgub3BlbkN1cnNvcihyYW5nZSk7XG4gICAgICAgICAgc2VxQ3Vyc29yLm9uc3VjY2VzcyA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICBzZXFDdXJzb3IgPSBlLnRhcmdldC5yZXN1bHQ7XG4gICAgICAgICAgICBpZiAoIXNlcUN1cnNvcikge1xuICAgICAgICAgICAgICAvLyBkb25lXG4gICAgICAgICAgICAgIGRvY1N0b3JlLmRlbGV0ZShjdXJzb3IucHJpbWFyeUtleSk7XG4gICAgICAgICAgICAgIGN1cnNvci5jb250aW51ZSgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdmFyIGRhdGEgPSBzZXFDdXJzb3IudmFsdWU7XG4gICAgICAgICAgICAgIGlmIChkYXRhLl9kb2NfaWRfcmV2ID09PSBkb2NJZFJldikge1xuICAgICAgICAgICAgICAgIGxvY2FsU3RvcmUucHV0KGRhdGEpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHNlcVN0b3JlLmRlbGV0ZShzZXFDdXJzb3IucHJpbWFyeUtleSk7XG4gICAgICAgICAgICAgIHNlcUN1cnNvci5jb250aW51ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY3Vyc29yLmNvbnRpbnVlKCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoY2IpIHtcbiAgICAgICAgY2IoKTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgLy8gbWlncmF0aW9uIHRvIHZlcnNpb24gNCAocGFydCAxKVxuICBmdW5jdGlvbiBhZGRBdHRhY2hBbmRTZXFTdG9yZShkYikge1xuICAgIHZhciBhdHRBbmRTZXFTdG9yZSA9IGRiLmNyZWF0ZU9iamVjdFN0b3JlKEFUVEFDSF9BTkRfU0VRX1NUT1JFLFxuICAgICAge2F1dG9JbmNyZW1lbnQ6IHRydWV9KTtcbiAgICBhdHRBbmRTZXFTdG9yZS5jcmVhdGVJbmRleCgnc2VxJywgJ3NlcScpO1xuICAgIGF0dEFuZFNlcVN0b3JlLmNyZWF0ZUluZGV4KCdkaWdlc3RTZXEnLCAnZGlnZXN0U2VxJywge3VuaXF1ZTogdHJ1ZX0pO1xuICB9XG5cbiAgLy8gbWlncmF0aW9uIHRvIHZlcnNpb24gNCAocGFydCAyKVxuICBmdW5jdGlvbiBtaWdyYXRlQXR0c0FuZFNlcXModHhuLCBjYWxsYmFjaykge1xuICAgIHZhciBzZXFTdG9yZSA9IHR4bi5vYmplY3RTdG9yZShCWV9TRVFfU1RPUkUpO1xuICAgIHZhciBhdHRTdG9yZSA9IHR4bi5vYmplY3RTdG9yZShBVFRBQ0hfU1RPUkUpO1xuICAgIHZhciBhdHRBbmRTZXFTdG9yZSA9IHR4bi5vYmplY3RTdG9yZShBVFRBQ0hfQU5EX1NFUV9TVE9SRSk7XG5cbiAgICAvLyBuZWVkIHRvIGFjdHVhbGx5IHBvcHVsYXRlIHRoZSB0YWJsZS4gdGhpcyBpcyB0aGUgZXhwZW5zaXZlIHBhcnQsXG4gICAgLy8gc28gYXMgYW4gb3B0aW1pemF0aW9uLCBjaGVjayBmaXJzdCB0aGF0IHRoaXMgZGF0YWJhc2UgZXZlblxuICAgIC8vIGNvbnRhaW5zIGF0dGFjaG1lbnRzXG4gICAgdmFyIHJlcSA9IGF0dFN0b3JlLmNvdW50KCk7XG4gICAgcmVxLm9uc3VjY2VzcyA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICB2YXIgY291bnQgPSBlLnRhcmdldC5yZXN1bHQ7XG4gICAgICBpZiAoIWNvdW50KSB7XG4gICAgICAgIHJldHVybiBjYWxsYmFjaygpOyAvLyBkb25lXG4gICAgICB9XG5cbiAgICAgIHNlcVN0b3JlLm9wZW5DdXJzb3IoKS5vbnN1Y2Nlc3MgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIgY3Vyc29yID0gZS50YXJnZXQucmVzdWx0O1xuICAgICAgICBpZiAoIWN1cnNvcikge1xuICAgICAgICAgIHJldHVybiBjYWxsYmFjaygpOyAvLyBkb25lXG4gICAgICAgIH1cbiAgICAgICAgdmFyIGRvYyA9IGN1cnNvci52YWx1ZTtcbiAgICAgICAgdmFyIHNlcSA9IGN1cnNvci5wcmltYXJ5S2V5O1xuICAgICAgICB2YXIgYXR0cyA9IE9iamVjdC5rZXlzKGRvYy5fYXR0YWNobWVudHMgfHwge30pO1xuICAgICAgICB2YXIgZGlnZXN0TWFwID0ge307XG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgYXR0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgIHZhciBhdHQgPSBkb2MuX2F0dGFjaG1lbnRzW2F0dHNbal1dO1xuICAgICAgICAgIGRpZ2VzdE1hcFthdHQuZGlnZXN0XSA9IHRydWU7IC8vIHVuaXEgZGlnZXN0cywganVzdCBpbiBjYXNlXG4gICAgICAgIH1cbiAgICAgICAgdmFyIGRpZ2VzdHMgPSBPYmplY3Qua2V5cyhkaWdlc3RNYXApO1xuICAgICAgICBmb3IgKGogPSAwOyBqIDwgZGlnZXN0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgIHZhciBkaWdlc3QgPSBkaWdlc3RzW2pdO1xuICAgICAgICAgIGF0dEFuZFNlcVN0b3JlLnB1dCh7XG4gICAgICAgICAgICBzZXE6IHNlcSxcbiAgICAgICAgICAgIGRpZ2VzdFNlcTogZGlnZXN0ICsgJzo6JyArIHNlcVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGN1cnNvci5jb250aW51ZSgpO1xuICAgICAgfTtcbiAgICB9O1xuICB9XG5cbiAgLy8gbWlncmF0aW9uIHRvIHZlcnNpb24gNVxuICAvLyBJbnN0ZWFkIG9mIHJlbHlpbmcgb24gb24tdGhlLWZseSBtaWdyYXRpb24gb2YgbWV0YWRhdGEsXG4gIC8vIHRoaXMgYnJpbmdzIHRoZSBkb2Mtc3RvcmUgdG8gaXRzIG1vZGVybiBmb3JtOlxuICAvLyAtIG1ldGFkYXRhLndpbm5pbmdyZXZcbiAgLy8gLSBtZXRhZGF0YS5zZXFcbiAgLy8gLSBzdHJpbmdpZnkgdGhlIG1ldGFkYXRhIHdoZW4gc3RvcmluZyBpdFxuICBmdW5jdGlvbiBtaWdyYXRlTWV0YWRhdGEodHhuKSB7XG5cbiAgICBmdW5jdGlvbiBkZWNvZGVNZXRhZGF0YUNvbXBhdChzdG9yZWRPYmplY3QpIHtcbiAgICAgIGlmICghc3RvcmVkT2JqZWN0LmRhdGEpIHtcbiAgICAgICAgLy8gb2xkIGZvcm1hdCwgd2hlbiB3ZSBkaWRuJ3Qgc3RvcmUgaXQgc3RyaW5naWZpZWRcbiAgICAgICAgc3RvcmVkT2JqZWN0LmRlbGV0ZWQgPSBzdG9yZWRPYmplY3QuZGVsZXRlZE9yTG9jYWwgPT09ICcxJztcbiAgICAgICAgcmV0dXJuIHN0b3JlZE9iamVjdDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBkZWNvZGVNZXRhZGF0YShzdG9yZWRPYmplY3QpO1xuICAgIH1cblxuICAgIC8vIGVuc3VyZSB0aGF0IGV2ZXJ5IG1ldGFkYXRhIGhhcyBhIHdpbm5pbmdSZXYgYW5kIHNlcSxcbiAgICAvLyB3aGljaCB3YXMgcHJldmlvdXNseSBjcmVhdGVkIG9uLXRoZS1mbHkgYnV0IGJldHRlciB0byBtaWdyYXRlXG4gICAgdmFyIGJ5U2VxU3RvcmUgPSB0eG4ub2JqZWN0U3RvcmUoQllfU0VRX1NUT1JFKTtcbiAgICB2YXIgZG9jU3RvcmUgPSB0eG4ub2JqZWN0U3RvcmUoRE9DX1NUT1JFKTtcbiAgICB2YXIgY3Vyc29yID0gZG9jU3RvcmUub3BlbkN1cnNvcigpO1xuICAgIGN1cnNvci5vbnN1Y2Nlc3MgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgdmFyIGN1cnNvciA9IGUudGFyZ2V0LnJlc3VsdDtcbiAgICAgIGlmICghY3Vyc29yKSB7XG4gICAgICAgIHJldHVybjsgLy8gZG9uZVxuICAgICAgfVxuICAgICAgdmFyIG1ldGFkYXRhID0gZGVjb2RlTWV0YWRhdGFDb21wYXQoY3Vyc29yLnZhbHVlKTtcblxuICAgICAgbWV0YWRhdGEud2lubmluZ1JldiA9IG1ldGFkYXRhLndpbm5pbmdSZXYgfHxcbiAgICAgICAgd2lubmluZ1JldihtZXRhZGF0YSk7XG5cbiAgICAgIGZ1bmN0aW9uIGZldGNoTWV0YWRhdGFTZXEoKSB7XG4gICAgICAgIC8vIG1ldGFkYXRhLnNlcSB3YXMgYWRkZWQgcG9zdC0zLjIuMCwgc28gaWYgaXQncyBtaXNzaW5nLFxuICAgICAgICAvLyB3ZSBuZWVkIHRvIGZldGNoIGl0IG1hbnVhbGx5XG4gICAgICAgIHZhciBzdGFydCA9IG1ldGFkYXRhLmlkICsgJzo6JztcbiAgICAgICAgdmFyIGVuZCA9IG1ldGFkYXRhLmlkICsgJzo6XFx1ZmZmZic7XG4gICAgICAgIHZhciByZXEgPSBieVNlcVN0b3JlLmluZGV4KCdfZG9jX2lkX3JldicpLm9wZW5DdXJzb3IoXG4gICAgICAgICAgSURCS2V5UmFuZ2UuYm91bmQoc3RhcnQsIGVuZCkpO1xuXG4gICAgICAgIHZhciBtZXRhZGF0YVNlcSA9IDA7XG4gICAgICAgIHJlcS5vbnN1Y2Nlc3MgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgIHZhciBjdXJzb3IgPSBlLnRhcmdldC5yZXN1bHQ7XG4gICAgICAgICAgaWYgKCFjdXJzb3IpIHtcbiAgICAgICAgICAgIG1ldGFkYXRhLnNlcSA9IG1ldGFkYXRhU2VxO1xuICAgICAgICAgICAgcmV0dXJuIG9uR2V0TWV0YWRhdGFTZXEoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIHNlcSA9IGN1cnNvci5wcmltYXJ5S2V5O1xuICAgICAgICAgIGlmIChzZXEgPiBtZXRhZGF0YVNlcSkge1xuICAgICAgICAgICAgbWV0YWRhdGFTZXEgPSBzZXE7XG4gICAgICAgICAgfVxuICAgICAgICAgIGN1cnNvci5jb250aW51ZSgpO1xuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBvbkdldE1ldGFkYXRhU2VxKCkge1xuICAgICAgICB2YXIgbWV0YWRhdGFUb1N0b3JlID0gZW5jb2RlTWV0YWRhdGEobWV0YWRhdGEsXG4gICAgICAgICAgbWV0YWRhdGEud2lubmluZ1JldiwgbWV0YWRhdGEuZGVsZXRlZCk7XG5cbiAgICAgICAgdmFyIHJlcSA9IGRvY1N0b3JlLnB1dChtZXRhZGF0YVRvU3RvcmUpO1xuICAgICAgICByZXEub25zdWNjZXNzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGN1cnNvci5jb250aW51ZSgpO1xuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBpZiAobWV0YWRhdGEuc2VxKSB7XG4gICAgICAgIHJldHVybiBvbkdldE1ldGFkYXRhU2VxKCk7XG4gICAgICB9XG5cbiAgICAgIGZldGNoTWV0YWRhdGFTZXEoKTtcbiAgICB9O1xuXG4gIH1cblxuICBhcGkudHlwZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gJ2lkYic7XG4gIH07XG5cbiAgYXBpLl9pZCA9IHRvUHJvbWlzZShmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayhudWxsLCBhcGkuX21ldGEuaW5zdGFuY2VJZCk7XG4gIH0pO1xuXG4gIGFwaS5fYnVsa0RvY3MgPSBmdW5jdGlvbiBpZGJfYnVsa0RvY3MocmVxLCByZXFPcHRzLCBjYWxsYmFjaykge1xuICAgIGlkYkJ1bGtEb2NzKG9wdHMsIHJlcSwgcmVxT3B0cywgYXBpLCBpZGIsIGlkYkNoYW5nZXMsIGNhbGxiYWNrKTtcbiAgfTtcblxuICAvLyBGaXJzdCB3ZSBsb29rIHVwIHRoZSBtZXRhZGF0YSBpbiB0aGUgaWRzIGRhdGFiYXNlLCB0aGVuIHdlIGZldGNoIHRoZVxuICAvLyBjdXJyZW50IHJldmlzaW9uKHMpIGZyb20gdGhlIGJ5IHNlcXVlbmNlIHN0b3JlXG4gIGFwaS5fZ2V0ID0gZnVuY3Rpb24gaWRiX2dldChpZCwgb3B0cywgY2FsbGJhY2spIHtcbiAgICB2YXIgZG9jO1xuICAgIHZhciBtZXRhZGF0YTtcbiAgICB2YXIgZXJyO1xuICAgIHZhciB0eG4gPSBvcHRzLmN0eDtcbiAgICBpZiAoIXR4bikge1xuICAgICAgdmFyIHR4blJlc3VsdCA9IG9wZW5UcmFuc2FjdGlvblNhZmVseShpZGIsXG4gICAgICAgIFtET0NfU1RPUkUsIEJZX1NFUV9TVE9SRSwgQVRUQUNIX1NUT1JFXSwgJ3JlYWRvbmx5Jyk7XG4gICAgICBpZiAodHhuUmVzdWx0LmVycm9yKSB7XG4gICAgICAgIHJldHVybiBjYWxsYmFjayh0eG5SZXN1bHQuZXJyb3IpO1xuICAgICAgfVxuICAgICAgdHhuID0gdHhuUmVzdWx0LnR4bjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmaW5pc2goKSB7XG4gICAgICBjYWxsYmFjayhlcnIsIHtkb2M6IGRvYywgbWV0YWRhdGE6IG1ldGFkYXRhLCBjdHg6IHR4bn0pO1xuICAgIH1cblxuICAgIHR4bi5vYmplY3RTdG9yZShET0NfU1RPUkUpLmdldChpZCkub25zdWNjZXNzID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgIG1ldGFkYXRhID0gZGVjb2RlTWV0YWRhdGEoZS50YXJnZXQucmVzdWx0KTtcbiAgICAgIC8vIHdlIGNhbiBkZXRlcm1pbmUgdGhlIHJlc3VsdCBoZXJlIGlmOlxuICAgICAgLy8gMS4gdGhlcmUgaXMgbm8gc3VjaCBkb2N1bWVudFxuICAgICAgLy8gMi4gdGhlIGRvY3VtZW50IGlzIGRlbGV0ZWQgYW5kIHdlIGRvbid0IGFzayBhYm91dCBzcGVjaWZpYyByZXZcbiAgICAgIC8vIFdoZW4gd2UgYXNrIHdpdGggb3B0cy5yZXYgd2UgZXhwZWN0IHRoZSBhbnN3ZXIgdG8gYmUgZWl0aGVyXG4gICAgICAvLyBkb2MgKHBvc3NpYmx5IHdpdGggX2RlbGV0ZWQ9dHJ1ZSkgb3IgbWlzc2luZyBlcnJvclxuICAgICAgaWYgKCFtZXRhZGF0YSkge1xuICAgICAgICBlcnIgPSBjcmVhdGVFcnJvcihNSVNTSU5HX0RPQywgJ21pc3NpbmcnKTtcbiAgICAgICAgcmV0dXJuIGZpbmlzaCgpO1xuICAgICAgfVxuXG4gICAgICB2YXIgcmV2O1xuICAgICAgaWYoIW9wdHMucmV2KSB7XG4gICAgICAgIHJldiA9IG1ldGFkYXRhLndpbm5pbmdSZXY7XG4gICAgICAgIHZhciBkZWxldGVkID0gaXNEZWxldGVkKG1ldGFkYXRhKTtcbiAgICAgICAgaWYgKGRlbGV0ZWQpIHtcbiAgICAgICAgICBlcnIgPSBjcmVhdGVFcnJvcihNSVNTSU5HX0RPQywgXCJkZWxldGVkXCIpO1xuICAgICAgICAgIHJldHVybiBmaW5pc2goKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV2ID0gb3B0cy5sYXRlc3QgPyBsYXRlc3Qob3B0cy5yZXYsIG1ldGFkYXRhKSA6IG9wdHMucmV2O1xuICAgICAgfVxuXG4gICAgICB2YXIgb2JqZWN0U3RvcmUgPSB0eG4ub2JqZWN0U3RvcmUoQllfU0VRX1NUT1JFKTtcbiAgICAgIHZhciBrZXkgPSBtZXRhZGF0YS5pZCArICc6OicgKyByZXY7XG5cbiAgICAgIG9iamVjdFN0b3JlLmluZGV4KCdfZG9jX2lkX3JldicpLmdldChrZXkpLm9uc3VjY2VzcyA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGRvYyA9IGUudGFyZ2V0LnJlc3VsdDtcbiAgICAgICAgaWYgKGRvYykge1xuICAgICAgICAgIGRvYyA9IGRlY29kZURvYyhkb2MpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghZG9jKSB7XG4gICAgICAgICAgZXJyID0gY3JlYXRlRXJyb3IoTUlTU0lOR19ET0MsICdtaXNzaW5nJyk7XG4gICAgICAgICAgcmV0dXJuIGZpbmlzaCgpO1xuICAgICAgICB9XG4gICAgICAgIGZpbmlzaCgpO1xuICAgICAgfTtcbiAgICB9O1xuICB9O1xuXG4gIGFwaS5fZ2V0QXR0YWNobWVudCA9IGZ1bmN0aW9uIChkb2NJZCwgYXR0YWNoSWQsIGF0dGFjaG1lbnQsIG9wdHMsIGNhbGxiYWNrKSB7XG4gICAgdmFyIHR4bjtcbiAgICBpZiAob3B0cy5jdHgpIHtcbiAgICAgIHR4biA9IG9wdHMuY3R4O1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgdHhuUmVzdWx0ID0gb3BlblRyYW5zYWN0aW9uU2FmZWx5KGlkYixcbiAgICAgICAgW0RPQ19TVE9SRSwgQllfU0VRX1NUT1JFLCBBVFRBQ0hfU1RPUkVdLCAncmVhZG9ubHknKTtcbiAgICAgIGlmICh0eG5SZXN1bHQuZXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKHR4blJlc3VsdC5lcnJvcik7XG4gICAgICB9XG4gICAgICB0eG4gPSB0eG5SZXN1bHQudHhuO1xuICAgIH1cbiAgICB2YXIgZGlnZXN0ID0gYXR0YWNobWVudC5kaWdlc3Q7XG4gICAgdmFyIHR5cGUgPSBhdHRhY2htZW50LmNvbnRlbnRfdHlwZTtcblxuICAgIHR4bi5vYmplY3RTdG9yZShBVFRBQ0hfU1RPUkUpLmdldChkaWdlc3QpLm9uc3VjY2VzcyA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICB2YXIgYm9keSA9IGUudGFyZ2V0LnJlc3VsdC5ib2R5O1xuICAgICAgcmVhZEJsb2JEYXRhKGJvZHksIHR5cGUsIG9wdHMuYmluYXJ5LCBmdW5jdGlvbiAoYmxvYkRhdGEpIHtcbiAgICAgICAgY2FsbGJhY2sobnVsbCwgYmxvYkRhdGEpO1xuICAgICAgfSk7XG4gICAgfTtcbiAgfTtcblxuICBhcGkuX2luZm8gPSBmdW5jdGlvbiBpZGJfaW5mbyhjYWxsYmFjaykge1xuXG4gICAgaWYgKGlkYiA9PT0gbnVsbCB8fCAhY2FjaGVkREJzLmhhcyhkYk5hbWUpKSB7XG4gICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ2RiIGlzblxcJ3Qgb3BlbicpO1xuICAgICAgZXJyb3IuaWQgPSAnaWRiTnVsbCc7XG4gICAgICByZXR1cm4gY2FsbGJhY2soZXJyb3IpO1xuICAgIH1cbiAgICB2YXIgdXBkYXRlU2VxO1xuICAgIHZhciBkb2NDb3VudDtcblxuICAgIHZhciB0eG5SZXN1bHQgPSBvcGVuVHJhbnNhY3Rpb25TYWZlbHkoaWRiLCBbQllfU0VRX1NUT1JFXSwgJ3JlYWRvbmx5Jyk7XG4gICAgaWYgKHR4blJlc3VsdC5lcnJvcikge1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKHR4blJlc3VsdC5lcnJvcik7XG4gICAgfVxuICAgIHZhciB0eG4gPSB0eG5SZXN1bHQudHhuO1xuICAgIHZhciBjdXJzb3IgPSB0eG4ub2JqZWN0U3RvcmUoQllfU0VRX1NUT1JFKS5vcGVuQ3Vyc29yKG51bGwsICdwcmV2Jyk7XG4gICAgY3Vyc29yLm9uc3VjY2VzcyA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgdmFyIGN1cnNvciA9IGV2ZW50LnRhcmdldC5yZXN1bHQ7XG4gICAgICB1cGRhdGVTZXEgPSBjdXJzb3IgPyBjdXJzb3Iua2V5IDogMDtcbiAgICAgIC8vIGNvdW50IHdpdGhpbiB0aGUgc2FtZSB0eG4gZm9yIGNvbnNpc3RlbmN5XG4gICAgICBkb2NDb3VudCA9IGFwaS5fbWV0YS5kb2NDb3VudDtcbiAgICB9O1xuXG4gICAgdHhuLm9uY29tcGxldGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICBjYWxsYmFjayhudWxsLCB7XG4gICAgICAgIGRvY19jb3VudDogZG9jQ291bnQsXG4gICAgICAgIHVwZGF0ZV9zZXE6IHVwZGF0ZVNlcSxcbiAgICAgICAgLy8gZm9yIGRlYnVnZ2luZ1xuICAgICAgICBpZGJfYXR0YWNobWVudF9mb3JtYXQ6IChhcGkuX21ldGEuYmxvYlN1cHBvcnQgPyAnYmluYXJ5JyA6ICdiYXNlNjQnKVxuICAgICAgfSk7XG4gICAgfTtcbiAgfTtcblxuICBhcGkuX2FsbERvY3MgPSBmdW5jdGlvbiBpZGJfYWxsRG9jcyhvcHRzLCBjYWxsYmFjaykge1xuICAgIGlkYkFsbERvY3Mob3B0cywgYXBpLCBpZGIsIGNhbGxiYWNrKTtcbiAgfTtcblxuICBhcGkuX2NoYW5nZXMgPSBmdW5jdGlvbiAob3B0cykge1xuICAgIG9wdHMgPSBjbG9uZShvcHRzKTtcblxuICAgIGlmIChvcHRzLmNvbnRpbnVvdXMpIHtcbiAgICAgIHZhciBpZCA9IGRiTmFtZSArICc6JyArIHV1aWQoKTtcbiAgICAgIGlkYkNoYW5nZXMuYWRkTGlzdGVuZXIoZGJOYW1lLCBpZCwgYXBpLCBvcHRzKTtcbiAgICAgIGlkYkNoYW5nZXMubm90aWZ5KGRiTmFtZSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjYW5jZWw6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBpZGJDaGFuZ2VzLnJlbW92ZUxpc3RlbmVyKGRiTmFtZSwgaWQpO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cblxuICAgIHZhciBkb2NJZHMgPSBvcHRzLmRvY19pZHMgJiYgbmV3IF9TZXQob3B0cy5kb2NfaWRzKTtcblxuICAgIG9wdHMuc2luY2UgPSBvcHRzLnNpbmNlIHx8IDA7XG4gICAgdmFyIGxhc3RTZXEgPSBvcHRzLnNpbmNlO1xuXG4gICAgdmFyIGxpbWl0ID0gJ2xpbWl0JyBpbiBvcHRzID8gb3B0cy5saW1pdCA6IC0xO1xuICAgIGlmIChsaW1pdCA9PT0gMCkge1xuICAgICAgbGltaXQgPSAxOyAvLyBwZXIgQ291Y2hEQiBfY2hhbmdlcyBzcGVjXG4gICAgfVxuICAgIHZhciByZXR1cm5Eb2NzO1xuICAgIGlmICgncmV0dXJuX2RvY3MnIGluIG9wdHMpIHtcbiAgICAgIHJldHVybkRvY3MgPSBvcHRzLnJldHVybl9kb2NzO1xuICAgIH0gZWxzZSBpZiAoJ3JldHVybkRvY3MnIGluIG9wdHMpIHtcbiAgICAgIC8vIFRPRE86IFJlbW92ZSAncmV0dXJuRG9jcycgaW4gZmF2b3Igb2YgJ3JldHVybl9kb2NzJyBpbiBhIGZ1dHVyZSByZWxlYXNlXG4gICAgICByZXR1cm5Eb2NzID0gb3B0cy5yZXR1cm5Eb2NzO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm5Eb2NzID0gdHJ1ZTtcbiAgICB9XG5cbiAgICB2YXIgcmVzdWx0cyA9IFtdO1xuICAgIHZhciBudW1SZXN1bHRzID0gMDtcbiAgICB2YXIgZmlsdGVyID0gZmlsdGVyQ2hhbmdlKG9wdHMpO1xuICAgIHZhciBkb2NJZHNUb01ldGFkYXRhID0gbmV3IF9NYXAoKTtcblxuICAgIHZhciB0eG47XG4gICAgdmFyIGJ5U2VxU3RvcmU7XG4gICAgdmFyIGRvY1N0b3JlO1xuICAgIHZhciBkb2NJZFJldkluZGV4O1xuXG4gICAgZnVuY3Rpb24gb25HZXRDdXJzb3IoY3Vyc29yKSB7XG5cbiAgICAgIHZhciBkb2MgPSBkZWNvZGVEb2MoY3Vyc29yLnZhbHVlKTtcbiAgICAgIHZhciBzZXEgPSBjdXJzb3Iua2V5O1xuXG4gICAgICBpZiAoZG9jSWRzICYmICFkb2NJZHMuaGFzKGRvYy5faWQpKSB7XG4gICAgICAgIHJldHVybiBjdXJzb3IuY29udGludWUoKTtcbiAgICAgIH1cblxuICAgICAgdmFyIG1ldGFkYXRhO1xuXG4gICAgICBmdW5jdGlvbiBvbkdldE1ldGFkYXRhKCkge1xuICAgICAgICBpZiAobWV0YWRhdGEuc2VxICE9PSBzZXEpIHtcbiAgICAgICAgICAvLyBzb21lIG90aGVyIHNlcSBpcyBsYXRlclxuICAgICAgICAgIHJldHVybiBjdXJzb3IuY29udGludWUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxhc3RTZXEgPSBzZXE7XG5cbiAgICAgICAgaWYgKG1ldGFkYXRhLndpbm5pbmdSZXYgPT09IGRvYy5fcmV2KSB7XG4gICAgICAgICAgcmV0dXJuIG9uR2V0V2lubmluZ0RvYyhkb2MpO1xuICAgICAgICB9XG5cbiAgICAgICAgZmV0Y2hXaW5uaW5nRG9jKCk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIGZldGNoV2lubmluZ0RvYygpIHtcbiAgICAgICAgdmFyIGRvY0lkUmV2ID0gZG9jLl9pZCArICc6OicgKyBtZXRhZGF0YS53aW5uaW5nUmV2O1xuICAgICAgICB2YXIgcmVxID0gZG9jSWRSZXZJbmRleC5nZXQoZG9jSWRSZXYpO1xuICAgICAgICByZXEub25zdWNjZXNzID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICBvbkdldFdpbm5pbmdEb2MoZGVjb2RlRG9jKGUudGFyZ2V0LnJlc3VsdCkpO1xuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBvbkdldFdpbm5pbmdEb2Mod2lubmluZ0RvYykge1xuXG4gICAgICAgIHZhciBjaGFuZ2UgPSBvcHRzLnByb2Nlc3NDaGFuZ2Uod2lubmluZ0RvYywgbWV0YWRhdGEsIG9wdHMpO1xuICAgICAgICBjaGFuZ2Uuc2VxID0gbWV0YWRhdGEuc2VxO1xuXG4gICAgICAgIHZhciBmaWx0ZXJlZCA9IGZpbHRlcihjaGFuZ2UpO1xuICAgICAgICBpZiAodHlwZW9mIGZpbHRlcmVkID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgIHJldHVybiBvcHRzLmNvbXBsZXRlKGZpbHRlcmVkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmaWx0ZXJlZCkge1xuICAgICAgICAgIG51bVJlc3VsdHMrKztcbiAgICAgICAgICBpZiAocmV0dXJuRG9jcykge1xuICAgICAgICAgICAgcmVzdWx0cy5wdXNoKGNoYW5nZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIHByb2Nlc3MgdGhlIGF0dGFjaG1lbnQgaW1tZWRpYXRlbHlcbiAgICAgICAgICAvLyBmb3IgdGhlIGJlbmVmaXQgb2YgbGl2ZSBsaXN0ZW5lcnNcbiAgICAgICAgICBpZiAob3B0cy5hdHRhY2htZW50cyAmJiBvcHRzLmluY2x1ZGVfZG9jcykge1xuICAgICAgICAgICAgZmV0Y2hBdHRhY2htZW50c0lmTmVjZXNzYXJ5KHdpbm5pbmdEb2MsIG9wdHMsIHR4biwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICBwb3N0UHJvY2Vzc0F0dGFjaG1lbnRzKFtjaGFuZ2VdLCBvcHRzLmJpbmFyeSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgb3B0cy5vbkNoYW5nZShjaGFuZ2UpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvcHRzLm9uQ2hhbmdlKGNoYW5nZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChudW1SZXN1bHRzICE9PSBsaW1pdCkge1xuICAgICAgICAgIGN1cnNvci5jb250aW51ZSgpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIG1ldGFkYXRhID0gZG9jSWRzVG9NZXRhZGF0YS5nZXQoZG9jLl9pZCk7XG4gICAgICBpZiAobWV0YWRhdGEpIHsgLy8gY2FjaGVkXG4gICAgICAgIHJldHVybiBvbkdldE1ldGFkYXRhKCk7XG4gICAgICB9XG4gICAgICAvLyBtZXRhZGF0YSBub3QgY2FjaGVkLCBoYXZlIHRvIGdvIGZldGNoIGl0XG4gICAgICBkb2NTdG9yZS5nZXQoZG9jLl9pZCkub25zdWNjZXNzID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIG1ldGFkYXRhID0gZGVjb2RlTWV0YWRhdGEoZXZlbnQudGFyZ2V0LnJlc3VsdCk7XG4gICAgICAgIGRvY0lkc1RvTWV0YWRhdGEuc2V0KGRvYy5faWQsIG1ldGFkYXRhKTtcbiAgICAgICAgb25HZXRNZXRhZGF0YSgpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBvbnN1Y2Nlc3MoZXZlbnQpIHtcbiAgICAgIHZhciBjdXJzb3IgPSBldmVudC50YXJnZXQucmVzdWx0O1xuXG4gICAgICBpZiAoIWN1cnNvcikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBvbkdldEN1cnNvcihjdXJzb3IpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZldGNoQ2hhbmdlcygpIHtcbiAgICAgIHZhciBvYmplY3RTdG9yZXMgPSBbRE9DX1NUT1JFLCBCWV9TRVFfU1RPUkVdO1xuICAgICAgaWYgKG9wdHMuYXR0YWNobWVudHMpIHtcbiAgICAgICAgb2JqZWN0U3RvcmVzLnB1c2goQVRUQUNIX1NUT1JFKTtcbiAgICAgIH1cbiAgICAgIHZhciB0eG5SZXN1bHQgPSBvcGVuVHJhbnNhY3Rpb25TYWZlbHkoaWRiLCBvYmplY3RTdG9yZXMsICdyZWFkb25seScpO1xuICAgICAgaWYgKHR4blJlc3VsdC5lcnJvcikge1xuICAgICAgICByZXR1cm4gb3B0cy5jb21wbGV0ZSh0eG5SZXN1bHQuZXJyb3IpO1xuICAgICAgfVxuICAgICAgdHhuID0gdHhuUmVzdWx0LnR4bjtcbiAgICAgIHR4bi5vbmFib3J0ID0gaWRiRXJyb3Iob3B0cy5jb21wbGV0ZSk7XG4gICAgICB0eG4ub25jb21wbGV0ZSA9IG9uVHhuQ29tcGxldGU7XG5cbiAgICAgIGJ5U2VxU3RvcmUgPSB0eG4ub2JqZWN0U3RvcmUoQllfU0VRX1NUT1JFKTtcbiAgICAgIGRvY1N0b3JlID0gdHhuLm9iamVjdFN0b3JlKERPQ19TVE9SRSk7XG4gICAgICBkb2NJZFJldkluZGV4ID0gYnlTZXFTdG9yZS5pbmRleCgnX2RvY19pZF9yZXYnKTtcblxuICAgICAgdmFyIHJlcTtcblxuICAgICAgaWYgKG9wdHMuZGVzY2VuZGluZykge1xuICAgICAgICByZXEgPSBieVNlcVN0b3JlLm9wZW5DdXJzb3IobnVsbCwgJ3ByZXYnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlcSA9IGJ5U2VxU3RvcmUub3BlbkN1cnNvcihJREJLZXlSYW5nZS5sb3dlckJvdW5kKG9wdHMuc2luY2UsIHRydWUpKTtcbiAgICAgIH1cblxuICAgICAgcmVxLm9uc3VjY2VzcyA9IG9uc3VjY2VzcztcbiAgICB9XG5cbiAgICBmZXRjaENoYW5nZXMoKTtcblxuICAgIGZ1bmN0aW9uIG9uVHhuQ29tcGxldGUoKSB7XG5cbiAgICAgIGZ1bmN0aW9uIGZpbmlzaCgpIHtcbiAgICAgICAgb3B0cy5jb21wbGV0ZShudWxsLCB7XG4gICAgICAgICAgcmVzdWx0czogcmVzdWx0cyxcbiAgICAgICAgICBsYXN0X3NlcTogbGFzdFNlcVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFvcHRzLmNvbnRpbnVvdXMgJiYgb3B0cy5hdHRhY2htZW50cykge1xuICAgICAgICAvLyBjYW5ub3QgZ3VhcmFudGVlIHRoYXQgcG9zdFByb2Nlc3Npbmcgd2FzIGFscmVhZHkgZG9uZSxcbiAgICAgICAgLy8gc28gZG8gaXQgYWdhaW5cbiAgICAgICAgcG9zdFByb2Nlc3NBdHRhY2htZW50cyhyZXN1bHRzKS50aGVuKGZpbmlzaCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBmaW5pc2goKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgYXBpLl9jbG9zZSA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIGlmIChpZGIgPT09IG51bGwpIHtcbiAgICAgIHJldHVybiBjYWxsYmFjayhjcmVhdGVFcnJvcihOT1RfT1BFTikpO1xuICAgIH1cblxuICAgIC8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvSW5kZXhlZERCL0lEQkRhdGFiYXNlI2Nsb3NlXG4gICAgLy8gXCJSZXR1cm5zIGltbWVkaWF0ZWx5IGFuZCBjbG9zZXMgdGhlIGNvbm5lY3Rpb24gaW4gYSBzZXBhcmF0ZSB0aHJlYWQuLi5cIlxuICAgIGlkYi5jbG9zZSgpO1xuICAgIGNhY2hlZERCcy5kZWxldGUoZGJOYW1lKTtcbiAgICBpZGIgPSBudWxsO1xuICAgIGNhbGxiYWNrKCk7XG4gIH07XG5cbiAgYXBpLl9nZXRSZXZpc2lvblRyZWUgPSBmdW5jdGlvbiAoZG9jSWQsIGNhbGxiYWNrKSB7XG4gICAgdmFyIHR4blJlc3VsdCA9IG9wZW5UcmFuc2FjdGlvblNhZmVseShpZGIsIFtET0NfU1RPUkVdLCAncmVhZG9ubHknKTtcbiAgICBpZiAodHhuUmVzdWx0LmVycm9yKSB7XG4gICAgICByZXR1cm4gY2FsbGJhY2sodHhuUmVzdWx0LmVycm9yKTtcbiAgICB9XG4gICAgdmFyIHR4biA9IHR4blJlc3VsdC50eG47XG4gICAgdmFyIHJlcSA9IHR4bi5vYmplY3RTdG9yZShET0NfU1RPUkUpLmdldChkb2NJZCk7XG4gICAgcmVxLm9uc3VjY2VzcyA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgdmFyIGRvYyA9IGRlY29kZU1ldGFkYXRhKGV2ZW50LnRhcmdldC5yZXN1bHQpO1xuICAgICAgaWYgKCFkb2MpIHtcbiAgICAgICAgY2FsbGJhY2soY3JlYXRlRXJyb3IoTUlTU0lOR19ET0MpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIGRvYy5yZXZfdHJlZSk7XG4gICAgICB9XG4gICAgfTtcbiAgfTtcblxuICAvLyBUaGlzIGZ1bmN0aW9uIHJlbW92ZXMgcmV2aXNpb25zIG9mIGRvY3VtZW50IGRvY0lkXG4gIC8vIHdoaWNoIGFyZSBsaXN0ZWQgaW4gcmV2cyBhbmQgc2V0cyB0aGlzIGRvY3VtZW50XG4gIC8vIHJldmlzaW9uIHRvIHRvIHJldl90cmVlXG4gIGFwaS5fZG9Db21wYWN0aW9uID0gZnVuY3Rpb24gKGRvY0lkLCByZXZzLCBjYWxsYmFjaykge1xuICAgIHZhciBzdG9yZXMgPSBbXG4gICAgICBET0NfU1RPUkUsXG4gICAgICBCWV9TRVFfU1RPUkUsXG4gICAgICBBVFRBQ0hfU1RPUkUsXG4gICAgICBBVFRBQ0hfQU5EX1NFUV9TVE9SRVxuICAgIF07XG4gICAgdmFyIHR4blJlc3VsdCA9IG9wZW5UcmFuc2FjdGlvblNhZmVseShpZGIsIHN0b3JlcywgJ3JlYWR3cml0ZScpO1xuICAgIGlmICh0eG5SZXN1bHQuZXJyb3IpIHtcbiAgICAgIHJldHVybiBjYWxsYmFjayh0eG5SZXN1bHQuZXJyb3IpO1xuICAgIH1cbiAgICB2YXIgdHhuID0gdHhuUmVzdWx0LnR4bjtcblxuICAgIHZhciBkb2NTdG9yZSA9IHR4bi5vYmplY3RTdG9yZShET0NfU1RPUkUpO1xuXG4gICAgZG9jU3RvcmUuZ2V0KGRvY0lkKS5vbnN1Y2Nlc3MgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgIHZhciBtZXRhZGF0YSA9IGRlY29kZU1ldGFkYXRhKGV2ZW50LnRhcmdldC5yZXN1bHQpO1xuICAgICAgdHJhdmVyc2VSZXZUcmVlKG1ldGFkYXRhLnJldl90cmVlLCBmdW5jdGlvbiAoaXNMZWFmLCBwb3MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXZIYXNoLCBjdHgsIG9wdHMpIHtcbiAgICAgICAgdmFyIHJldiA9IHBvcyArICctJyArIHJldkhhc2g7XG4gICAgICAgIGlmIChyZXZzLmluZGV4T2YocmV2KSAhPT0gLTEpIHtcbiAgICAgICAgICBvcHRzLnN0YXR1cyA9ICdtaXNzaW5nJztcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBjb21wYWN0UmV2cyhyZXZzLCBkb2NJZCwgdHhuKTtcbiAgICAgIHZhciB3aW5uaW5nUmV2ID0gbWV0YWRhdGEud2lubmluZ1JldjtcbiAgICAgIHZhciBkZWxldGVkID0gbWV0YWRhdGEuZGVsZXRlZDtcbiAgICAgIHR4bi5vYmplY3RTdG9yZShET0NfU1RPUkUpLnB1dChcbiAgICAgICAgZW5jb2RlTWV0YWRhdGEobWV0YWRhdGEsIHdpbm5pbmdSZXYsIGRlbGV0ZWQpKTtcbiAgICB9O1xuICAgIHR4bi5vbmFib3J0ID0gaWRiRXJyb3IoY2FsbGJhY2spO1xuICAgIHR4bi5vbmNvbXBsZXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgY2FsbGJhY2soKTtcbiAgICB9O1xuICB9O1xuXG5cbiAgYXBpLl9nZXRMb2NhbCA9IGZ1bmN0aW9uIChpZCwgY2FsbGJhY2spIHtcbiAgICB2YXIgdHhuUmVzdWx0ID0gb3BlblRyYW5zYWN0aW9uU2FmZWx5KGlkYiwgW0xPQ0FMX1NUT1JFXSwgJ3JlYWRvbmx5Jyk7XG4gICAgaWYgKHR4blJlc3VsdC5lcnJvcikge1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKHR4blJlc3VsdC5lcnJvcik7XG4gICAgfVxuICAgIHZhciB0eCA9IHR4blJlc3VsdC50eG47XG4gICAgdmFyIHJlcSA9IHR4Lm9iamVjdFN0b3JlKExPQ0FMX1NUT1JFKS5nZXQoaWQpO1xuXG4gICAgcmVxLm9uZXJyb3IgPSBpZGJFcnJvcihjYWxsYmFjayk7XG4gICAgcmVxLm9uc3VjY2VzcyA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICB2YXIgZG9jID0gZS50YXJnZXQucmVzdWx0O1xuICAgICAgaWYgKCFkb2MpIHtcbiAgICAgICAgY2FsbGJhY2soY3JlYXRlRXJyb3IoTUlTU0lOR19ET0MpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlbGV0ZSBkb2NbJ19kb2NfaWRfcmV2J107IC8vIGZvciBiYWNrd2FyZHMgY29tcGF0XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIGRvYyk7XG4gICAgICB9XG4gICAgfTtcbiAgfTtcblxuICBhcGkuX3B1dExvY2FsID0gZnVuY3Rpb24gKGRvYywgb3B0cywgY2FsbGJhY2spIHtcbiAgICBpZiAodHlwZW9mIG9wdHMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGNhbGxiYWNrID0gb3B0cztcbiAgICAgIG9wdHMgPSB7fTtcbiAgICB9XG4gICAgZGVsZXRlIGRvYy5fcmV2aXNpb25zOyAvLyBpZ25vcmUgdGhpcywgdHJ1c3QgdGhlIHJldlxuICAgIHZhciBvbGRSZXYgPSBkb2MuX3JldjtcbiAgICB2YXIgaWQgPSBkb2MuX2lkO1xuICAgIGlmICghb2xkUmV2KSB7XG4gICAgICBkb2MuX3JldiA9ICcwLTEnO1xuICAgIH0gZWxzZSB7XG4gICAgICBkb2MuX3JldiA9ICcwLScgKyAocGFyc2VJbnQob2xkUmV2LnNwbGl0KCctJylbMV0sIDEwKSArIDEpO1xuICAgIH1cblxuICAgIHZhciB0eCA9IG9wdHMuY3R4O1xuICAgIHZhciByZXQ7XG4gICAgaWYgKCF0eCkge1xuICAgICAgdmFyIHR4blJlc3VsdCA9IG9wZW5UcmFuc2FjdGlvblNhZmVseShpZGIsIFtMT0NBTF9TVE9SRV0sICdyZWFkd3JpdGUnKTtcbiAgICAgIGlmICh0eG5SZXN1bHQuZXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKHR4blJlc3VsdC5lcnJvcik7XG4gICAgICB9XG4gICAgICB0eCA9IHR4blJlc3VsdC50eG47XG4gICAgICB0eC5vbmVycm9yID0gaWRiRXJyb3IoY2FsbGJhY2spO1xuICAgICAgdHgub25jb21wbGV0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHJldCkge1xuICAgICAgICAgIGNhbGxiYWNrKG51bGwsIHJldCk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIG9TdG9yZSA9IHR4Lm9iamVjdFN0b3JlKExPQ0FMX1NUT1JFKTtcbiAgICB2YXIgcmVxO1xuICAgIGlmIChvbGRSZXYpIHtcbiAgICAgIHJlcSA9IG9TdG9yZS5nZXQoaWQpO1xuICAgICAgcmVxLm9uc3VjY2VzcyA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHZhciBvbGREb2MgPSBlLnRhcmdldC5yZXN1bHQ7XG4gICAgICAgIGlmICghb2xkRG9jIHx8IG9sZERvYy5fcmV2ICE9PSBvbGRSZXYpIHtcbiAgICAgICAgICBjYWxsYmFjayhjcmVhdGVFcnJvcihSRVZfQ09ORkxJQ1QpKTtcbiAgICAgICAgfSBlbHNlIHsgLy8gdXBkYXRlXG4gICAgICAgICAgdmFyIHJlcSA9IG9TdG9yZS5wdXQoZG9jKTtcbiAgICAgICAgICByZXEub25zdWNjZXNzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0ID0ge29rOiB0cnVlLCBpZDogZG9jLl9pZCwgcmV2OiBkb2MuX3Jldn07XG4gICAgICAgICAgICBpZiAob3B0cy5jdHgpIHsgLy8gcmV0dXJuIGltbWVkaWF0ZWx5XG4gICAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIHJldCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9IGVsc2UgeyAvLyBuZXcgZG9jXG4gICAgICByZXEgPSBvU3RvcmUuYWRkKGRvYyk7XG4gICAgICByZXEub25lcnJvciA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIC8vIGNvbnN0cmFpbnQgZXJyb3IsIGFscmVhZHkgZXhpc3RzXG4gICAgICAgIGNhbGxiYWNrKGNyZWF0ZUVycm9yKFJFVl9DT05GTElDVCkpO1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7IC8vIGF2b2lkIHRyYW5zYWN0aW9uIGFib3J0XG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7IC8vIGF2b2lkIHRyYW5zYWN0aW9uIG9uZXJyb3JcbiAgICAgIH07XG4gICAgICByZXEub25zdWNjZXNzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXQgPSB7b2s6IHRydWUsIGlkOiBkb2MuX2lkLCByZXY6IGRvYy5fcmV2fTtcbiAgICAgICAgaWYgKG9wdHMuY3R4KSB7IC8vIHJldHVybiBpbW1lZGlhdGVseVxuICAgICAgICAgIGNhbGxiYWNrKG51bGwsIHJldCk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfVxuICB9O1xuXG4gIGFwaS5fcmVtb3ZlTG9jYWwgPSBmdW5jdGlvbiAoZG9jLCBvcHRzLCBjYWxsYmFjaykge1xuICAgIGlmICh0eXBlb2Ygb3B0cyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgY2FsbGJhY2sgPSBvcHRzO1xuICAgICAgb3B0cyA9IHt9O1xuICAgIH1cbiAgICB2YXIgdHggPSBvcHRzLmN0eDtcbiAgICBpZiAoIXR4KSB7XG4gICAgICB2YXIgdHhuUmVzdWx0ID0gb3BlblRyYW5zYWN0aW9uU2FmZWx5KGlkYiwgW0xPQ0FMX1NUT1JFXSwgJ3JlYWR3cml0ZScpO1xuICAgICAgaWYgKHR4blJlc3VsdC5lcnJvcikge1xuICAgICAgICByZXR1cm4gY2FsbGJhY2sodHhuUmVzdWx0LmVycm9yKTtcbiAgICAgIH1cbiAgICAgIHR4ID0gdHhuUmVzdWx0LnR4bjtcbiAgICAgIHR4Lm9uY29tcGxldGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChyZXQpIHtcbiAgICAgICAgICBjYWxsYmFjayhudWxsLCByZXQpO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cbiAgICB2YXIgcmV0O1xuICAgIHZhciBpZCA9IGRvYy5faWQ7XG4gICAgdmFyIG9TdG9yZSA9IHR4Lm9iamVjdFN0b3JlKExPQ0FMX1NUT1JFKTtcbiAgICB2YXIgcmVxID0gb1N0b3JlLmdldChpZCk7XG5cbiAgICByZXEub25lcnJvciA9IGlkYkVycm9yKGNhbGxiYWNrKTtcbiAgICByZXEub25zdWNjZXNzID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgIHZhciBvbGREb2MgPSBlLnRhcmdldC5yZXN1bHQ7XG4gICAgICBpZiAoIW9sZERvYyB8fCBvbGREb2MuX3JldiAhPT0gZG9jLl9yZXYpIHtcbiAgICAgICAgY2FsbGJhY2soY3JlYXRlRXJyb3IoTUlTU0lOR19ET0MpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG9TdG9yZS5kZWxldGUoaWQpO1xuICAgICAgICByZXQgPSB7b2s6IHRydWUsIGlkOiBpZCwgcmV2OiAnMC0wJ307XG4gICAgICAgIGlmIChvcHRzLmN0eCkgeyAvLyByZXR1cm4gaW1tZWRpYXRlbHlcbiAgICAgICAgICBjYWxsYmFjayhudWxsLCByZXQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcbiAgfTtcblxuICBhcGkuX2Rlc3Ryb3kgPSBmdW5jdGlvbiAob3B0cywgY2FsbGJhY2spIHtcbiAgICBpZGJDaGFuZ2VzLnJlbW92ZUFsbExpc3RlbmVycyhkYk5hbWUpO1xuXG4gICAgLy9DbG9zZSBvcGVuIHJlcXVlc3QgZm9yIFwiZGJOYW1lXCIgZGF0YWJhc2UgdG8gZml4IGllIGRlbGF5LlxuICAgIHZhciBvcGVuUmVxID0gb3BlblJlcUxpc3QuZ2V0KGRiTmFtZSk7XG4gICAgaWYgKG9wZW5SZXEgJiYgb3BlblJlcS5yZXN1bHQpIHtcbiAgICAgIG9wZW5SZXEucmVzdWx0LmNsb3NlKCk7XG4gICAgICBjYWNoZWREQnMuZGVsZXRlKGRiTmFtZSk7XG4gICAgfVxuICAgIHZhciByZXEgPSBpbmRleGVkREIuZGVsZXRlRGF0YWJhc2UoZGJOYW1lKTtcblxuICAgIHJlcS5vbnN1Y2Nlc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAvL1JlbW92ZSBvcGVuIHJlcXVlc3QgZnJvbSB0aGUgbGlzdC5cbiAgICAgIG9wZW5SZXFMaXN0LmRlbGV0ZShkYk5hbWUpO1xuICAgICAgaWYgKGhhc0xvY2FsU3RvcmFnZSgpICYmIChkYk5hbWUgaW4gbG9jYWxTdG9yYWdlKSkge1xuICAgICAgICBkZWxldGUgbG9jYWxTdG9yYWdlW2RiTmFtZV07XG4gICAgICB9XG4gICAgICBjYWxsYmFjayhudWxsLCB7ICdvayc6IHRydWUgfSk7XG4gICAgfTtcblxuICAgIHJlcS5vbmVycm9yID0gaWRiRXJyb3IoY2FsbGJhY2spO1xuICB9O1xuXG4gIHZhciBjYWNoZWQgPSBjYWNoZWREQnMuZ2V0KGRiTmFtZSk7XG5cbiAgaWYgKGNhY2hlZCkge1xuICAgIGlkYiA9IGNhY2hlZC5pZGI7XG4gICAgYXBpLl9tZXRhID0gY2FjaGVkLmdsb2JhbDtcbiAgICByZXR1cm4gaW1tZWRpYXRlKGZ1bmN0aW9uICgpIHtcbiAgICAgIGNhbGxiYWNrKG51bGwsIGFwaSk7XG4gICAgfSk7XG4gIH1cblxuICB2YXIgcmVxO1xuICBpZiAob3B0cy5zdG9yYWdlKSB7XG4gICAgcmVxID0gdHJ5U3RvcmFnZU9wdGlvbihkYk5hbWUsIG9wdHMuc3RvcmFnZSk7XG4gIH0gZWxzZSB7XG4gICAgcmVxID0gaW5kZXhlZERCLm9wZW4oZGJOYW1lLCBBREFQVEVSX1ZFUlNJT04pO1xuICB9XG5cbiAgb3BlblJlcUxpc3Quc2V0KGRiTmFtZSwgcmVxKTtcblxuICByZXEub251cGdyYWRlbmVlZGVkID0gZnVuY3Rpb24gKGUpIHtcbiAgICB2YXIgZGIgPSBlLnRhcmdldC5yZXN1bHQ7XG4gICAgaWYgKGUub2xkVmVyc2lvbiA8IDEpIHtcbiAgICAgIHJldHVybiBjcmVhdGVTY2hlbWEoZGIpOyAvLyBuZXcgZGIsIGluaXRpYWwgc2NoZW1hXG4gICAgfVxuICAgIC8vIGRvIG1pZ3JhdGlvbnNcblxuICAgIHZhciB0eG4gPSBlLmN1cnJlbnRUYXJnZXQudHJhbnNhY3Rpb247XG4gICAgLy8gdGhlc2UgbWlncmF0aW9ucyBoYXZlIHRvIGJlIGRvbmUgaW4gdGhpcyBmdW5jdGlvbiwgYmVmb3JlXG4gICAgLy8gY29udHJvbCBpcyByZXR1cm5lZCB0byB0aGUgZXZlbnQgbG9vcCwgYmVjYXVzZSBJbmRleGVkREJcblxuICAgIGlmIChlLm9sZFZlcnNpb24gPCAzKSB7XG4gICAgICBjcmVhdGVMb2NhbFN0b3JlU2NoZW1hKGRiKTsgLy8gdjIgLT4gdjNcbiAgICB9XG4gICAgaWYgKGUub2xkVmVyc2lvbiA8IDQpIHtcbiAgICAgIGFkZEF0dGFjaEFuZFNlcVN0b3JlKGRiKTsgLy8gdjMgLT4gdjRcbiAgICB9XG5cbiAgICB2YXIgbWlncmF0aW9ucyA9IFtcbiAgICAgIGFkZERlbGV0ZWRPckxvY2FsSW5kZXgsIC8vIHYxIC0+IHYyXG4gICAgICBtaWdyYXRlTG9jYWxTdG9yZSwgICAgICAvLyB2MiAtPiB2M1xuICAgICAgbWlncmF0ZUF0dHNBbmRTZXFzLCAgICAgLy8gdjMgLT4gdjRcbiAgICAgIG1pZ3JhdGVNZXRhZGF0YSAgICAgICAgIC8vIHY0IC0+IHY1XG4gICAgXTtcblxuICAgIHZhciBpID0gZS5vbGRWZXJzaW9uO1xuXG4gICAgZnVuY3Rpb24gbmV4dCgpIHtcbiAgICAgIHZhciBtaWdyYXRpb24gPSBtaWdyYXRpb25zW2kgLSAxXTtcbiAgICAgIGkrKztcbiAgICAgIGlmIChtaWdyYXRpb24pIHtcbiAgICAgICAgbWlncmF0aW9uKHR4biwgbmV4dCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgbmV4dCgpO1xuICB9O1xuXG4gIHJlcS5vbnN1Y2Nlc3MgPSBmdW5jdGlvbiAoZSkge1xuXG4gICAgaWRiID0gZS50YXJnZXQucmVzdWx0O1xuXG4gICAgaWRiLm9udmVyc2lvbmNoYW5nZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIGlkYi5jbG9zZSgpO1xuICAgICAgY2FjaGVkREJzLmRlbGV0ZShkYk5hbWUpO1xuICAgIH07XG5cbiAgICBpZGIub25hYm9ydCA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICBndWFyZGVkQ29uc29sZSgnZXJyb3InLCAnRGF0YWJhc2UgaGFzIGEgZ2xvYmFsIGZhaWx1cmUnLCBlLnRhcmdldC5lcnJvcik7XG4gICAgICBpZGIuY2xvc2UoKTtcbiAgICAgIGNhY2hlZERCcy5kZWxldGUoZGJOYW1lKTtcbiAgICB9O1xuXG4gICAgdmFyIHR4biA9IGlkYi50cmFuc2FjdGlvbihbXG4gICAgICBNRVRBX1NUT1JFLFxuICAgICAgREVURUNUX0JMT0JfU1VQUE9SVF9TVE9SRSxcbiAgICAgIERPQ19TVE9SRVxuICAgIF0sICdyZWFkd3JpdGUnKTtcblxuICAgIHZhciByZXEgPSB0eG4ub2JqZWN0U3RvcmUoTUVUQV9TVE9SRSkuZ2V0KE1FVEFfU1RPUkUpO1xuXG4gICAgdmFyIGJsb2JTdXBwb3J0ID0gbnVsbDtcbiAgICB2YXIgZG9jQ291bnQgPSBudWxsO1xuICAgIHZhciBpbnN0YW5jZUlkID0gbnVsbDtcblxuICAgIHJlcS5vbnN1Y2Nlc3MgPSBmdW5jdGlvbiAoZSkge1xuXG4gICAgICB2YXIgY2hlY2tTZXR1cENvbXBsZXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoYmxvYlN1cHBvcnQgPT09IG51bGwgfHwgZG9jQ291bnQgPT09IG51bGwgfHxcbiAgICAgICAgICAgIGluc3RhbmNlSWQgPT09IG51bGwpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYXBpLl9tZXRhID0ge1xuICAgICAgICAgICAgbmFtZTogZGJOYW1lLFxuICAgICAgICAgICAgaW5zdGFuY2VJZDogaW5zdGFuY2VJZCxcbiAgICAgICAgICAgIGJsb2JTdXBwb3J0OiBibG9iU3VwcG9ydCxcbiAgICAgICAgICAgIGRvY0NvdW50OiBkb2NDb3VudFxuICAgICAgICAgIH07XG5cbiAgICAgICAgICBjYWNoZWREQnMuc2V0KGRiTmFtZSwge1xuICAgICAgICAgICAgaWRiOiBpZGIsXG4gICAgICAgICAgICBnbG9iYWw6IGFwaS5fbWV0YVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGNhbGxiYWNrKG51bGwsIGFwaSk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIC8vXG4gICAgICAvLyBmZXRjaC9zdG9yZSB0aGUgaWRcbiAgICAgIC8vXG5cbiAgICAgIHZhciBtZXRhID0gZS50YXJnZXQucmVzdWx0IHx8IHtpZDogTUVUQV9TVE9SRX07XG4gICAgICBpZiAoZGJOYW1lICArICdfaWQnIGluIG1ldGEpIHtcbiAgICAgICAgaW5zdGFuY2VJZCA9IG1ldGFbZGJOYW1lICsgJ19pZCddO1xuICAgICAgICBjaGVja1NldHVwQ29tcGxldGUoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGluc3RhbmNlSWQgPSB1dWlkKCk7XG4gICAgICAgIG1ldGFbZGJOYW1lICsgJ19pZCddID0gaW5zdGFuY2VJZDtcbiAgICAgICAgdHhuLm9iamVjdFN0b3JlKE1FVEFfU1RPUkUpLnB1dChtZXRhKS5vbnN1Y2Nlc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgY2hlY2tTZXR1cENvbXBsZXRlKCk7XG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIC8vXG4gICAgICAvLyBjaGVjayBibG9iIHN1cHBvcnRcbiAgICAgIC8vXG5cbiAgICAgIGlmICghYmxvYlN1cHBvcnRQcm9taXNlKSB7XG4gICAgICAgIC8vIG1ha2Ugc3VyZSBibG9iIHN1cHBvcnQgaXMgb25seSBjaGVja2VkIG9uY2VcbiAgICAgICAgYmxvYlN1cHBvcnRQcm9taXNlID0gY2hlY2tCbG9iU3VwcG9ydCh0eG4pO1xuICAgICAgfVxuXG4gICAgICBibG9iU3VwcG9ydFByb21pc2UudGhlbihmdW5jdGlvbiAodmFsKSB7XG4gICAgICAgIGJsb2JTdXBwb3J0ID0gdmFsO1xuICAgICAgICBjaGVja1NldHVwQ29tcGxldGUoKTtcbiAgICAgIH0pO1xuXG4gICAgICAvL1xuICAgICAgLy8gY291bnQgZG9jc1xuICAgICAgLy9cblxuICAgICAgdmFyIGluZGV4ID0gdHhuLm9iamVjdFN0b3JlKERPQ19TVE9SRSkuaW5kZXgoJ2RlbGV0ZWRPckxvY2FsJyk7XG4gICAgICBpbmRleC5jb3VudChJREJLZXlSYW5nZS5vbmx5KCcwJykpLm9uc3VjY2VzcyA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGRvY0NvdW50ID0gZS50YXJnZXQucmVzdWx0O1xuICAgICAgICBjaGVja1NldHVwQ29tcGxldGUoKTtcbiAgICAgIH07XG5cbiAgICB9O1xuICB9O1xuXG4gIHJlcS5vbmVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBtc2cgPSAnRmFpbGVkIHRvIG9wZW4gaW5kZXhlZERCLCBhcmUgeW91IGluIHByaXZhdGUgYnJvd3NpbmcgbW9kZT8nO1xuICAgIGd1YXJkZWRDb25zb2xlKCdlcnJvcicsIG1zZyk7XG4gICAgY2FsbGJhY2soY3JlYXRlRXJyb3IoSURCX0VSUk9SLCBtc2cpKTtcbiAgfTtcbn1cblxuSWRiUG91Y2gudmFsaWQgPSBmdW5jdGlvbiAoKSB7XG4gIC8vIElzc3VlICMyNTMzLCB3ZSBmaW5hbGx5IGdhdmUgdXAgb24gZG9pbmcgYnVnXG4gIC8vIGRldGVjdGlvbiBpbnN0ZWFkIG9mIGJyb3dzZXIgc25pZmZpbmcuIFNhZmFyaSBicm91Z2h0IHVzXG4gIC8vIHRvIG91ciBrbmVlcy5cbiAgdmFyIGlzU2FmYXJpID0gdHlwZW9mIG9wZW5EYXRhYmFzZSAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAvKFNhZmFyaXxpUGhvbmV8aVBhZHxpUG9kKS8udGVzdChuYXZpZ2F0b3IudXNlckFnZW50KSAmJlxuICAgICEvQ2hyb21lLy50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpICYmXG4gICAgIS9CbGFja0JlcnJ5Ly50ZXN0KG5hdmlnYXRvci5wbGF0Zm9ybSk7XG5cbiAgLy8gc29tZSBvdXRkYXRlZCBpbXBsZW1lbnRhdGlvbnMgb2YgSURCIHRoYXQgYXBwZWFyIG9uIFNhbXN1bmdcbiAgLy8gYW5kIEhUQyBBbmRyb2lkIGRldmljZXMgPDQuNCBhcmUgbWlzc2luZyBJREJLZXlSYW5nZVxuICByZXR1cm4gIWlzU2FmYXJpICYmIHR5cGVvZiBpbmRleGVkREIgIT09ICd1bmRlZmluZWQnICYmXG4gICAgdHlwZW9mIElEQktleVJhbmdlICE9PSAndW5kZWZpbmVkJztcbn07XG5cbmZ1bmN0aW9uIHRyeVN0b3JhZ2VPcHRpb24oZGJOYW1lLCBzdG9yYWdlKSB7XG4gIHRyeSB7IC8vIG9wdGlvbiBvbmx5IGF2YWlsYWJsZSBpbiBGaXJlZm94IDI2K1xuICAgIHJldHVybiBpbmRleGVkREIub3BlbihkYk5hbWUsIHtcbiAgICAgIHZlcnNpb246IEFEQVBURVJfVkVSU0lPTixcbiAgICAgIHN0b3JhZ2U6IHN0b3JhZ2VcbiAgICB9KTtcbiAgfSBjYXRjaChlcnIpIHtcbiAgICAgIHJldHVybiBpbmRleGVkREIub3BlbihkYk5hbWUsIEFEQVBURVJfVkVSU0lPTik7XG4gIH1cbn1cblxuZnVuY3Rpb24gSURCUG91Y2ggKFBvdWNoREIpIHtcbiAgUG91Y2hEQi5hZGFwdGVyKCdpZGInLCBJZGJQb3VjaCwgdHJ1ZSk7XG59XG5cbi8vXG4vLyBQYXJzaW5nIGhleCBzdHJpbmdzLiBZZWFoLlxuLy9cbi8vIFNvIGJhc2ljYWxseSB3ZSBuZWVkIHRoaXMgYmVjYXVzZSBvZiBhIGJ1ZyBpbiBXZWJTUUw6XG4vLyBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NDIyNjkwXG4vLyBodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTM3NjM3XG4vL1xuLy8gVVRGLTggYW5kIFVURi0xNiBhcmUgcHJvdmlkZWQgYXMgc2VwYXJhdGUgZnVuY3Rpb25zXG4vLyBmb3IgbWVhZ2VyIHBlcmZvcm1hbmNlIGltcHJvdmVtZW50c1xuLy9cblxuZnVuY3Rpb24gZGVjb2RlVXRmOChzdHIpIHtcbiAgcmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChlc2NhcGUoc3RyKSk7XG59XG5cbmZ1bmN0aW9uIGhleFRvSW50KGNoYXJDb2RlKSB7XG4gIC8vICcwJy0nOScgaXMgNDgtNTdcbiAgLy8gJ0EnLSdGJyBpcyA2NS03MFxuICAvLyBTUUxpdGUgd2lsbCBvbmx5IGdpdmUgdXMgdXBwZXJjYXNlIGhleFxuICByZXR1cm4gY2hhckNvZGUgPCA2NSA/IChjaGFyQ29kZSAtIDQ4KSA6IChjaGFyQ29kZSAtIDU1KTtcbn1cblxuXG4vLyBFeGFtcGxlOlxuLy8gcHJhZ21hIGVuY29kaW5nPXV0Zjg7XG4vLyBzZWxlY3QgaGV4KCdBJyk7XG4vLyByZXR1cm5zICc0MSdcbmZ1bmN0aW9uIHBhcnNlSGV4VXRmOChzdHIsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHJlc3VsdCA9ICcnO1xuICB3aGlsZSAoc3RhcnQgPCBlbmQpIHtcbiAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShcbiAgICAgIChoZXhUb0ludChzdHIuY2hhckNvZGVBdChzdGFydCsrKSkgPDwgNCkgfFxuICAgICAgICBoZXhUb0ludChzdHIuY2hhckNvZGVBdChzdGFydCsrKSkpO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8vIEV4YW1wbGU6XG4vLyBwcmFnbWEgZW5jb2Rpbmc9dXRmMTY7XG4vLyBzZWxlY3QgaGV4KCdBJyk7XG4vLyByZXR1cm5zICc0MTAwJ1xuLy8gbm90aWNlIHRoYXQgdGhlIDAwIGNvbWVzIGFmdGVyIHRoZSA0MSAoaS5lLiBpdCdzIHN3aXp6bGVkKVxuZnVuY3Rpb24gcGFyc2VIZXhVdGYxNihzdHIsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHJlc3VsdCA9ICcnO1xuICB3aGlsZSAoc3RhcnQgPCBlbmQpIHtcbiAgICAvLyBVVEYtMTYsIHNvIHN3aXp6bGUgdGhlIGJ5dGVzXG4gICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoXG4gICAgICAoaGV4VG9JbnQoc3RyLmNoYXJDb2RlQXQoc3RhcnQgKyAyKSkgPDwgMTIpIHxcbiAgICAgICAgKGhleFRvSW50KHN0ci5jaGFyQ29kZUF0KHN0YXJ0ICsgMykpIDw8IDgpIHxcbiAgICAgICAgKGhleFRvSW50KHN0ci5jaGFyQ29kZUF0KHN0YXJ0KSkgPDwgNCkgfFxuICAgICAgICBoZXhUb0ludChzdHIuY2hhckNvZGVBdChzdGFydCArIDEpKSk7XG4gICAgc3RhcnQgKz0gNDtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5mdW5jdGlvbiBwYXJzZUhleFN0cmluZyhzdHIsIGVuY29kaW5nKSB7XG4gIGlmIChlbmNvZGluZyA9PT0gJ1VURi04Jykge1xuICAgIHJldHVybiBkZWNvZGVVdGY4KHBhcnNlSGV4VXRmOChzdHIsIDAsIHN0ci5sZW5ndGgpKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gcGFyc2VIZXhVdGYxNihzdHIsIDAsIHN0ci5sZW5ndGgpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHF1b3RlKHN0cikge1xuICByZXR1cm4gXCInXCIgKyBzdHIgKyBcIidcIjtcbn1cblxudmFyIEFEQVBURVJfVkVSU0lPTiQxID0gNzsgLy8gdXNlZCB0byBtYW5hZ2UgbWlncmF0aW9uc1xuXG4vLyBUaGUgb2JqZWN0IHN0b3JlcyBjcmVhdGVkIGZvciBlYWNoIGRhdGFiYXNlXG4vLyBET0NfU1RPUkUgc3RvcmVzIHRoZSBkb2N1bWVudCBtZXRhIGRhdGEsIGl0cyByZXZpc2lvbiBoaXN0b3J5IGFuZCBzdGF0ZVxudmFyIERPQ19TVE9SRSQxID0gcXVvdGUoJ2RvY3VtZW50LXN0b3JlJyk7XG4vLyBCWV9TRVFfU1RPUkUgc3RvcmVzIGEgcGFydGljdWxhciB2ZXJzaW9uIG9mIGEgZG9jdW1lbnQsIGtleWVkIGJ5IGl0c1xuLy8gc2VxdWVuY2UgaWRcbnZhciBCWV9TRVFfU1RPUkUkMSA9IHF1b3RlKCdieS1zZXF1ZW5jZScpO1xuLy8gV2hlcmUgd2Ugc3RvcmUgYXR0YWNobWVudHNcbnZhciBBVFRBQ0hfU1RPUkUkMSA9IHF1b3RlKCdhdHRhY2gtc3RvcmUnKTtcbnZhciBMT0NBTF9TVE9SRSQxID0gcXVvdGUoJ2xvY2FsLXN0b3JlJyk7XG52YXIgTUVUQV9TVE9SRSQxID0gcXVvdGUoJ21ldGFkYXRhLXN0b3JlJyk7XG4vLyB3aGVyZSB3ZSBzdG9yZSBtYW55LXRvLW1hbnkgcmVsYXRpb25zIGJldHdlZW4gYXR0YWNobWVudFxuLy8gZGlnZXN0cyBhbmQgc2Vxc1xudmFyIEFUVEFDSF9BTkRfU0VRX1NUT1JFJDEgPSBxdW90ZSgnYXR0YWNoLXNlcS1zdG9yZScpO1xuXG4vLyBlc2NhcGVCbG9iIGFuZCB1bmVzY2FwZUJsb2IgYXJlIHdvcmthcm91bmRzIGZvciBhIHdlYnNxbCBidWc6XG4vLyBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NDIyNjkwXG4vLyBodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTM3NjM3XG4vLyBUaGUgZ29hbCBpcyB0byBuZXZlciBhY3R1YWxseSBpbnNlcnQgdGhlIFxcdTAwMDAgY2hhcmFjdGVyXG4vLyBpbiB0aGUgZGF0YWJhc2UuXG5mdW5jdGlvbiBlc2NhcGVCbG9iKHN0cikge1xuICByZXR1cm4gc3RyXG4gICAgLnJlcGxhY2UoL1xcdTAwMDIvZywgJ1xcdTAwMDJcXHUwMDAyJylcbiAgICAucmVwbGFjZSgvXFx1MDAwMS9nLCAnXFx1MDAwMVxcdTAwMDInKVxuICAgIC5yZXBsYWNlKC9cXHUwMDAwL2csICdcXHUwMDAxXFx1MDAwMScpO1xufVxuXG5mdW5jdGlvbiB1bmVzY2FwZUJsb2Ioc3RyKSB7XG4gIHJldHVybiBzdHJcbiAgICAucmVwbGFjZSgvXFx1MDAwMVxcdTAwMDEvZywgJ1xcdTAwMDAnKVxuICAgIC5yZXBsYWNlKC9cXHUwMDAxXFx1MDAwMi9nLCAnXFx1MDAwMScpXG4gICAgLnJlcGxhY2UoL1xcdTAwMDJcXHUwMDAyL2csICdcXHUwMDAyJyk7XG59XG5cbmZ1bmN0aW9uIHN0cmluZ2lmeURvYyhkb2MpIHtcbiAgLy8gZG9uJ3QgYm90aGVyIHN0b3JpbmcgdGhlIGlkL3Jldi4gaXQgdXNlcyBsb3RzIG9mIHNwYWNlLFxuICAvLyBpbiBwZXJzaXN0ZW50IG1hcC9yZWR1Y2UgZXNwZWNpYWxseVxuICBkZWxldGUgZG9jLl9pZDtcbiAgZGVsZXRlIGRvYy5fcmV2O1xuICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoZG9jKTtcbn1cblxuZnVuY3Rpb24gdW5zdHJpbmdpZnlEb2MoZG9jLCBpZCwgcmV2KSB7XG4gIGRvYyA9IEpTT04ucGFyc2UoZG9jKTtcbiAgZG9jLl9pZCA9IGlkO1xuICBkb2MuX3JldiA9IHJldjtcbiAgcmV0dXJuIGRvYztcbn1cblxuLy8gcXVlc3Rpb24gbWFyayBncm91cHMgSU4gcXVlcmllcywgZS5nLiAzIC0+ICcoPyw/LD8pJ1xuZnVuY3Rpb24gcU1hcmtzKG51bSkge1xuICB2YXIgcyA9ICcoJztcbiAgd2hpbGUgKG51bS0tKSB7XG4gICAgcyArPSAnPyc7XG4gICAgaWYgKG51bSkge1xuICAgICAgcyArPSAnLCc7XG4gICAgfVxuICB9XG4gIHJldHVybiBzICsgJyknO1xufVxuXG5mdW5jdGlvbiBzZWxlY3Qoc2VsZWN0b3IsIHRhYmxlLCBqb2luZXIsIHdoZXJlLCBvcmRlckJ5KSB7XG4gIHJldHVybiAnU0VMRUNUICcgKyBzZWxlY3RvciArICcgRlJPTSAnICtcbiAgICAodHlwZW9mIHRhYmxlID09PSAnc3RyaW5nJyA/IHRhYmxlIDogdGFibGUuam9pbignIEpPSU4gJykpICtcbiAgICAoam9pbmVyID8gKCcgT04gJyArIGpvaW5lcikgOiAnJykgK1xuICAgICh3aGVyZSA/ICgnIFdIRVJFICcgK1xuICAgICh0eXBlb2Ygd2hlcmUgPT09ICdzdHJpbmcnID8gd2hlcmUgOiB3aGVyZS5qb2luKCcgQU5EICcpKSkgOiAnJykgK1xuICAgIChvcmRlckJ5ID8gKCcgT1JERVIgQlkgJyArIG9yZGVyQnkpIDogJycpO1xufVxuXG5mdW5jdGlvbiBjb21wYWN0UmV2cyQxKHJldnMsIGRvY0lkLCB0eCkge1xuXG4gIGlmICghcmV2cy5sZW5ndGgpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICB2YXIgbnVtRG9uZSA9IDA7XG4gIHZhciBzZXFzID0gW107XG5cbiAgZnVuY3Rpb24gY2hlY2tEb25lKCkge1xuICAgIGlmICgrK251bURvbmUgPT09IHJldnMubGVuZ3RoKSB7IC8vIGRvbmVcbiAgICAgIGRlbGV0ZU9ycGhhbnMoKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBkZWxldGVPcnBoYW5zKCkge1xuICAgIC8vIGZpbmQgb3JwaGFuZWQgYXR0YWNobWVudCBkaWdlc3RzXG5cbiAgICBpZiAoIXNlcXMubGVuZ3RoKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHNxbCA9ICdTRUxFQ1QgRElTVElOQ1QgZGlnZXN0IEFTIGRpZ2VzdCBGUk9NICcgK1xuICAgICAgQVRUQUNIX0FORF9TRVFfU1RPUkUkMSArICcgV0hFUkUgc2VxIElOICcgKyBxTWFya3Moc2Vxcy5sZW5ndGgpO1xuXG4gICAgdHguZXhlY3V0ZVNxbChzcWwsIHNlcXMsIGZ1bmN0aW9uICh0eCwgcmVzKSB7XG5cbiAgICAgIHZhciBkaWdlc3RzVG9DaGVjayA9IFtdO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZXMucm93cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBkaWdlc3RzVG9DaGVjay5wdXNoKHJlcy5yb3dzLml0ZW0oaSkuZGlnZXN0KTtcbiAgICAgIH1cbiAgICAgIGlmICghZGlnZXN0c1RvQ2hlY2subGVuZ3RoKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIHNxbCA9ICdERUxFVEUgRlJPTSAnICsgQVRUQUNIX0FORF9TRVFfU1RPUkUkMSArXG4gICAgICAgICcgV0hFUkUgc2VxIElOICgnICtcbiAgICAgICAgc2Vxcy5tYXAoZnVuY3Rpb24gKCkgeyByZXR1cm4gJz8nOyB9KS5qb2luKCcsJykgK1xuICAgICAgICAnKSc7XG4gICAgICB0eC5leGVjdXRlU3FsKHNxbCwgc2VxcywgZnVuY3Rpb24gKHR4KSB7XG5cbiAgICAgICAgdmFyIHNxbCA9ICdTRUxFQ1QgZGlnZXN0IEZST00gJyArIEFUVEFDSF9BTkRfU0VRX1NUT1JFJDEgK1xuICAgICAgICAgICcgV0hFUkUgZGlnZXN0IElOICgnICtcbiAgICAgICAgICBkaWdlc3RzVG9DaGVjay5tYXAoZnVuY3Rpb24gKCkgeyByZXR1cm4gJz8nOyB9KS5qb2luKCcsJykgK1xuICAgICAgICAgICcpJztcbiAgICAgICAgdHguZXhlY3V0ZVNxbChzcWwsIGRpZ2VzdHNUb0NoZWNrLCBmdW5jdGlvbiAodHgsIHJlcykge1xuICAgICAgICAgIHZhciBub25PcnBoYW5lZERpZ2VzdHMgPSBuZXcgX1NldCgpO1xuICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVzLnJvd3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIG5vbk9ycGhhbmVkRGlnZXN0cy5hZGQocmVzLnJvd3MuaXRlbShpKS5kaWdlc3QpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBkaWdlc3RzVG9DaGVjay5mb3JFYWNoKGZ1bmN0aW9uIChkaWdlc3QpIHtcbiAgICAgICAgICAgIGlmIChub25PcnBoYW5lZERpZ2VzdHMuaGFzKGRpZ2VzdCkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdHguZXhlY3V0ZVNxbChcbiAgICAgICAgICAgICAgJ0RFTEVURSBGUk9NICcgKyBBVFRBQ0hfQU5EX1NFUV9TVE9SRSQxICsgJyBXSEVSRSBkaWdlc3Q9PycsXG4gICAgICAgICAgICAgIFtkaWdlc3RdKTtcbiAgICAgICAgICAgIHR4LmV4ZWN1dGVTcWwoXG4gICAgICAgICAgICAgICdERUxFVEUgRlJPTSAnICsgQVRUQUNIX1NUT1JFJDEgKyAnIFdIRVJFIGRpZ2VzdD0/JywgW2RpZ2VzdF0pO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gdXBkYXRlIGJ5LXNlcSBhbmQgYXR0YWNoIHN0b3JlcyBpbiBwYXJhbGxlbFxuICByZXZzLmZvckVhY2goZnVuY3Rpb24gKHJldikge1xuICAgIHZhciBzcWwgPSAnU0VMRUNUIHNlcSBGUk9NICcgKyBCWV9TRVFfU1RPUkUkMSArXG4gICAgICAnIFdIRVJFIGRvY19pZD0/IEFORCByZXY9Pyc7XG5cbiAgICB0eC5leGVjdXRlU3FsKHNxbCwgW2RvY0lkLCByZXZdLCBmdW5jdGlvbiAodHgsIHJlcykge1xuICAgICAgaWYgKCFyZXMucm93cy5sZW5ndGgpIHsgLy8gYWxyZWFkeSBkZWxldGVkXG4gICAgICAgIHJldHVybiBjaGVja0RvbmUoKTtcbiAgICAgIH1cbiAgICAgIHZhciBzZXEgPSByZXMucm93cy5pdGVtKDApLnNlcTtcbiAgICAgIHNlcXMucHVzaChzZXEpO1xuXG4gICAgICB0eC5leGVjdXRlU3FsKFxuICAgICAgICAnREVMRVRFIEZST00gJyArIEJZX1NFUV9TVE9SRSQxICsgJyBXSEVSRSBzZXE9PycsIFtzZXFdLCBjaGVja0RvbmUpO1xuICAgIH0pO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gd2Vic3FsRXJyb3IoY2FsbGJhY2spIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIChldmVudCkge1xuICAgIGd1YXJkZWRDb25zb2xlKCdlcnJvcicsICdXZWJTUUwgdGhyZXcgYW4gZXJyb3InLCBldmVudCk7XG4gICAgLy8gZXZlbnQgbWF5IGFjdHVhbGx5IGJlIGEgU1FMRXJyb3Igb2JqZWN0LCBzbyByZXBvcnQgaXMgYXMgc3VjaFxuICAgIHZhciBlcnJvck5hbWVNYXRjaCA9IGV2ZW50ICYmIGV2ZW50LmNvbnN0cnVjdG9yLnRvU3RyaW5nKClcbiAgICAgICAgLm1hdGNoKC9mdW5jdGlvbiAoW15cXChdKykvKTtcbiAgICB2YXIgZXJyb3JOYW1lID0gKGVycm9yTmFtZU1hdGNoICYmIGVycm9yTmFtZU1hdGNoWzFdKSB8fCBldmVudC50eXBlO1xuICAgIHZhciBlcnJvclJlYXNvbiA9IGV2ZW50LnRhcmdldCB8fCBldmVudC5tZXNzYWdlO1xuICAgIGNhbGxiYWNrKGNyZWF0ZUVycm9yKFdTUV9FUlJPUiwgZXJyb3JSZWFzb24sIGVycm9yTmFtZSkpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBnZXRTaXplKG9wdHMpIHtcbiAgaWYgKCdzaXplJyBpbiBvcHRzKSB7XG4gICAgLy8gdHJpZ2dlcnMgaW1tZWRpYXRlIHBvcHVwIGluIGlPUywgZml4ZXMgIzIzNDdcbiAgICAvLyBlLmcuIDUwMDAwMDEgYXNrcyBmb3IgNSBNQiwgMTAwMDAwMDEgYXNrcyBmb3IgMTAgTUIsXG4gICAgcmV0dXJuIG9wdHMuc2l6ZSAqIDEwMDAwMDA7XG4gIH1cbiAgLy8gSW4gaU9TLCBkb2Vzbid0IG1hdHRlciBhcyBsb25nIGFzIGl0J3MgPD0gNTAwMDAwMC5cbiAgLy8gRXhjZXB0IHRoYXQgaWYgeW91IHJlcXVlc3QgdG9vIG11Y2gsIG91ciB0ZXN0cyBmYWlsXG4gIC8vIGJlY2F1c2Ugb2YgdGhlIG5hdGl2ZSBcImRvIHlvdSBhY2NlcHQ/XCIgcG9wdXAuXG4gIC8vIEluIEFuZHJvaWQgPD00LjMsIHRoaXMgdmFsdWUgaXMgYWN0dWFsbHkgdXNlZCBhcyBhblxuICAvLyBob25lc3QtdG8tZ29kIGNlaWxpbmcgZm9yIGRhdGEsIHNvIHdlIG5lZWQgdG9cbiAgLy8gc2V0IGl0IHRvIGEgZGVjZW50bHkgaGlnaCBudW1iZXIuXG4gIHZhciBpc0FuZHJvaWQgPSB0eXBlb2YgbmF2aWdhdG9yICE9PSAndW5kZWZpbmVkJyAmJlxuICAgIC9BbmRyb2lkLy50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICByZXR1cm4gaXNBbmRyb2lkID8gNTAwMDAwMCA6IDE7IC8vIGluIFBoYW50b21KUywgaWYgeW91IHVzZSAwIGl0IHdpbGwgY3Jhc2hcbn1cblxuZnVuY3Rpb24gd2Vic3FsQnVsa0RvY3MoZGJPcHRzLCByZXEsIG9wdHMsIGFwaSwgZGIsIHdlYnNxbENoYW5nZXMsIGNhbGxiYWNrKSB7XG4gIHZhciBuZXdFZGl0cyA9IG9wdHMubmV3X2VkaXRzO1xuICB2YXIgdXNlckRvY3MgPSByZXEuZG9jcztcblxuICAvLyBQYXJzZSB0aGUgZG9jcywgZ2l2ZSB0aGVtIGEgc2VxdWVuY2UgbnVtYmVyIGZvciB0aGUgcmVzdWx0XG4gIHZhciBkb2NJbmZvcyA9IHVzZXJEb2NzLm1hcChmdW5jdGlvbiAoZG9jKSB7XG4gICAgaWYgKGRvYy5faWQgJiYgaXNMb2NhbElkKGRvYy5faWQpKSB7XG4gICAgICByZXR1cm4gZG9jO1xuICAgIH1cbiAgICB2YXIgbmV3RG9jID0gcGFyc2VEb2MoZG9jLCBuZXdFZGl0cyk7XG4gICAgcmV0dXJuIG5ld0RvYztcbiAgfSk7XG5cbiAgdmFyIGRvY0luZm9FcnJvcnMgPSBkb2NJbmZvcy5maWx0ZXIoZnVuY3Rpb24gKGRvY0luZm8pIHtcbiAgICByZXR1cm4gZG9jSW5mby5lcnJvcjtcbiAgfSk7XG4gIGlmIChkb2NJbmZvRXJyb3JzLmxlbmd0aCkge1xuICAgIHJldHVybiBjYWxsYmFjayhkb2NJbmZvRXJyb3JzWzBdKTtcbiAgfVxuXG4gIHZhciB0eDtcbiAgdmFyIHJlc3VsdHMgPSBuZXcgQXJyYXkoZG9jSW5mb3MubGVuZ3RoKTtcbiAgdmFyIGZldGNoZWREb2NzID0gbmV3IF9NYXAoKTtcblxuICB2YXIgcHJlY29uZGl0aW9uRXJyb3JlZDtcbiAgZnVuY3Rpb24gY29tcGxldGUoKSB7XG4gICAgaWYgKHByZWNvbmRpdGlvbkVycm9yZWQpIHtcbiAgICAgIHJldHVybiBjYWxsYmFjayhwcmVjb25kaXRpb25FcnJvcmVkKTtcbiAgICB9XG4gICAgd2Vic3FsQ2hhbmdlcy5ub3RpZnkoYXBpLl9uYW1lKTtcbiAgICBhcGkuX2RvY0NvdW50ID0gLTE7IC8vIGludmFsaWRhdGVcbiAgICBjYWxsYmFjayhudWxsLCByZXN1bHRzKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHZlcmlmeUF0dGFjaG1lbnQoZGlnZXN0LCBjYWxsYmFjaykge1xuICAgIHZhciBzcWwgPSAnU0VMRUNUIGNvdW50KCopIGFzIGNudCBGUk9NICcgKyBBVFRBQ0hfU1RPUkUkMSArXG4gICAgICAnIFdIRVJFIGRpZ2VzdD0/JztcbiAgICB0eC5leGVjdXRlU3FsKHNxbCwgW2RpZ2VzdF0sIGZ1bmN0aW9uICh0eCwgcmVzdWx0KSB7XG4gICAgICBpZiAocmVzdWx0LnJvd3MuaXRlbSgwKS5jbnQgPT09IDApIHtcbiAgICAgICAgdmFyIGVyciA9IGNyZWF0ZUVycm9yKE1JU1NJTkdfU1RVQixcbiAgICAgICAgICAndW5rbm93biBzdHViIGF0dGFjaG1lbnQgd2l0aCBkaWdlc3QgJyArXG4gICAgICAgICAgZGlnZXN0KTtcbiAgICAgICAgY2FsbGJhY2soZXJyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiB2ZXJpZnlBdHRhY2htZW50cyhmaW5pc2gpIHtcbiAgICB2YXIgZGlnZXN0cyA9IFtdO1xuICAgIGRvY0luZm9zLmZvckVhY2goZnVuY3Rpb24gKGRvY0luZm8pIHtcbiAgICAgIGlmIChkb2NJbmZvLmRhdGEgJiYgZG9jSW5mby5kYXRhLl9hdHRhY2htZW50cykge1xuICAgICAgICBPYmplY3Qua2V5cyhkb2NJbmZvLmRhdGEuX2F0dGFjaG1lbnRzKS5mb3JFYWNoKGZ1bmN0aW9uIChmaWxlbmFtZSkge1xuICAgICAgICAgIHZhciBhdHQgPSBkb2NJbmZvLmRhdGEuX2F0dGFjaG1lbnRzW2ZpbGVuYW1lXTtcbiAgICAgICAgICBpZiAoYXR0LnN0dWIpIHtcbiAgICAgICAgICAgIGRpZ2VzdHMucHVzaChhdHQuZGlnZXN0KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGlmICghZGlnZXN0cy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmaW5pc2goKTtcbiAgICB9XG4gICAgdmFyIG51bURvbmUgPSAwO1xuICAgIHZhciBlcnI7XG5cbiAgICBmdW5jdGlvbiBjaGVja0RvbmUoKSB7XG4gICAgICBpZiAoKytudW1Eb25lID09PSBkaWdlc3RzLmxlbmd0aCkge1xuICAgICAgICBmaW5pc2goZXJyKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZGlnZXN0cy5mb3JFYWNoKGZ1bmN0aW9uIChkaWdlc3QpIHtcbiAgICAgIHZlcmlmeUF0dGFjaG1lbnQoZGlnZXN0LCBmdW5jdGlvbiAoYXR0RXJyKSB7XG4gICAgICAgIGlmIChhdHRFcnIgJiYgIWVycikge1xuICAgICAgICAgIGVyciA9IGF0dEVycjtcbiAgICAgICAgfVxuICAgICAgICBjaGVja0RvbmUoKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gd3JpdGVEb2MoZG9jSW5mbywgd2lubmluZ1Jldiwgd2lubmluZ1JldklzRGVsZXRlZCwgbmV3UmV2SXNEZWxldGVkLFxuICAgICAgICAgICAgICAgICAgICBpc1VwZGF0ZSwgZGVsdGEsIHJlc3VsdHNJZHgsIGNhbGxiYWNrKSB7XG5cbiAgICBmdW5jdGlvbiBmaW5pc2goKSB7XG4gICAgICB2YXIgZGF0YSA9IGRvY0luZm8uZGF0YTtcbiAgICAgIHZhciBkZWxldGVkSW50ID0gbmV3UmV2SXNEZWxldGVkID8gMSA6IDA7XG5cbiAgICAgIHZhciBpZCA9IGRhdGEuX2lkO1xuICAgICAgdmFyIHJldiA9IGRhdGEuX3JldjtcbiAgICAgIHZhciBqc29uID0gc3RyaW5naWZ5RG9jKGRhdGEpO1xuICAgICAgdmFyIHNxbCA9ICdJTlNFUlQgSU5UTyAnICsgQllfU0VRX1NUT1JFJDEgK1xuICAgICAgICAnIChkb2NfaWQsIHJldiwganNvbiwgZGVsZXRlZCkgVkFMVUVTICg/LCA/LCA/LCA/KTsnO1xuICAgICAgdmFyIHNxbEFyZ3MgPSBbaWQsIHJldiwganNvbiwgZGVsZXRlZEludF07XG5cbiAgICAgIC8vIG1hcCBzZXFzIHRvIGF0dGFjaG1lbnQgZGlnZXN0cywgd2hpY2hcbiAgICAgIC8vIHdlIHdpbGwgbmVlZCBsYXRlciBkdXJpbmcgY29tcGFjdGlvblxuICAgICAgZnVuY3Rpb24gaW5zZXJ0QXR0YWNobWVudE1hcHBpbmdzKHNlcSwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIGF0dHNBZGRlZCA9IDA7XG4gICAgICAgIHZhciBhdHRzVG9BZGQgPSBPYmplY3Qua2V5cyhkYXRhLl9hdHRhY2htZW50cyB8fCB7fSk7XG5cbiAgICAgICAgaWYgKCFhdHRzVG9BZGQubGVuZ3RoKSB7XG4gICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gY2hlY2tEb25lKCkge1xuICAgICAgICAgIGlmICgrK2F0dHNBZGRlZCA9PT0gYXR0c1RvQWRkLmxlbmd0aCkge1xuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBhY2sgaGFuZGxpbmcgYSBjb25zdHJhaW50IGVycm9yXG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gYWRkKGF0dCkge1xuICAgICAgICAgIHZhciBzcWwgPSAnSU5TRVJUIElOVE8gJyArIEFUVEFDSF9BTkRfU0VRX1NUT1JFJDEgK1xuICAgICAgICAgICAgJyAoZGlnZXN0LCBzZXEpIFZBTFVFUyAoPyw/KSc7XG4gICAgICAgICAgdmFyIHNxbEFyZ3MgPSBbZGF0YS5fYXR0YWNobWVudHNbYXR0XS5kaWdlc3QsIHNlcV07XG4gICAgICAgICAgdHguZXhlY3V0ZVNxbChzcWwsIHNxbEFyZ3MsIGNoZWNrRG9uZSwgY2hlY2tEb25lKTtcbiAgICAgICAgICAvLyBzZWNvbmQgY2FsbGJhY2sgaXMgZm9yIGEgY29uc3RhaW50IGVycm9yLCB3aGljaCB3ZSBpZ25vcmVcbiAgICAgICAgICAvLyBiZWNhdXNlIHRoaXMgZG9jaWQvcmV2IGhhcyBhbHJlYWR5IGJlZW4gYXNzb2NpYXRlZCB3aXRoXG4gICAgICAgICAgLy8gdGhlIGRpZ2VzdCAoZS5nLiB3aGVuIG5ld19lZGl0cyA9PSBmYWxzZSlcbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGF0dHNUb0FkZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGFkZChhdHRzVG9BZGRbaV0pOyAvLyBkbyBpbiBwYXJhbGxlbFxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHR4LmV4ZWN1dGVTcWwoc3FsLCBzcWxBcmdzLCBmdW5jdGlvbiAodHgsIHJlc3VsdCkge1xuICAgICAgICB2YXIgc2VxID0gcmVzdWx0Lmluc2VydElkO1xuICAgICAgICBpbnNlcnRBdHRhY2htZW50TWFwcGluZ3Moc2VxLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgZGF0YVdyaXR0ZW4odHgsIHNlcSk7XG4gICAgICAgIH0pO1xuICAgICAgfSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBjb25zdHJhaW50IGVycm9yLCByZWNvdmVyIGJ5IHVwZGF0aW5nIGluc3RlYWQgKHNlZSAjMTYzOClcbiAgICAgICAgdmFyIGZldGNoU3FsID0gc2VsZWN0KCdzZXEnLCBCWV9TRVFfU1RPUkUkMSwgbnVsbCxcbiAgICAgICAgICAnZG9jX2lkPT8gQU5EIHJldj0/Jyk7XG4gICAgICAgIHR4LmV4ZWN1dGVTcWwoZmV0Y2hTcWwsIFtpZCwgcmV2XSwgZnVuY3Rpb24gKHR4LCByZXMpIHtcbiAgICAgICAgICB2YXIgc2VxID0gcmVzLnJvd3MuaXRlbSgwKS5zZXE7XG4gICAgICAgICAgdmFyIHNxbCA9ICdVUERBVEUgJyArIEJZX1NFUV9TVE9SRSQxICtcbiAgICAgICAgICAgICcgU0VUIGpzb249PywgZGVsZXRlZD0/IFdIRVJFIGRvY19pZD0/IEFORCByZXY9PzsnO1xuICAgICAgICAgIHZhciBzcWxBcmdzID0gW2pzb24sIGRlbGV0ZWRJbnQsIGlkLCByZXZdO1xuICAgICAgICAgIHR4LmV4ZWN1dGVTcWwoc3FsLCBzcWxBcmdzLCBmdW5jdGlvbiAodHgpIHtcbiAgICAgICAgICAgIGluc2VydEF0dGFjaG1lbnRNYXBwaW5ncyhzZXEsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgZGF0YVdyaXR0ZW4odHgsIHNlcSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBmYWxzZTsgLy8gYWNrIHRoYXQgd2UndmUgaGFuZGxlZCB0aGUgZXJyb3JcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvbGxlY3RSZXN1bHRzKGF0dGFjaG1lbnRFcnIpIHtcbiAgICAgIGlmICghZXJyKSB7XG4gICAgICAgIGlmIChhdHRhY2htZW50RXJyKSB7XG4gICAgICAgICAgZXJyID0gYXR0YWNobWVudEVycjtcbiAgICAgICAgICBjYWxsYmFjayhlcnIpO1xuICAgICAgICB9IGVsc2UgaWYgKHJlY3YgPT09IGF0dGFjaG1lbnRzLmxlbmd0aCkge1xuICAgICAgICAgIGZpbmlzaCgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGVyciA9IG51bGw7XG4gICAgdmFyIHJlY3YgPSAwO1xuXG4gICAgZG9jSW5mby5kYXRhLl9pZCA9IGRvY0luZm8ubWV0YWRhdGEuaWQ7XG4gICAgZG9jSW5mby5kYXRhLl9yZXYgPSBkb2NJbmZvLm1ldGFkYXRhLnJldjtcbiAgICB2YXIgYXR0YWNobWVudHMgPSBPYmplY3Qua2V5cyhkb2NJbmZvLmRhdGEuX2F0dGFjaG1lbnRzIHx8IHt9KTtcblxuXG4gICAgaWYgKG5ld1JldklzRGVsZXRlZCkge1xuICAgICAgZG9jSW5mby5kYXRhLl9kZWxldGVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhdHRhY2htZW50U2F2ZWQoZXJyKSB7XG4gICAgICByZWN2Kys7XG4gICAgICBjb2xsZWN0UmVzdWx0cyhlcnIpO1xuICAgIH1cblxuICAgIGF0dGFjaG1lbnRzLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgdmFyIGF0dCA9IGRvY0luZm8uZGF0YS5fYXR0YWNobWVudHNba2V5XTtcbiAgICAgIGlmICghYXR0LnN0dWIpIHtcbiAgICAgICAgdmFyIGRhdGEgPSBhdHQuZGF0YTtcbiAgICAgICAgZGVsZXRlIGF0dC5kYXRhO1xuICAgICAgICBhdHQucmV2cG9zID0gcGFyc2VJbnQod2lubmluZ1JldiwgMTApO1xuICAgICAgICB2YXIgZGlnZXN0ID0gYXR0LmRpZ2VzdDtcbiAgICAgICAgc2F2ZUF0dGFjaG1lbnQoZGlnZXN0LCBkYXRhLCBhdHRhY2htZW50U2F2ZWQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVjdisrO1xuICAgICAgICBjb2xsZWN0UmVzdWx0cygpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaWYgKCFhdHRhY2htZW50cy5sZW5ndGgpIHtcbiAgICAgIGZpbmlzaCgpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRhdGFXcml0dGVuKHR4LCBzZXEpIHtcbiAgICAgIHZhciBpZCA9IGRvY0luZm8ubWV0YWRhdGEuaWQ7XG5cbiAgICAgIHZhciByZXZzVG9Db21wYWN0ID0gZG9jSW5mby5zdGVtbWVkUmV2cyB8fCBbXTtcbiAgICAgIGlmIChpc1VwZGF0ZSAmJiBhcGkuYXV0b19jb21wYWN0aW9uKSB7XG4gICAgICAgIHJldnNUb0NvbXBhY3QgPSBjb21wYWN0VHJlZShkb2NJbmZvLm1ldGFkYXRhKS5jb25jYXQocmV2c1RvQ29tcGFjdCk7XG4gICAgICB9XG4gICAgICBpZiAocmV2c1RvQ29tcGFjdC5sZW5ndGgpIHtcbiAgICAgICAgY29tcGFjdFJldnMkMShyZXZzVG9Db21wYWN0LCBpZCwgdHgpO1xuICAgICAgfVxuXG4gICAgICBkb2NJbmZvLm1ldGFkYXRhLnNlcSA9IHNlcTtcbiAgICAgIHZhciByZXYgPSBkb2NJbmZvLm1ldGFkYXRhLnJldjtcbiAgICAgIGRlbGV0ZSBkb2NJbmZvLm1ldGFkYXRhLnJldjtcblxuICAgICAgdmFyIHNxbCA9IGlzVXBkYXRlID9cbiAgICAgICdVUERBVEUgJyArIERPQ19TVE9SRSQxICtcbiAgICAgICcgU0VUIGpzb249PywgbWF4X3NlcT0/LCB3aW5uaW5nc2VxPScgK1xuICAgICAgJyhTRUxFQ1Qgc2VxIEZST00gJyArIEJZX1NFUV9TVE9SRSQxICtcbiAgICAgICcgV0hFUkUgZG9jX2lkPScgKyBET0NfU1RPUkUkMSArICcuaWQgQU5EIHJldj0/KSBXSEVSRSBpZD0/J1xuICAgICAgICA6ICdJTlNFUlQgSU5UTyAnICsgRE9DX1NUT1JFJDEgK1xuICAgICAgJyAoaWQsIHdpbm5pbmdzZXEsIG1heF9zZXEsIGpzb24pIFZBTFVFUyAoPyw/LD8sPyk7JztcbiAgICAgIHZhciBtZXRhZGF0YVN0ciA9IHNhZmVKc29uU3RyaW5naWZ5KGRvY0luZm8ubWV0YWRhdGEpO1xuICAgICAgdmFyIHBhcmFtcyA9IGlzVXBkYXRlID9cbiAgICAgICAgW21ldGFkYXRhU3RyLCBzZXEsIHdpbm5pbmdSZXYsIGlkXSA6XG4gICAgICAgIFtpZCwgc2VxLCBzZXEsIG1ldGFkYXRhU3RyXTtcbiAgICAgIHR4LmV4ZWN1dGVTcWwoc3FsLCBwYXJhbXMsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmVzdWx0c1tyZXN1bHRzSWR4XSA9IHtcbiAgICAgICAgICBvazogdHJ1ZSxcbiAgICAgICAgICBpZDogZG9jSW5mby5tZXRhZGF0YS5pZCxcbiAgICAgICAgICByZXY6IHJldlxuICAgICAgICB9O1xuICAgICAgICBmZXRjaGVkRG9jcy5zZXQoaWQsIGRvY0luZm8ubWV0YWRhdGEpO1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gd2Vic3FsUHJvY2Vzc0RvY3MoKSB7XG4gICAgcHJvY2Vzc0RvY3MoZGJPcHRzLnJldnNfbGltaXQsIGRvY0luZm9zLCBhcGksIGZldGNoZWREb2NzLCB0eCxcbiAgICAgICAgICAgICAgICByZXN1bHRzLCB3cml0ZURvYywgb3B0cyk7XG4gIH1cblxuICBmdW5jdGlvbiBmZXRjaEV4aXN0aW5nRG9jcyhjYWxsYmFjaykge1xuICAgIGlmICghZG9jSW5mb3MubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgICB9XG5cbiAgICB2YXIgbnVtRmV0Y2hlZCA9IDA7XG5cbiAgICBmdW5jdGlvbiBjaGVja0RvbmUoKSB7XG4gICAgICBpZiAoKytudW1GZXRjaGVkID09PSBkb2NJbmZvcy5sZW5ndGgpIHtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBkb2NJbmZvcy5mb3JFYWNoKGZ1bmN0aW9uIChkb2NJbmZvKSB7XG4gICAgICBpZiAoZG9jSW5mby5faWQgJiYgaXNMb2NhbElkKGRvY0luZm8uX2lkKSkge1xuICAgICAgICByZXR1cm4gY2hlY2tEb25lKCk7IC8vIHNraXAgbG9jYWwgZG9jc1xuICAgICAgfVxuICAgICAgdmFyIGlkID0gZG9jSW5mby5tZXRhZGF0YS5pZDtcbiAgICAgIHR4LmV4ZWN1dGVTcWwoJ1NFTEVDVCBqc29uIEZST00gJyArIERPQ19TVE9SRSQxICtcbiAgICAgICcgV0hFUkUgaWQgPSA/JywgW2lkXSwgZnVuY3Rpb24gKHR4LCByZXN1bHQpIHtcbiAgICAgICAgaWYgKHJlc3VsdC5yb3dzLmxlbmd0aCkge1xuICAgICAgICAgIHZhciBtZXRhZGF0YSA9IHNhZmVKc29uUGFyc2UocmVzdWx0LnJvd3MuaXRlbSgwKS5qc29uKTtcbiAgICAgICAgICBmZXRjaGVkRG9jcy5zZXQoaWQsIG1ldGFkYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBjaGVja0RvbmUoKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gc2F2ZUF0dGFjaG1lbnQoZGlnZXN0LCBkYXRhLCBjYWxsYmFjaykge1xuICAgIHZhciBzcWwgPSAnU0VMRUNUIGRpZ2VzdCBGUk9NICcgKyBBVFRBQ0hfU1RPUkUkMSArICcgV0hFUkUgZGlnZXN0PT8nO1xuICAgIHR4LmV4ZWN1dGVTcWwoc3FsLCBbZGlnZXN0XSwgZnVuY3Rpb24gKHR4LCByZXN1bHQpIHtcbiAgICAgIGlmIChyZXN1bHQucm93cy5sZW5ndGgpIHsgLy8gYXR0YWNobWVudCBhbHJlYWR5IGV4aXN0c1xuICAgICAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgICAgIH1cbiAgICAgIC8vIHdlIGNvdWxkIGp1c3QgaW5zZXJ0IGJlZm9yZSBzZWxlY3RpbmcgYW5kIGNhdGNoIHRoZSBlcnJvcixcbiAgICAgIC8vIGJ1dCBteSBodW5jaCBpcyB0aGF0IGl0J3MgY2hlYXBlciBub3QgdG8gc2VyaWFsaXplIHRoZSBibG9iXG4gICAgICAvLyBmcm9tIEpTIHRvIEMgaWYgd2UgZG9uJ3QgaGF2ZSB0byAoVE9ETzogY29uZmlybSB0aGlzKVxuICAgICAgc3FsID0gJ0lOU0VSVCBJTlRPICcgKyBBVFRBQ0hfU1RPUkUkMSArXG4gICAgICAnIChkaWdlc3QsIGJvZHksIGVzY2FwZWQpIFZBTFVFUyAoPyw/LDEpJztcbiAgICAgIHR4LmV4ZWN1dGVTcWwoc3FsLCBbZGlnZXN0LCBlc2NhcGVCbG9iKGRhdGEpXSwgZnVuY3Rpb24gKCkge1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgfSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBpZ25vcmUgY29uc3RhaW50IGVycm9ycywgbWVhbnMgaXQgYWxyZWFkeSBleGlzdHNcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBhY2sgd2UgaGFuZGxlZCB0aGUgZXJyb3JcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgcHJlcHJvY2Vzc0F0dGFjaG1lbnRzKGRvY0luZm9zLCAnYmluYXJ5JywgZnVuY3Rpb24gKGVycikge1xuICAgIGlmIChlcnIpIHtcbiAgICAgIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgIH1cbiAgICBkYi50cmFuc2FjdGlvbihmdW5jdGlvbiAodHhuKSB7XG4gICAgICB0eCA9IHR4bjtcbiAgICAgIHZlcmlmeUF0dGFjaG1lbnRzKGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgIHByZWNvbmRpdGlvbkVycm9yZWQgPSBlcnI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZmV0Y2hFeGlzdGluZ0RvY3Mod2Vic3FsUHJvY2Vzc0RvY3MpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9LCB3ZWJzcWxFcnJvcihjYWxsYmFjayksIGNvbXBsZXRlKTtcbiAgfSk7XG59XG5cbnZhciBjYWNoZWREYXRhYmFzZXMgPSBuZXcgX01hcCgpO1xuXG4vLyBvcGVuRGF0YWJhc2UgcGFzc2VkIGluIHRocm91Z2ggb3B0cyAoZS5nLiBmb3Igbm9kZS13ZWJzcWwpXG5mdW5jdGlvbiBvcGVuRGF0YWJhc2VXaXRoT3B0cyhvcHRzKSB7XG4gIHJldHVybiBvcHRzLndlYnNxbChvcHRzLm5hbWUsIG9wdHMudmVyc2lvbiwgb3B0cy5kZXNjcmlwdGlvbiwgb3B0cy5zaXplKTtcbn1cblxuZnVuY3Rpb24gb3BlbkRCU2FmZWx5KG9wdHMpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4ge1xuICAgICAgZGI6IG9wZW5EYXRhYmFzZVdpdGhPcHRzKG9wdHMpXG4gICAgfTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGVycm9yOiBlcnJcbiAgICB9O1xuICB9XG59XG5cbmZ1bmN0aW9uIG9wZW5EQiQxKG9wdHMpIHtcbiAgdmFyIGNhY2hlZFJlc3VsdCA9IGNhY2hlZERhdGFiYXNlcy5nZXQob3B0cy5uYW1lKTtcbiAgaWYgKCFjYWNoZWRSZXN1bHQpIHtcbiAgICBjYWNoZWRSZXN1bHQgPSBvcGVuREJTYWZlbHkob3B0cyk7XG4gICAgY2FjaGVkRGF0YWJhc2VzLnNldChvcHRzLm5hbWUsIGNhY2hlZFJlc3VsdCk7XG4gIH1cbiAgcmV0dXJuIGNhY2hlZFJlc3VsdDtcbn1cblxudmFyIHdlYnNxbENoYW5nZXMgPSBuZXcgQ2hhbmdlcygpO1xuXG5mdW5jdGlvbiBmZXRjaEF0dGFjaG1lbnRzSWZOZWNlc3NhcnkkMShkb2MsIG9wdHMsIGFwaSwgdHhuLCBjYikge1xuICB2YXIgYXR0YWNobWVudHMgPSBPYmplY3Qua2V5cyhkb2MuX2F0dGFjaG1lbnRzIHx8IHt9KTtcbiAgaWYgKCFhdHRhY2htZW50cy5sZW5ndGgpIHtcbiAgICByZXR1cm4gY2IgJiYgY2IoKTtcbiAgfVxuICB2YXIgbnVtRG9uZSA9IDA7XG5cbiAgZnVuY3Rpb24gY2hlY2tEb25lKCkge1xuICAgIGlmICgrK251bURvbmUgPT09IGF0dGFjaG1lbnRzLmxlbmd0aCAmJiBjYikge1xuICAgICAgY2IoKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBmZXRjaEF0dGFjaG1lbnQoZG9jLCBhdHQpIHtcbiAgICB2YXIgYXR0T2JqID0gZG9jLl9hdHRhY2htZW50c1thdHRdO1xuICAgIHZhciBhdHRPcHRzID0ge2JpbmFyeTogb3B0cy5iaW5hcnksIGN0eDogdHhufTtcbiAgICBhcGkuX2dldEF0dGFjaG1lbnQoZG9jLl9pZCwgYXR0LCBhdHRPYmosIGF0dE9wdHMsIGZ1bmN0aW9uIChfLCBkYXRhKSB7XG4gICAgICBkb2MuX2F0dGFjaG1lbnRzW2F0dF0gPSBleHRlbmQkMShcbiAgICAgICAgcGljayhhdHRPYmosIFsnZGlnZXN0JywgJ2NvbnRlbnRfdHlwZSddKSxcbiAgICAgICAgeyBkYXRhOiBkYXRhIH1cbiAgICAgICk7XG4gICAgICBjaGVja0RvbmUoKTtcbiAgICB9KTtcbiAgfVxuXG4gIGF0dGFjaG1lbnRzLmZvckVhY2goZnVuY3Rpb24gKGF0dCkge1xuICAgIGlmIChvcHRzLmF0dGFjaG1lbnRzICYmIG9wdHMuaW5jbHVkZV9kb2NzKSB7XG4gICAgICBmZXRjaEF0dGFjaG1lbnQoZG9jLCBhdHQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBkb2MuX2F0dGFjaG1lbnRzW2F0dF0uc3R1YiA9IHRydWU7XG4gICAgICBjaGVja0RvbmUoKTtcbiAgICB9XG4gIH0pO1xufVxuXG52YXIgUE9VQ0hfVkVSU0lPTiA9IDE7XG5cbi8vIHRoZXNlIGluZGV4ZXMgY292ZXIgdGhlIGdyb3VuZCBmb3IgbW9zdCBhbGxEb2NzIHF1ZXJpZXNcbnZhciBCWV9TRVFfU1RPUkVfREVMRVRFRF9JTkRFWF9TUUwgPVxuICAnQ1JFQVRFIElOREVYIElGIE5PVCBFWElTVFMgXFwnYnktc2VxLWRlbGV0ZWQtaWR4XFwnIE9OICcgK1xuICBCWV9TRVFfU1RPUkUkMSArICcgKHNlcSwgZGVsZXRlZCknO1xudmFyIEJZX1NFUV9TVE9SRV9ET0NfSURfUkVWX0lOREVYX1NRTCA9XG4gICdDUkVBVEUgVU5JUVVFIElOREVYIElGIE5PVCBFWElTVFMgXFwnYnktc2VxLWRvYy1pZC1yZXZcXCcgT04gJyArXG4gICAgQllfU0VRX1NUT1JFJDEgKyAnIChkb2NfaWQsIHJldiknO1xudmFyIERPQ19TVE9SRV9XSU5OSU5HU0VRX0lOREVYX1NRTCA9XG4gICdDUkVBVEUgSU5ERVggSUYgTk9UIEVYSVNUUyBcXCdkb2Mtd2lubmluZ3NlcS1pZHhcXCcgT04gJyArXG4gIERPQ19TVE9SRSQxICsgJyAod2lubmluZ3NlcSknO1xudmFyIEFUVEFDSF9BTkRfU0VRX1NUT1JFX1NFUV9JTkRFWF9TUUwgPVxuICAnQ1JFQVRFIElOREVYIElGIE5PVCBFWElTVFMgXFwnYXR0YWNoLXNlcS1zZXEtaWR4XFwnIE9OICcgK1xuICAgIEFUVEFDSF9BTkRfU0VRX1NUT1JFJDEgKyAnIChzZXEpJztcbnZhciBBVFRBQ0hfQU5EX1NFUV9TVE9SRV9BVFRBQ0hfSU5ERVhfU1FMID1cbiAgJ0NSRUFURSBVTklRVUUgSU5ERVggSUYgTk9UIEVYSVNUUyBcXCdhdHRhY2gtc2VxLWRpZ2VzdC1pZHhcXCcgT04gJyArXG4gICAgQVRUQUNIX0FORF9TRVFfU1RPUkUkMSArICcgKGRpZ2VzdCwgc2VxKSc7XG5cbnZhciBET0NfU1RPUkVfQU5EX0JZX1NFUV9KT0lORVIgPSBCWV9TRVFfU1RPUkUkMSArXG4gICcuc2VxID0gJyArIERPQ19TVE9SRSQxICsgJy53aW5uaW5nc2VxJztcblxudmFyIFNFTEVDVF9ET0NTID0gQllfU0VRX1NUT1JFJDEgKyAnLnNlcSBBUyBzZXEsICcgK1xuICBCWV9TRVFfU1RPUkUkMSArICcuZGVsZXRlZCBBUyBkZWxldGVkLCAnICtcbiAgQllfU0VRX1NUT1JFJDEgKyAnLmpzb24gQVMgZGF0YSwgJyArXG4gIEJZX1NFUV9TVE9SRSQxICsgJy5yZXYgQVMgcmV2LCAnICtcbiAgRE9DX1NUT1JFJDEgKyAnLmpzb24gQVMgbWV0YWRhdGEnO1xuXG5mdW5jdGlvbiBXZWJTcWxQb3VjaCQxKG9wdHMsIGNhbGxiYWNrKSB7XG4gIHZhciBhcGkgPSB0aGlzO1xuICB2YXIgaW5zdGFuY2VJZCA9IG51bGw7XG4gIHZhciBzaXplID0gZ2V0U2l6ZShvcHRzKTtcbiAgdmFyIGlkUmVxdWVzdHMgPSBbXTtcbiAgdmFyIGVuY29kaW5nO1xuXG4gIGFwaS5fZG9jQ291bnQgPSAtMTsgLy8gY2FjaGUgc3FsaXRlIGNvdW50KCopIGZvciBwZXJmb3JtYW5jZVxuICBhcGkuX25hbWUgPSBvcHRzLm5hbWU7XG5cbiAgLy8gZXh0ZW5kIHRoZSBvcHRpb25zIGhlcmUsIGJlY2F1c2Ugc3FsaXRlIHBsdWdpbiBoYXMgYSB0b24gb2Ygb3B0aW9uc1xuICAvLyBhbmQgdGhleSBhcmUgY29uc3RhbnRseSBjaGFuZ2luZywgc28gaXQncyBtb3JlIHBydWRlbnQgdG8gYWxsb3cgYW55dGhpbmdcbiAgdmFyIHdlYnNxbE9wdHMgPSBleHRlbmQkMSh7fSwgb3B0cywge1xuICAgIHZlcnNpb246IFBPVUNIX1ZFUlNJT04sXG4gICAgZGVzY3JpcHRpb246IG9wdHMubmFtZSxcbiAgICBzaXplOiBzaXplXG4gIH0pO1xuICB2YXIgb3BlbkRCUmVzdWx0ID0gb3BlbkRCJDEod2Vic3FsT3B0cyk7XG4gIGlmIChvcGVuREJSZXN1bHQuZXJyb3IpIHtcbiAgICByZXR1cm4gd2Vic3FsRXJyb3IoY2FsbGJhY2spKG9wZW5EQlJlc3VsdC5lcnJvcik7XG4gIH1cbiAgdmFyIGRiID0gb3BlbkRCUmVzdWx0LmRiO1xuICBpZiAodHlwZW9mIGRiLnJlYWRUcmFuc2FjdGlvbiAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIC8vIGRvZXNuJ3QgZXhpc3QgaW4gc3FsaXRlIHBsdWdpblxuICAgIGRiLnJlYWRUcmFuc2FjdGlvbiA9IGRiLnRyYW5zYWN0aW9uO1xuICB9XG5cbiAgZnVuY3Rpb24gZGJDcmVhdGVkKCkge1xuICAgIC8vIG5vdGUgdGhlIGRiIG5hbWUgaW4gY2FzZSB0aGUgYnJvd3NlciB1cGdyYWRlcyB0byBpZGJcbiAgICBpZiAoaGFzTG9jYWxTdG9yYWdlKCkpIHtcbiAgICAgIHdpbmRvdy5sb2NhbFN0b3JhZ2VbJ19wb3VjaF9fd2Vic3FsZGJfJyArIGFwaS5fbmFtZV0gPSB0cnVlO1xuICAgIH1cbiAgICBjYWxsYmFjayhudWxsLCBhcGkpO1xuICB9XG5cbiAgLy8gSW4gdGhpcyBtaWdyYXRpb24sIHdlIGFkZGVkIHRoZSAnZGVsZXRlZCcgYW5kICdsb2NhbCcgY29sdW1ucyB0byB0aGVcbiAgLy8gYnktc2VxIGFuZCBkb2Mgc3RvcmUgdGFibGVzLlxuICAvLyBUbyBwcmVzZXJ2ZSBleGlzdGluZyB1c2VyIGRhdGEsIHdlIHJlLXByb2Nlc3MgYWxsIHRoZSBleGlzdGluZyBKU09OXG4gIC8vIGFuZCBhZGQgdGhlc2UgdmFsdWVzLlxuICAvLyBDYWxsZWQgbWlncmF0aW9uMiBiZWNhdXNlIGl0IGNvcnJlc3BvbmRzIHRvIGFkYXB0ZXIgdmVyc2lvbiAoZGJfdmVyc2lvbikgIzJcbiAgZnVuY3Rpb24gcnVuTWlncmF0aW9uMih0eCwgY2FsbGJhY2spIHtcbiAgICAvLyBpbmRleCB1c2VkIGZvciB0aGUgam9pbiBpbiB0aGUgYWxsRG9jcyBxdWVyeVxuICAgIHR4LmV4ZWN1dGVTcWwoRE9DX1NUT1JFX1dJTk5JTkdTRVFfSU5ERVhfU1FMKTtcblxuICAgIHR4LmV4ZWN1dGVTcWwoJ0FMVEVSIFRBQkxFICcgKyBCWV9TRVFfU1RPUkUkMSArXG4gICAgICAnIEFERCBDT0xVTU4gZGVsZXRlZCBUSU5ZSU5UKDEpIERFRkFVTFQgMCcsIFtdLCBmdW5jdGlvbiAoKSB7XG4gICAgICB0eC5leGVjdXRlU3FsKEJZX1NFUV9TVE9SRV9ERUxFVEVEX0lOREVYX1NRTCk7XG4gICAgICB0eC5leGVjdXRlU3FsKCdBTFRFUiBUQUJMRSAnICsgRE9DX1NUT1JFJDEgK1xuICAgICAgICAnIEFERCBDT0xVTU4gbG9jYWwgVElOWUlOVCgxKSBERUZBVUxUIDAnLCBbXSwgZnVuY3Rpb24gKCkge1xuICAgICAgICB0eC5leGVjdXRlU3FsKCdDUkVBVEUgSU5ERVggSUYgTk9UIEVYSVNUUyBcXCdkb2Mtc3RvcmUtbG9jYWwtaWR4XFwnIE9OICcgK1xuICAgICAgICAgIERPQ19TVE9SRSQxICsgJyAobG9jYWwsIGlkKScpO1xuXG4gICAgICAgIHZhciBzcWwgPSAnU0VMRUNUICcgKyBET0NfU1RPUkUkMSArICcud2lubmluZ3NlcSBBUyBzZXEsICcgKyBET0NfU1RPUkUkMSArXG4gICAgICAgICAgJy5qc29uIEFTIG1ldGFkYXRhIEZST00gJyArIEJZX1NFUV9TVE9SRSQxICsgJyBKT0lOICcgKyBET0NfU1RPUkUkMSArXG4gICAgICAgICAgJyBPTiAnICsgQllfU0VRX1NUT1JFJDEgKyAnLnNlcSA9ICcgKyBET0NfU1RPUkUkMSArICcud2lubmluZ3NlcSc7XG5cbiAgICAgICAgdHguZXhlY3V0ZVNxbChzcWwsIFtdLCBmdW5jdGlvbiAodHgsIHJlc3VsdCkge1xuXG4gICAgICAgICAgdmFyIGRlbGV0ZWQgPSBbXTtcbiAgICAgICAgICB2YXIgbG9jYWwgPSBbXTtcblxuICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVzdWx0LnJvd3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBpdGVtID0gcmVzdWx0LnJvd3MuaXRlbShpKTtcbiAgICAgICAgICAgIHZhciBzZXEgPSBpdGVtLnNlcTtcbiAgICAgICAgICAgIHZhciBtZXRhZGF0YSA9IEpTT04ucGFyc2UoaXRlbS5tZXRhZGF0YSk7XG4gICAgICAgICAgICBpZiAoaXNEZWxldGVkKG1ldGFkYXRhKSkge1xuICAgICAgICAgICAgICBkZWxldGVkLnB1c2goc2VxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpc0xvY2FsSWQobWV0YWRhdGEuaWQpKSB7XG4gICAgICAgICAgICAgIGxvY2FsLnB1c2gobWV0YWRhdGEuaWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICB0eC5leGVjdXRlU3FsKCdVUERBVEUgJyArIERPQ19TVE9SRSQxICsgJ1NFVCBsb2NhbCA9IDEgV0hFUkUgaWQgSU4gJyArXG4gICAgICAgICAgICBxTWFya3MobG9jYWwubGVuZ3RoKSwgbG9jYWwsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHR4LmV4ZWN1dGVTcWwoJ1VQREFURSAnICsgQllfU0VRX1NUT1JFJDEgK1xuICAgICAgICAgICAgICAnIFNFVCBkZWxldGVkID0gMSBXSEVSRSBzZXEgSU4gJyArXG4gICAgICAgICAgICAgIHFNYXJrcyhkZWxldGVkLmxlbmd0aCksIGRlbGV0ZWQsIGNhbGxiYWNrKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIGluIHRoaXMgbWlncmF0aW9uLCB3ZSBtYWtlIGFsbCB0aGUgbG9jYWwgZG9jcyB1bnZlcnNpb25lZFxuICBmdW5jdGlvbiBydW5NaWdyYXRpb24zKHR4LCBjYWxsYmFjaykge1xuICAgIHZhciBsb2NhbCA9ICdDUkVBVEUgVEFCTEUgSUYgTk9UIEVYSVNUUyAnICsgTE9DQUxfU1RPUkUkMSArXG4gICAgICAnIChpZCBVTklRVUUsIHJldiwganNvbiknO1xuICAgIHR4LmV4ZWN1dGVTcWwobG9jYWwsIFtdLCBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgc3FsID0gJ1NFTEVDVCAnICsgRE9DX1NUT1JFJDEgKyAnLmlkIEFTIGlkLCAnICtcbiAgICAgICAgQllfU0VRX1NUT1JFJDEgKyAnLmpzb24gQVMgZGF0YSAnICtcbiAgICAgICAgJ0ZST00gJyArIEJZX1NFUV9TVE9SRSQxICsgJyBKT0lOICcgK1xuICAgICAgICBET0NfU1RPUkUkMSArICcgT04gJyArIEJZX1NFUV9TVE9SRSQxICsgJy5zZXEgPSAnICtcbiAgICAgICAgRE9DX1NUT1JFJDEgKyAnLndpbm5pbmdzZXEgV0hFUkUgbG9jYWwgPSAxJztcbiAgICAgIHR4LmV4ZWN1dGVTcWwoc3FsLCBbXSwgZnVuY3Rpb24gKHR4LCByZXMpIHtcbiAgICAgICAgdmFyIHJvd3MgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZXMucm93cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIHJvd3MucHVzaChyZXMucm93cy5pdGVtKGkpKTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBkb05leHQoKSB7XG4gICAgICAgICAgaWYgKCFyb3dzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKHR4KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIHJvdyA9IHJvd3Muc2hpZnQoKTtcbiAgICAgICAgICB2YXIgcmV2ID0gSlNPTi5wYXJzZShyb3cuZGF0YSkuX3JldjtcbiAgICAgICAgICB0eC5leGVjdXRlU3FsKCdJTlNFUlQgSU5UTyAnICsgTE9DQUxfU1RPUkUkMSArXG4gICAgICAgICAgICAgICcgKGlkLCByZXYsIGpzb24pIFZBTFVFUyAoPyw/LD8pJyxcbiAgICAgICAgICAgICAgW3Jvdy5pZCwgcmV2LCByb3cuZGF0YV0sIGZ1bmN0aW9uICh0eCkge1xuICAgICAgICAgICAgdHguZXhlY3V0ZVNxbCgnREVMRVRFIEZST00gJyArIERPQ19TVE9SRSQxICsgJyBXSEVSRSBpZD0/JyxcbiAgICAgICAgICAgICAgICBbcm93LmlkXSwgZnVuY3Rpb24gKHR4KSB7XG4gICAgICAgICAgICAgIHR4LmV4ZWN1dGVTcWwoJ0RFTEVURSBGUk9NICcgKyBCWV9TRVFfU1RPUkUkMSArICcgV0hFUkUgc2VxPT8nLFxuICAgICAgICAgICAgICAgICAgW3Jvdy5zZXFdLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgZG9OZXh0KCk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZG9OZXh0KCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIGluIHRoaXMgbWlncmF0aW9uLCB3ZSByZW1vdmUgZG9jX2lkX3JldiBhbmQganVzdCB1c2UgcmV2XG4gIGZ1bmN0aW9uIHJ1bk1pZ3JhdGlvbjQodHgsIGNhbGxiYWNrKSB7XG5cbiAgICBmdW5jdGlvbiB1cGRhdGVSb3dzKHJvd3MpIHtcbiAgICAgIGZ1bmN0aW9uIGRvTmV4dCgpIHtcbiAgICAgICAgaWYgKCFyb3dzLmxlbmd0aCkge1xuICAgICAgICAgIHJldHVybiBjYWxsYmFjayh0eCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHJvdyA9IHJvd3Muc2hpZnQoKTtcbiAgICAgICAgdmFyIGRvY19pZF9yZXYgPSBwYXJzZUhleFN0cmluZyhyb3cuaGV4LCBlbmNvZGluZyk7XG4gICAgICAgIHZhciBpZHggPSBkb2NfaWRfcmV2Lmxhc3RJbmRleE9mKCc6OicpO1xuICAgICAgICB2YXIgZG9jX2lkID0gZG9jX2lkX3Jldi5zdWJzdHJpbmcoMCwgaWR4KTtcbiAgICAgICAgdmFyIHJldiA9IGRvY19pZF9yZXYuc3Vic3RyaW5nKGlkeCArIDIpO1xuICAgICAgICB2YXIgc3FsID0gJ1VQREFURSAnICsgQllfU0VRX1NUT1JFJDEgK1xuICAgICAgICAgICcgU0VUIGRvY19pZD0/LCByZXY9PyBXSEVSRSBkb2NfaWRfcmV2PT8nO1xuICAgICAgICB0eC5leGVjdXRlU3FsKHNxbCwgW2RvY19pZCwgcmV2LCBkb2NfaWRfcmV2XSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGRvTmV4dCgpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGRvTmV4dCgpO1xuICAgIH1cblxuICAgIHZhciBzcWwgPSAnQUxURVIgVEFCTEUgJyArIEJZX1NFUV9TVE9SRSQxICsgJyBBREQgQ09MVU1OIGRvY19pZCc7XG4gICAgdHguZXhlY3V0ZVNxbChzcWwsIFtdLCBmdW5jdGlvbiAodHgpIHtcbiAgICAgIHZhciBzcWwgPSAnQUxURVIgVEFCTEUgJyArIEJZX1NFUV9TVE9SRSQxICsgJyBBREQgQ09MVU1OIHJldic7XG4gICAgICB0eC5leGVjdXRlU3FsKHNxbCwgW10sIGZ1bmN0aW9uICh0eCkge1xuICAgICAgICB0eC5leGVjdXRlU3FsKEJZX1NFUV9TVE9SRV9ET0NfSURfUkVWX0lOREVYX1NRTCwgW10sIGZ1bmN0aW9uICh0eCkge1xuICAgICAgICAgIHZhciBzcWwgPSAnU0VMRUNUIGhleChkb2NfaWRfcmV2KSBhcyBoZXggRlJPTSAnICsgQllfU0VRX1NUT1JFJDE7XG4gICAgICAgICAgdHguZXhlY3V0ZVNxbChzcWwsIFtdLCBmdW5jdGlvbiAodHgsIHJlcykge1xuICAgICAgICAgICAgdmFyIHJvd3MgPSBbXTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVzLnJvd3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgcm93cy5wdXNoKHJlcy5yb3dzLml0ZW0oaSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdXBkYXRlUm93cyhyb3dzKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIGluIHRoaXMgbWlncmF0aW9uLCB3ZSBhZGQgdGhlIGF0dGFjaF9hbmRfc2VxIHRhYmxlXG4gIC8vIGZvciBpc3N1ZSAjMjgxOFxuICBmdW5jdGlvbiBydW5NaWdyYXRpb241KHR4LCBjYWxsYmFjaykge1xuXG4gICAgZnVuY3Rpb24gbWlncmF0ZUF0dHNBbmRTZXFzKHR4KSB7XG4gICAgICAvLyBuZWVkIHRvIGFjdHVhbGx5IHBvcHVsYXRlIHRoZSB0YWJsZS4gdGhpcyBpcyB0aGUgZXhwZW5zaXZlIHBhcnQsXG4gICAgICAvLyBzbyBhcyBhbiBvcHRpbWl6YXRpb24sIGNoZWNrIGZpcnN0IHRoYXQgdGhpcyBkYXRhYmFzZSBldmVuXG4gICAgICAvLyBjb250YWlucyBhdHRhY2htZW50c1xuICAgICAgdmFyIHNxbCA9ICdTRUxFQ1QgQ09VTlQoKikgQVMgY250IEZST00gJyArIEFUVEFDSF9TVE9SRSQxO1xuICAgICAgdHguZXhlY3V0ZVNxbChzcWwsIFtdLCBmdW5jdGlvbiAodHgsIHJlcykge1xuICAgICAgICB2YXIgY291bnQgPSByZXMucm93cy5pdGVtKDApLmNudDtcbiAgICAgICAgaWYgKCFjb3VudCkge1xuICAgICAgICAgIHJldHVybiBjYWxsYmFjayh0eCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgb2Zmc2V0ID0gMDtcbiAgICAgICAgdmFyIHBhZ2VTaXplID0gMTA7XG4gICAgICAgIGZ1bmN0aW9uIG5leHRQYWdlKCkge1xuICAgICAgICAgIHZhciBzcWwgPSBzZWxlY3QoXG4gICAgICAgICAgICBTRUxFQ1RfRE9DUyArICcsICcgKyBET0NfU1RPUkUkMSArICcuaWQgQVMgaWQnLFxuICAgICAgICAgICAgW0RPQ19TVE9SRSQxLCBCWV9TRVFfU1RPUkUkMV0sXG4gICAgICAgICAgICBET0NfU1RPUkVfQU5EX0JZX1NFUV9KT0lORVIsXG4gICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgRE9DX1NUT1JFJDEgKyAnLmlkICdcbiAgICAgICAgICApO1xuICAgICAgICAgIHNxbCArPSAnIExJTUlUICcgKyBwYWdlU2l6ZSArICcgT0ZGU0VUICcgKyBvZmZzZXQ7XG4gICAgICAgICAgb2Zmc2V0ICs9IHBhZ2VTaXplO1xuICAgICAgICAgIHR4LmV4ZWN1dGVTcWwoc3FsLCBbXSwgZnVuY3Rpb24gKHR4LCByZXMpIHtcbiAgICAgICAgICAgIGlmICghcmVzLnJvd3MubGVuZ3RoKSB7XG4gICAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayh0eCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZGlnZXN0U2VxcyA9IHt9O1xuICAgICAgICAgICAgZnVuY3Rpb24gYWRkRGlnZXN0U2VxKGRpZ2VzdCwgc2VxKSB7XG4gICAgICAgICAgICAgIC8vIHVuaXEgZGlnZXN0L3NlcSBwYWlycywganVzdCBpbiBjYXNlIHRoZXJlIGFyZSBkdXBzXG4gICAgICAgICAgICAgIHZhciBzZXFzID0gZGlnZXN0U2Vxc1tkaWdlc3RdID0gKGRpZ2VzdFNlcXNbZGlnZXN0XSB8fCBbXSk7XG4gICAgICAgICAgICAgIGlmIChzZXFzLmluZGV4T2Yoc2VxKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBzZXFzLnB1c2goc2VxKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZXMucm93cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICB2YXIgcm93ID0gcmVzLnJvd3MuaXRlbShpKTtcbiAgICAgICAgICAgICAgdmFyIGRvYyA9IHVuc3RyaW5naWZ5RG9jKHJvdy5kYXRhLCByb3cuaWQsIHJvdy5yZXYpO1xuICAgICAgICAgICAgICB2YXIgYXR0cyA9IE9iamVjdC5rZXlzKGRvYy5fYXR0YWNobWVudHMgfHwge30pO1xuICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGF0dHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgYXR0ID0gZG9jLl9hdHRhY2htZW50c1thdHRzW2pdXTtcbiAgICAgICAgICAgICAgICBhZGREaWdlc3RTZXEoYXR0LmRpZ2VzdCwgcm93LnNlcSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBkaWdlc3RTZXFQYWlycyA9IFtdO1xuICAgICAgICAgICAgT2JqZWN0LmtleXMoZGlnZXN0U2VxcykuZm9yRWFjaChmdW5jdGlvbiAoZGlnZXN0KSB7XG4gICAgICAgICAgICAgIHZhciBzZXFzID0gZGlnZXN0U2Vxc1tkaWdlc3RdO1xuICAgICAgICAgICAgICBzZXFzLmZvckVhY2goZnVuY3Rpb24gKHNlcSkge1xuICAgICAgICAgICAgICAgIGRpZ2VzdFNlcVBhaXJzLnB1c2goW2RpZ2VzdCwgc2VxXSk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAoIWRpZ2VzdFNlcVBhaXJzLmxlbmd0aCkge1xuICAgICAgICAgICAgICByZXR1cm4gbmV4dFBhZ2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBudW1Eb25lID0gMDtcbiAgICAgICAgICAgIGRpZ2VzdFNlcVBhaXJzLmZvckVhY2goZnVuY3Rpb24gKHBhaXIpIHtcbiAgICAgICAgICAgICAgdmFyIHNxbCA9ICdJTlNFUlQgSU5UTyAnICsgQVRUQUNIX0FORF9TRVFfU1RPUkUkMSArXG4gICAgICAgICAgICAgICAgJyAoZGlnZXN0LCBzZXEpIFZBTFVFUyAoPyw/KSc7XG4gICAgICAgICAgICAgIHR4LmV4ZWN1dGVTcWwoc3FsLCBwYWlyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCsrbnVtRG9uZSA9PT0gZGlnZXN0U2VxUGFpcnMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICBuZXh0UGFnZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBuZXh0UGFnZSgpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgdmFyIGF0dGFjaEFuZFJldiA9ICdDUkVBVEUgVEFCTEUgSUYgTk9UIEVYSVNUUyAnICtcbiAgICAgIEFUVEFDSF9BTkRfU0VRX1NUT1JFJDEgKyAnIChkaWdlc3QsIHNlcSBJTlRFR0VSKSc7XG4gICAgdHguZXhlY3V0ZVNxbChhdHRhY2hBbmRSZXYsIFtdLCBmdW5jdGlvbiAodHgpIHtcbiAgICAgIHR4LmV4ZWN1dGVTcWwoXG4gICAgICAgIEFUVEFDSF9BTkRfU0VRX1NUT1JFX0FUVEFDSF9JTkRFWF9TUUwsIFtdLCBmdW5jdGlvbiAodHgpIHtcbiAgICAgICAgICB0eC5leGVjdXRlU3FsKFxuICAgICAgICAgICAgQVRUQUNIX0FORF9TRVFfU1RPUkVfU0VRX0lOREVYX1NRTCwgW10sXG4gICAgICAgICAgICBtaWdyYXRlQXR0c0FuZFNlcXMpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIGluIHRoaXMgbWlncmF0aW9uLCB3ZSB1c2UgZXNjYXBlQmxvYigpIGFuZCB1bmVzY2FwZUJsb2IoKVxuICAvLyBpbnN0ZWFkIG9mIHJlYWRpbmcgb3V0IHRoZSBiaW5hcnkgYXMgSEVYLCB3aGljaCBpcyBzbG93XG4gIGZ1bmN0aW9uIHJ1bk1pZ3JhdGlvbjYodHgsIGNhbGxiYWNrKSB7XG4gICAgdmFyIHNxbCA9ICdBTFRFUiBUQUJMRSAnICsgQVRUQUNIX1NUT1JFJDEgK1xuICAgICAgJyBBREQgQ09MVU1OIGVzY2FwZWQgVElOWUlOVCgxKSBERUZBVUxUIDAnO1xuICAgIHR4LmV4ZWN1dGVTcWwoc3FsLCBbXSwgY2FsbGJhY2spO1xuICB9XG5cbiAgLy8gaXNzdWUgIzMxMzYsIGluIHRoaXMgbWlncmF0aW9uIHdlIG5lZWQgYSBcImxhdGVzdCBzZXFcIiBhcyB3ZWxsXG4gIC8vIGFzIHRoZSBcIndpbm5pbmcgc2VxXCIgaW4gdGhlIGRvYyBzdG9yZVxuICBmdW5jdGlvbiBydW5NaWdyYXRpb243KHR4LCBjYWxsYmFjaykge1xuICAgIHZhciBzcWwgPSAnQUxURVIgVEFCTEUgJyArIERPQ19TVE9SRSQxICtcbiAgICAgICcgQUREIENPTFVNTiBtYXhfc2VxIElOVEVHRVInO1xuICAgIHR4LmV4ZWN1dGVTcWwoc3FsLCBbXSwgZnVuY3Rpb24gKHR4KSB7XG4gICAgICB2YXIgc3FsID0gJ1VQREFURSAnICsgRE9DX1NUT1JFJDEgKyAnIFNFVCBtYXhfc2VxPShTRUxFQ1QgTUFYKHNlcSkgRlJPTSAnICtcbiAgICAgICAgQllfU0VRX1NUT1JFJDEgKyAnIFdIRVJFIGRvY19pZD1pZCknO1xuICAgICAgdHguZXhlY3V0ZVNxbChzcWwsIFtdLCBmdW5jdGlvbiAodHgpIHtcbiAgICAgICAgLy8gYWRkIHVuaXF1ZSBpbmRleCBhZnRlciBmaWxsaW5nLCBlbHNlIHdlJ2xsIGdldCBhIGNvbnN0cmFpbnRcbiAgICAgICAgLy8gZXJyb3Igd2hlbiB3ZSBkbyB0aGUgQUxURVIgVEFCTEVcbiAgICAgICAgdmFyIHNxbCA9XG4gICAgICAgICAgJ0NSRUFURSBVTklRVUUgSU5ERVggSUYgTk9UIEVYSVNUUyBcXCdkb2MtbWF4LXNlcS1pZHhcXCcgT04gJyArXG4gICAgICAgICAgRE9DX1NUT1JFJDEgKyAnIChtYXhfc2VxKSc7XG4gICAgICAgIHR4LmV4ZWN1dGVTcWwoc3FsLCBbXSwgY2FsbGJhY2spO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVja0VuY29kaW5nKHR4LCBjYikge1xuICAgIC8vIFVURi04IG9uIGNocm9tZS9hbmRyb2lkLCBVVEYtMTYgb24gc2FmYXJpIDwgNy4xXG4gICAgdHguZXhlY3V0ZVNxbCgnU0VMRUNUIEhFWChcImFcIikgQVMgaGV4JywgW10sIGZ1bmN0aW9uICh0eCwgcmVzKSB7XG4gICAgICAgIHZhciBoZXggPSByZXMucm93cy5pdGVtKDApLmhleDtcbiAgICAgICAgZW5jb2RpbmcgPSBoZXgubGVuZ3RoID09PSAyID8gJ1VURi04JyA6ICdVVEYtMTYnO1xuICAgICAgICBjYigpO1xuICAgICAgfVxuICAgICk7XG4gIH1cblxuICBmdW5jdGlvbiBvbkdldEluc3RhbmNlSWQoKSB7XG4gICAgd2hpbGUgKGlkUmVxdWVzdHMubGVuZ3RoID4gMCkge1xuICAgICAgdmFyIGlkQ2FsbGJhY2sgPSBpZFJlcXVlc3RzLnBvcCgpO1xuICAgICAgaWRDYWxsYmFjayhudWxsLCBpbnN0YW5jZUlkKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBvbkdldFZlcnNpb24odHgsIGRiVmVyc2lvbikge1xuICAgIGlmIChkYlZlcnNpb24gPT09IDApIHtcbiAgICAgIC8vIGluaXRpYWwgc2NoZW1hXG5cbiAgICAgIHZhciBtZXRhID0gJ0NSRUFURSBUQUJMRSBJRiBOT1QgRVhJU1RTICcgKyBNRVRBX1NUT1JFJDEgK1xuICAgICAgICAnIChkYmlkLCBkYl92ZXJzaW9uIElOVEVHRVIpJztcbiAgICAgIHZhciBhdHRhY2ggPSAnQ1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgJyArIEFUVEFDSF9TVE9SRSQxICtcbiAgICAgICAgJyAoZGlnZXN0IFVOSVFVRSwgZXNjYXBlZCBUSU5ZSU5UKDEpLCBib2R5IEJMT0IpJztcbiAgICAgIHZhciBhdHRhY2hBbmRSZXYgPSAnQ1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgJyArXG4gICAgICAgIEFUVEFDSF9BTkRfU0VRX1NUT1JFJDEgKyAnIChkaWdlc3QsIHNlcSBJTlRFR0VSKSc7XG4gICAgICAvLyBUT0RPOiBtaWdyYXRlIHdpbm5pbmdzZXEgdG8gSU5URUdFUlxuICAgICAgdmFyIGRvYyA9ICdDUkVBVEUgVEFCTEUgSUYgTk9UIEVYSVNUUyAnICsgRE9DX1NUT1JFJDEgK1xuICAgICAgICAnIChpZCB1bmlxdWUsIGpzb24sIHdpbm5pbmdzZXEsIG1heF9zZXEgSU5URUdFUiBVTklRVUUpJztcbiAgICAgIHZhciBzZXEgPSAnQ1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgJyArIEJZX1NFUV9TVE9SRSQxICtcbiAgICAgICAgJyAoc2VxIElOVEVHRVIgTk9UIE5VTEwgUFJJTUFSWSBLRVkgQVVUT0lOQ1JFTUVOVCwgJyArXG4gICAgICAgICdqc29uLCBkZWxldGVkIFRJTllJTlQoMSksIGRvY19pZCwgcmV2KSc7XG4gICAgICB2YXIgbG9jYWwgPSAnQ1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgJyArIExPQ0FMX1NUT1JFJDEgK1xuICAgICAgICAnIChpZCBVTklRVUUsIHJldiwganNvbiknO1xuXG4gICAgICAvLyBjcmVhdGVzXG4gICAgICB0eC5leGVjdXRlU3FsKGF0dGFjaCk7XG4gICAgICB0eC5leGVjdXRlU3FsKGxvY2FsKTtcbiAgICAgIHR4LmV4ZWN1dGVTcWwoYXR0YWNoQW5kUmV2LCBbXSwgZnVuY3Rpb24gKCkge1xuICAgICAgICB0eC5leGVjdXRlU3FsKEFUVEFDSF9BTkRfU0VRX1NUT1JFX1NFUV9JTkRFWF9TUUwpO1xuICAgICAgICB0eC5leGVjdXRlU3FsKEFUVEFDSF9BTkRfU0VRX1NUT1JFX0FUVEFDSF9JTkRFWF9TUUwpO1xuICAgICAgfSk7XG4gICAgICB0eC5leGVjdXRlU3FsKGRvYywgW10sIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdHguZXhlY3V0ZVNxbChET0NfU1RPUkVfV0lOTklOR1NFUV9JTkRFWF9TUUwpO1xuICAgICAgICB0eC5leGVjdXRlU3FsKHNlcSwgW10sIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICB0eC5leGVjdXRlU3FsKEJZX1NFUV9TVE9SRV9ERUxFVEVEX0lOREVYX1NRTCk7XG4gICAgICAgICAgdHguZXhlY3V0ZVNxbChCWV9TRVFfU1RPUkVfRE9DX0lEX1JFVl9JTkRFWF9TUUwpO1xuICAgICAgICAgIHR4LmV4ZWN1dGVTcWwobWV0YSwgW10sIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIC8vIG1hcmsgdGhlIGRiIHZlcnNpb24sIGFuZCBuZXcgZGJpZFxuICAgICAgICAgICAgdmFyIGluaXRTZXEgPSAnSU5TRVJUIElOVE8gJyArIE1FVEFfU1RPUkUkMSArXG4gICAgICAgICAgICAgICcgKGRiX3ZlcnNpb24sIGRiaWQpIFZBTFVFUyAoPyw/KSc7XG4gICAgICAgICAgICBpbnN0YW5jZUlkID0gdXVpZCgpO1xuICAgICAgICAgICAgdmFyIGluaXRTZXFBcmdzID0gW0FEQVBURVJfVkVSU0lPTiQxLCBpbnN0YW5jZUlkXTtcbiAgICAgICAgICAgIHR4LmV4ZWN1dGVTcWwoaW5pdFNlcSwgaW5pdFNlcUFyZ3MsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgb25HZXRJbnN0YW5jZUlkKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9IGVsc2UgeyAvLyB2ZXJzaW9uID4gMFxuXG4gICAgICB2YXIgc2V0dXBEb25lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbWlncmF0ZWQgPSBkYlZlcnNpb24gPCBBREFQVEVSX1ZFUlNJT04kMTtcbiAgICAgICAgaWYgKG1pZ3JhdGVkKSB7XG4gICAgICAgICAgLy8gdXBkYXRlIHRoZSBkYiB2ZXJzaW9uIHdpdGhpbiB0aGlzIHRyYW5zYWN0aW9uXG4gICAgICAgICAgdHguZXhlY3V0ZVNxbCgnVVBEQVRFICcgKyBNRVRBX1NUT1JFJDEgKyAnIFNFVCBkYl92ZXJzaW9uID0gJyArXG4gICAgICAgICAgICBBREFQVEVSX1ZFUlNJT04kMSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gbm90aWZ5IGRiLmlkKCkgY2FsbGVyc1xuICAgICAgICB2YXIgc3FsID0gJ1NFTEVDVCBkYmlkIEZST00gJyArIE1FVEFfU1RPUkUkMTtcbiAgICAgICAgdHguZXhlY3V0ZVNxbChzcWwsIFtdLCBmdW5jdGlvbiAodHgsIHJlc3VsdCkge1xuICAgICAgICAgIGluc3RhbmNlSWQgPSByZXN1bHQucm93cy5pdGVtKDApLmRiaWQ7XG4gICAgICAgICAgb25HZXRJbnN0YW5jZUlkKCk7XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgLy8gd291bGQgbG92ZSB0byB1c2UgcHJvbWlzZXMgaGVyZSwgYnV0IHRoZW4gd2Vic3FsXG4gICAgICAvLyBlbmRzIHRoZSB0cmFuc2FjdGlvbiBlYXJseVxuICAgICAgdmFyIHRhc2tzID0gW1xuICAgICAgICBydW5NaWdyYXRpb24yLFxuICAgICAgICBydW5NaWdyYXRpb24zLFxuICAgICAgICBydW5NaWdyYXRpb240LFxuICAgICAgICBydW5NaWdyYXRpb241LFxuICAgICAgICBydW5NaWdyYXRpb242LFxuICAgICAgICBydW5NaWdyYXRpb243LFxuICAgICAgICBzZXR1cERvbmVcbiAgICAgIF07XG5cbiAgICAgIC8vIHJ1biBlYWNoIG1pZ3JhdGlvbiBzZXF1ZW50aWFsbHlcbiAgICAgIHZhciBpID0gZGJWZXJzaW9uO1xuICAgICAgdmFyIG5leHRNaWdyYXRpb24gPSBmdW5jdGlvbiAodHgpIHtcbiAgICAgICAgdGFza3NbaSAtIDFdKHR4LCBuZXh0TWlncmF0aW9uKTtcbiAgICAgICAgaSsrO1xuICAgICAgfTtcbiAgICAgIG5leHRNaWdyYXRpb24odHgpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHNldHVwKCkge1xuICAgIGRiLnRyYW5zYWN0aW9uKGZ1bmN0aW9uICh0eCkge1xuICAgICAgLy8gZmlyc3QgY2hlY2sgdGhlIGVuY29kaW5nXG4gICAgICBjaGVja0VuY29kaW5nKHR4LCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIHRoZW4gZ2V0IHRoZSB2ZXJzaW9uXG4gICAgICAgIGZldGNoVmVyc2lvbih0eCk7XG4gICAgICB9KTtcbiAgICB9LCB3ZWJzcWxFcnJvcihjYWxsYmFjayksIGRiQ3JlYXRlZCk7XG4gIH1cblxuICBmdW5jdGlvbiBmZXRjaFZlcnNpb24odHgpIHtcbiAgICB2YXIgc3FsID0gJ1NFTEVDVCBzcWwgRlJPTSBzcWxpdGVfbWFzdGVyIFdIRVJFIHRibF9uYW1lID0gJyArIE1FVEFfU1RPUkUkMTtcbiAgICB0eC5leGVjdXRlU3FsKHNxbCwgW10sIGZ1bmN0aW9uICh0eCwgcmVzdWx0KSB7XG4gICAgICBpZiAoIXJlc3VsdC5yb3dzLmxlbmd0aCkge1xuICAgICAgICAvLyBkYXRhYmFzZSBoYXNuJ3QgZXZlbiBiZWVuIGNyZWF0ZWQgeWV0ICh2ZXJzaW9uIDApXG4gICAgICAgIG9uR2V0VmVyc2lvbih0eCwgMCk7XG4gICAgICB9IGVsc2UgaWYgKCEvZGJfdmVyc2lvbi8udGVzdChyZXN1bHQucm93cy5pdGVtKDApLnNxbCkpIHtcbiAgICAgICAgLy8gdGFibGUgd2FzIGNyZWF0ZWQsIGJ1dCB3aXRob3V0IHRoZSBuZXcgZGJfdmVyc2lvbiBjb2x1bW4sXG4gICAgICAgIC8vIHNvIGFkZCBpdC5cbiAgICAgICAgdHguZXhlY3V0ZVNxbCgnQUxURVIgVEFCTEUgJyArIE1FVEFfU1RPUkUkMSArXG4gICAgICAgICAgJyBBREQgQ09MVU1OIGRiX3ZlcnNpb24gSU5URUdFUicsIFtdLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgLy8gYmVmb3JlIHZlcnNpb24gMiwgdGhpcyBjb2x1bW4gZGlkbid0IGV2ZW4gZXhpc3RcbiAgICAgICAgICBvbkdldFZlcnNpb24odHgsIDEpO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7IC8vIGNvbHVtbiBleGlzdHMsIHdlIGNhbiBzYWZlbHkgZ2V0IGl0XG4gICAgICAgIHR4LmV4ZWN1dGVTcWwoJ1NFTEVDVCBkYl92ZXJzaW9uIEZST00gJyArIE1FVEFfU1RPUkUkMSxcbiAgICAgICAgICBbXSwgZnVuY3Rpb24gKHR4LCByZXN1bHQpIHtcbiAgICAgICAgICB2YXIgZGJWZXJzaW9uID0gcmVzdWx0LnJvd3MuaXRlbSgwKS5kYl92ZXJzaW9uO1xuICAgICAgICAgIG9uR2V0VmVyc2lvbih0eCwgZGJWZXJzaW9uKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBzZXR1cCgpO1xuXG4gIGFwaS50eXBlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAnd2Vic3FsJztcbiAgfTtcblxuICBhcGkuX2lkID0gdG9Qcm9taXNlKGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrKG51bGwsIGluc3RhbmNlSWQpO1xuICB9KTtcblxuICBhcGkuX2luZm8gPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBkYi5yZWFkVHJhbnNhY3Rpb24oZnVuY3Rpb24gKHR4KSB7XG4gICAgICBjb3VudERvY3ModHgsIGZ1bmN0aW9uIChkb2NDb3VudCkge1xuICAgICAgICB2YXIgc3FsID0gJ1NFTEVDVCBNQVgoc2VxKSBBUyBzZXEgRlJPTSAnICsgQllfU0VRX1NUT1JFJDE7XG4gICAgICAgIHR4LmV4ZWN1dGVTcWwoc3FsLCBbXSwgZnVuY3Rpb24gKHR4LCByZXMpIHtcbiAgICAgICAgICB2YXIgdXBkYXRlU2VxID0gcmVzLnJvd3MuaXRlbSgwKS5zZXEgfHwgMDtcbiAgICAgICAgICBjYWxsYmFjayhudWxsLCB7XG4gICAgICAgICAgICBkb2NfY291bnQ6IGRvY0NvdW50LFxuICAgICAgICAgICAgdXBkYXRlX3NlcTogdXBkYXRlU2VxLFxuICAgICAgICAgICAgd2Vic3FsX2VuY29kaW5nOiBlbmNvZGluZ1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0sIHdlYnNxbEVycm9yKGNhbGxiYWNrKSk7XG4gIH07XG5cbiAgYXBpLl9idWxrRG9jcyA9IGZ1bmN0aW9uIChyZXEsIHJlcU9wdHMsIGNhbGxiYWNrKSB7XG4gICAgd2Vic3FsQnVsa0RvY3Mob3B0cywgcmVxLCByZXFPcHRzLCBhcGksIGRiLCB3ZWJzcWxDaGFuZ2VzLCBjYWxsYmFjayk7XG4gIH07XG5cbiAgZnVuY3Rpb24gbGF0ZXN0JCQodHgsIGlkLCByZXYsIGNhbGxiYWNrLCBmaW5pc2gpIHtcbiAgICB2YXIgc3FsID0gc2VsZWN0KFxuICAgICAgICBTRUxFQ1RfRE9DUyxcbiAgICAgICAgW0RPQ19TVE9SRSQxLCBCWV9TRVFfU1RPUkUkMV0sXG4gICAgICAgIERPQ19TVE9SRV9BTkRfQllfU0VRX0pPSU5FUixcbiAgICAgICAgRE9DX1NUT1JFJDEgKyAnLmlkPT8nKTtcbiAgICB2YXIgc3FsQXJncyA9IFtpZF07XG5cbiAgICB0eC5leGVjdXRlU3FsKHNxbCwgc3FsQXJncywgZnVuY3Rpb24gKGEsIHJlc3VsdHMpIHtcbiAgICAgIGlmICghcmVzdWx0cy5yb3dzLmxlbmd0aCkge1xuICAgICAgICB2YXIgZXJyID0gY3JlYXRlRXJyb3IoTUlTU0lOR19ET0MsICdtaXNzaW5nJyk7XG4gICAgICAgIHJldHVybiBmaW5pc2goZXJyKTtcbiAgICAgIH1cbiAgICAgIHZhciBpdGVtID0gcmVzdWx0cy5yb3dzLml0ZW0oMCk7XG4gICAgICB2YXIgbWV0YWRhdGEgPSBzYWZlSnNvblBhcnNlKGl0ZW0ubWV0YWRhdGEpO1xuICAgICAgY2FsbGJhY2sobGF0ZXN0KHJldiwgbWV0YWRhdGEpKTtcbiAgICB9KTtcbiAgfVxuXG4gIGFwaS5fZ2V0ID0gZnVuY3Rpb24gKGlkLCBvcHRzLCBjYWxsYmFjaykge1xuICAgIHZhciBkb2M7XG4gICAgdmFyIG1ldGFkYXRhO1xuICAgIHZhciB0eCA9IG9wdHMuY3R4O1xuICAgIGlmICghdHgpIHtcbiAgICAgIHJldHVybiBkYi5yZWFkVHJhbnNhY3Rpb24oZnVuY3Rpb24gKHR4bikge1xuICAgICAgICBhcGkuX2dldChpZCwgZXh0ZW5kJDEoe2N0eDogdHhufSwgb3B0cyksIGNhbGxiYWNrKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZpbmlzaChlcnIpIHtcbiAgICAgIGNhbGxiYWNrKGVyciwge2RvYzogZG9jLCBtZXRhZGF0YTogbWV0YWRhdGEsIGN0eDogdHh9KTtcbiAgICB9XG5cbiAgICB2YXIgc3FsO1xuICAgIHZhciBzcWxBcmdzO1xuXG4gICAgaWYoIW9wdHMucmV2KSB7XG4gICAgICBzcWwgPSBzZWxlY3QoXG4gICAgICAgIFNFTEVDVF9ET0NTLFxuICAgICAgICBbRE9DX1NUT1JFJDEsIEJZX1NFUV9TVE9SRSQxXSxcbiAgICAgICAgRE9DX1NUT1JFX0FORF9CWV9TRVFfSk9JTkVSLFxuICAgICAgICBET0NfU1RPUkUkMSArICcuaWQ9PycpO1xuICAgICAgc3FsQXJncyA9IFtpZF07XG4gICAgfSBlbHNlIGlmIChvcHRzLmxhdGVzdCkge1xuICAgICAgbGF0ZXN0JCQodHgsIGlkLCBvcHRzLnJldiwgZnVuY3Rpb24gKGxhdGVzdFJldikge1xuICAgICAgICBvcHRzLmxhdGVzdCA9IGZhbHNlO1xuICAgICAgICBvcHRzLnJldiA9IGxhdGVzdFJldjtcbiAgICAgICAgYXBpLl9nZXQoaWQsIG9wdHMsIGNhbGxiYWNrKTtcbiAgICAgIH0sIGZpbmlzaCk7XG4gICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgIHNxbCA9IHNlbGVjdChcbiAgICAgICAgU0VMRUNUX0RPQ1MsXG4gICAgICAgIFtET0NfU1RPUkUkMSwgQllfU0VRX1NUT1JFJDFdLFxuICAgICAgICBET0NfU1RPUkUkMSArICcuaWQ9JyArIEJZX1NFUV9TVE9SRSQxICsgJy5kb2NfaWQnLFxuICAgICAgICBbQllfU0VRX1NUT1JFJDEgKyAnLmRvY19pZD0/JywgQllfU0VRX1NUT1JFJDEgKyAnLnJldj0/J10pO1xuICAgICAgc3FsQXJncyA9IFtpZCwgb3B0cy5yZXZdO1xuICAgIH1cblxuICAgIHR4LmV4ZWN1dGVTcWwoc3FsLCBzcWxBcmdzLCBmdW5jdGlvbiAoYSwgcmVzdWx0cykge1xuICAgICAgaWYgKCFyZXN1bHRzLnJvd3MubGVuZ3RoKSB7XG4gICAgICAgIHZhciBtaXNzaW5nRXJyID0gY3JlYXRlRXJyb3IoTUlTU0lOR19ET0MsICdtaXNzaW5nJyk7XG4gICAgICAgIHJldHVybiBmaW5pc2gobWlzc2luZ0Vycik7XG4gICAgICB9XG4gICAgICB2YXIgaXRlbSA9IHJlc3VsdHMucm93cy5pdGVtKDApO1xuICAgICAgbWV0YWRhdGEgPSBzYWZlSnNvblBhcnNlKGl0ZW0ubWV0YWRhdGEpO1xuICAgICAgaWYgKGl0ZW0uZGVsZXRlZCAmJiAhb3B0cy5yZXYpIHtcbiAgICAgICAgdmFyIGRlbGV0ZWRFcnIgPSBjcmVhdGVFcnJvcihNSVNTSU5HX0RPQywgJ2RlbGV0ZWQnKTtcbiAgICAgICAgcmV0dXJuIGZpbmlzaChkZWxldGVkRXJyKTtcbiAgICAgIH1cbiAgICAgIGRvYyA9IHVuc3RyaW5naWZ5RG9jKGl0ZW0uZGF0YSwgbWV0YWRhdGEuaWQsIGl0ZW0ucmV2KTtcbiAgICAgIGZpbmlzaCgpO1xuICAgIH0pO1xuICB9O1xuXG4gIGZ1bmN0aW9uIGNvdW50RG9jcyh0eCwgY2FsbGJhY2spIHtcblxuICAgIGlmIChhcGkuX2RvY0NvdW50ICE9PSAtMSkge1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKGFwaS5fZG9jQ291bnQpO1xuICAgIH1cblxuICAgIC8vIGNvdW50IHRoZSB0b3RhbCByb3dzXG4gICAgdmFyIHNxbCA9IHNlbGVjdChcbiAgICAgICdDT1VOVCgnICsgRE9DX1NUT1JFJDEgKyAnLmlkKSBBUyBcXCdudW1cXCcnLFxuICAgICAgW0RPQ19TVE9SRSQxLCBCWV9TRVFfU1RPUkUkMV0sXG4gICAgICBET0NfU1RPUkVfQU5EX0JZX1NFUV9KT0lORVIsXG4gICAgICBCWV9TRVFfU1RPUkUkMSArICcuZGVsZXRlZD0wJyk7XG5cbiAgICB0eC5leGVjdXRlU3FsKHNxbCwgW10sIGZ1bmN0aW9uICh0eCwgcmVzdWx0KSB7XG4gICAgICBhcGkuX2RvY0NvdW50ID0gcmVzdWx0LnJvd3MuaXRlbSgwKS5udW07XG4gICAgICBjYWxsYmFjayhhcGkuX2RvY0NvdW50KTtcbiAgICB9KTtcbiAgfVxuXG4gIGFwaS5fYWxsRG9jcyA9IGZ1bmN0aW9uIChvcHRzLCBjYWxsYmFjaykge1xuICAgIHZhciByZXN1bHRzID0gW107XG4gICAgdmFyIHRvdGFsUm93cztcblxuICAgIHZhciBzdGFydCA9ICdzdGFydGtleScgaW4gb3B0cyA/IG9wdHMuc3RhcnRrZXkgOiBmYWxzZTtcbiAgICB2YXIgZW5kID0gJ2VuZGtleScgaW4gb3B0cyA/IG9wdHMuZW5ka2V5IDogZmFsc2U7XG4gICAgdmFyIGtleSA9ICdrZXknIGluIG9wdHMgPyBvcHRzLmtleSA6IGZhbHNlO1xuICAgIHZhciBkZXNjZW5kaW5nID0gJ2Rlc2NlbmRpbmcnIGluIG9wdHMgPyBvcHRzLmRlc2NlbmRpbmcgOiBmYWxzZTtcbiAgICB2YXIgbGltaXQgPSAnbGltaXQnIGluIG9wdHMgPyBvcHRzLmxpbWl0IDogLTE7XG4gICAgdmFyIG9mZnNldCA9ICdza2lwJyBpbiBvcHRzID8gb3B0cy5za2lwIDogMDtcbiAgICB2YXIgaW5jbHVzaXZlRW5kID0gb3B0cy5pbmNsdXNpdmVfZW5kICE9PSBmYWxzZTtcblxuICAgIHZhciBzcWxBcmdzID0gW107XG4gICAgdmFyIGNyaXRlcmlhID0gW107XG5cbiAgICBpZiAoa2V5ICE9PSBmYWxzZSkge1xuICAgICAgY3JpdGVyaWEucHVzaChET0NfU1RPUkUkMSArICcuaWQgPSA/Jyk7XG4gICAgICBzcWxBcmdzLnB1c2goa2V5KTtcbiAgICB9IGVsc2UgaWYgKHN0YXJ0ICE9PSBmYWxzZSB8fCBlbmQgIT09IGZhbHNlKSB7XG4gICAgICBpZiAoc3RhcnQgIT09IGZhbHNlKSB7XG4gICAgICAgIGNyaXRlcmlhLnB1c2goRE9DX1NUT1JFJDEgKyAnLmlkICcgKyAoZGVzY2VuZGluZyA/ICc8PScgOiAnPj0nKSArICcgPycpO1xuICAgICAgICBzcWxBcmdzLnB1c2goc3RhcnQpO1xuICAgICAgfVxuICAgICAgaWYgKGVuZCAhPT0gZmFsc2UpIHtcbiAgICAgICAgdmFyIGNvbXBhcmF0b3IgPSBkZXNjZW5kaW5nID8gJz4nIDogJzwnO1xuICAgICAgICBpZiAoaW5jbHVzaXZlRW5kKSB7XG4gICAgICAgICAgY29tcGFyYXRvciArPSAnPSc7XG4gICAgICAgIH1cbiAgICAgICAgY3JpdGVyaWEucHVzaChET0NfU1RPUkUkMSArICcuaWQgJyArIGNvbXBhcmF0b3IgKyAnID8nKTtcbiAgICAgICAgc3FsQXJncy5wdXNoKGVuZCk7XG4gICAgICB9XG4gICAgICBpZiAoa2V5ICE9PSBmYWxzZSkge1xuICAgICAgICBjcml0ZXJpYS5wdXNoKERPQ19TVE9SRSQxICsgJy5pZCA9ID8nKTtcbiAgICAgICAgc3FsQXJncy5wdXNoKGtleSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKG9wdHMuZGVsZXRlZCAhPT0gJ29rJykge1xuICAgICAgLy8gcmVwb3J0IGRlbGV0ZWQgaWYga2V5cyBhcmUgc3BlY2lmaWVkXG4gICAgICBjcml0ZXJpYS5wdXNoKEJZX1NFUV9TVE9SRSQxICsgJy5kZWxldGVkID0gMCcpO1xuICAgIH1cblxuICAgIGRiLnJlYWRUcmFuc2FjdGlvbihmdW5jdGlvbiAodHgpIHtcblxuICAgICAgLy8gZmlyc3QgY291bnQgdXAgdGhlIHRvdGFsIHJvd3NcbiAgICAgIGNvdW50RG9jcyh0eCwgZnVuY3Rpb24gKGNvdW50KSB7XG4gICAgICAgIHRvdGFsUm93cyA9IGNvdW50O1xuXG4gICAgICAgIGlmIChsaW1pdCA9PT0gMCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHRoZW4gYWN0dWFsbHkgZmV0Y2ggdGhlIGRvY3VtZW50c1xuICAgICAgICB2YXIgc3FsID0gc2VsZWN0KFxuICAgICAgICAgIFNFTEVDVF9ET0NTLFxuICAgICAgICAgIFtET0NfU1RPUkUkMSwgQllfU0VRX1NUT1JFJDFdLFxuICAgICAgICAgIERPQ19TVE9SRV9BTkRfQllfU0VRX0pPSU5FUixcbiAgICAgICAgICBjcml0ZXJpYSxcbiAgICAgICAgICBET0NfU1RPUkUkMSArICcuaWQgJyArIChkZXNjZW5kaW5nID8gJ0RFU0MnIDogJ0FTQycpXG4gICAgICAgICAgKTtcbiAgICAgICAgc3FsICs9ICcgTElNSVQgJyArIGxpbWl0ICsgJyBPRkZTRVQgJyArIG9mZnNldDtcblxuICAgICAgICB0eC5leGVjdXRlU3FsKHNxbCwgc3FsQXJncywgZnVuY3Rpb24gKHR4LCByZXN1bHQpIHtcbiAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IHJlc3VsdC5yb3dzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgICAgdmFyIGl0ZW0gPSByZXN1bHQucm93cy5pdGVtKGkpO1xuICAgICAgICAgICAgdmFyIG1ldGFkYXRhID0gc2FmZUpzb25QYXJzZShpdGVtLm1ldGFkYXRhKTtcbiAgICAgICAgICAgIHZhciBpZCA9IG1ldGFkYXRhLmlkO1xuICAgICAgICAgICAgdmFyIGRhdGEgPSB1bnN0cmluZ2lmeURvYyhpdGVtLmRhdGEsIGlkLCBpdGVtLnJldik7XG4gICAgICAgICAgICB2YXIgd2lubmluZ1JldiA9IGRhdGEuX3JldjtcbiAgICAgICAgICAgIHZhciBkb2MgPSB7XG4gICAgICAgICAgICAgIGlkOiBpZCxcbiAgICAgICAgICAgICAga2V5OiBpZCxcbiAgICAgICAgICAgICAgdmFsdWU6IHtyZXY6IHdpbm5pbmdSZXZ9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKG9wdHMuaW5jbHVkZV9kb2NzKSB7XG4gICAgICAgICAgICAgIGRvYy5kb2MgPSBkYXRhO1xuICAgICAgICAgICAgICBkb2MuZG9jLl9yZXYgPSB3aW5uaW5nUmV2O1xuICAgICAgICAgICAgICBpZiAob3B0cy5jb25mbGljdHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgY29uZmxpY3RzID0gY29sbGVjdENvbmZsaWN0cyhtZXRhZGF0YSk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbmZsaWN0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgIGRvYy5kb2MuX2NvbmZsaWN0cyA9IGNvbmZsaWN0cztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZmV0Y2hBdHRhY2htZW50c0lmTmVjZXNzYXJ5JDEoZG9jLmRvYywgb3B0cywgYXBpLCB0eCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXRlbS5kZWxldGVkKSB7XG4gICAgICAgICAgICAgIGlmIChvcHRzLmRlbGV0ZWQgPT09ICdvaycpIHtcbiAgICAgICAgICAgICAgICBkb2MudmFsdWUuZGVsZXRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgZG9jLmRvYyA9IG51bGw7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlc3VsdHMucHVzaChkb2MpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9LCB3ZWJzcWxFcnJvcihjYWxsYmFjayksIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNhbGxiYWNrKG51bGwsIHtcbiAgICAgICAgdG90YWxfcm93czogdG90YWxSb3dzLFxuICAgICAgICBvZmZzZXQ6IG9wdHMuc2tpcCxcbiAgICAgICAgcm93czogcmVzdWx0c1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH07XG5cbiAgYXBpLl9jaGFuZ2VzID0gZnVuY3Rpb24gKG9wdHMpIHtcbiAgICBvcHRzID0gY2xvbmUob3B0cyk7XG5cbiAgICBpZiAob3B0cy5jb250aW51b3VzKSB7XG4gICAgICB2YXIgaWQgPSBhcGkuX25hbWUgKyAnOicgKyB1dWlkKCk7XG4gICAgICB3ZWJzcWxDaGFuZ2VzLmFkZExpc3RlbmVyKGFwaS5fbmFtZSwgaWQsIGFwaSwgb3B0cyk7XG4gICAgICB3ZWJzcWxDaGFuZ2VzLm5vdGlmeShhcGkuX25hbWUpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY2FuY2VsOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgd2Vic3FsQ2hhbmdlcy5yZW1vdmVMaXN0ZW5lcihhcGkuX25hbWUsIGlkKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG5cbiAgICB2YXIgZGVzY2VuZGluZyA9IG9wdHMuZGVzY2VuZGluZztcblxuICAgIC8vIElnbm9yZSB0aGUgYHNpbmNlYCBwYXJhbWV0ZXIgd2hlbiBgZGVzY2VuZGluZ2AgaXMgdHJ1ZVxuICAgIG9wdHMuc2luY2UgPSBvcHRzLnNpbmNlICYmICFkZXNjZW5kaW5nID8gb3B0cy5zaW5jZSA6IDA7XG5cbiAgICB2YXIgbGltaXQgPSAnbGltaXQnIGluIG9wdHMgPyBvcHRzLmxpbWl0IDogLTE7XG4gICAgaWYgKGxpbWl0ID09PSAwKSB7XG4gICAgICBsaW1pdCA9IDE7IC8vIHBlciBDb3VjaERCIF9jaGFuZ2VzIHNwZWNcbiAgICB9XG5cbiAgICB2YXIgcmV0dXJuRG9jcztcbiAgICBpZiAoJ3JldHVybl9kb2NzJyBpbiBvcHRzKSB7XG4gICAgICByZXR1cm5Eb2NzID0gb3B0cy5yZXR1cm5fZG9jcztcbiAgICB9IGVsc2UgaWYgKCdyZXR1cm5Eb2NzJyBpbiBvcHRzKSB7XG4gICAgICAvLyBUT0RPOiBSZW1vdmUgJ3JldHVybkRvY3MnIGluIGZhdm9yIG9mICdyZXR1cm5fZG9jcycgaW4gYSBmdXR1cmUgcmVsZWFzZVxuICAgICAgcmV0dXJuRG9jcyA9IG9wdHMucmV0dXJuRG9jcztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuRG9jcyA9IHRydWU7XG4gICAgfVxuICAgIHZhciByZXN1bHRzID0gW107XG4gICAgdmFyIG51bVJlc3VsdHMgPSAwO1xuXG4gICAgZnVuY3Rpb24gZmV0Y2hDaGFuZ2VzKCkge1xuXG4gICAgICB2YXIgc2VsZWN0U3RtdCA9XG4gICAgICAgIERPQ19TVE9SRSQxICsgJy5qc29uIEFTIG1ldGFkYXRhLCAnICtcbiAgICAgICAgRE9DX1NUT1JFJDEgKyAnLm1heF9zZXEgQVMgbWF4U2VxLCAnICtcbiAgICAgICAgQllfU0VRX1NUT1JFJDEgKyAnLmpzb24gQVMgd2lubmluZ0RvYywgJyArXG4gICAgICAgIEJZX1NFUV9TVE9SRSQxICsgJy5yZXYgQVMgd2lubmluZ1JldiAnO1xuXG4gICAgICB2YXIgZnJvbSA9IERPQ19TVE9SRSQxICsgJyBKT0lOICcgKyBCWV9TRVFfU1RPUkUkMTtcblxuICAgICAgdmFyIGpvaW5lciA9IERPQ19TVE9SRSQxICsgJy5pZD0nICsgQllfU0VRX1NUT1JFJDEgKyAnLmRvY19pZCcgK1xuICAgICAgICAnIEFORCAnICsgRE9DX1NUT1JFJDEgKyAnLndpbm5pbmdzZXE9JyArIEJZX1NFUV9TVE9SRSQxICsgJy5zZXEnO1xuXG4gICAgICB2YXIgY3JpdGVyaWEgPSBbJ21heFNlcSA+ID8nXTtcbiAgICAgIHZhciBzcWxBcmdzID0gW29wdHMuc2luY2VdO1xuXG4gICAgICBpZiAob3B0cy5kb2NfaWRzKSB7XG4gICAgICAgIGNyaXRlcmlhLnB1c2goRE9DX1NUT1JFJDEgKyAnLmlkIElOICcgKyBxTWFya3Mob3B0cy5kb2NfaWRzLmxlbmd0aCkpO1xuICAgICAgICBzcWxBcmdzID0gc3FsQXJncy5jb25jYXQob3B0cy5kb2NfaWRzKTtcbiAgICAgIH1cblxuICAgICAgdmFyIG9yZGVyQnkgPSAnbWF4U2VxICcgKyAoZGVzY2VuZGluZyA/ICdERVNDJyA6ICdBU0MnKTtcblxuICAgICAgdmFyIHNxbCA9IHNlbGVjdChzZWxlY3RTdG10LCBmcm9tLCBqb2luZXIsIGNyaXRlcmlhLCBvcmRlckJ5KTtcblxuICAgICAgdmFyIGZpbHRlciA9IGZpbHRlckNoYW5nZShvcHRzKTtcbiAgICAgIGlmICghb3B0cy52aWV3ICYmICFvcHRzLmZpbHRlcikge1xuICAgICAgICAvLyB3ZSBjYW4ganVzdCBsaW1pdCBpbiB0aGUgcXVlcnlcbiAgICAgICAgc3FsICs9ICcgTElNSVQgJyArIGxpbWl0O1xuICAgICAgfVxuXG4gICAgICB2YXIgbGFzdFNlcSA9IG9wdHMuc2luY2UgfHwgMDtcbiAgICAgIGRiLnJlYWRUcmFuc2FjdGlvbihmdW5jdGlvbiAodHgpIHtcbiAgICAgICAgdHguZXhlY3V0ZVNxbChzcWwsIHNxbEFyZ3MsIGZ1bmN0aW9uICh0eCwgcmVzdWx0KSB7XG4gICAgICAgICAgZnVuY3Rpb24gcmVwb3J0Q2hhbmdlKGNoYW5nZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgb3B0cy5vbkNoYW5nZShjaGFuZ2UpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSByZXN1bHQucm93cy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBpdGVtID0gcmVzdWx0LnJvd3MuaXRlbShpKTtcbiAgICAgICAgICAgIHZhciBtZXRhZGF0YSA9IHNhZmVKc29uUGFyc2UoaXRlbS5tZXRhZGF0YSk7XG4gICAgICAgICAgICBsYXN0U2VxID0gaXRlbS5tYXhTZXE7XG5cbiAgICAgICAgICAgIHZhciBkb2MgPSB1bnN0cmluZ2lmeURvYyhpdGVtLndpbm5pbmdEb2MsIG1ldGFkYXRhLmlkLFxuICAgICAgICAgICAgICBpdGVtLndpbm5pbmdSZXYpO1xuICAgICAgICAgICAgdmFyIGNoYW5nZSA9IG9wdHMucHJvY2Vzc0NoYW5nZShkb2MsIG1ldGFkYXRhLCBvcHRzKTtcbiAgICAgICAgICAgIGNoYW5nZS5zZXEgPSBpdGVtLm1heFNlcTtcblxuICAgICAgICAgICAgdmFyIGZpbHRlcmVkID0gZmlsdGVyKGNoYW5nZSk7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGZpbHRlcmVkID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICByZXR1cm4gb3B0cy5jb21wbGV0ZShmaWx0ZXJlZCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChmaWx0ZXJlZCkge1xuICAgICAgICAgICAgICBudW1SZXN1bHRzKys7XG4gICAgICAgICAgICAgIGlmIChyZXR1cm5Eb2NzKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0cy5wdXNoKGNoYW5nZSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgLy8gcHJvY2VzcyB0aGUgYXR0YWNobWVudCBpbW1lZGlhdGVseVxuICAgICAgICAgICAgICAvLyBmb3IgdGhlIGJlbmVmaXQgb2YgbGl2ZSBsaXN0ZW5lcnNcbiAgICAgICAgICAgICAgaWYgKG9wdHMuYXR0YWNobWVudHMgJiYgb3B0cy5pbmNsdWRlX2RvY3MpIHtcbiAgICAgICAgICAgICAgICBmZXRjaEF0dGFjaG1lbnRzSWZOZWNlc3NhcnkkMShkb2MsIG9wdHMsIGFwaSwgdHgsXG4gICAgICAgICAgICAgICAgICByZXBvcnRDaGFuZ2UoY2hhbmdlKSk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVwb3J0Q2hhbmdlKGNoYW5nZSkoKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG51bVJlc3VsdHMgPT09IGxpbWl0KSB7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9LCB3ZWJzcWxFcnJvcihvcHRzLmNvbXBsZXRlKSwgZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIW9wdHMuY29udGludW91cykge1xuICAgICAgICAgIG9wdHMuY29tcGxldGUobnVsbCwge1xuICAgICAgICAgICAgcmVzdWx0czogcmVzdWx0cyxcbiAgICAgICAgICAgIGxhc3Rfc2VxOiBsYXN0U2VxXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZldGNoQ2hhbmdlcygpO1xuICB9O1xuXG4gIGFwaS5fY2xvc2UgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAvL1dlYlNRTCBkYXRhYmFzZXMgZG8gbm90IG5lZWQgdG8gYmUgY2xvc2VkXG4gICAgY2FsbGJhY2soKTtcbiAgfTtcblxuICBhcGkuX2dldEF0dGFjaG1lbnQgPSBmdW5jdGlvbiAoZG9jSWQsIGF0dGFjaElkLCBhdHRhY2htZW50LCBvcHRzLCBjYWxsYmFjaykge1xuICAgIHZhciByZXM7XG4gICAgdmFyIHR4ID0gb3B0cy5jdHg7XG4gICAgdmFyIGRpZ2VzdCA9IGF0dGFjaG1lbnQuZGlnZXN0O1xuICAgIHZhciB0eXBlID0gYXR0YWNobWVudC5jb250ZW50X3R5cGU7XG4gICAgdmFyIHNxbCA9ICdTRUxFQ1QgZXNjYXBlZCwgJyArXG4gICAgICAnQ0FTRSBXSEVOIGVzY2FwZWQgPSAxIFRIRU4gYm9keSBFTFNFIEhFWChib2R5KSBFTkQgQVMgYm9keSBGUk9NICcgK1xuICAgICAgQVRUQUNIX1NUT1JFJDEgKyAnIFdIRVJFIGRpZ2VzdD0/JztcbiAgICB0eC5leGVjdXRlU3FsKHNxbCwgW2RpZ2VzdF0sIGZ1bmN0aW9uICh0eCwgcmVzdWx0KSB7XG4gICAgICAvLyB3ZWJzcWwgaGFzIGEgYnVnIHdoZXJlIFxcdTAwMDAgY2F1c2VzIGVhcmx5IHRydW5jYXRpb24gaW4gc3RyaW5nc1xuICAgICAgLy8gYW5kIGJsb2JzLiB0byB3b3JrIGFyb3VuZCB0aGlzLCB3ZSB1c2VkIHRvIHVzZSB0aGUgaGV4KCkgZnVuY3Rpb24sXG4gICAgICAvLyBidXQgdGhhdCdzIG5vdCBwZXJmb3JtYW50LiBhZnRlciBtaWdyYXRpb24gNiwgd2UgcmVtb3ZlIFxcdTAwMDBcbiAgICAgIC8vIGFuZCBhZGQgaXQgYmFjayBpbiBhZnRlcndhcmRzXG4gICAgICB2YXIgaXRlbSA9IHJlc3VsdC5yb3dzLml0ZW0oMCk7XG4gICAgICB2YXIgZGF0YSA9IGl0ZW0uZXNjYXBlZCA/IHVuZXNjYXBlQmxvYihpdGVtLmJvZHkpIDpcbiAgICAgICAgcGFyc2VIZXhTdHJpbmcoaXRlbS5ib2R5LCBlbmNvZGluZyk7XG4gICAgICBpZiAob3B0cy5iaW5hcnkpIHtcbiAgICAgICAgcmVzID0gYmluU3RyaW5nVG9CbHVmZmVyKGRhdGEsIHR5cGUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzID0gYnRvYSQxKGRhdGEpO1xuICAgICAgfVxuICAgICAgY2FsbGJhY2sobnVsbCwgcmVzKTtcbiAgICB9KTtcbiAgfTtcblxuICBhcGkuX2dldFJldmlzaW9uVHJlZSA9IGZ1bmN0aW9uIChkb2NJZCwgY2FsbGJhY2spIHtcbiAgICBkYi5yZWFkVHJhbnNhY3Rpb24oZnVuY3Rpb24gKHR4KSB7XG4gICAgICB2YXIgc3FsID0gJ1NFTEVDVCBqc29uIEFTIG1ldGFkYXRhIEZST00gJyArIERPQ19TVE9SRSQxICsgJyBXSEVSRSBpZCA9ID8nO1xuICAgICAgdHguZXhlY3V0ZVNxbChzcWwsIFtkb2NJZF0sIGZ1bmN0aW9uICh0eCwgcmVzdWx0KSB7XG4gICAgICAgIGlmICghcmVzdWx0LnJvd3MubGVuZ3RoKSB7XG4gICAgICAgICAgY2FsbGJhY2soY3JlYXRlRXJyb3IoTUlTU0lOR19ET0MpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2YXIgZGF0YSA9IHNhZmVKc29uUGFyc2UocmVzdWx0LnJvd3MuaXRlbSgwKS5tZXRhZGF0YSk7XG4gICAgICAgICAgY2FsbGJhY2sobnVsbCwgZGF0YS5yZXZfdHJlZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9O1xuXG4gIGFwaS5fZG9Db21wYWN0aW9uID0gZnVuY3Rpb24gKGRvY0lkLCByZXZzLCBjYWxsYmFjaykge1xuICAgIGlmICghcmV2cy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBjYWxsYmFjaygpO1xuICAgIH1cbiAgICBkYi50cmFuc2FjdGlvbihmdW5jdGlvbiAodHgpIHtcblxuICAgICAgLy8gdXBkYXRlIGRvYyBzdG9yZVxuICAgICAgdmFyIHNxbCA9ICdTRUxFQ1QganNvbiBBUyBtZXRhZGF0YSBGUk9NICcgKyBET0NfU1RPUkUkMSArICcgV0hFUkUgaWQgPSA/JztcbiAgICAgIHR4LmV4ZWN1dGVTcWwoc3FsLCBbZG9jSWRdLCBmdW5jdGlvbiAodHgsIHJlc3VsdCkge1xuICAgICAgICB2YXIgbWV0YWRhdGEgPSBzYWZlSnNvblBhcnNlKHJlc3VsdC5yb3dzLml0ZW0oMCkubWV0YWRhdGEpO1xuICAgICAgICB0cmF2ZXJzZVJldlRyZWUobWV0YWRhdGEucmV2X3RyZWUsIGZ1bmN0aW9uIChpc0xlYWYsIHBvcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV2SGFzaCwgY3R4LCBvcHRzKSB7XG4gICAgICAgICAgdmFyIHJldiA9IHBvcyArICctJyArIHJldkhhc2g7XG4gICAgICAgICAgaWYgKHJldnMuaW5kZXhPZihyZXYpICE9PSAtMSkge1xuICAgICAgICAgICAgb3B0cy5zdGF0dXMgPSAnbWlzc2luZyc7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICB2YXIgc3FsID0gJ1VQREFURSAnICsgRE9DX1NUT1JFJDEgKyAnIFNFVCBqc29uID0gPyBXSEVSRSBpZCA9ID8nO1xuICAgICAgICB0eC5leGVjdXRlU3FsKHNxbCwgW3NhZmVKc29uU3RyaW5naWZ5KG1ldGFkYXRhKSwgZG9jSWRdKTtcbiAgICAgIH0pO1xuXG4gICAgICBjb21wYWN0UmV2cyQxKHJldnMsIGRvY0lkLCB0eCk7XG4gICAgfSwgd2Vic3FsRXJyb3IoY2FsbGJhY2spLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjYWxsYmFjaygpO1xuICAgIH0pO1xuICB9O1xuXG4gIGFwaS5fZ2V0TG9jYWwgPSBmdW5jdGlvbiAoaWQsIGNhbGxiYWNrKSB7XG4gICAgZGIucmVhZFRyYW5zYWN0aW9uKGZ1bmN0aW9uICh0eCkge1xuICAgICAgdmFyIHNxbCA9ICdTRUxFQ1QganNvbiwgcmV2IEZST00gJyArIExPQ0FMX1NUT1JFJDEgKyAnIFdIRVJFIGlkPT8nO1xuICAgICAgdHguZXhlY3V0ZVNxbChzcWwsIFtpZF0sIGZ1bmN0aW9uICh0eCwgcmVzKSB7XG4gICAgICAgIGlmIChyZXMucm93cy5sZW5ndGgpIHtcbiAgICAgICAgICB2YXIgaXRlbSA9IHJlcy5yb3dzLml0ZW0oMCk7XG4gICAgICAgICAgdmFyIGRvYyA9IHVuc3RyaW5naWZ5RG9jKGl0ZW0uanNvbiwgaWQsIGl0ZW0ucmV2KTtcbiAgICAgICAgICBjYWxsYmFjayhudWxsLCBkb2MpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNhbGxiYWNrKGNyZWF0ZUVycm9yKE1JU1NJTkdfRE9DKSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9O1xuXG4gIGFwaS5fcHV0TG9jYWwgPSBmdW5jdGlvbiAoZG9jLCBvcHRzLCBjYWxsYmFjaykge1xuICAgIGlmICh0eXBlb2Ygb3B0cyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgY2FsbGJhY2sgPSBvcHRzO1xuICAgICAgb3B0cyA9IHt9O1xuICAgIH1cbiAgICBkZWxldGUgZG9jLl9yZXZpc2lvbnM7IC8vIGlnbm9yZSB0aGlzLCB0cnVzdCB0aGUgcmV2XG4gICAgdmFyIG9sZFJldiA9IGRvYy5fcmV2O1xuICAgIHZhciBpZCA9IGRvYy5faWQ7XG4gICAgdmFyIG5ld1JldjtcbiAgICBpZiAoIW9sZFJldikge1xuICAgICAgbmV3UmV2ID0gZG9jLl9yZXYgPSAnMC0xJztcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3UmV2ID0gZG9jLl9yZXYgPSAnMC0nICsgKHBhcnNlSW50KG9sZFJldi5zcGxpdCgnLScpWzFdLCAxMCkgKyAxKTtcbiAgICB9XG4gICAgdmFyIGpzb24gPSBzdHJpbmdpZnlEb2MoZG9jKTtcblxuICAgIHZhciByZXQ7XG4gICAgZnVuY3Rpb24gcHV0TG9jYWwodHgpIHtcbiAgICAgIHZhciBzcWw7XG4gICAgICB2YXIgdmFsdWVzO1xuICAgICAgaWYgKG9sZFJldikge1xuICAgICAgICBzcWwgPSAnVVBEQVRFICcgKyBMT0NBTF9TVE9SRSQxICsgJyBTRVQgcmV2PT8sIGpzb249PyAnICtcbiAgICAgICAgICAnV0hFUkUgaWQ9PyBBTkQgcmV2PT8nO1xuICAgICAgICB2YWx1ZXMgPSBbbmV3UmV2LCBqc29uLCBpZCwgb2xkUmV2XTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNxbCA9ICdJTlNFUlQgSU5UTyAnICsgTE9DQUxfU1RPUkUkMSArICcgKGlkLCByZXYsIGpzb24pIFZBTFVFUyAoPyw/LD8pJztcbiAgICAgICAgdmFsdWVzID0gW2lkLCBuZXdSZXYsIGpzb25dO1xuICAgICAgfVxuICAgICAgdHguZXhlY3V0ZVNxbChzcWwsIHZhbHVlcywgZnVuY3Rpb24gKHR4LCByZXMpIHtcbiAgICAgICAgaWYgKHJlcy5yb3dzQWZmZWN0ZWQpIHtcbiAgICAgICAgICByZXQgPSB7b2s6IHRydWUsIGlkOiBpZCwgcmV2OiBuZXdSZXZ9O1xuICAgICAgICAgIGlmIChvcHRzLmN0eCkgeyAvLyByZXR1cm4gaW1tZWRpYXRlbHlcbiAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIHJldCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNhbGxiYWNrKGNyZWF0ZUVycm9yKFJFVl9DT05GTElDVCkpO1xuICAgICAgICB9XG4gICAgICB9LCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNhbGxiYWNrKGNyZWF0ZUVycm9yKFJFVl9DT05GTElDVCkpO1xuICAgICAgICByZXR1cm4gZmFsc2U7IC8vIGFjayB0aGF0IHdlIGhhbmRsZWQgdGhlIGVycm9yXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAob3B0cy5jdHgpIHtcbiAgICAgIHB1dExvY2FsKG9wdHMuY3R4KTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGIudHJhbnNhY3Rpb24ocHV0TG9jYWwsIHdlYnNxbEVycm9yKGNhbGxiYWNrKSwgZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAocmV0KSB7XG4gICAgICAgICAgY2FsbGJhY2sobnVsbCwgcmV0KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9O1xuXG4gIGFwaS5fcmVtb3ZlTG9jYWwgPSBmdW5jdGlvbiAoZG9jLCBvcHRzLCBjYWxsYmFjaykge1xuICAgIGlmICh0eXBlb2Ygb3B0cyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgY2FsbGJhY2sgPSBvcHRzO1xuICAgICAgb3B0cyA9IHt9O1xuICAgIH1cbiAgICB2YXIgcmV0O1xuXG4gICAgZnVuY3Rpb24gcmVtb3ZlTG9jYWwodHgpIHtcbiAgICAgIHZhciBzcWwgPSAnREVMRVRFIEZST00gJyArIExPQ0FMX1NUT1JFJDEgKyAnIFdIRVJFIGlkPT8gQU5EIHJldj0/JztcbiAgICAgIHZhciBwYXJhbXMgPSBbZG9jLl9pZCwgZG9jLl9yZXZdO1xuICAgICAgdHguZXhlY3V0ZVNxbChzcWwsIHBhcmFtcywgZnVuY3Rpb24gKHR4LCByZXMpIHtcbiAgICAgICAgaWYgKCFyZXMucm93c0FmZmVjdGVkKSB7XG4gICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGNyZWF0ZUVycm9yKE1JU1NJTkdfRE9DKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0ID0ge29rOiB0cnVlLCBpZDogZG9jLl9pZCwgcmV2OiAnMC0wJ307XG4gICAgICAgIGlmIChvcHRzLmN0eCkgeyAvLyByZXR1cm4gaW1tZWRpYXRlbHlcbiAgICAgICAgICBjYWxsYmFjayhudWxsLCByZXQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAob3B0cy5jdHgpIHtcbiAgICAgIHJlbW92ZUxvY2FsKG9wdHMuY3R4KTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGIudHJhbnNhY3Rpb24ocmVtb3ZlTG9jYWwsIHdlYnNxbEVycm9yKGNhbGxiYWNrKSwgZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAocmV0KSB7XG4gICAgICAgICAgY2FsbGJhY2sobnVsbCwgcmV0KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9O1xuXG4gIGFwaS5fZGVzdHJveSA9IGZ1bmN0aW9uIChvcHRzLCBjYWxsYmFjaykge1xuICAgIHdlYnNxbENoYW5nZXMucmVtb3ZlQWxsTGlzdGVuZXJzKGFwaS5fbmFtZSk7XG4gICAgZGIudHJhbnNhY3Rpb24oZnVuY3Rpb24gKHR4KSB7XG4gICAgICB2YXIgc3RvcmVzID0gW0RPQ19TVE9SRSQxLCBCWV9TRVFfU1RPUkUkMSwgQVRUQUNIX1NUT1JFJDEsIE1FVEFfU1RPUkUkMSxcbiAgICAgICAgTE9DQUxfU1RPUkUkMSwgQVRUQUNIX0FORF9TRVFfU1RPUkUkMV07XG4gICAgICBzdG9yZXMuZm9yRWFjaChmdW5jdGlvbiAoc3RvcmUpIHtcbiAgICAgICAgdHguZXhlY3V0ZVNxbCgnRFJPUCBUQUJMRSBJRiBFWElTVFMgJyArIHN0b3JlLCBbXSk7XG4gICAgICB9KTtcbiAgICB9LCB3ZWJzcWxFcnJvcihjYWxsYmFjayksIGZ1bmN0aW9uICgpIHtcbiAgICAgIGlmIChoYXNMb2NhbFN0b3JhZ2UoKSkge1xuICAgICAgICBkZWxldGUgd2luZG93LmxvY2FsU3RvcmFnZVsnX3BvdWNoX193ZWJzcWxkYl8nICsgYXBpLl9uYW1lXTtcbiAgICAgICAgZGVsZXRlIHdpbmRvdy5sb2NhbFN0b3JhZ2VbYXBpLl9uYW1lXTtcbiAgICAgIH1cbiAgICAgIGNhbGxiYWNrKG51bGwsIHsnb2snOiB0cnVlfSk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGNhbk9wZW5UZXN0REIoKSB7XG4gIHRyeSB7XG4gICAgb3BlbkRhdGFiYXNlKCdfcG91Y2hfdmFsaWRhdGVfd2Vic3FsJywgMSwgJycsIDEpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuLy8gV0tXZWJWaWV3IGhhZCBhIGJ1ZyB3aGVyZSBXZWJTUUwgd291bGQgdGhyb3cgYSBET00gRXhjZXB0aW9uIDE4XG4vLyAoc2VlIGh0dHBzOi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0xMzc3NjAgYW5kXG4vLyBodHRwczovL2dpdGh1Yi5jb20vcG91Y2hkYi9wb3VjaGRiL2lzc3Vlcy81MDc5KVxuLy8gVGhpcyBoYXMgYmVlbiBmaXhlZCBpbiBsYXRlc3QgV2ViS2l0LCBzbyB3ZSB0cnkgdG8gZGV0ZWN0IGl0IGhlcmUuXG5mdW5jdGlvbiBpc1ZhbGlkV2ViU1FMKCkge1xuICAvLyBXS1dlYlZpZXcgVUE6XG4gIC8vICAgTW96aWxsYS81LjAgKGlQaG9uZTsgQ1BVIGlQaG9uZSBPUyA5XzIgbGlrZSBNYWMgT1MgWClcbiAgLy8gICBBcHBsZVdlYktpdC82MDEuMS40NiAoS0hUTUwsIGxpa2UgR2Vja28pIE1vYmlsZS8xM0M3NVxuICAvLyBDaHJvbWUgZm9yIGlPUyBVQTpcbiAgLy8gICBNb3ppbGxhLzUuMCAoaVBob25lOyBVOyBDUFUgaVBob25lIE9TIDVfMV8xIGxpa2UgTWFjIE9TIFg7IGVuKVxuICAvLyAgIEFwcGxlV2ViS2l0LzUzNC40Ni4wIChLSFRNTCwgbGlrZSBHZWNrbykgQ3JpT1MvMTkuMC4xMDg0LjYwXG4gIC8vICAgTW9iaWxlLzlCMjA2IFNhZmFyaS83NTM0LjQ4LjNcbiAgLy8gRmlyZWZveCBmb3IgaU9TIFVBOlxuICAvLyAgIE1vemlsbGEvNS4wIChpUGhvbmU7IENQVSBpUGhvbmUgT1MgOF8zIGxpa2UgTWFjIE9TIFgpIEFwcGxlV2ViS2l0LzYwMC4xLjRcbiAgLy8gICAoS0hUTUwsIGxpa2UgR2Vja28pIEZ4aU9TLzEuMCBNb2JpbGUvMTJGNjkgU2FmYXJpLzYwMC4xLjRcblxuICAvLyBpbmRleGVkREIgaXMgbnVsbCBvbiBzb21lIFVJV2ViVmlld3MgYW5kIHVuZGVmaW5lZCBpbiBvdGhlcnNcbiAgLy8gc2VlOiBodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTM3MDM0XG4gIGlmICh0eXBlb2YgaW5kZXhlZERCID09PSAndW5kZWZpbmVkJyB8fCBpbmRleGVkREIgPT09IG51bGwgfHxcbiAgICAgICEvaVAoaG9uZXxvZHxhZCkvLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkpIHtcbiAgICAvLyBkZWZpbml0ZWx5IG5vdCBXS1dlYlZpZXcsIGF2b2lkIGNyZWF0aW5nIGFuIHVubmVjZXNzYXJ5IGRhdGFiYXNlXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgLy8gQ2FjaGUgdGhlIHJlc3VsdCBpbiBMb2NhbFN0b3JhZ2UuIFJlYXNvbiB3ZSBkbyB0aGlzIGlzIGJlY2F1c2UgaWYgd2VcbiAgLy8gY2FsbCBvcGVuRGF0YWJhc2UoKSB0b28gbWFueSB0aW1lcywgU2FmYXJpIGNyYXBzIG91dCBpbiBTYXVjZUxhYnMgYW5kXG4gIC8vIHN0YXJ0cyB0aHJvd2luZyBET00gRXhjZXB0aW9uIDE0cy5cbiAgdmFyIGhhc0xTID0gaGFzTG9jYWxTdG9yYWdlKCk7XG4gIC8vIEluY2x1ZGUgdXNlciBhZ2VudCBpbiB0aGUgaGFzaCwgc28gdGhhdCBpZiBTYWZhcmkgaXMgdXBncmFkZWQsIHdlIGRvbid0XG4gIC8vIGNvbnRpbnVhbGx5IHRoaW5rIGl0J3MgYnJva2VuLlxuICB2YXIgbG9jYWxTdG9yYWdlS2V5ID0gJ19wb3VjaF9fd2Vic3FsZGJfdmFsaWRfJyArIG5hdmlnYXRvci51c2VyQWdlbnQ7XG4gIGlmIChoYXNMUyAmJiBsb2NhbFN0b3JhZ2VbbG9jYWxTdG9yYWdlS2V5XSkge1xuICAgIHJldHVybiBsb2NhbFN0b3JhZ2VbbG9jYWxTdG9yYWdlS2V5XSA9PT0gJzEnO1xuICB9XG4gIHZhciBvcGVuZWRUZXN0REIgPSBjYW5PcGVuVGVzdERCKCk7XG4gIGlmIChoYXNMUykge1xuICAgIGxvY2FsU3RvcmFnZVtsb2NhbFN0b3JhZ2VLZXldID0gb3BlbmVkVGVzdERCID8gJzEnIDogJzAnO1xuICB9XG4gIHJldHVybiBvcGVuZWRUZXN0REI7XG59XG5cbmZ1bmN0aW9uIHZhbGlkKCkge1xuICBpZiAodHlwZW9mIG9wZW5EYXRhYmFzZSAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4gaXNWYWxpZFdlYlNRTCgpO1xufVxuXG5mdW5jdGlvbiBvcGVuREIobmFtZSwgdmVyc2lvbiwgZGVzY3JpcHRpb24sIHNpemUpIHtcbiAgLy8gVHJhZGl0aW9uYWwgV2ViU1FMIEFQSVxuICByZXR1cm4gb3BlbkRhdGFiYXNlKG5hbWUsIHZlcnNpb24sIGRlc2NyaXB0aW9uLCBzaXplKTtcbn1cblxuZnVuY3Rpb24gV2ViU1FMUG91Y2gob3B0cywgY2FsbGJhY2spIHtcbiAgdmFyIF9vcHRzID0gZXh0ZW5kJDEoe1xuICAgIHdlYnNxbDogb3BlbkRCXG4gIH0sIG9wdHMpO1xuXG4gIFdlYlNxbFBvdWNoJDEuY2FsbCh0aGlzLCBfb3B0cywgY2FsbGJhY2spO1xufVxuXG5XZWJTUUxQb3VjaC52YWxpZCA9IHZhbGlkO1xuXG5XZWJTUUxQb3VjaC51c2VfcHJlZml4ID0gdHJ1ZTtcblxuZnVuY3Rpb24gV2ViU3FsUG91Y2ggKFBvdWNoREIpIHtcbiAgUG91Y2hEQi5hZGFwdGVyKCd3ZWJzcWwnLCBXZWJTUUxQb3VjaCwgdHJ1ZSk7XG59XG5cbi8qIGdsb2JhbCBmZXRjaCAqL1xuLyogZ2xvYmFsIEhlYWRlcnMgKi9cbmZ1bmN0aW9uIHdyYXBwZWRGZXRjaCgpIHtcbiAgdmFyIHdyYXBwZWRQcm9taXNlID0ge307XG5cbiAgdmFyIHByb21pc2UgPSBuZXcgUG91Y2hQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICB3cmFwcGVkUHJvbWlzZS5yZXNvbHZlID0gcmVzb2x2ZTtcbiAgICB3cmFwcGVkUHJvbWlzZS5yZWplY3QgPSByZWplY3Q7XG4gIH0pO1xuXG4gIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgpO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7IGkrKykge1xuICAgIGFyZ3NbaV0gPSBhcmd1bWVudHNbaV07XG4gIH1cblxuICB3cmFwcGVkUHJvbWlzZS5wcm9taXNlID0gcHJvbWlzZTtcblxuICBQb3VjaFByb21pc2UucmVzb2x2ZSgpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmZXRjaC5hcHBseShudWxsLCBhcmdzKTtcbiAgfSkudGhlbihmdW5jdGlvbiAocmVzcG9uc2UpIHtcbiAgICB3cmFwcGVkUHJvbWlzZS5yZXNvbHZlKHJlc3BvbnNlKTtcbiAgfSkuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgd3JhcHBlZFByb21pc2UucmVqZWN0KGVycm9yKTtcbiAgfSk7XG5cbiAgcmV0dXJuIHdyYXBwZWRQcm9taXNlO1xufVxuXG5mdW5jdGlvbiBmZXRjaFJlcXVlc3Qob3B0aW9ucywgY2FsbGJhY2spIHtcbiAgdmFyIHdyYXBwZWRQcm9taXNlLCB0aW1lciwgcmVzcG9uc2U7XG5cbiAgdmFyIGhlYWRlcnMgPSBuZXcgSGVhZGVycygpO1xuXG4gIHZhciBmZXRjaE9wdGlvbnMgPSB7XG4gICAgbWV0aG9kOiBvcHRpb25zLm1ldGhvZCxcbiAgICBjcmVkZW50aWFsczogJ2luY2x1ZGUnLFxuICAgIGhlYWRlcnM6IGhlYWRlcnNcbiAgfTtcblxuICBpZiAob3B0aW9ucy5qc29uKSB7XG4gICAgaGVhZGVycy5zZXQoJ0FjY2VwdCcsICdhcHBsaWNhdGlvbi9qc29uJyk7XG4gICAgaGVhZGVycy5zZXQoJ0NvbnRlbnQtVHlwZScsIG9wdGlvbnMuaGVhZGVyc1snQ29udGVudC1UeXBlJ10gfHxcbiAgICAgICdhcHBsaWNhdGlvbi9qc29uJyk7XG4gIH1cblxuICBpZiAob3B0aW9ucy5ib2R5ICYmXG4gICAgICBvcHRpb25zLnByb2Nlc3NEYXRhICYmXG4gICAgICB0eXBlb2Ygb3B0aW9ucy5ib2R5ICE9PSAnc3RyaW5nJykge1xuICAgIGZldGNoT3B0aW9ucy5ib2R5ID0gSlNPTi5zdHJpbmdpZnkob3B0aW9ucy5ib2R5KTtcbiAgfSBlbHNlIGlmICgnYm9keScgaW4gb3B0aW9ucykge1xuICAgIGZldGNoT3B0aW9ucy5ib2R5ID0gb3B0aW9ucy5ib2R5O1xuICB9IGVsc2Uge1xuICAgIGZldGNoT3B0aW9ucy5ib2R5ID0gbnVsbDtcbiAgfVxuXG4gIE9iamVjdC5rZXlzKG9wdGlvbnMuaGVhZGVycykuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgaWYgKG9wdGlvbnMuaGVhZGVycy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICBoZWFkZXJzLnNldChrZXksIG9wdGlvbnMuaGVhZGVyc1trZXldKTtcbiAgICB9XG4gIH0pO1xuXG4gIHdyYXBwZWRQcm9taXNlID0gd3JhcHBlZEZldGNoKG9wdGlvbnMudXJsLCBmZXRjaE9wdGlvbnMpO1xuXG4gIGlmIChvcHRpb25zLnRpbWVvdXQgPiAwKSB7XG4gICAgdGltZXIgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgIHdyYXBwZWRQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ0xvYWQgdGltZW91dCBmb3IgcmVzb3VyY2U6ICcgK1xuICAgICAgICBvcHRpb25zLnVybCkpO1xuICAgIH0sIG9wdGlvbnMudGltZW91dCk7XG4gIH1cblxuICB3cmFwcGVkUHJvbWlzZS5wcm9taXNlLnRoZW4oZnVuY3Rpb24gKGZldGNoUmVzcG9uc2UpIHtcbiAgICByZXNwb25zZSA9IHtcbiAgICAgIHN0YXR1c0NvZGU6IGZldGNoUmVzcG9uc2Uuc3RhdHVzXG4gICAgfTtcblxuICAgIGlmIChvcHRpb25zLnRpbWVvdXQgPiAwKSB7XG4gICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICAgIH1cblxuICAgIGlmIChyZXNwb25zZS5zdGF0dXNDb2RlID49IDIwMCAmJiByZXNwb25zZS5zdGF0dXNDb2RlIDwgMzAwKSB7XG4gICAgICByZXR1cm4gb3B0aW9ucy5iaW5hcnkgPyBmZXRjaFJlc3BvbnNlLmJsb2IoKSA6IGZldGNoUmVzcG9uc2UudGV4dCgpO1xuICAgIH1cblxuICAgIHJldHVybiBmZXRjaFJlc3BvbnNlLmpzb24oKTtcbiAgfSkudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgaWYgKHJlc3BvbnNlLnN0YXR1c0NvZGUgPj0gMjAwICYmIHJlc3BvbnNlLnN0YXR1c0NvZGUgPCAzMDApIHtcbiAgICAgIGNhbGxiYWNrKG51bGwsIHJlc3BvbnNlLCByZXN1bHQpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHQuc3RhdHVzID0gcmVzcG9uc2Uuc3RhdHVzQ29kZTtcbiAgICAgIGNhbGxiYWNrKHJlc3VsdCk7XG4gICAgfVxuICB9KS5jYXRjaChmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICBpZiAoIWVycm9yKSB7XG4gICAgICAvLyB0aGlzIGhhcHBlbnMgd2hlbiB0aGUgbGlzdGVuZXIgaXMgY2FuY2VsZWRcbiAgICAgIGVycm9yID0gbmV3IEVycm9yKCdjYW5jZWxlZCcpO1xuICAgIH1cbiAgICBjYWxsYmFjayhlcnJvcik7XG4gIH0pO1xuXG4gIHJldHVybiB7YWJvcnQ6IHdyYXBwZWRQcm9taXNlLnJlamVjdH07XG59XG5cbmZ1bmN0aW9uIHhoUmVxdWVzdChvcHRpb25zLCBjYWxsYmFjaykge1xuXG4gIHZhciB4aHIsIHRpbWVyO1xuICB2YXIgdGltZWRvdXQgPSBmYWxzZTtcblxuICB2YXIgYWJvcnRSZXEgPSBmdW5jdGlvbiAoKSB7XG4gICAgeGhyLmFib3J0KCk7XG4gICAgY2xlYW5VcCgpO1xuICB9O1xuXG4gIHZhciB0aW1lb3V0UmVxID0gZnVuY3Rpb24gKCkge1xuICAgIHRpbWVkb3V0ID0gdHJ1ZTtcbiAgICB4aHIuYWJvcnQoKTtcbiAgICBjbGVhblVwKCk7XG4gIH07XG5cbiAgdmFyIHJldCA9IHthYm9ydDogYWJvcnRSZXF9O1xuXG4gIHZhciBjbGVhblVwID0gZnVuY3Rpb24gKCkge1xuICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG4gICAgcmV0LmFib3J0ID0gZnVuY3Rpb24gKCkge307XG4gICAgaWYgKHhocikge1xuICAgICAgeGhyLm9ucHJvZ3Jlc3MgPSB1bmRlZmluZWQ7XG4gICAgICBpZiAoeGhyLnVwbG9hZCkge1xuICAgICAgICB4aHIudXBsb2FkLm9ucHJvZ3Jlc3MgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICB4aHIub25yZWFkeXN0YXRlY2hhbmdlID0gdW5kZWZpbmVkO1xuICAgICAgeGhyID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgfTtcblxuICBpZiAob3B0aW9ucy54aHIpIHtcbiAgICB4aHIgPSBuZXcgb3B0aW9ucy54aHIoKTtcbiAgfSBlbHNlIHtcbiAgICB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgeGhyLm9wZW4ob3B0aW9ucy5tZXRob2QsIG9wdGlvbnMudXJsKTtcbiAgfSBjYXRjaCAoZXhjZXB0aW9uKSB7XG4gICAgcmV0dXJuIGNhbGxiYWNrKG5ldyBFcnJvcihleGNlcHRpb24ubmFtZSB8fCAnVXJsIGlzIGludmFsaWQnKSk7XG4gIH1cblxuICB4aHIud2l0aENyZWRlbnRpYWxzID0gKCd3aXRoQ3JlZGVudGlhbHMnIGluIG9wdGlvbnMpID9cbiAgICBvcHRpb25zLndpdGhDcmVkZW50aWFscyA6IHRydWU7XG5cbiAgaWYgKG9wdGlvbnMubWV0aG9kID09PSAnR0VUJykge1xuICAgIGRlbGV0ZSBvcHRpb25zLmhlYWRlcnNbJ0NvbnRlbnQtVHlwZSddO1xuICB9IGVsc2UgaWYgKG9wdGlvbnMuanNvbikge1xuICAgIG9wdGlvbnMuaGVhZGVycy5BY2NlcHQgPSAnYXBwbGljYXRpb24vanNvbic7XG4gICAgb3B0aW9ucy5oZWFkZXJzWydDb250ZW50LVR5cGUnXSA9IG9wdGlvbnMuaGVhZGVyc1snQ29udGVudC1UeXBlJ10gfHxcbiAgICAgICdhcHBsaWNhdGlvbi9qc29uJztcbiAgICBpZiAob3B0aW9ucy5ib2R5ICYmXG4gICAgICAgIG9wdGlvbnMucHJvY2Vzc0RhdGEgJiZcbiAgICAgICAgdHlwZW9mIG9wdGlvbnMuYm9keSAhPT0gXCJzdHJpbmdcIikge1xuICAgICAgb3B0aW9ucy5ib2R5ID0gSlNPTi5zdHJpbmdpZnkob3B0aW9ucy5ib2R5KTtcbiAgICB9XG4gIH1cblxuICBpZiAob3B0aW9ucy5iaW5hcnkpIHtcbiAgICB4aHIucmVzcG9uc2VUeXBlID0gJ2FycmF5YnVmZmVyJztcbiAgfVxuXG4gIGlmICghKCdib2R5JyBpbiBvcHRpb25zKSkge1xuICAgIG9wdGlvbnMuYm9keSA9IG51bGw7XG4gIH1cblxuICBmb3IgKHZhciBrZXkgaW4gb3B0aW9ucy5oZWFkZXJzKSB7XG4gICAgaWYgKG9wdGlvbnMuaGVhZGVycy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlcihrZXksIG9wdGlvbnMuaGVhZGVyc1trZXldKTtcbiAgICB9XG4gIH1cblxuICBpZiAob3B0aW9ucy50aW1lb3V0ID4gMCkge1xuICAgIHRpbWVyID0gc2V0VGltZW91dCh0aW1lb3V0UmVxLCBvcHRpb25zLnRpbWVvdXQpO1xuICAgIHhoci5vbnByb2dyZXNzID0gZnVuY3Rpb24gKCkge1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgIGlmKHhoci5yZWFkeVN0YXRlICE9PSA0KSB7XG4gICAgICAgIHRpbWVyID0gc2V0VGltZW91dCh0aW1lb3V0UmVxLCBvcHRpb25zLnRpbWVvdXQpO1xuICAgICAgfVxuICAgIH07XG4gICAgaWYgKHR5cGVvZiB4aHIudXBsb2FkICE9PSAndW5kZWZpbmVkJykgeyAvLyBkb2VzIG5vdCBleGlzdCBpbiBpZTlcbiAgICAgIHhoci51cGxvYWQub25wcm9ncmVzcyA9IHhoci5vbnByb2dyZXNzO1xuICAgIH1cbiAgfVxuXG4gIHhoci5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHhoci5yZWFkeVN0YXRlICE9PSA0KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHJlc3BvbnNlID0ge1xuICAgICAgc3RhdHVzQ29kZTogeGhyLnN0YXR1c1xuICAgIH07XG5cbiAgICBpZiAoeGhyLnN0YXR1cyA+PSAyMDAgJiYgeGhyLnN0YXR1cyA8IDMwMCkge1xuICAgICAgdmFyIGRhdGE7XG4gICAgICBpZiAob3B0aW9ucy5iaW5hcnkpIHtcbiAgICAgICAgZGF0YSA9IGNyZWF0ZUJsb2IoW3hoci5yZXNwb25zZSB8fCAnJ10sIHtcbiAgICAgICAgICB0eXBlOiB4aHIuZ2V0UmVzcG9uc2VIZWFkZXIoJ0NvbnRlbnQtVHlwZScpXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGF0YSA9IHhoci5yZXNwb25zZVRleHQ7XG4gICAgICB9XG4gICAgICBjYWxsYmFjayhudWxsLCByZXNwb25zZSwgZGF0YSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBlcnIgPSB7fTtcbiAgICAgIGlmICh0aW1lZG91dCkge1xuICAgICAgICBlcnIgPSBuZXcgRXJyb3IoJ0VUSU1FRE9VVCcpO1xuICAgICAgICBlcnIuY29kZSA9ICdFVElNRURPVVQnO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgeGhyLnJlc3BvbnNlID09PSAnc3RyaW5nJykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGVyciA9IEpTT04ucGFyc2UoeGhyLnJlc3BvbnNlKTtcbiAgICAgICAgfSBjYXRjaChlKSB7fVxuICAgICAgfVxuICAgICAgZXJyLnN0YXR1cyA9IHhoci5zdGF0dXM7XG4gICAgICBjYWxsYmFjayhlcnIpO1xuICAgIH1cbiAgICBjbGVhblVwKCk7XG4gIH07XG5cbiAgaWYgKG9wdGlvbnMuYm9keSAmJiAob3B0aW9ucy5ib2R5IGluc3RhbmNlb2YgQmxvYikpIHtcbiAgICByZWFkQXNBcnJheUJ1ZmZlcihvcHRpb25zLmJvZHksIGZ1bmN0aW9uIChhcnJheUJ1ZmZlcikge1xuICAgICAgeGhyLnNlbmQoYXJyYXlCdWZmZXIpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHhoci5zZW5kKG9wdGlvbnMuYm9keSk7XG4gIH1cblxuICByZXR1cm4gcmV0O1xufVxuXG5mdW5jdGlvbiB0ZXN0WGhyKCkge1xuICB0cnkge1xuICAgIG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIGhhc1hociA9IHRlc3RYaHIoKTtcblxuZnVuY3Rpb24gYWpheCQxKG9wdGlvbnMsIGNhbGxiYWNrKSB7XG4gIGlmICghZmFsc2UgJiYgKGhhc1hociB8fCBvcHRpb25zLnhocikpIHtcbiAgICByZXR1cm4geGhSZXF1ZXN0KG9wdGlvbnMsIGNhbGxiYWNrKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gZmV0Y2hSZXF1ZXN0KG9wdGlvbnMsIGNhbGxiYWNrKTtcbiAgfVxufVxuXG4vLyB0aGUgYmxvYiBhbHJlYWR5IGhhcyBhIHR5cGU7IGRvIG5vdGhpbmdcbnZhciByZXMkMiA9IGZ1bmN0aW9uICgpIHt9O1xuXG5mdW5jdGlvbiBkZWZhdWx0Qm9keSgpIHtcbiAgcmV0dXJuICcnO1xufVxuXG5mdW5jdGlvbiBhamF4Q29yZShvcHRpb25zLCBjYWxsYmFjaykge1xuXG4gIG9wdGlvbnMgPSBjbG9uZShvcHRpb25zKTtcblxuICB2YXIgZGVmYXVsdE9wdGlvbnMgPSB7XG4gICAgbWV0aG9kIDogXCJHRVRcIixcbiAgICBoZWFkZXJzOiB7fSxcbiAgICBqc29uOiB0cnVlLFxuICAgIHByb2Nlc3NEYXRhOiB0cnVlLFxuICAgIHRpbWVvdXQ6IDEwMDAwLFxuICAgIGNhY2hlOiBmYWxzZVxuICB9O1xuXG4gIG9wdGlvbnMgPSBleHRlbmQkMShkZWZhdWx0T3B0aW9ucywgb3B0aW9ucyk7XG5cbiAgZnVuY3Rpb24gb25TdWNjZXNzKG9iaiwgcmVzcCwgY2IpIHtcbiAgICBpZiAoIW9wdGlvbnMuYmluYXJ5ICYmIG9wdGlvbnMuanNvbiAmJiB0eXBlb2Ygb2JqID09PSAnc3RyaW5nJykge1xuICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgIHRyeSB7XG4gICAgICAgIG9iaiA9IEpTT04ucGFyc2Uob2JqKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgLy8gUHJvYmFibHkgYSBtYWxmb3JtZWQgSlNPTiBmcm9tIHNlcnZlclxuICAgICAgICByZXR1cm4gY2IoZSk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHtcbiAgICAgIG9iaiA9IG9iai5tYXAoZnVuY3Rpb24gKHYpIHtcbiAgICAgICAgaWYgKHYuZXJyb3IgfHwgdi5taXNzaW5nKSB7XG4gICAgICAgICAgcmV0dXJuIGdlbmVyYXRlRXJyb3JGcm9tUmVzcG9uc2Uodik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIHY7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy5iaW5hcnkpIHtcbiAgICAgIHJlcyQyKG9iaiwgcmVzcCk7XG4gICAgfVxuICAgIGNiKG51bGwsIG9iaiwgcmVzcCk7XG4gIH1cblxuICBpZiAob3B0aW9ucy5qc29uKSB7XG4gICAgaWYgKCFvcHRpb25zLmJpbmFyeSkge1xuICAgICAgb3B0aW9ucy5oZWFkZXJzLkFjY2VwdCA9ICdhcHBsaWNhdGlvbi9qc29uJztcbiAgICB9XG4gICAgb3B0aW9ucy5oZWFkZXJzWydDb250ZW50LVR5cGUnXSA9IG9wdGlvbnMuaGVhZGVyc1snQ29udGVudC1UeXBlJ10gfHxcbiAgICAgICdhcHBsaWNhdGlvbi9qc29uJztcbiAgfVxuXG4gIGlmIChvcHRpb25zLmJpbmFyeSkge1xuICAgIG9wdGlvbnMuZW5jb2RpbmcgPSBudWxsO1xuICAgIG9wdGlvbnMuanNvbiA9IGZhbHNlO1xuICB9XG5cbiAgaWYgKCFvcHRpb25zLnByb2Nlc3NEYXRhKSB7XG4gICAgb3B0aW9ucy5qc29uID0gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gYWpheCQxKG9wdGlvbnMsIGZ1bmN0aW9uIChlcnIsIHJlc3BvbnNlLCBib2R5KSB7XG5cbiAgICBpZiAoZXJyKSB7XG4gICAgICByZXR1cm4gY2FsbGJhY2soZ2VuZXJhdGVFcnJvckZyb21SZXNwb25zZShlcnIpKTtcbiAgICB9XG5cbiAgICB2YXIgZXJyb3I7XG4gICAgdmFyIGNvbnRlbnRfdHlwZSA9IHJlc3BvbnNlLmhlYWRlcnMgJiYgcmVzcG9uc2UuaGVhZGVyc1snY29udGVudC10eXBlJ107XG4gICAgdmFyIGRhdGEgPSBib2R5IHx8IGRlZmF1bHRCb2R5KCk7XG5cbiAgICAvLyBDb3VjaERCIGRvZXNuJ3QgYWx3YXlzIHJldHVybiB0aGUgcmlnaHQgY29udGVudC10eXBlIGZvciBKU09OIGRhdGEsIHNvXG4gICAgLy8gd2UgY2hlY2sgZm9yIF57IGFuZCB9JCAoaWdub3JpbmcgbGVhZGluZy90cmFpbGluZyB3aGl0ZXNwYWNlKVxuICAgIGlmICghb3B0aW9ucy5iaW5hcnkgJiYgKG9wdGlvbnMuanNvbiB8fCAhb3B0aW9ucy5wcm9jZXNzRGF0YSkgJiZcbiAgICAgICAgdHlwZW9mIGRhdGEgIT09ICdvYmplY3QnICYmXG4gICAgICAgICgvanNvbi8udGVzdChjb250ZW50X3R5cGUpIHx8XG4gICAgICAgICAoL15bXFxzXSpcXHsvLnRlc3QoZGF0YSkgJiYgL1xcfVtcXHNdKiQvLnRlc3QoZGF0YSkpKSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZGF0YSA9IEpTT04ucGFyc2UoZGF0YS50b1N0cmluZygpKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgfVxuXG4gICAgaWYgKHJlc3BvbnNlLnN0YXR1c0NvZGUgPj0gMjAwICYmIHJlc3BvbnNlLnN0YXR1c0NvZGUgPCAzMDApIHtcbiAgICAgIG9uU3VjY2VzcyhkYXRhLCByZXNwb25zZSwgY2FsbGJhY2spO1xuICAgIH0gZWxzZSB7XG4gICAgICBlcnJvciA9IGdlbmVyYXRlRXJyb3JGcm9tUmVzcG9uc2UoZGF0YSk7XG4gICAgICBlcnJvci5zdGF0dXMgPSByZXNwb25zZS5zdGF0dXNDb2RlO1xuICAgICAgY2FsbGJhY2soZXJyb3IpO1xuICAgIH1cbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGFqYXgob3B0cywgY2FsbGJhY2spIHtcblxuICAvLyBjYWNoZS1idXN0ZXIsIHNwZWNpZmljYWxseSBkZXNpZ25lZCB0byB3b3JrIGFyb3VuZCBJRSdzIGFnZ3Jlc3NpdmUgY2FjaGluZ1xuICAvLyBzZWUgaHR0cDovL3d3dy5kYXNoYmF5LmNvbS8yMDExLzA1L2ludGVybmV0LWV4cGxvcmVyLWNhY2hlcy1hamF4L1xuICAvLyBBbHNvIFNhZmFyaSBjYWNoZXMgUE9TVHMsIHNvIHdlIG5lZWQgdG8gY2FjaGUtYnVzdCB0aG9zZSB0b28uXG4gIHZhciB1YSA9IChuYXZpZ2F0b3IgJiYgbmF2aWdhdG9yLnVzZXJBZ2VudCkgP1xuICAgIG5hdmlnYXRvci51c2VyQWdlbnQudG9Mb3dlckNhc2UoKSA6ICcnO1xuXG4gIHZhciBpc1NhZmFyaSA9IHVhLmluZGV4T2YoJ3NhZmFyaScpICE9PSAtMSAmJiB1YS5pbmRleE9mKCdjaHJvbWUnKSA9PT0gLTE7XG4gIHZhciBpc0lFID0gdWEuaW5kZXhPZignbXNpZScpICE9PSAtMTtcbiAgdmFyIGlzRWRnZSA9IHVhLmluZGV4T2YoJ2VkZ2UnKSAhPT0gLTE7XG5cbiAgLy8gaXQgYXBwZWFycyB0aGUgbmV3IHZlcnNpb24gb2Ygc2FmYXJpIGFsc28gY2FjaGVzIEdFVHMsXG4gIC8vIHNlZSBodHRwczovL2dpdGh1Yi5jb20vcG91Y2hkYi9wb3VjaGRiL2lzc3Vlcy81MDEwXG4gIHZhciBzaG91bGRDYWNoZUJ1c3QgPSAoaXNTYWZhcmkgfHxcbiAgICAoKGlzSUUgfHwgaXNFZGdlKSAmJiBvcHRzLm1ldGhvZCA9PT0gJ0dFVCcpKTtcblxuICB2YXIgY2FjaGUgPSAnY2FjaGUnIGluIG9wdHMgPyBvcHRzLmNhY2hlIDogdHJ1ZTtcblxuICB2YXIgaXNCbG9iVXJsID0gL15ibG9iOi8udGVzdChvcHRzLnVybCk7IC8vIGRvbid0IGFwcGVuZCBub25jZXMgZm9yIGJsb2IgVVJMc1xuXG4gIGlmICghaXNCbG9iVXJsICYmIChzaG91bGRDYWNoZUJ1c3QgfHwgIWNhY2hlKSkge1xuICAgIHZhciBoYXNBcmdzID0gb3B0cy51cmwuaW5kZXhPZignPycpICE9PSAtMTtcbiAgICBvcHRzLnVybCArPSAoaGFzQXJncyA/ICcmJyA6ICc/JykgKyAnX25vbmNlPScgKyBEYXRlLm5vdygpO1xuICB9XG5cbiAgcmV0dXJuIGFqYXhDb3JlKG9wdHMsIGNhbGxiYWNrKTtcbn1cblxuLy8gZGVhZCBzaW1wbGUgcHJvbWlzZSBwb29sLCBpbnNwaXJlZCBieSBodHRwczovL2dpdGh1Yi5jb20vdGltZHAvZXM2LXByb21pc2UtcG9vbFxuLy8gYnV0IG11Y2ggc21hbGxlciBpbiBjb2RlIHNpemUuIGxpbWl0cyB0aGUgbnVtYmVyIG9mIGNvbmN1cnJlbnQgcHJvbWlzZXMgdGhhdCBhcmUgZXhlY3V0ZWRcblxuZnVuY3Rpb24gcG9vbChwcm9taXNlRmFjdG9yaWVzLCBsaW1pdCkge1xuICByZXR1cm4gbmV3IFBvdWNoUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgdmFyIHJ1bm5pbmcgPSAwO1xuICAgIHZhciBjdXJyZW50ID0gMDtcbiAgICB2YXIgZG9uZSA9IDA7XG4gICAgdmFyIGxlbiA9IHByb21pc2VGYWN0b3JpZXMubGVuZ3RoO1xuICAgIHZhciBlcnI7XG5cbiAgICBmdW5jdGlvbiBydW5OZXh0KCkge1xuICAgICAgcnVubmluZysrO1xuICAgICAgcHJvbWlzZUZhY3Rvcmllc1tjdXJyZW50KytdKCkudGhlbihvblN1Y2Nlc3MsIG9uRXJyb3IpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRvTmV4dCgpIHtcbiAgICAgIGlmICgrK2RvbmUgPT09IGxlbikge1xuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcnVuTmV4dEJhdGNoKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gb25TdWNjZXNzKCkge1xuICAgICAgcnVubmluZy0tO1xuICAgICAgZG9OZXh0KCk7XG4gICAgfVxuXG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICBmdW5jdGlvbiBvbkVycm9yKHRoaXNFcnIpIHtcbiAgICAgIHJ1bm5pbmctLTtcbiAgICAgIGVyciA9IGVyciB8fCB0aGlzRXJyO1xuICAgICAgZG9OZXh0KCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcnVuTmV4dEJhdGNoKCkge1xuICAgICAgd2hpbGUgKHJ1bm5pbmcgPCBsaW1pdCAmJiBjdXJyZW50IDwgbGVuKSB7XG4gICAgICAgIHJ1bk5leHQoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBydW5OZXh0QmF0Y2goKTtcbiAgfSk7XG59XG5cbnZhciBDSEFOR0VTX0JBVENIX1NJWkUgPSAyNTtcbnZhciBNQVhfU0lNVUxUQU5FT1VTX1JFVlMgPSA1MDtcblxudmFyIHN1cHBvcnRzQnVsa0dldE1hcCA9IHt9O1xuXG52YXIgbG9nJDEgPSBkZWJ1ZygncG91Y2hkYjpodHRwJyk7XG5cbmZ1bmN0aW9uIHJlYWRBdHRhY2htZW50c0FzQmxvYk9yQnVmZmVyKHJvdykge1xuICB2YXIgYXR0cyA9IHJvdy5kb2MgJiYgcm93LmRvYy5fYXR0YWNobWVudHM7XG4gIGlmICghYXR0cykge1xuICAgIHJldHVybjtcbiAgfVxuICBPYmplY3Qua2V5cyhhdHRzKS5mb3JFYWNoKGZ1bmN0aW9uIChmaWxlbmFtZSkge1xuICAgIHZhciBhdHQgPSBhdHRzW2ZpbGVuYW1lXTtcbiAgICBhdHQuZGF0YSA9IGI2NFRvQmx1ZmZlcihhdHQuZGF0YSwgYXR0LmNvbnRlbnRfdHlwZSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBlbmNvZGVEb2NJZChpZCkge1xuICBpZiAoL15fZGVzaWduLy50ZXN0KGlkKSkge1xuICAgIHJldHVybiAnX2Rlc2lnbi8nICsgZW5jb2RlVVJJQ29tcG9uZW50KGlkLnNsaWNlKDgpKTtcbiAgfVxuICBpZiAoL15fbG9jYWwvLnRlc3QoaWQpKSB7XG4gICAgcmV0dXJuICdfbG9jYWwvJyArIGVuY29kZVVSSUNvbXBvbmVudChpZC5zbGljZSg3KSk7XG4gIH1cbiAgcmV0dXJuIGVuY29kZVVSSUNvbXBvbmVudChpZCk7XG59XG5cbmZ1bmN0aW9uIHByZXByb2Nlc3NBdHRhY2htZW50cyQxKGRvYykge1xuICBpZiAoIWRvYy5fYXR0YWNobWVudHMgfHwgIU9iamVjdC5rZXlzKGRvYy5fYXR0YWNobWVudHMpKSB7XG4gICAgcmV0dXJuIFBvdWNoUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICByZXR1cm4gUG91Y2hQcm9taXNlLmFsbChPYmplY3Qua2V5cyhkb2MuX2F0dGFjaG1lbnRzKS5tYXAoZnVuY3Rpb24gKGtleSkge1xuICAgIHZhciBhdHRhY2htZW50ID0gZG9jLl9hdHRhY2htZW50c1trZXldO1xuICAgIGlmIChhdHRhY2htZW50LmRhdGEgJiYgdHlwZW9mIGF0dGFjaG1lbnQuZGF0YSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBuZXcgUG91Y2hQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlKSB7XG4gICAgICAgIGJsb2JUb0Jhc2U2NChhdHRhY2htZW50LmRhdGEsIHJlc29sdmUpO1xuICAgICAgfSkudGhlbihmdW5jdGlvbiAoYjY0KSB7XG4gICAgICAgIGF0dGFjaG1lbnQuZGF0YSA9IGI2NDtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSkpO1xufVxuXG5mdW5jdGlvbiBoYXNVcmxQcmVmaXgob3B0cykge1xuICBpZiAoIW9wdHMucHJlZml4KSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgdmFyIHByb3RvY29sID0gcGFyc2VVcmkob3B0cy5wcmVmaXgpLnByb3RvY29sO1xuXG4gIHJldHVybiBwcm90b2NvbCA9PT0gJ2h0dHAnIHx8IHByb3RvY29sID09PSAnaHR0cHMnO1xufVxuXG4vLyBHZXQgYWxsIHRoZSBpbmZvcm1hdGlvbiB5b3UgcG9zc2libHkgY2FuIGFib3V0IHRoZSBVUkkgZ2l2ZW4gYnkgbmFtZSBhbmRcbi8vIHJldHVybiBpdCBhcyBhIHN1aXRhYmxlIG9iamVjdC5cbmZ1bmN0aW9uIGdldEhvc3QobmFtZSwgb3B0cykge1xuXG4gIC8vIGVuY29kZSBkYiBuYW1lIGlmIG9wdHMucHJlZml4IGlzIGEgdXJsICgjNTU3NClcbiAgaWYgKGhhc1VybFByZWZpeChvcHRzKSkge1xuICAgIHZhciBkYk5hbWUgPSBvcHRzLm5hbWUuc3Vic3RyKG9wdHMucHJlZml4Lmxlbmd0aCk7XG4gICAgbmFtZSA9IG9wdHMucHJlZml4ICsgZW5jb2RlVVJJQ29tcG9uZW50KGRiTmFtZSk7XG4gIH1cblxuICAvLyBQcmFzZSB0aGUgVVJJIGludG8gYWxsIGl0cyBsaXR0bGUgYml0c1xuICB2YXIgdXJpID0gcGFyc2VVcmkobmFtZSk7XG5cbiAgLy8gU3RvcmUgdGhlIHVzZXIgYW5kIHBhc3N3b3JkIGFzIGEgc2VwYXJhdGUgYXV0aCBvYmplY3RcbiAgaWYgKHVyaS51c2VyIHx8IHVyaS5wYXNzd29yZCkge1xuICAgIHVyaS5hdXRoID0ge3VzZXJuYW1lOiB1cmkudXNlciwgcGFzc3dvcmQ6IHVyaS5wYXNzd29yZH07XG4gIH1cblxuICAvLyBTcGxpdCB0aGUgcGF0aCBwYXJ0IG9mIHRoZSBVUkkgaW50byBwYXJ0cyB1c2luZyAnLycgYXMgdGhlIGRlbGltaXRlclxuICAvLyBhZnRlciByZW1vdmluZyBhbnkgbGVhZGluZyAnLycgYW5kIGFueSB0cmFpbGluZyAnLydcbiAgdmFyIHBhcnRzID0gdXJpLnBhdGgucmVwbGFjZSgvKF5cXC98XFwvJCkvZywgJycpLnNwbGl0KCcvJyk7XG5cbiAgLy8gU3RvcmUgdGhlIGZpcnN0IHBhcnQgYXMgdGhlIGRhdGFiYXNlIG5hbWUgYW5kIHJlbW92ZSBpdCBmcm9tIHRoZSBwYXJ0c1xuICAvLyBhcnJheVxuICB1cmkuZGIgPSBwYXJ0cy5wb3AoKTtcbiAgLy8gUHJldmVudCBkb3VibGUgZW5jb2Rpbmcgb2YgVVJJIGNvbXBvbmVudFxuICBpZiAodXJpLmRiLmluZGV4T2YoJyUnKSA9PT0gLTEpIHtcbiAgICB1cmkuZGIgPSBlbmNvZGVVUklDb21wb25lbnQodXJpLmRiKTtcbiAgfVxuXG4gIC8vIFJlc3RvcmUgdGhlIHBhdGggYnkgam9pbmluZyBhbGwgdGhlIHJlbWFpbmluZyBwYXJ0cyAoYWxsIHRoZSBwYXJ0c1xuICAvLyBleGNlcHQgZm9yIHRoZSBkYXRhYmFzZSBuYW1lKSB3aXRoICcvJ3NcbiAgdXJpLnBhdGggPSBwYXJ0cy5qb2luKCcvJyk7XG5cbiAgcmV0dXJuIHVyaTtcbn1cblxuLy8gR2VuZXJhdGUgYSBVUkwgd2l0aCB0aGUgaG9zdCBkYXRhIGdpdmVuIGJ5IG9wdHMgYW5kIHRoZSBnaXZlbiBwYXRoXG5mdW5jdGlvbiBnZW5EQlVybChvcHRzLCBwYXRoKSB7XG4gIHJldHVybiBnZW5Vcmwob3B0cywgb3B0cy5kYiArICcvJyArIHBhdGgpO1xufVxuXG4vLyBHZW5lcmF0ZSBhIFVSTCB3aXRoIHRoZSBob3N0IGRhdGEgZ2l2ZW4gYnkgb3B0cyBhbmQgdGhlIGdpdmVuIHBhdGhcbmZ1bmN0aW9uIGdlblVybChvcHRzLCBwYXRoKSB7XG4gIC8vIElmIHRoZSBob3N0IGFscmVhZHkgaGFzIGEgcGF0aCwgdGhlbiB3ZSBuZWVkIHRvIGhhdmUgYSBwYXRoIGRlbGltaXRlclxuICAvLyBPdGhlcndpc2UsIHRoZSBwYXRoIGRlbGltaXRlciBpcyB0aGUgZW1wdHkgc3RyaW5nXG4gIHZhciBwYXRoRGVsID0gIW9wdHMucGF0aCA/ICcnIDogJy8nO1xuXG4gIC8vIElmIHRoZSBob3N0IGFscmVhZHkgaGFzIGEgcGF0aCwgdGhlbiB3ZSBuZWVkIHRvIGhhdmUgYSBwYXRoIGRlbGltaXRlclxuICAvLyBPdGhlcndpc2UsIHRoZSBwYXRoIGRlbGltaXRlciBpcyB0aGUgZW1wdHkgc3RyaW5nXG4gIHJldHVybiBvcHRzLnByb3RvY29sICsgJzovLycgKyBvcHRzLmhvc3QgK1xuICAgICAgICAgKG9wdHMucG9ydCA/ICgnOicgKyBvcHRzLnBvcnQpIDogJycpICtcbiAgICAgICAgICcvJyArIG9wdHMucGF0aCArIHBhdGhEZWwgKyBwYXRoO1xufVxuXG5mdW5jdGlvbiBwYXJhbXNUb1N0cihwYXJhbXMpIHtcbiAgcmV0dXJuICc/JyArIE9iamVjdC5rZXlzKHBhcmFtcykubWFwKGZ1bmN0aW9uIChrKSB7XG4gICAgcmV0dXJuIGsgKyAnPScgKyBlbmNvZGVVUklDb21wb25lbnQocGFyYW1zW2tdKTtcbiAgfSkuam9pbignJicpO1xufVxuXG4vLyBJbXBsZW1lbnRzIHRoZSBQb3VjaERCIEFQSSBmb3IgZGVhbGluZyB3aXRoIENvdWNoREIgaW5zdGFuY2VzIG92ZXIgSFRUUFxuZnVuY3Rpb24gSHR0cFBvdWNoKG9wdHMsIGNhbGxiYWNrKSB7XG5cbiAgLy8gVGhlIGZ1bmN0aW9ucyB0aGF0IHdpbGwgYmUgcHVibGljbHkgYXZhaWxhYmxlIGZvciBIdHRwUG91Y2hcbiAgdmFyIGFwaSA9IHRoaXM7XG5cbiAgdmFyIGhvc3QgPSBnZXRIb3N0KG9wdHMubmFtZSwgb3B0cyk7XG4gIHZhciBkYlVybCA9IGdlbkRCVXJsKGhvc3QsICcnKTtcblxuICBvcHRzID0gY2xvbmUob3B0cyk7XG4gIHZhciBhamF4T3B0cyA9IG9wdHMuYWpheCB8fCB7fTtcblxuICBpZiAob3B0cy5hdXRoIHx8IGhvc3QuYXV0aCkge1xuICAgIHZhciBuQXV0aCA9IG9wdHMuYXV0aCB8fCBob3N0LmF1dGg7XG4gICAgdmFyIHN0ciA9IG5BdXRoLnVzZXJuYW1lICsgJzonICsgbkF1dGgucGFzc3dvcmQ7XG4gICAgdmFyIHRva2VuID0gYnRvYSQxKHVuZXNjYXBlKGVuY29kZVVSSUNvbXBvbmVudChzdHIpKSk7XG4gICAgYWpheE9wdHMuaGVhZGVycyA9IGFqYXhPcHRzLmhlYWRlcnMgfHwge307XG4gICAgYWpheE9wdHMuaGVhZGVycy5BdXRob3JpemF0aW9uID0gJ0Jhc2ljICcgKyB0b2tlbjtcbiAgfVxuXG4gIC8vIE5vdCBzdHJpY3RseSBuZWNlc3NhcnksIGJ1dCB3ZSBkbyB0aGlzIGJlY2F1c2UgbnVtZXJvdXMgdGVzdHNcbiAgLy8gcmVseSBvbiBzd2FwcGluZyBhamF4IGluIGFuZCBvdXQuXG4gIGFwaS5fYWpheCA9IGFqYXg7XG5cbiAgZnVuY3Rpb24gYWpheCQkKHVzZXJPcHRzLCBvcHRpb25zLCBjYWxsYmFjaykge1xuICAgIHZhciByZXFBamF4ID0gdXNlck9wdHMuYWpheCB8fCB7fTtcbiAgICB2YXIgcmVxT3B0cyA9IGV4dGVuZCQxKGNsb25lKGFqYXhPcHRzKSwgcmVxQWpheCwgb3B0aW9ucyk7XG4gICAgbG9nJDEocmVxT3B0cy5tZXRob2QgKyAnICcgKyByZXFPcHRzLnVybCk7XG4gICAgcmV0dXJuIGFwaS5fYWpheChyZXFPcHRzLCBjYWxsYmFjayk7XG4gIH1cblxuICBmdW5jdGlvbiBhamF4UHJvbWlzZSh1c2VyT3B0cywgb3B0cykge1xuICAgIHJldHVybiBuZXcgUG91Y2hQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIGFqYXgkJCh1c2VyT3B0cywgb3B0cywgZnVuY3Rpb24gKGVyciwgcmVzKSB7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgcmV0dXJuIHJlamVjdChlcnIpO1xuICAgICAgICB9XG4gICAgICAgIHJlc29sdmUocmVzKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gYWRhcHRlckZ1biQkKG5hbWUsIGZ1bikge1xuICAgIHJldHVybiBhZGFwdGVyRnVuKG5hbWUsIGdldEFyZ3VtZW50cyhmdW5jdGlvbiAoYXJncykge1xuICAgICAgc2V0dXAoKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGZ1bi5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHZhciBjYWxsYmFjayA9IGFyZ3MucG9wKCk7XG4gICAgICAgIGNhbGxiYWNrKGUpO1xuICAgICAgfSk7XG4gICAgfSkpO1xuICB9XG5cbiAgdmFyIHNldHVwUHJvbWlzZTtcblxuICBmdW5jdGlvbiBzZXR1cCgpIHtcbiAgICAvLyBUT0RPOiBSZW1vdmUgYHNraXBTZXR1cGAgaW4gZmF2b3Igb2YgYHNraXBfc2V0dXBgIGluIGEgZnV0dXJlIHJlbGVhc2VcbiAgICBpZiAob3B0cy5za2lwU2V0dXAgfHwgb3B0cy5za2lwX3NldHVwKSB7XG4gICAgICByZXR1cm4gUG91Y2hQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG5cbiAgICAvLyBJZiB0aGVyZSBpcyBhIHNldHVwIGluIHByb2Nlc3Mgb3IgcHJldmlvdXMgc3VjY2Vzc2Z1bCBzZXR1cFxuICAgIC8vIGRvbmUgdGhlbiB3ZSB3aWxsIHVzZSB0aGF0XG4gICAgLy8gSWYgcHJldmlvdXMgc2V0dXBzIGhhdmUgYmVlbiByZWplY3RlZCB3ZSB3aWxsIHRyeSBhZ2FpblxuICAgIGlmIChzZXR1cFByb21pc2UpIHtcbiAgICAgIHJldHVybiBzZXR1cFByb21pc2U7XG4gICAgfVxuXG4gICAgdmFyIGNoZWNrRXhpc3RzID0ge21ldGhvZDogJ0dFVCcsIHVybDogZGJVcmx9O1xuICAgIHNldHVwUHJvbWlzZSA9IGFqYXhQcm9taXNlKHt9LCBjaGVja0V4aXN0cykuY2F0Y2goZnVuY3Rpb24gKGVycikge1xuICAgICAgaWYgKGVyciAmJiBlcnIuc3RhdHVzICYmIGVyci5zdGF0dXMgPT09IDQwNCkge1xuICAgICAgICAvLyBEb2VzbnQgZXhpc3QsIGNyZWF0ZSBpdFxuICAgICAgICBleHBsYWluRXJyb3IoNDA0LCAnUG91Y2hEQiBpcyBqdXN0IGRldGVjdGluZyBpZiB0aGUgcmVtb3RlIGV4aXN0cy4nKTtcbiAgICAgICAgcmV0dXJuIGFqYXhQcm9taXNlKHt9LCB7bWV0aG9kOiAnUFVUJywgdXJsOiBkYlVybH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFBvdWNoUHJvbWlzZS5yZWplY3QoZXJyKTtcbiAgICAgIH1cbiAgICB9KS5jYXRjaChmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAvLyBJZiB3ZSB0cnkgdG8gY3JlYXRlIGEgZGF0YWJhc2UgdGhhdCBhbHJlYWR5IGV4aXN0cywgc2tpcHBlZCBpblxuICAgICAgLy8gaXN0YW5idWwgc2luY2UgaXRzIGNhdGNoaW5nIGEgcmFjZSBjb25kaXRpb24uXG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICAgIGlmIChlcnIgJiYgZXJyLnN0YXR1cyAmJiBlcnIuc3RhdHVzID09PSA0MTIpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gUG91Y2hQcm9taXNlLnJlamVjdChlcnIpO1xuICAgIH0pO1xuXG4gICAgc2V0dXBQcm9taXNlLmNhdGNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHNldHVwUHJvbWlzZSA9IG51bGw7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gc2V0dXBQcm9taXNlO1xuICB9XG5cbiAgaW1tZWRpYXRlKGZ1bmN0aW9uICgpIHtcbiAgICBjYWxsYmFjayhudWxsLCBhcGkpO1xuICB9KTtcblxuICBhcGkudHlwZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gJ2h0dHAnO1xuICB9O1xuXG4gIGFwaS5pZCA9IGFkYXB0ZXJGdW4kJCgnaWQnLCBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBhamF4JCQoe30sIHttZXRob2Q6ICdHRVQnLCB1cmw6IGdlblVybChob3N0LCAnJyl9LCBmdW5jdGlvbiAoZXJyLCByZXN1bHQpIHtcbiAgICAgIHZhciB1dWlkID0gKHJlc3VsdCAmJiByZXN1bHQudXVpZCkgP1xuICAgICAgICAocmVzdWx0LnV1aWQgKyBob3N0LmRiKSA6IGdlbkRCVXJsKGhvc3QsICcnKTtcbiAgICAgIGNhbGxiYWNrKG51bGwsIHV1aWQpO1xuICAgIH0pO1xuICB9KTtcblxuICBhcGkucmVxdWVzdCA9IGFkYXB0ZXJGdW4kJCgncmVxdWVzdCcsIGZ1bmN0aW9uIChvcHRpb25zLCBjYWxsYmFjaykge1xuICAgIG9wdGlvbnMudXJsID0gZ2VuREJVcmwoaG9zdCwgb3B0aW9ucy51cmwpO1xuICAgIGFqYXgkJCh7fSwgb3B0aW9ucywgY2FsbGJhY2spO1xuICB9KTtcblxuICAvLyBTZW5kcyBhIFBPU1QgcmVxdWVzdCB0byB0aGUgaG9zdCBjYWxsaW5nIHRoZSBjb3VjaGRiIF9jb21wYWN0IGZ1bmN0aW9uXG4gIC8vICAgIHZlcnNpb246IFRoZSB2ZXJzaW9uIG9mIENvdWNoREIgaXQgaXMgcnVubmluZ1xuICBhcGkuY29tcGFjdCA9IGFkYXB0ZXJGdW4kJCgnY29tcGFjdCcsIGZ1bmN0aW9uIChvcHRzLCBjYWxsYmFjaykge1xuICAgIGlmICh0eXBlb2Ygb3B0cyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgY2FsbGJhY2sgPSBvcHRzO1xuICAgICAgb3B0cyA9IHt9O1xuICAgIH1cbiAgICBvcHRzID0gY2xvbmUob3B0cyk7XG4gICAgYWpheCQkKG9wdHMsIHtcbiAgICAgIHVybDogZ2VuREJVcmwoaG9zdCwgJ19jb21wYWN0JyksXG4gICAgICBtZXRob2Q6ICdQT1NUJ1xuICAgIH0sIGZ1bmN0aW9uICgpIHtcbiAgICAgIGZ1bmN0aW9uIHBpbmcoKSB7XG4gICAgICAgIGFwaS5pbmZvKGZ1bmN0aW9uIChlcnIsIHJlcykge1xuICAgICAgICAgIGlmIChyZXMgJiYgIXJlcy5jb21wYWN0X3J1bm5pbmcpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIHtvazogdHJ1ZX0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KHBpbmcsIG9wdHMuaW50ZXJ2YWwgfHwgMjAwKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgLy8gUGluZyB0aGUgaHR0cCBpZiBpdCdzIGZpbmlzaGVkIGNvbXBhY3Rpb25cbiAgICAgIHBpbmcoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgYXBpLmJ1bGtHZXQgPSBhZGFwdGVyRnVuKCdidWxrR2V0JywgZnVuY3Rpb24gKG9wdHMsIGNhbGxiYWNrKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgZnVuY3Rpb24gZG9CdWxrR2V0KGNiKSB7XG4gICAgICB2YXIgcGFyYW1zID0ge307XG4gICAgICBpZiAob3B0cy5yZXZzKSB7XG4gICAgICAgIHBhcmFtcy5yZXZzID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGlmIChvcHRzLmF0dGFjaG1lbnRzKSB7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICAgIHBhcmFtcy5hdHRhY2htZW50cyA9IHRydWU7XG4gICAgICB9XG4gICAgICBpZiAob3B0cy5sYXRlc3QpIHtcbiAgICAgICAgcGFyYW1zLmxhdGVzdCA9IHRydWU7XG4gICAgICB9XG4gICAgICBhamF4JCQob3B0cywge1xuICAgICAgICB1cmw6IGdlbkRCVXJsKGhvc3QsICdfYnVsa19nZXQnICsgcGFyYW1zVG9TdHIocGFyYW1zKSksXG4gICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICBib2R5OiB7IGRvY3M6IG9wdHMuZG9jc31cbiAgICAgIH0sIGNiKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkb0J1bGtHZXRTaGltKCkge1xuICAgICAgLy8gYXZvaWQgXCJ1cmwgdG9vIGxvbmcgZXJyb3JcIiBieSBzcGxpdHRpbmcgdXAgaW50byBtdWx0aXBsZSByZXF1ZXN0c1xuICAgICAgdmFyIGJhdGNoU2l6ZSA9IE1BWF9TSU1VTFRBTkVPVVNfUkVWUztcbiAgICAgIHZhciBudW1CYXRjaGVzID0gTWF0aC5jZWlsKG9wdHMuZG9jcy5sZW5ndGggLyBiYXRjaFNpemUpO1xuICAgICAgdmFyIG51bURvbmUgPSAwO1xuICAgICAgdmFyIHJlc3VsdHMgPSBuZXcgQXJyYXkobnVtQmF0Y2hlcyk7XG5cbiAgICAgIGZ1bmN0aW9uIG9uUmVzdWx0KGJhdGNoTnVtKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoZXJyLCByZXMpIHtcbiAgICAgICAgICAvLyBlcnIgaXMgaW1wb3NzaWJsZSBiZWNhdXNlIHNoaW0gcmV0dXJucyBhIGxpc3Qgb2YgZXJycyBpbiB0aGF0IGNhc2VcbiAgICAgICAgICByZXN1bHRzW2JhdGNoTnVtXSA9IHJlcy5yZXN1bHRzO1xuICAgICAgICAgIGlmICgrK251bURvbmUgPT09IG51bUJhdGNoZXMpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKG51bGwsIHtyZXN1bHRzOiBmbGF0dGVuKHJlc3VsdHMpfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG51bUJhdGNoZXM7IGkrKykge1xuICAgICAgICB2YXIgc3ViT3B0cyA9IHBpY2sob3B0cywgWydyZXZzJywgJ2F0dGFjaG1lbnRzJywgJ2xhdGVzdCddKTtcbiAgICAgICAgc3ViT3B0cy5hamF4ID0gYWpheE9wdHM7XG4gICAgICAgIHN1Yk9wdHMuZG9jcyA9IG9wdHMuZG9jcy5zbGljZShpICogYmF0Y2hTaXplLFxuICAgICAgICAgIE1hdGgubWluKG9wdHMuZG9jcy5sZW5ndGgsIChpICsgMSkgKiBiYXRjaFNpemUpKTtcbiAgICAgICAgYnVsa0dldChzZWxmLCBzdWJPcHRzLCBvblJlc3VsdChpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gbWFyayB0aGUgd2hvbGUgZGF0YWJhc2UgYXMgZWl0aGVyIHN1cHBvcnRpbmcgb3Igbm90IHN1cHBvcnRpbmcgX2J1bGtfZ2V0XG4gICAgdmFyIGRiVXJsID0gZ2VuVXJsKGhvc3QsICcnKTtcbiAgICB2YXIgc3VwcG9ydHNCdWxrR2V0ID0gc3VwcG9ydHNCdWxrR2V0TWFwW2RiVXJsXTtcblxuICAgIGlmICh0eXBlb2Ygc3VwcG9ydHNCdWxrR2V0ICE9PSAnYm9vbGVhbicpIHtcbiAgICAgIC8vIGNoZWNrIGlmIHRoaXMgZGF0YWJhc2Ugc3VwcG9ydHMgX2J1bGtfZ2V0XG4gICAgICBkb0J1bGtHZXQoZnVuY3Rpb24gKGVyciwgcmVzKSB7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICB2YXIgc3RhdHVzID0gTWF0aC5mbG9vcihlcnIuc3RhdHVzIC8gMTAwKTtcbiAgICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgICAgICAgIGlmIChzdGF0dXMgPT09IDQgfHwgc3RhdHVzID09PSA1KSB7IC8vIDQweCBvciA1MHhcbiAgICAgICAgICAgIHN1cHBvcnRzQnVsa0dldE1hcFtkYlVybF0gPSBmYWxzZTtcbiAgICAgICAgICAgIGV4cGxhaW5FcnJvcihcbiAgICAgICAgICAgICAgZXJyLnN0YXR1cyxcbiAgICAgICAgICAgICAgJ1BvdWNoREIgaXMganVzdCBkZXRlY3RpbmcgaWYgdGhlIHJlbW90ZSAnICtcbiAgICAgICAgICAgICAgJ3N1cHBvcnRzIHRoZSBfYnVsa19nZXQgQVBJLidcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBkb0J1bGtHZXRTaGltKCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGVycik7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN1cHBvcnRzQnVsa0dldE1hcFtkYlVybF0gPSB0cnVlO1xuICAgICAgICAgIGNhbGxiYWNrKG51bGwsIHJlcyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0gZWxzZSBpZiAoc3VwcG9ydHNCdWxrR2V0KSB7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgZG9CdWxrR2V0KGNhbGxiYWNrKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZG9CdWxrR2V0U2hpbSgpO1xuICAgIH1cbiAgfSk7XG5cbiAgLy8gQ2FsbHMgR0VUIG9uIHRoZSBob3N0LCB3aGljaCBnZXRzIGJhY2sgYSBKU09OIHN0cmluZyBjb250YWluaW5nXG4gIC8vICAgIGNvdWNoZGI6IEEgd2VsY29tZSBzdHJpbmdcbiAgLy8gICAgdmVyc2lvbjogVGhlIHZlcnNpb24gb2YgQ291Y2hEQiBpdCBpcyBydW5uaW5nXG4gIGFwaS5faW5mbyA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIHNldHVwKCkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICBhamF4JCQoe30sIHtcbiAgICAgICAgbWV0aG9kOiAnR0VUJyxcbiAgICAgICAgdXJsOiBnZW5EQlVybChob3N0LCAnJylcbiAgICAgIH0sIGZ1bmN0aW9uIChlcnIsIHJlcykge1xuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgICAgICB9XG4gICAgICAgIHJlcy5ob3N0ID0gZ2VuREJVcmwoaG9zdCwgJycpO1xuICAgICAgICBjYWxsYmFjayhudWxsLCByZXMpO1xuICAgICAgfSk7XG4gICAgfSkuY2F0Y2goY2FsbGJhY2spO1xuICB9O1xuXG4gIC8vIEdldCB0aGUgZG9jdW1lbnQgd2l0aCB0aGUgZ2l2ZW4gaWQgZnJvbSB0aGUgZGF0YWJhc2UgZ2l2ZW4gYnkgaG9zdC5cbiAgLy8gVGhlIGlkIGNvdWxkIGJlIHNvbGVseSB0aGUgX2lkIGluIHRoZSBkYXRhYmFzZSwgb3IgaXQgbWF5IGJlIGFcbiAgLy8gX2Rlc2lnbi9JRCBvciBfbG9jYWwvSUQgcGF0aFxuICBhcGkuZ2V0ID0gYWRhcHRlckZ1biQkKCdnZXQnLCBmdW5jdGlvbiAoaWQsIG9wdHMsIGNhbGxiYWNrKSB7XG4gICAgLy8gSWYgbm8gb3B0aW9ucyB3ZXJlIGdpdmVuLCBzZXQgdGhlIGNhbGxiYWNrIHRvIHRoZSBzZWNvbmQgcGFyYW1ldGVyXG4gICAgaWYgKHR5cGVvZiBvcHRzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBjYWxsYmFjayA9IG9wdHM7XG4gICAgICBvcHRzID0ge307XG4gICAgfVxuICAgIG9wdHMgPSBjbG9uZShvcHRzKTtcblxuICAgIC8vIExpc3Qgb2YgcGFyYW1ldGVycyB0byBhZGQgdG8gdGhlIEdFVCByZXF1ZXN0XG4gICAgdmFyIHBhcmFtcyA9IHt9O1xuXG4gICAgaWYgKG9wdHMucmV2cykge1xuICAgICAgcGFyYW1zLnJldnMgPSB0cnVlO1xuICAgIH1cblxuICAgIGlmIChvcHRzLnJldnNfaW5mbykge1xuICAgICAgcGFyYW1zLnJldnNfaW5mbyA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKG9wdHMubGF0ZXN0KSB7XG4gICAgICBwYXJhbXMubGF0ZXN0ID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAob3B0cy5vcGVuX3JldnMpIHtcbiAgICAgIGlmIChvcHRzLm9wZW5fcmV2cyAhPT0gXCJhbGxcIikge1xuICAgICAgICBvcHRzLm9wZW5fcmV2cyA9IEpTT04uc3RyaW5naWZ5KG9wdHMub3Blbl9yZXZzKTtcbiAgICAgIH1cbiAgICAgIHBhcmFtcy5vcGVuX3JldnMgPSBvcHRzLm9wZW5fcmV2cztcbiAgICB9XG5cbiAgICBpZiAob3B0cy5yZXYpIHtcbiAgICAgIHBhcmFtcy5yZXYgPSBvcHRzLnJldjtcbiAgICB9XG5cbiAgICBpZiAob3B0cy5jb25mbGljdHMpIHtcbiAgICAgIHBhcmFtcy5jb25mbGljdHMgPSBvcHRzLmNvbmZsaWN0cztcbiAgICB9XG5cbiAgICBpZCA9IGVuY29kZURvY0lkKGlkKTtcblxuICAgIC8vIFNldCB0aGUgb3B0aW9ucyBmb3IgdGhlIGFqYXggY2FsbFxuICAgIHZhciBvcHRpb25zID0ge1xuICAgICAgbWV0aG9kOiAnR0VUJyxcbiAgICAgIHVybDogZ2VuREJVcmwoaG9zdCwgaWQgKyBwYXJhbXNUb1N0cihwYXJhbXMpKVxuICAgIH07XG5cbiAgICBmdW5jdGlvbiBmZXRjaEF0dGFjaG1lbnRzKGRvYykge1xuICAgICAgdmFyIGF0dHMgPSBkb2MuX2F0dGFjaG1lbnRzO1xuICAgICAgdmFyIGZpbGVuYW1lcyA9IGF0dHMgJiYgT2JqZWN0LmtleXMoYXR0cyk7XG4gICAgICBpZiAoIWF0dHMgfHwgIWZpbGVuYW1lcy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgLy8gd2UgZmV0Y2ggdGhlc2UgbWFudWFsbHkgaW4gc2VwYXJhdGUgWEhScywgYmVjYXVzZVxuICAgICAgLy8gU3luYyBHYXRld2F5IHdvdWxkIG5vcm1hbGx5IHNlbmQgaXQgYmFjayBhcyBtdWx0aXBhcnQvbWl4ZWQsXG4gICAgICAvLyB3aGljaCB3ZSBjYW5ub3QgcGFyc2UuIEFsc28sIHRoaXMgaXMgbW9yZSBlZmZpY2llbnQgdGhhblxuICAgICAgLy8gcmVjZWl2aW5nIGF0dGFjaG1lbnRzIGFzIGJhc2U2NC1lbmNvZGVkIHN0cmluZ3MuXG4gICAgICBmdW5jdGlvbiBmZXRjaChmaWxlbmFtZSkge1xuICAgICAgICB2YXIgYXR0ID0gYXR0c1tmaWxlbmFtZV07XG4gICAgICAgIHZhciBwYXRoID0gZW5jb2RlRG9jSWQoZG9jLl9pZCkgKyAnLycgKyBlbmNvZGVBdHRhY2htZW50SWQoZmlsZW5hbWUpICtcbiAgICAgICAgICAnP3Jldj0nICsgZG9jLl9yZXY7XG4gICAgICAgIHJldHVybiBhamF4UHJvbWlzZShvcHRzLCB7XG4gICAgICAgICAgbWV0aG9kOiAnR0VUJyxcbiAgICAgICAgICB1cmw6IGdlbkRCVXJsKGhvc3QsIHBhdGgpLFxuICAgICAgICAgIGJpbmFyeTogdHJ1ZVxuICAgICAgICB9KS50aGVuKGZ1bmN0aW9uIChibG9iKSB7XG4gICAgICAgICAgaWYgKG9wdHMuYmluYXJ5KSB7XG4gICAgICAgICAgICByZXR1cm4gYmxvYjtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG5ldyBQb3VjaFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUpIHtcbiAgICAgICAgICAgIGJsb2JUb0Jhc2U2NChibG9iLCByZXNvbHZlKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSkudGhlbihmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgIGRlbGV0ZSBhdHQuc3R1YjtcbiAgICAgICAgICBkZWxldGUgYXR0Lmxlbmd0aDtcbiAgICAgICAgICBhdHQuZGF0YSA9IGRhdGE7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICB2YXIgcHJvbWlzZUZhY3RvcmllcyA9IGZpbGVuYW1lcy5tYXAoZnVuY3Rpb24gKGZpbGVuYW1lKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgcmV0dXJuIGZldGNoKGZpbGVuYW1lKTtcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBUaGlzIGxpbWl0cyB0aGUgbnVtYmVyIG9mIHBhcmFsbGVsIHhociByZXF1ZXN0cyB0byA1IGFueSB0aW1lXG4gICAgICAvLyB0byBhdm9pZCBpc3N1ZXMgd2l0aCBtYXhpbXVtIGJyb3dzZXIgcmVxdWVzdCBsaW1pdHNcbiAgICAgIHJldHVybiBwb29sKHByb21pc2VGYWN0b3JpZXMsIDUpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZldGNoQWxsQXR0YWNobWVudHMoZG9jT3JEb2NzKSB7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShkb2NPckRvY3MpKSB7XG4gICAgICAgIHJldHVybiBQb3VjaFByb21pc2UuYWxsKGRvY09yRG9jcy5tYXAoZnVuY3Rpb24gKGRvYykge1xuICAgICAgICAgIGlmIChkb2Mub2spIHtcbiAgICAgICAgICAgIHJldHVybiBmZXRjaEF0dGFjaG1lbnRzKGRvYy5vayk7XG4gICAgICAgICAgfVxuICAgICAgICB9KSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZmV0Y2hBdHRhY2htZW50cyhkb2NPckRvY3MpO1xuICAgIH1cblxuICAgIGFqYXhQcm9taXNlKG9wdHMsIG9wdGlvbnMpLnRoZW4oZnVuY3Rpb24gKHJlcykge1xuICAgICAgcmV0dXJuIFBvdWNoUHJvbWlzZS5yZXNvbHZlKCkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChvcHRzLmF0dGFjaG1lbnRzKSB7XG4gICAgICAgICAgcmV0dXJuIGZldGNoQWxsQXR0YWNobWVudHMocmVzKTtcbiAgICAgICAgfVxuICAgICAgfSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIHJlcyk7XG4gICAgICB9KTtcbiAgICB9KS5jYXRjaChjYWxsYmFjayk7XG4gIH0pO1xuXG4gIC8vIERlbGV0ZSB0aGUgZG9jdW1lbnQgZ2l2ZW4gYnkgZG9jIGZyb20gdGhlIGRhdGFiYXNlIGdpdmVuIGJ5IGhvc3QuXG4gIGFwaS5yZW1vdmUgPSBhZGFwdGVyRnVuJCQoJ3JlbW92ZScsXG4gICAgICBmdW5jdGlvbiAoZG9jT3JJZCwgb3B0c09yUmV2LCBvcHRzLCBjYWxsYmFjaykge1xuICAgIHZhciBkb2M7XG4gICAgaWYgKHR5cGVvZiBvcHRzT3JSZXYgPT09ICdzdHJpbmcnKSB7XG4gICAgICAvLyBpZCwgcmV2LCBvcHRzLCBjYWxsYmFjayBzdHlsZVxuICAgICAgZG9jID0ge1xuICAgICAgICBfaWQ6IGRvY09ySWQsXG4gICAgICAgIF9yZXY6IG9wdHNPclJldlxuICAgICAgfTtcbiAgICAgIGlmICh0eXBlb2Ygb3B0cyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBjYWxsYmFjayA9IG9wdHM7XG4gICAgICAgIG9wdHMgPSB7fTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gZG9jLCBvcHRzLCBjYWxsYmFjayBzdHlsZVxuICAgICAgZG9jID0gZG9jT3JJZDtcbiAgICAgIGlmICh0eXBlb2Ygb3B0c09yUmV2ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGNhbGxiYWNrID0gb3B0c09yUmV2O1xuICAgICAgICBvcHRzID0ge307XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjYWxsYmFjayA9IG9wdHM7XG4gICAgICAgIG9wdHMgPSBvcHRzT3JSZXY7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHJldiA9IChkb2MuX3JldiB8fCBvcHRzLnJldik7XG5cbiAgICAvLyBEZWxldGUgdGhlIGRvY3VtZW50XG4gICAgYWpheCQkKG9wdHMsIHtcbiAgICAgIG1ldGhvZDogJ0RFTEVURScsXG4gICAgICB1cmw6IGdlbkRCVXJsKGhvc3QsIGVuY29kZURvY0lkKGRvYy5faWQpKSArICc/cmV2PScgKyByZXZcbiAgICB9LCBjYWxsYmFjayk7XG4gIH0pO1xuXG4gIGZ1bmN0aW9uIGVuY29kZUF0dGFjaG1lbnRJZChhdHRhY2htZW50SWQpIHtcbiAgICByZXR1cm4gYXR0YWNobWVudElkLnNwbGl0KFwiL1wiKS5tYXAoZW5jb2RlVVJJQ29tcG9uZW50KS5qb2luKFwiL1wiKTtcbiAgfVxuXG4gIC8vIEdldCB0aGUgYXR0YWNobWVudFxuICBhcGkuZ2V0QXR0YWNobWVudCA9XG4gICAgYWRhcHRlckZ1biQkKCdnZXRBdHRhY2htZW50JywgZnVuY3Rpb24gKGRvY0lkLCBhdHRhY2htZW50SWQsIG9wdHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWxsYmFjaykge1xuICAgIGlmICh0eXBlb2Ygb3B0cyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgY2FsbGJhY2sgPSBvcHRzO1xuICAgICAgb3B0cyA9IHt9O1xuICAgIH1cbiAgICB2YXIgcGFyYW1zID0gb3B0cy5yZXYgPyAoJz9yZXY9JyArIG9wdHMucmV2KSA6ICcnO1xuICAgIHZhciB1cmwgPSBnZW5EQlVybChob3N0LCBlbmNvZGVEb2NJZChkb2NJZCkpICsgJy8nICtcbiAgICAgIGVuY29kZUF0dGFjaG1lbnRJZChhdHRhY2htZW50SWQpICsgcGFyYW1zO1xuICAgIGFqYXgkJChvcHRzLCB7XG4gICAgICBtZXRob2Q6ICdHRVQnLFxuICAgICAgdXJsOiB1cmwsXG4gICAgICBiaW5hcnk6IHRydWVcbiAgICB9LCBjYWxsYmFjayk7XG4gIH0pO1xuXG4gIC8vIFJlbW92ZSB0aGUgYXR0YWNobWVudCBnaXZlbiBieSB0aGUgaWQgYW5kIHJldlxuICBhcGkucmVtb3ZlQXR0YWNobWVudCA9XG4gICAgYWRhcHRlckZ1biQkKCdyZW1vdmVBdHRhY2htZW50JywgZnVuY3Rpb24gKGRvY0lkLCBhdHRhY2htZW50SWQsIHJldixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKSB7XG5cbiAgICB2YXIgdXJsID0gZ2VuREJVcmwoaG9zdCwgZW5jb2RlRG9jSWQoZG9jSWQpICsgJy8nICtcbiAgICAgIGVuY29kZUF0dGFjaG1lbnRJZChhdHRhY2htZW50SWQpKSArICc/cmV2PScgKyByZXY7XG5cbiAgICBhamF4JCQoe30sIHtcbiAgICAgIG1ldGhvZDogJ0RFTEVURScsXG4gICAgICB1cmw6IHVybFxuICAgIH0sIGNhbGxiYWNrKTtcbiAgfSk7XG5cbiAgLy8gQWRkIHRoZSBhdHRhY2htZW50IGdpdmVuIGJ5IGJsb2IgYW5kIGl0cyBjb250ZW50VHlwZSBwcm9wZXJ0eVxuICAvLyB0byB0aGUgZG9jdW1lbnQgd2l0aCB0aGUgZ2l2ZW4gaWQsIHRoZSByZXZpc2lvbiBnaXZlbiBieSByZXYsIGFuZFxuICAvLyBhZGQgaXQgdG8gdGhlIGRhdGFiYXNlIGdpdmVuIGJ5IGhvc3QuXG4gIGFwaS5wdXRBdHRhY2htZW50ID1cbiAgICBhZGFwdGVyRnVuJCQoJ3B1dEF0dGFjaG1lbnQnLCBmdW5jdGlvbiAoZG9jSWQsIGF0dGFjaG1lbnRJZCwgcmV2LCBibG9iLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSwgY2FsbGJhY2spIHtcbiAgICBpZiAodHlwZW9mIHR5cGUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGNhbGxiYWNrID0gdHlwZTtcbiAgICAgIHR5cGUgPSBibG9iO1xuICAgICAgYmxvYiA9IHJldjtcbiAgICAgIHJldiA9IG51bGw7XG4gICAgfVxuICAgIHZhciBpZCA9IGVuY29kZURvY0lkKGRvY0lkKSArICcvJyArIGVuY29kZUF0dGFjaG1lbnRJZChhdHRhY2htZW50SWQpO1xuICAgIHZhciB1cmwgPSBnZW5EQlVybChob3N0LCBpZCk7XG4gICAgaWYgKHJldikge1xuICAgICAgdXJsICs9ICc/cmV2PScgKyByZXY7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBibG9iID09PSAnc3RyaW5nJykge1xuICAgICAgLy8gaW5wdXQgaXMgYXNzdW1lZCB0byBiZSBhIGJhc2U2NCBzdHJpbmdcbiAgICAgIHZhciBiaW5hcnk7XG4gICAgICB0cnkge1xuICAgICAgICBiaW5hcnkgPSBhdG9iJDEoYmxvYik7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGNyZWF0ZUVycm9yKEJBRF9BUkcsXG4gICAgICAgICAgICAgICAgICAgICAgICAnQXR0YWNobWVudCBpcyBub3QgYSB2YWxpZCBiYXNlNjQgc3RyaW5nJykpO1xuICAgICAgfVxuICAgICAgYmxvYiA9IGJpbmFyeSA/IGJpblN0cmluZ1RvQmx1ZmZlcihiaW5hcnksIHR5cGUpIDogJyc7XG4gICAgfVxuXG4gICAgdmFyIG9wdHMgPSB7XG4gICAgICBoZWFkZXJzOiB7J0NvbnRlbnQtVHlwZSc6IHR5cGV9LFxuICAgICAgbWV0aG9kOiAnUFVUJyxcbiAgICAgIHVybDogdXJsLFxuICAgICAgcHJvY2Vzc0RhdGE6IGZhbHNlLFxuICAgICAgYm9keTogYmxvYixcbiAgICAgIHRpbWVvdXQ6IGFqYXhPcHRzLnRpbWVvdXQgfHwgNjAwMDBcbiAgICB9O1xuICAgIC8vIEFkZCB0aGUgYXR0YWNobWVudFxuICAgIGFqYXgkJCh7fSwgb3B0cywgY2FsbGJhY2spO1xuICB9KTtcblxuICAvLyBVcGRhdGUvY3JlYXRlIG11bHRpcGxlIGRvY3VtZW50cyBnaXZlbiBieSByZXEgaW4gdGhlIGRhdGFiYXNlXG4gIC8vIGdpdmVuIGJ5IGhvc3QuXG4gIGFwaS5fYnVsa0RvY3MgPSBmdW5jdGlvbiAocmVxLCBvcHRzLCBjYWxsYmFjaykge1xuICAgIC8vIElmIG5ld19lZGl0cz1mYWxzZSB0aGVuIGl0IHByZXZlbnRzIHRoZSBkYXRhYmFzZSBmcm9tIGNyZWF0aW5nXG4gICAgLy8gbmV3IHJldmlzaW9uIG51bWJlcnMgZm9yIHRoZSBkb2N1bWVudHMuIEluc3RlYWQgaXQganVzdCB1c2VzXG4gICAgLy8gdGhlIG9sZCBvbmVzLiBUaGlzIGlzIHVzZWQgaW4gZGF0YWJhc2UgcmVwbGljYXRpb24uXG4gICAgcmVxLm5ld19lZGl0cyA9IG9wdHMubmV3X2VkaXRzO1xuXG4gICAgc2V0dXAoKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBQb3VjaFByb21pc2UuYWxsKHJlcS5kb2NzLm1hcChwcmVwcm9jZXNzQXR0YWNobWVudHMkMSkpO1xuICAgIH0pLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgLy8gVXBkYXRlL2NyZWF0ZSB0aGUgZG9jdW1lbnRzXG4gICAgICBhamF4JCQob3B0cywge1xuICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgdXJsOiBnZW5EQlVybChob3N0LCAnX2J1bGtfZG9jcycpLFxuICAgICAgICB0aW1lb3V0OiBvcHRzLnRpbWVvdXQsXG4gICAgICAgIGJvZHk6IHJlcVxuICAgICAgfSwgZnVuY3Rpb24gKGVyciwgcmVzdWx0cykge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGVycik7XG4gICAgICAgIH1cbiAgICAgICAgcmVzdWx0cy5mb3JFYWNoKGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgICByZXN1bHQub2sgPSB0cnVlOyAvLyBzbW9vdGhzIG91dCBjbG91ZGFudCBub3QgYWRkaW5nIHRoaXNcbiAgICAgICAgfSk7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIHJlc3VsdHMpO1xuICAgICAgfSk7XG4gICAgfSkuY2F0Y2goY2FsbGJhY2spO1xuICB9O1xuXG5cbiAgLy8gVXBkYXRlL2NyZWF0ZSBkb2N1bWVudFxuICBhcGkuX3B1dCA9IGZ1bmN0aW9uIChkb2MsIG9wdHMsIGNhbGxiYWNrKSB7XG4gICAgc2V0dXAoKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBwcmVwcm9jZXNzQXR0YWNobWVudHMkMShkb2MpO1xuICAgIH0pLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgLy8gVXBkYXRlL2NyZWF0ZSB0aGUgZG9jdW1lbnRcbiAgICAgIGFqYXgkJChvcHRzLCB7XG4gICAgICAgIG1ldGhvZDogJ1BVVCcsXG4gICAgICAgIHVybDogZ2VuREJVcmwoaG9zdCwgZW5jb2RlRG9jSWQoZG9jLl9pZCkpLFxuICAgICAgICBib2R5OiBkb2NcbiAgICAgIH0sIGZ1bmN0aW9uIChlcnIsIHJlc3VsdCkge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGVycik7XG4gICAgICAgIH1cbiAgICAgICAgY2FsbGJhY2sobnVsbCwgcmVzdWx0KTtcbiAgICAgIH0pO1xuICAgIH0pLmNhdGNoKGNhbGxiYWNrKTtcbiAgfTtcblxuXG4gIC8vIEdldCBhIGxpc3Rpbmcgb2YgdGhlIGRvY3VtZW50cyBpbiB0aGUgZGF0YWJhc2UgZ2l2ZW5cbiAgLy8gYnkgaG9zdCBhbmQgb3JkZXJlZCBieSBpbmNyZWFzaW5nIGlkLlxuICBhcGkuYWxsRG9jcyA9IGFkYXB0ZXJGdW4kJCgnYWxsRG9jcycsIGZ1bmN0aW9uIChvcHRzLCBjYWxsYmFjaykge1xuICAgIGlmICh0eXBlb2Ygb3B0cyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgY2FsbGJhY2sgPSBvcHRzO1xuICAgICAgb3B0cyA9IHt9O1xuICAgIH1cbiAgICBvcHRzID0gY2xvbmUob3B0cyk7XG5cbiAgICAvLyBMaXN0IG9mIHBhcmFtZXRlcnMgdG8gYWRkIHRvIHRoZSBHRVQgcmVxdWVzdFxuICAgIHZhciBwYXJhbXMgPSB7fTtcbiAgICB2YXIgYm9keTtcbiAgICB2YXIgbWV0aG9kID0gJ0dFVCc7XG5cbiAgICBpZiAob3B0cy5jb25mbGljdHMpIHtcbiAgICAgIHBhcmFtcy5jb25mbGljdHMgPSB0cnVlO1xuICAgIH1cblxuICAgIGlmIChvcHRzLmRlc2NlbmRpbmcpIHtcbiAgICAgIHBhcmFtcy5kZXNjZW5kaW5nID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAob3B0cy5pbmNsdWRlX2RvY3MpIHtcbiAgICAgIHBhcmFtcy5pbmNsdWRlX2RvY3MgPSB0cnVlO1xuICAgIH1cblxuICAgIC8vIGFkZGVkIGluIENvdWNoREIgMS42LjBcbiAgICBpZiAob3B0cy5hdHRhY2htZW50cykge1xuICAgICAgcGFyYW1zLmF0dGFjaG1lbnRzID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAob3B0cy5rZXkpIHtcbiAgICAgIHBhcmFtcy5rZXkgPSBKU09OLnN0cmluZ2lmeShvcHRzLmtleSk7XG4gICAgfVxuXG4gICAgaWYgKG9wdHMuc3RhcnRfa2V5KSB7XG4gICAgICBvcHRzLnN0YXJ0a2V5ID0gb3B0cy5zdGFydF9rZXk7XG4gICAgfVxuXG4gICAgaWYgKG9wdHMuc3RhcnRrZXkpIHtcbiAgICAgIHBhcmFtcy5zdGFydGtleSA9IEpTT04uc3RyaW5naWZ5KG9wdHMuc3RhcnRrZXkpO1xuICAgIH1cblxuICAgIGlmIChvcHRzLmVuZF9rZXkpIHtcbiAgICAgIG9wdHMuZW5ka2V5ID0gb3B0cy5lbmRfa2V5O1xuICAgIH1cblxuICAgIGlmIChvcHRzLmVuZGtleSkge1xuICAgICAgcGFyYW1zLmVuZGtleSA9IEpTT04uc3RyaW5naWZ5KG9wdHMuZW5ka2V5KTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIG9wdHMuaW5jbHVzaXZlX2VuZCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHBhcmFtcy5pbmNsdXNpdmVfZW5kID0gISFvcHRzLmluY2x1c2l2ZV9lbmQ7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBvcHRzLmxpbWl0ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgcGFyYW1zLmxpbWl0ID0gb3B0cy5saW1pdDtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIG9wdHMuc2tpcCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHBhcmFtcy5za2lwID0gb3B0cy5za2lwO1xuICAgIH1cblxuICAgIHZhciBwYXJhbVN0ciA9IHBhcmFtc1RvU3RyKHBhcmFtcyk7XG5cbiAgICBpZiAodHlwZW9mIG9wdHMua2V5cyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIG1ldGhvZCA9ICdQT1NUJztcbiAgICAgIGJvZHkgPSB7a2V5czogb3B0cy5rZXlzfTtcbiAgICB9XG5cbiAgICAvLyBHZXQgdGhlIGRvY3VtZW50IGxpc3RpbmdcbiAgICBhamF4UHJvbWlzZShvcHRzLCB7XG4gICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgIHVybDogZ2VuREJVcmwoaG9zdCwgJ19hbGxfZG9jcycgKyBwYXJhbVN0ciksXG4gICAgICBib2R5OiBib2R5XG4gICAgfSkudGhlbihmdW5jdGlvbiAocmVzKSB7XG4gICAgICBpZiAob3B0cy5pbmNsdWRlX2RvY3MgJiYgb3B0cy5hdHRhY2htZW50cyAmJiBvcHRzLmJpbmFyeSkge1xuICAgICAgICByZXMucm93cy5mb3JFYWNoKHJlYWRBdHRhY2htZW50c0FzQmxvYk9yQnVmZmVyKTtcbiAgICAgIH1cbiAgICAgIGNhbGxiYWNrKG51bGwsIHJlcyk7XG4gICAgfSkuY2F0Y2goY2FsbGJhY2spO1xuICB9KTtcblxuICAvLyBHZXQgYSBsaXN0IG9mIGNoYW5nZXMgbWFkZSB0byBkb2N1bWVudHMgaW4gdGhlIGRhdGFiYXNlIGdpdmVuIGJ5IGhvc3QuXG4gIC8vIFRPRE8gQWNjb3JkaW5nIHRvIHRoZSBSRUFETUUsIHRoZXJlIHNob3VsZCBiZSB0d28gb3RoZXIgbWV0aG9kcyBoZXJlLFxuICAvLyBhcGkuY2hhbmdlcy5hZGRMaXN0ZW5lciBhbmQgYXBpLmNoYW5nZXMucmVtb3ZlTGlzdGVuZXIuXG4gIGFwaS5fY2hhbmdlcyA9IGZ1bmN0aW9uIChvcHRzKSB7XG5cbiAgICAvLyBXZSBpbnRlcm5hbGx5IHBhZ2UgdGhlIHJlc3VsdHMgb2YgYSBjaGFuZ2VzIHJlcXVlc3QsIHRoaXMgbWVhbnNcbiAgICAvLyBpZiB0aGVyZSBpcyBhIGxhcmdlIHNldCBvZiBjaGFuZ2VzIHRvIGJlIHJldHVybmVkIHdlIGNhbiBzdGFydFxuICAgIC8vIHByb2Nlc3NpbmcgdGhlbSBxdWlja2VyIGluc3RlYWQgb2Ygd2FpdGluZyBvbiB0aGUgZW50aXJlXG4gICAgLy8gc2V0IG9mIGNoYW5nZXMgdG8gcmV0dXJuIGFuZCBhdHRlbXB0aW5nIHRvIHByb2Nlc3MgdGhlbSBhdCBvbmNlXG4gICAgdmFyIGJhdGNoU2l6ZSA9ICdiYXRjaF9zaXplJyBpbiBvcHRzID8gb3B0cy5iYXRjaF9zaXplIDogQ0hBTkdFU19CQVRDSF9TSVpFO1xuXG4gICAgb3B0cyA9IGNsb25lKG9wdHMpO1xuICAgIG9wdHMudGltZW91dCA9ICgndGltZW91dCcgaW4gb3B0cykgPyBvcHRzLnRpbWVvdXQgOlxuICAgICAgKCd0aW1lb3V0JyBpbiBhamF4T3B0cykgPyBhamF4T3B0cy50aW1lb3V0IDpcbiAgICAgIDMwICogMTAwMDtcblxuICAgIC8vIFdlIGdpdmUgYSA1IHNlY29uZCBidWZmZXIgZm9yIENvdWNoREIgY2hhbmdlcyB0byByZXNwb25kIHdpdGhcbiAgICAvLyBhbiBvayB0aW1lb3V0IChpZiBhIHRpbWVvdXQgaXQgc2V0KVxuICAgIHZhciBwYXJhbXMgPSBvcHRzLnRpbWVvdXQgPyB7dGltZW91dDogb3B0cy50aW1lb3V0IC0gKDUgKiAxMDAwKX0gOiB7fTtcbiAgICB2YXIgbGltaXQgPSAodHlwZW9mIG9wdHMubGltaXQgIT09ICd1bmRlZmluZWQnKSA/IG9wdHMubGltaXQgOiBmYWxzZTtcbiAgICB2YXIgcmV0dXJuRG9jcztcbiAgICBpZiAoJ3JldHVybl9kb2NzJyBpbiBvcHRzKSB7XG4gICAgICByZXR1cm5Eb2NzID0gb3B0cy5yZXR1cm5fZG9jcztcbiAgICB9IGVsc2UgaWYgKCdyZXR1cm5Eb2NzJyBpbiBvcHRzKSB7XG4gICAgICAvLyBUT0RPOiBSZW1vdmUgJ3JldHVybkRvY3MnIGluIGZhdm9yIG9mICdyZXR1cm5fZG9jcycgaW4gYSBmdXR1cmUgcmVsZWFzZVxuICAgICAgcmV0dXJuRG9jcyA9IG9wdHMucmV0dXJuRG9jcztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuRG9jcyA9IHRydWU7XG4gICAgfVxuICAgIC8vXG4gICAgdmFyIGxlZnRUb0ZldGNoID0gbGltaXQ7XG5cbiAgICBpZiAob3B0cy5zdHlsZSkge1xuICAgICAgcGFyYW1zLnN0eWxlID0gb3B0cy5zdHlsZTtcbiAgICB9XG5cbiAgICBpZiAob3B0cy5pbmNsdWRlX2RvY3MgfHwgb3B0cy5maWx0ZXIgJiYgdHlwZW9mIG9wdHMuZmlsdGVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBwYXJhbXMuaW5jbHVkZV9kb2NzID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAob3B0cy5hdHRhY2htZW50cykge1xuICAgICAgcGFyYW1zLmF0dGFjaG1lbnRzID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAob3B0cy5jb250aW51b3VzKSB7XG4gICAgICBwYXJhbXMuZmVlZCA9ICdsb25ncG9sbCc7XG4gICAgfVxuXG4gICAgaWYgKG9wdHMuY29uZmxpY3RzKSB7XG4gICAgICBwYXJhbXMuY29uZmxpY3RzID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAob3B0cy5kZXNjZW5kaW5nKSB7XG4gICAgICBwYXJhbXMuZGVzY2VuZGluZyA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKCdoZWFydGJlYXQnIGluIG9wdHMpIHtcbiAgICAgIC8vIElmIHRoZSBoZWFydGJlYXQgdmFsdWUgaXMgZmFsc2UsIGl0IGRpc2FibGVzIHRoZSBkZWZhdWx0IGhlYXJ0YmVhdFxuICAgICAgaWYgKG9wdHMuaGVhcnRiZWF0KSB7XG4gICAgICAgIHBhcmFtcy5oZWFydGJlYXQgPSBvcHRzLmhlYXJ0YmVhdDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRGVmYXVsdCBoZWFydGJlYXQgdG8gMTAgc2Vjb25kc1xuICAgICAgcGFyYW1zLmhlYXJ0YmVhdCA9IDEwMDAwO1xuICAgIH1cblxuICAgIGlmIChvcHRzLmZpbHRlciAmJiB0eXBlb2Ygb3B0cy5maWx0ZXIgPT09ICdzdHJpbmcnKSB7XG4gICAgICBwYXJhbXMuZmlsdGVyID0gb3B0cy5maWx0ZXI7XG4gICAgfVxuXG4gICAgaWYgKG9wdHMudmlldyAmJiB0eXBlb2Ygb3B0cy52aWV3ID09PSAnc3RyaW5nJykge1xuICAgICAgcGFyYW1zLmZpbHRlciA9ICdfdmlldyc7XG4gICAgICBwYXJhbXMudmlldyA9IG9wdHMudmlldztcbiAgICB9XG5cbiAgICAvLyBJZiBvcHRzLnF1ZXJ5X3BhcmFtcyBleGlzdHMsIHBhc3MgaXQgdGhyb3VnaCB0byB0aGUgY2hhbmdlcyByZXF1ZXN0LlxuICAgIC8vIFRoZXNlIHBhcmFtZXRlcnMgbWF5IGJlIHVzZWQgYnkgdGhlIGZpbHRlciBvbiB0aGUgc291cmNlIGRhdGFiYXNlLlxuICAgIGlmIChvcHRzLnF1ZXJ5X3BhcmFtcyAmJiB0eXBlb2Ygb3B0cy5xdWVyeV9wYXJhbXMgPT09ICdvYmplY3QnKSB7XG4gICAgICBmb3IgKHZhciBwYXJhbV9uYW1lIGluIG9wdHMucXVlcnlfcGFyYW1zKSB7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgICAgIGlmIChvcHRzLnF1ZXJ5X3BhcmFtcy5oYXNPd25Qcm9wZXJ0eShwYXJhbV9uYW1lKSkge1xuICAgICAgICAgIHBhcmFtc1twYXJhbV9uYW1lXSA9IG9wdHMucXVlcnlfcGFyYW1zW3BhcmFtX25hbWVdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIG1ldGhvZCA9ICdHRVQnO1xuICAgIHZhciBib2R5O1xuXG4gICAgaWYgKG9wdHMuZG9jX2lkcykge1xuICAgICAgLy8gc2V0IHRoaXMgYXV0b21hZ2ljYWxseSBmb3IgdGhlIHVzZXI7IGl0J3MgYW5ub3lpbmcgdGhhdCBjb3VjaGRiXG4gICAgICAvLyByZXF1aXJlcyBib3RoIGEgXCJmaWx0ZXJcIiBhbmQgYSBcImRvY19pZHNcIiBwYXJhbS5cbiAgICAgIHBhcmFtcy5maWx0ZXIgPSAnX2RvY19pZHMnO1xuICAgICAgbWV0aG9kID0gJ1BPU1QnO1xuICAgICAgYm9keSA9IHtkb2NfaWRzOiBvcHRzLmRvY19pZHMgfTtcbiAgICB9XG5cbiAgICB2YXIgeGhyO1xuICAgIHZhciBsYXN0RmV0Y2hlZFNlcTtcblxuICAgIC8vIEdldCBhbGwgdGhlIGNoYW5nZXMgc3RhcnRpbmcgd3RpaCB0aGUgb25lIGltbWVkaWF0ZWx5IGFmdGVyIHRoZVxuICAgIC8vIHNlcXVlbmNlIG51bWJlciBnaXZlbiBieSBzaW5jZS5cbiAgICB2YXIgZmV0Y2ggPSBmdW5jdGlvbiAoc2luY2UsIGNhbGxiYWNrKSB7XG4gICAgICBpZiAob3B0cy5hYm9ydGVkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHBhcmFtcy5zaW5jZSA9IHNpbmNlO1xuICAgICAgLy8gXCJzaW5jZVwiIGNhbiBiZSBhbnkga2luZCBvZiBqc29uIG9iamVjdCBpbiBDb3VkYW50L0NvdWNoREIgMi54XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgaWYgKHR5cGVvZiBwYXJhbXMuc2luY2UgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgcGFyYW1zLnNpbmNlID0gSlNPTi5zdHJpbmdpZnkocGFyYW1zLnNpbmNlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdHMuZGVzY2VuZGluZykge1xuICAgICAgICBpZiAobGltaXQpIHtcbiAgICAgICAgICBwYXJhbXMubGltaXQgPSBsZWZ0VG9GZXRjaDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGFyYW1zLmxpbWl0ID0gKCFsaW1pdCB8fCBsZWZ0VG9GZXRjaCA+IGJhdGNoU2l6ZSkgP1xuICAgICAgICAgIGJhdGNoU2l6ZSA6IGxlZnRUb0ZldGNoO1xuICAgICAgfVxuXG4gICAgICAvLyBTZXQgdGhlIG9wdGlvbnMgZm9yIHRoZSBhamF4IGNhbGxcbiAgICAgIHZhciB4aHJPcHRzID0ge1xuICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgdXJsOiBnZW5EQlVybChob3N0LCAnX2NoYW5nZXMnICsgcGFyYW1zVG9TdHIocGFyYW1zKSksXG4gICAgICAgIHRpbWVvdXQ6IG9wdHMudGltZW91dCxcbiAgICAgICAgYm9keTogYm9keVxuICAgICAgfTtcbiAgICAgIGxhc3RGZXRjaGVkU2VxID0gc2luY2U7XG5cbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgICAgaWYgKG9wdHMuYWJvcnRlZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIEdldCB0aGUgY2hhbmdlc1xuICAgICAgc2V0dXAoKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgeGhyID0gYWpheCQkKG9wdHMsIHhock9wdHMsIGNhbGxiYWNrKTtcbiAgICAgIH0pLmNhdGNoKGNhbGxiYWNrKTtcbiAgICB9O1xuXG4gICAgLy8gSWYgb3B0cy5zaW5jZSBleGlzdHMsIGdldCBhbGwgdGhlIGNoYW5nZXMgZnJvbSB0aGUgc2VxdWVuY2VcbiAgICAvLyBudW1iZXIgZ2l2ZW4gYnkgb3B0cy5zaW5jZS4gT3RoZXJ3aXNlLCBnZXQgYWxsIHRoZSBjaGFuZ2VzXG4gICAgLy8gZnJvbSB0aGUgc2VxdWVuY2UgbnVtYmVyIDAuXG4gICAgdmFyIHJlc3VsdHMgPSB7cmVzdWx0czogW119O1xuXG4gICAgdmFyIGZldGNoZWQgPSBmdW5jdGlvbiAoZXJyLCByZXMpIHtcbiAgICAgIGlmIChvcHRzLmFib3J0ZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdmFyIHJhd19yZXN1bHRzX2xlbmd0aCA9IDA7XG4gICAgICAvLyBJZiB0aGUgcmVzdWx0IG9mIHRoZSBhamF4IGNhbGwgKHJlcykgY29udGFpbnMgY2hhbmdlcyAocmVzLnJlc3VsdHMpXG4gICAgICBpZiAocmVzICYmIHJlcy5yZXN1bHRzKSB7XG4gICAgICAgIHJhd19yZXN1bHRzX2xlbmd0aCA9IHJlcy5yZXN1bHRzLmxlbmd0aDtcbiAgICAgICAgcmVzdWx0cy5sYXN0X3NlcSA9IHJlcy5sYXN0X3NlcTtcbiAgICAgICAgLy8gRm9yIGVhY2ggY2hhbmdlXG4gICAgICAgIHZhciByZXEgPSB7fTtcbiAgICAgICAgcmVxLnF1ZXJ5ID0gb3B0cy5xdWVyeV9wYXJhbXM7XG4gICAgICAgIHJlcy5yZXN1bHRzID0gcmVzLnJlc3VsdHMuZmlsdGVyKGZ1bmN0aW9uIChjKSB7XG4gICAgICAgICAgbGVmdFRvRmV0Y2gtLTtcbiAgICAgICAgICB2YXIgcmV0ID0gZmlsdGVyQ2hhbmdlKG9wdHMpKGMpO1xuICAgICAgICAgIGlmIChyZXQpIHtcbiAgICAgICAgICAgIGlmIChvcHRzLmluY2x1ZGVfZG9jcyAmJiBvcHRzLmF0dGFjaG1lbnRzICYmIG9wdHMuYmluYXJ5KSB7XG4gICAgICAgICAgICAgIHJlYWRBdHRhY2htZW50c0FzQmxvYk9yQnVmZmVyKGMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJldHVybkRvY3MpIHtcbiAgICAgICAgICAgICAgcmVzdWx0cy5yZXN1bHRzLnB1c2goYyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvcHRzLm9uQ2hhbmdlKGMpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSBpZiAoZXJyKSB7XG4gICAgICAgIC8vIEluIGNhc2Ugb2YgYW4gZXJyb3IsIHN0b3AgbGlzdGVuaW5nIGZvciBjaGFuZ2VzIGFuZCBjYWxsXG4gICAgICAgIC8vIG9wdHMuY29tcGxldGVcbiAgICAgICAgb3B0cy5hYm9ydGVkID0gdHJ1ZTtcbiAgICAgICAgb3B0cy5jb21wbGV0ZShlcnIpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIFRoZSBjaGFuZ2VzIGZlZWQgbWF5IGhhdmUgdGltZWQgb3V0IHdpdGggbm8gcmVzdWx0c1xuICAgICAgLy8gaWYgc28gcmV1c2UgbGFzdCB1cGRhdGUgc2VxdWVuY2VcbiAgICAgIGlmIChyZXMgJiYgcmVzLmxhc3Rfc2VxKSB7XG4gICAgICAgIGxhc3RGZXRjaGVkU2VxID0gcmVzLmxhc3Rfc2VxO1xuICAgICAgfVxuXG4gICAgICB2YXIgZmluaXNoZWQgPSAobGltaXQgJiYgbGVmdFRvRmV0Y2ggPD0gMCkgfHxcbiAgICAgICAgKHJlcyAmJiByYXdfcmVzdWx0c19sZW5ndGggPCBiYXRjaFNpemUpIHx8XG4gICAgICAgIChvcHRzLmRlc2NlbmRpbmcpO1xuXG4gICAgICBpZiAoKG9wdHMuY29udGludW91cyAmJiAhKGxpbWl0ICYmIGxlZnRUb0ZldGNoIDw9IDApKSB8fCAhZmluaXNoZWQpIHtcbiAgICAgICAgLy8gUXVldWUgYSBjYWxsIHRvIGZldGNoIGFnYWluIHdpdGggdGhlIG5ld2VzdCBzZXF1ZW5jZSBudW1iZXJcbiAgICAgICAgaW1tZWRpYXRlKGZ1bmN0aW9uICgpIHsgZmV0Y2gobGFzdEZldGNoZWRTZXEsIGZldGNoZWQpOyB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFdlJ3JlIGRvbmUsIGNhbGwgdGhlIGNhbGxiYWNrXG4gICAgICAgIG9wdHMuY29tcGxldGUobnVsbCwgcmVzdWx0cyk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGZldGNoKG9wdHMuc2luY2UgfHwgMCwgZmV0Y2hlZCk7XG5cbiAgICAvLyBSZXR1cm4gYSBtZXRob2QgdG8gY2FuY2VsIHRoaXMgbWV0aG9kIGZyb20gcHJvY2Vzc2luZyBhbnkgbW9yZVxuICAgIHJldHVybiB7XG4gICAgICBjYW5jZWw6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgb3B0cy5hYm9ydGVkID0gdHJ1ZTtcbiAgICAgICAgaWYgKHhocikge1xuICAgICAgICAgIHhoci5hYm9ydCgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcbiAgfTtcblxuICAvLyBHaXZlbiBhIHNldCBvZiBkb2N1bWVudC9yZXZpc2lvbiBJRHMgKGdpdmVuIGJ5IHJlcSksIHRldHMgdGhlIHN1YnNldCBvZlxuICAvLyB0aG9zZSB0aGF0IGRvIE5PVCBjb3JyZXNwb25kIHRvIHJldmlzaW9ucyBzdG9yZWQgaW4gdGhlIGRhdGFiYXNlLlxuICAvLyBTZWUgaHR0cDovL3dpa2kuYXBhY2hlLm9yZy9jb3VjaGRiL0h0dHBQb3N0UmV2c0RpZmZcbiAgYXBpLnJldnNEaWZmID0gYWRhcHRlckZ1biQkKCdyZXZzRGlmZicsIGZ1bmN0aW9uIChyZXEsIG9wdHMsIGNhbGxiYWNrKSB7XG4gICAgLy8gSWYgbm8gb3B0aW9ucyB3ZXJlIGdpdmVuLCBzZXQgdGhlIGNhbGxiYWNrIHRvIGJlIHRoZSBzZWNvbmQgcGFyYW1ldGVyXG4gICAgaWYgKHR5cGVvZiBvcHRzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBjYWxsYmFjayA9IG9wdHM7XG4gICAgICBvcHRzID0ge307XG4gICAgfVxuXG4gICAgLy8gR2V0IHRoZSBtaXNzaW5nIGRvY3VtZW50L3JldmlzaW9uIElEc1xuICAgIGFqYXgkJChvcHRzLCB7XG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIHVybDogZ2VuREJVcmwoaG9zdCwgJ19yZXZzX2RpZmYnKSxcbiAgICAgIGJvZHk6IHJlcVxuICAgIH0sIGNhbGxiYWNrKTtcbiAgfSk7XG5cbiAgYXBpLl9jbG9zZSA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrKCk7XG4gIH07XG5cbiAgYXBpLl9kZXN0cm95ID0gZnVuY3Rpb24gKG9wdGlvbnMsIGNhbGxiYWNrKSB7XG4gICAgYWpheCQkKG9wdGlvbnMsIHtcbiAgICAgIHVybDogZ2VuREJVcmwoaG9zdCwgJycpLFxuICAgICAgbWV0aG9kOiAnREVMRVRFJ1xuICAgIH0sIGZ1bmN0aW9uIChlcnIsIHJlc3ApIHtcbiAgICAgIGlmIChlcnIgJiYgZXJyLnN0YXR1cyAmJiBlcnIuc3RhdHVzICE9PSA0MDQpIHtcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGVycik7XG4gICAgICB9XG4gICAgICBjYWxsYmFjayhudWxsLCByZXNwKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuLy8gSHR0cFBvdWNoIGlzIGEgdmFsaWQgYWRhcHRlci5cbkh0dHBQb3VjaC52YWxpZCA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRydWU7XG59O1xuXG5mdW5jdGlvbiBIdHRwUG91Y2gkMSAoUG91Y2hEQikge1xuICBQb3VjaERCLmFkYXB0ZXIoJ2h0dHAnLCBIdHRwUG91Y2gsIGZhbHNlKTtcbiAgUG91Y2hEQi5hZGFwdGVyKCdodHRwcycsIEh0dHBQb3VjaCwgZmFsc2UpO1xufVxuXG5mdW5jdGlvbiBwYWQoc3RyLCBwYWRXaXRoLCB1cFRvTGVuZ3RoKSB7XG4gIHZhciBwYWRkaW5nID0gJyc7XG4gIHZhciB0YXJnZXRMZW5ndGggPSB1cFRvTGVuZ3RoIC0gc3RyLmxlbmd0aDtcbiAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgd2hpbGUgKHBhZGRpbmcubGVuZ3RoIDwgdGFyZ2V0TGVuZ3RoKSB7XG4gICAgcGFkZGluZyArPSBwYWRXaXRoO1xuICB9XG4gIHJldHVybiBwYWRkaW5nO1xufVxuXG5mdW5jdGlvbiBwYWRMZWZ0KHN0ciwgcGFkV2l0aCwgdXBUb0xlbmd0aCkge1xuICB2YXIgcGFkZGluZyA9IHBhZChzdHIsIHBhZFdpdGgsIHVwVG9MZW5ndGgpO1xuICByZXR1cm4gcGFkZGluZyArIHN0cjtcbn1cblxudmFyIE1JTl9NQUdOSVRVREUgPSAtMzI0OyAvLyB2ZXJpZmllZCBieSAtTnVtYmVyLk1JTl9WQUxVRVxudmFyIE1BR05JVFVERV9ESUdJVFMgPSAzOyAvLyBkaXR0b1xudmFyIFNFUCA9ICcnOyAvLyBzZXQgdG8gJ18nIGZvciBlYXNpZXIgZGVidWdnaW5nIFxuXG5mdW5jdGlvbiBjb2xsYXRlKGEsIGIpIHtcblxuICBpZiAoYSA9PT0gYikge1xuICAgIHJldHVybiAwO1xuICB9XG5cbiAgYSA9IG5vcm1hbGl6ZUtleShhKTtcbiAgYiA9IG5vcm1hbGl6ZUtleShiKTtcblxuICB2YXIgYWkgPSBjb2xsYXRpb25JbmRleChhKTtcbiAgdmFyIGJpID0gY29sbGF0aW9uSW5kZXgoYik7XG4gIGlmICgoYWkgLSBiaSkgIT09IDApIHtcbiAgICByZXR1cm4gYWkgLSBiaTtcbiAgfVxuICBpZiAoYSA9PT0gbnVsbCkge1xuICAgIHJldHVybiAwO1xuICB9XG4gIHN3aXRjaCAodHlwZW9mIGEpIHtcbiAgICBjYXNlICdudW1iZXInOlxuICAgICAgcmV0dXJuIGEgLSBiO1xuICAgIGNhc2UgJ2Jvb2xlYW4nOlxuICAgICAgcmV0dXJuIGEgPT09IGIgPyAwIDogKGEgPCBiID8gLTEgOiAxKTtcbiAgICBjYXNlICdzdHJpbmcnOlxuICAgICAgcmV0dXJuIHN0cmluZ0NvbGxhdGUoYSwgYik7XG4gIH1cbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkoYSkgPyBhcnJheUNvbGxhdGUoYSwgYikgOiBvYmplY3RDb2xsYXRlKGEsIGIpO1xufVxuXG4vLyBjb3VjaCBjb25zaWRlcnMgbnVsbC9OYU4vSW5maW5pdHkvLUluZmluaXR5ID09PSB1bmRlZmluZWQsXG4vLyBmb3IgdGhlIHB1cnBvc2VzIG9mIG1hcHJlZHVjZSBpbmRleGVzLiBhbHNvLCBkYXRlcyBnZXQgc3RyaW5naWZpZWQuXG5mdW5jdGlvbiBub3JtYWxpemVLZXkoa2V5KSB7XG4gIHN3aXRjaCAodHlwZW9mIGtleSkge1xuICAgIGNhc2UgJ3VuZGVmaW5lZCc6XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICBjYXNlICdudW1iZXInOlxuICAgICAgaWYgKGtleSA9PT0gSW5maW5pdHkgfHwga2V5ID09PSAtSW5maW5pdHkgfHwgaXNOYU4oa2V5KSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBrZXk7XG4gICAgY2FzZSAnb2JqZWN0JzpcbiAgICAgIHZhciBvcmlnS2V5ID0ga2V5O1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoa2V5KSkge1xuICAgICAgICB2YXIgbGVuID0ga2V5Lmxlbmd0aDtcbiAgICAgICAga2V5ID0gbmV3IEFycmF5KGxlbik7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICBrZXlbaV0gPSBub3JtYWxpemVLZXkob3JpZ0tleVtpXSk7XG4gICAgICAgIH1cbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICB9IGVsc2UgaWYgKGtleSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgICAgcmV0dXJuIGtleS50b0pTT04oKTtcbiAgICAgIH0gZWxzZSBpZiAoa2V5ICE9PSBudWxsKSB7IC8vIGdlbmVyaWMgb2JqZWN0XG4gICAgICAgIGtleSA9IHt9O1xuICAgICAgICBmb3IgKHZhciBrIGluIG9yaWdLZXkpIHtcbiAgICAgICAgICBpZiAob3JpZ0tleS5oYXNPd25Qcm9wZXJ0eShrKSkge1xuICAgICAgICAgICAgdmFyIHZhbCA9IG9yaWdLZXlba107XG4gICAgICAgICAgICBpZiAodHlwZW9mIHZhbCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAga2V5W2tdID0gbm9ybWFsaXplS2V5KHZhbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gIH1cbiAgcmV0dXJuIGtleTtcbn1cblxuZnVuY3Rpb24gaW5kZXhpZnkoa2V5KSB7XG4gIGlmIChrZXkgIT09IG51bGwpIHtcbiAgICBzd2l0Y2ggKHR5cGVvZiBrZXkpIHtcbiAgICAgIGNhc2UgJ2Jvb2xlYW4nOlxuICAgICAgICByZXR1cm4ga2V5ID8gMSA6IDA7XG4gICAgICBjYXNlICdudW1iZXInOlxuICAgICAgICByZXR1cm4gbnVtVG9JbmRleGFibGVTdHJpbmcoa2V5KTtcbiAgICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICAgIC8vIFdlJ3ZlIHRvIGJlIHN1cmUgdGhhdCBrZXkgZG9lcyBub3QgY29udGFpbiBcXHUwMDAwXG4gICAgICAgIC8vIERvIG9yZGVyLXByZXNlcnZpbmcgcmVwbGFjZW1lbnRzOlxuICAgICAgICAvLyAwIC0+IDEsIDFcbiAgICAgICAgLy8gMSAtPiAxLCAyXG4gICAgICAgIC8vIDIgLT4gMiwgMlxuICAgICAgICByZXR1cm4ga2V5XG4gICAgICAgICAgLnJlcGxhY2UoL1xcdTAwMDIvZywgJ1xcdTAwMDJcXHUwMDAyJylcbiAgICAgICAgICAucmVwbGFjZSgvXFx1MDAwMS9nLCAnXFx1MDAwMVxcdTAwMDInKVxuICAgICAgICAgIC5yZXBsYWNlKC9cXHUwMDAwL2csICdcXHUwMDAxXFx1MDAwMScpO1xuICAgICAgY2FzZSAnb2JqZWN0JzpcbiAgICAgICAgdmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5KGtleSk7XG4gICAgICAgIHZhciBhcnIgPSBpc0FycmF5ID8ga2V5IDogT2JqZWN0LmtleXMoa2V5KTtcbiAgICAgICAgdmFyIGkgPSAtMTtcbiAgICAgICAgdmFyIGxlbiA9IGFyci5sZW5ndGg7XG4gICAgICAgIHZhciByZXN1bHQgPSAnJztcbiAgICAgICAgaWYgKGlzQXJyYXkpIHtcbiAgICAgICAgICB3aGlsZSAoKytpIDwgbGVuKSB7XG4gICAgICAgICAgICByZXN1bHQgKz0gdG9JbmRleGFibGVTdHJpbmcoYXJyW2ldKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgd2hpbGUgKCsraSA8IGxlbikge1xuICAgICAgICAgICAgdmFyIG9iaktleSA9IGFycltpXTtcbiAgICAgICAgICAgIHJlc3VsdCArPSB0b0luZGV4YWJsZVN0cmluZyhvYmpLZXkpICtcbiAgICAgICAgICAgICAgICB0b0luZGV4YWJsZVN0cmluZyhrZXlbb2JqS2V5XSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9XG4gIHJldHVybiAnJztcbn1cblxuLy8gY29udmVydCB0aGUgZ2l2ZW4ga2V5IHRvIGEgc3RyaW5nIHRoYXQgd291bGQgYmUgYXBwcm9wcmlhdGVcbi8vIGZvciBsZXhpY2FsIHNvcnRpbmcsIGUuZy4gd2l0aGluIGEgZGF0YWJhc2UsIHdoZXJlIHRoZVxuLy8gc29ydGluZyBpcyB0aGUgc2FtZSBnaXZlbiBieSB0aGUgY29sbGF0ZSgpIGZ1bmN0aW9uLlxuZnVuY3Rpb24gdG9JbmRleGFibGVTdHJpbmcoa2V5KSB7XG4gIHZhciB6ZXJvID0gJ1xcdTAwMDAnO1xuICBrZXkgPSBub3JtYWxpemVLZXkoa2V5KTtcbiAgcmV0dXJuIGNvbGxhdGlvbkluZGV4KGtleSkgKyBTRVAgKyBpbmRleGlmeShrZXkpICsgemVybztcbn1cblxuZnVuY3Rpb24gcGFyc2VOdW1iZXIoc3RyLCBpKSB7XG4gIHZhciBvcmlnaW5hbElkeCA9IGk7XG4gIHZhciBudW07XG4gIHZhciB6ZXJvID0gc3RyW2ldID09PSAnMSc7XG4gIGlmICh6ZXJvKSB7XG4gICAgbnVtID0gMDtcbiAgICBpKys7XG4gIH0gZWxzZSB7XG4gICAgdmFyIG5lZyA9IHN0cltpXSA9PT0gJzAnO1xuICAgIGkrKztcbiAgICB2YXIgbnVtQXNTdHJpbmcgPSAnJztcbiAgICB2YXIgbWFnQXNTdHJpbmcgPSBzdHIuc3Vic3RyaW5nKGksIGkgKyBNQUdOSVRVREVfRElHSVRTKTtcbiAgICB2YXIgbWFnbml0dWRlID0gcGFyc2VJbnQobWFnQXNTdHJpbmcsIDEwKSArIE1JTl9NQUdOSVRVREU7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICBpZiAobmVnKSB7XG4gICAgICBtYWduaXR1ZGUgPSAtbWFnbml0dWRlO1xuICAgIH1cbiAgICBpICs9IE1BR05JVFVERV9ESUdJVFM7XG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIHZhciBjaCA9IHN0cltpXTtcbiAgICAgIGlmIChjaCA9PT0gJ1xcdTAwMDAnKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbnVtQXNTdHJpbmcgKz0gY2g7XG4gICAgICB9XG4gICAgICBpKys7XG4gICAgfVxuICAgIG51bUFzU3RyaW5nID0gbnVtQXNTdHJpbmcuc3BsaXQoJy4nKTtcbiAgICBpZiAobnVtQXNTdHJpbmcubGVuZ3RoID09PSAxKSB7XG4gICAgICBudW0gPSBwYXJzZUludChudW1Bc1N0cmluZywgMTApO1xuICAgIH0gZWxzZSB7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgbnVtID0gcGFyc2VGbG9hdChudW1Bc1N0cmluZ1swXSArICcuJyArIG51bUFzU3RyaW5nWzFdKTtcbiAgICB9XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICBpZiAobmVnKSB7XG4gICAgICBudW0gPSBudW0gLSAxMDtcbiAgICB9XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICBpZiAobWFnbml0dWRlICE9PSAwKSB7XG4gICAgICAvLyBwYXJzZUZsb2F0IGlzIG1vcmUgcmVsaWFibGUgdGhhbiBwb3cgZHVlIHRvIHJvdW5kaW5nIGVycm9yc1xuICAgICAgLy8gZS5nLiBOdW1iZXIuTUFYX1ZBTFVFIHdvdWxkIHJldHVybiBJbmZpbml0eSBpZiB3ZSBkaWRcbiAgICAgIC8vIG51bSAqIE1hdGgucG93KDEwLCBtYWduaXR1ZGUpO1xuICAgICAgbnVtID0gcGFyc2VGbG9hdChudW0gKyAnZScgKyBtYWduaXR1ZGUpO1xuICAgIH1cbiAgfVxuICByZXR1cm4ge251bTogbnVtLCBsZW5ndGggOiBpIC0gb3JpZ2luYWxJZHh9O1xufVxuXG4vLyBtb3ZlIHVwIHRoZSBzdGFjayB3aGlsZSBwYXJzaW5nXG4vLyB0aGlzIGZ1bmN0aW9uIG1vdmVkIG91dHNpZGUgb2YgcGFyc2VJbmRleGFibGVTdHJpbmcgZm9yIHBlcmZvcm1hbmNlXG5mdW5jdGlvbiBwb3Aoc3RhY2ssIG1ldGFTdGFjaykge1xuICB2YXIgb2JqID0gc3RhY2sucG9wKCk7XG5cbiAgaWYgKG1ldGFTdGFjay5sZW5ndGgpIHtcbiAgICB2YXIgbGFzdE1ldGFFbGVtZW50ID0gbWV0YVN0YWNrW21ldGFTdGFjay5sZW5ndGggLSAxXTtcbiAgICBpZiAob2JqID09PSBsYXN0TWV0YUVsZW1lbnQuZWxlbWVudCkge1xuICAgICAgLy8gcG9wcGluZyBhIG1ldGEtZWxlbWVudCwgZS5nLiBhbiBvYmplY3Qgd2hvc2UgdmFsdWUgaXMgYW5vdGhlciBvYmplY3RcbiAgICAgIG1ldGFTdGFjay5wb3AoKTtcbiAgICAgIGxhc3RNZXRhRWxlbWVudCA9IG1ldGFTdGFja1ttZXRhU3RhY2subGVuZ3RoIC0gMV07XG4gICAgfVxuICAgIHZhciBlbGVtZW50ID0gbGFzdE1ldGFFbGVtZW50LmVsZW1lbnQ7XG4gICAgdmFyIGxhc3RFbGVtZW50SW5kZXggPSBsYXN0TWV0YUVsZW1lbnQuaW5kZXg7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoZWxlbWVudCkpIHtcbiAgICAgIGVsZW1lbnQucHVzaChvYmopO1xuICAgIH0gZWxzZSBpZiAobGFzdEVsZW1lbnRJbmRleCA9PT0gc3RhY2subGVuZ3RoIC0gMikgeyAvLyBvYmogd2l0aCBrZXkrdmFsdWVcbiAgICAgIHZhciBrZXkgPSBzdGFjay5wb3AoKTtcbiAgICAgIGVsZW1lbnRba2V5XSA9IG9iajtcbiAgICB9IGVsc2Uge1xuICAgICAgc3RhY2sucHVzaChvYmopOyAvLyBvYmogd2l0aCBrZXkgb25seVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZUluZGV4YWJsZVN0cmluZyhzdHIpIHtcbiAgdmFyIHN0YWNrID0gW107XG4gIHZhciBtZXRhU3RhY2sgPSBbXTsgLy8gc3RhY2sgZm9yIGFycmF5cyBhbmQgb2JqZWN0c1xuICB2YXIgaSA9IDA7XG5cbiAgLyplc2xpbnQgbm8tY29uc3RhbnQtY29uZGl0aW9uOiBbXCJlcnJvclwiLCB7IFwiY2hlY2tMb29wc1wiOiBmYWxzZSB9XSovXG4gIHdoaWxlICh0cnVlKSB7XG4gICAgdmFyIGNvbGxhdGlvbkluZGV4ID0gc3RyW2krK107XG4gICAgaWYgKGNvbGxhdGlvbkluZGV4ID09PSAnXFx1MDAwMCcpIHtcbiAgICAgIGlmIChzdGFjay5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgcmV0dXJuIHN0YWNrLnBvcCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcG9wKHN0YWNrLCBtZXRhU3RhY2spO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgc3dpdGNoIChjb2xsYXRpb25JbmRleCkge1xuICAgICAgY2FzZSAnMSc6XG4gICAgICAgIHN0YWNrLnB1c2gobnVsbCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnMic6XG4gICAgICAgIHN0YWNrLnB1c2goc3RyW2ldID09PSAnMScpO1xuICAgICAgICBpKys7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnMyc6XG4gICAgICAgIHZhciBwYXJzZWROdW0gPSBwYXJzZU51bWJlcihzdHIsIGkpO1xuICAgICAgICBzdGFjay5wdXNoKHBhcnNlZE51bS5udW0pO1xuICAgICAgICBpICs9IHBhcnNlZE51bS5sZW5ndGg7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnNCc6XG4gICAgICAgIHZhciBwYXJzZWRTdHIgPSAnJztcbiAgICAgICAgLyplc2xpbnQgbm8tY29uc3RhbnQtY29uZGl0aW9uOiBbXCJlcnJvclwiLCB7IFwiY2hlY2tMb29wc1wiOiBmYWxzZSB9XSovXG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgdmFyIGNoID0gc3RyW2ldO1xuICAgICAgICAgIGlmIChjaCA9PT0gJ1xcdTAwMDAnKSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgcGFyc2VkU3RyICs9IGNoO1xuICAgICAgICAgIGkrKztcbiAgICAgICAgfVxuICAgICAgICAvLyBwZXJmb3JtIHRoZSByZXZlcnNlIG9mIHRoZSBvcmRlci1wcmVzZXJ2aW5nIHJlcGxhY2VtZW50XG4gICAgICAgIC8vIGFsZ29yaXRobSAoc2VlIGFib3ZlKVxuICAgICAgICBwYXJzZWRTdHIgPSBwYXJzZWRTdHIucmVwbGFjZSgvXFx1MDAwMVxcdTAwMDEvZywgJ1xcdTAwMDAnKVxuICAgICAgICAgIC5yZXBsYWNlKC9cXHUwMDAxXFx1MDAwMi9nLCAnXFx1MDAwMScpXG4gICAgICAgICAgLnJlcGxhY2UoL1xcdTAwMDJcXHUwMDAyL2csICdcXHUwMDAyJyk7XG4gICAgICAgIHN0YWNrLnB1c2gocGFyc2VkU3RyKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICc1JzpcbiAgICAgICAgdmFyIGFycmF5RWxlbWVudCA9IHsgZWxlbWVudDogW10sIGluZGV4OiBzdGFjay5sZW5ndGggfTtcbiAgICAgICAgc3RhY2sucHVzaChhcnJheUVsZW1lbnQuZWxlbWVudCk7XG4gICAgICAgIG1ldGFTdGFjay5wdXNoKGFycmF5RWxlbWVudCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnNic6XG4gICAgICAgIHZhciBvYmpFbGVtZW50ID0geyBlbGVtZW50OiB7fSwgaW5kZXg6IHN0YWNrLmxlbmd0aCB9O1xuICAgICAgICBzdGFjay5wdXNoKG9iakVsZW1lbnQuZWxlbWVudCk7XG4gICAgICAgIG1ldGFTdGFjay5wdXNoKG9iakVsZW1lbnQpO1xuICAgICAgICBicmVhaztcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgJ2JhZCBjb2xsYXRpb25JbmRleCBvciB1bmV4cGVjdGVkbHkgcmVhY2hlZCBlbmQgb2YgaW5wdXQ6ICcgK1xuICAgICAgICAgICAgY29sbGF0aW9uSW5kZXgpO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBhcnJheUNvbGxhdGUoYSwgYikge1xuICB2YXIgbGVuID0gTWF0aC5taW4oYS5sZW5ndGgsIGIubGVuZ3RoKTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgIHZhciBzb3J0ID0gY29sbGF0ZShhW2ldLCBiW2ldKTtcbiAgICBpZiAoc29ydCAhPT0gMCkge1xuICAgICAgcmV0dXJuIHNvcnQ7XG4gICAgfVxuICB9XG4gIHJldHVybiAoYS5sZW5ndGggPT09IGIubGVuZ3RoKSA/IDAgOlxuICAgIChhLmxlbmd0aCA+IGIubGVuZ3RoKSA/IDEgOiAtMTtcbn1cbmZ1bmN0aW9uIHN0cmluZ0NvbGxhdGUoYSwgYikge1xuICAvLyBTZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9kYWxlaGFydmV5L3BvdWNoZGIvaXNzdWVzLzQwXG4gIC8vIFRoaXMgaXMgaW5jb21wYXRpYmxlIHdpdGggdGhlIENvdWNoREIgaW1wbGVtZW50YXRpb24sIGJ1dCBpdHMgdGhlXG4gIC8vIGJlc3Qgd2UgY2FuIGRvIGZvciBub3dcbiAgcmV0dXJuIChhID09PSBiKSA/IDAgOiAoKGEgPiBiKSA/IDEgOiAtMSk7XG59XG5mdW5jdGlvbiBvYmplY3RDb2xsYXRlKGEsIGIpIHtcbiAgdmFyIGFrID0gT2JqZWN0LmtleXMoYSksIGJrID0gT2JqZWN0LmtleXMoYik7XG4gIHZhciBsZW4gPSBNYXRoLm1pbihhay5sZW5ndGgsIGJrLmxlbmd0aCk7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAvLyBGaXJzdCBzb3J0IHRoZSBrZXlzXG4gICAgdmFyIHNvcnQgPSBjb2xsYXRlKGFrW2ldLCBia1tpXSk7XG4gICAgaWYgKHNvcnQgIT09IDApIHtcbiAgICAgIHJldHVybiBzb3J0O1xuICAgIH1cbiAgICAvLyBpZiB0aGUga2V5cyBhcmUgZXF1YWwgc29ydCB0aGUgdmFsdWVzXG4gICAgc29ydCA9IGNvbGxhdGUoYVtha1tpXV0sIGJbYmtbaV1dKTtcbiAgICBpZiAoc29ydCAhPT0gMCkge1xuICAgICAgcmV0dXJuIHNvcnQ7XG4gICAgfVxuXG4gIH1cbiAgcmV0dXJuIChhay5sZW5ndGggPT09IGJrLmxlbmd0aCkgPyAwIDpcbiAgICAoYWsubGVuZ3RoID4gYmsubGVuZ3RoKSA/IDEgOiAtMTtcbn1cbi8vIFRoZSBjb2xsYXRpb24gaXMgZGVmaW5lZCBieSBlcmxhbmdzIG9yZGVyZWQgdGVybXNcbi8vIHRoZSBhdG9tcyBudWxsLCB0cnVlLCBmYWxzZSBjb21lIGZpcnN0LCB0aGVuIG51bWJlcnMsIHN0cmluZ3MsXG4vLyBhcnJheXMsIHRoZW4gb2JqZWN0c1xuLy8gbnVsbC91bmRlZmluZWQvTmFOL0luZmluaXR5Ly1JbmZpbml0eSBhcmUgYWxsIGNvbnNpZGVyZWQgbnVsbFxuZnVuY3Rpb24gY29sbGF0aW9uSW5kZXgoeCkge1xuICB2YXIgaWQgPSBbJ2Jvb2xlYW4nLCAnbnVtYmVyJywgJ3N0cmluZycsICdvYmplY3QnXTtcbiAgdmFyIGlkeCA9IGlkLmluZGV4T2YodHlwZW9mIHgpO1xuICAvL2ZhbHNlIGlmIC0xIG90aGVyd2lzZSB0cnVlLCBidXQgZmFzdCEhISExXG4gIGlmICh+aWR4KSB7XG4gICAgaWYgKHggPT09IG51bGwpIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH1cbiAgICBpZiAoQXJyYXkuaXNBcnJheSh4KSkge1xuICAgICAgcmV0dXJuIDU7XG4gICAgfVxuICAgIHJldHVybiBpZHggPCAzID8gKGlkeCArIDIpIDogKGlkeCArIDMpO1xuICB9XG4gIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gIGlmIChBcnJheS5pc0FycmF5KHgpKSB7XG4gICAgcmV0dXJuIDU7XG4gIH1cbn1cblxuLy8gY29udmVyc2lvbjpcbi8vIHggeXl5IHp6Li4uenpcbi8vIHggPSAwIGZvciBuZWdhdGl2ZSwgMSBmb3IgMCwgMiBmb3IgcG9zaXRpdmVcbi8vIHkgPSBleHBvbmVudCAoZm9yIG5lZ2F0aXZlIG51bWJlcnMgbmVnYXRlZCkgbW92ZWQgc28gdGhhdCBpdCdzID49IDBcbi8vIHogPSBtYW50aXNzZVxuZnVuY3Rpb24gbnVtVG9JbmRleGFibGVTdHJpbmcobnVtKSB7XG5cbiAgaWYgKG51bSA9PT0gMCkge1xuICAgIHJldHVybiAnMSc7XG4gIH1cblxuICAvLyBjb252ZXJ0IG51bWJlciB0byBleHBvbmVudGlhbCBmb3JtYXQgZm9yIGVhc2llciBhbmRcbiAgLy8gbW9yZSBzdWNjaW5jdCBzdHJpbmcgc29ydGluZ1xuICB2YXIgZXhwRm9ybWF0ID0gbnVtLnRvRXhwb25lbnRpYWwoKS5zcGxpdCgvZVxcKz8vKTtcbiAgdmFyIG1hZ25pdHVkZSA9IHBhcnNlSW50KGV4cEZvcm1hdFsxXSwgMTApO1xuXG4gIHZhciBuZWcgPSBudW0gPCAwO1xuXG4gIHZhciByZXN1bHQgPSBuZWcgPyAnMCcgOiAnMic7XG5cbiAgLy8gZmlyc3Qgc29ydCBieSBtYWduaXR1ZGVcbiAgLy8gaXQncyBlYXNpZXIgaWYgYWxsIG1hZ25pdHVkZXMgYXJlIHBvc2l0aXZlXG4gIHZhciBtYWdGb3JDb21wYXJpc29uID0gKChuZWcgPyAtbWFnbml0dWRlIDogbWFnbml0dWRlKSAtIE1JTl9NQUdOSVRVREUpO1xuICB2YXIgbWFnU3RyaW5nID0gcGFkTGVmdCgobWFnRm9yQ29tcGFyaXNvbikudG9TdHJpbmcoKSwgJzAnLCBNQUdOSVRVREVfRElHSVRTKTtcblxuICByZXN1bHQgKz0gU0VQICsgbWFnU3RyaW5nO1xuXG4gIC8vIHRoZW4gc29ydCBieSB0aGUgZmFjdG9yXG4gIHZhciBmYWN0b3IgPSBNYXRoLmFicyhwYXJzZUZsb2F0KGV4cEZvcm1hdFswXSkpOyAvLyBbMS4uMTApXG4gIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gIGlmIChuZWcpIHsgLy8gZm9yIG5lZ2F0aXZlIHJldmVyc2Ugb3JkZXJpbmdcbiAgICBmYWN0b3IgPSAxMCAtIGZhY3RvcjtcbiAgfVxuXG4gIHZhciBmYWN0b3JTdHIgPSBmYWN0b3IudG9GaXhlZCgyMCk7XG5cbiAgLy8gc3RyaXAgemVyb3MgZnJvbSB0aGUgZW5kXG4gIGZhY3RvclN0ciA9IGZhY3RvclN0ci5yZXBsYWNlKC9cXC4/MCskLywgJycpO1xuXG4gIHJlc3VsdCArPSBTRVAgKyBmYWN0b3JTdHI7XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLypcbiAqIFNpbXBsZSB0YXNrIHF1ZXVlIHRvIHNlcXVlbnRpYWxpemUgYWN0aW9ucy4gQXNzdW1lc1xuICogY2FsbGJhY2tzIHdpbGwgZXZlbnR1YWxseSBmaXJlIChvbmNlKS5cbiAqL1xuXG5mdW5jdGlvbiBUYXNrUXVldWUkMSgpIHtcbiAgdGhpcy5wcm9taXNlID0gbmV3IFBvdWNoUHJvbWlzZShmdW5jdGlvbiAoZnVsZmlsbCkge2Z1bGZpbGwoKTsgfSk7XG59XG5UYXNrUXVldWUkMS5wcm90b3R5cGUuYWRkID0gZnVuY3Rpb24gKHByb21pc2VGYWN0b3J5KSB7XG4gIHRoaXMucHJvbWlzZSA9IHRoaXMucHJvbWlzZS5jYXRjaChmdW5jdGlvbiAoKSB7XG4gICAgLy8ganVzdCByZWNvdmVyXG4gIH0pLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBwcm9taXNlRmFjdG9yeSgpO1xuICB9KTtcbiAgcmV0dXJuIHRoaXMucHJvbWlzZTtcbn07XG5UYXNrUXVldWUkMS5wcm90b3R5cGUuZmluaXNoID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy5wcm9taXNlO1xufTtcblxuZnVuY3Rpb24gY3JlYXRlVmlldyhvcHRzKSB7XG4gIHZhciBzb3VyY2VEQiA9IG9wdHMuZGI7XG4gIHZhciB2aWV3TmFtZSA9IG9wdHMudmlld05hbWU7XG4gIHZhciBtYXBGdW4gPSBvcHRzLm1hcDtcbiAgdmFyIHJlZHVjZUZ1biA9IG9wdHMucmVkdWNlO1xuICB2YXIgdGVtcG9yYXJ5ID0gb3B0cy50ZW1wb3Jhcnk7XG5cbiAgLy8gdGhlIFwidW5kZWZpbmVkXCIgcGFydCBpcyBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHlcbiAgdmFyIHZpZXdTaWduYXR1cmUgPSBtYXBGdW4udG9TdHJpbmcoKSArIChyZWR1Y2VGdW4gJiYgcmVkdWNlRnVuLnRvU3RyaW5nKCkpICtcbiAgICAndW5kZWZpbmVkJztcblxuICB2YXIgY2FjaGVkVmlld3M7XG4gIGlmICghdGVtcG9yYXJ5KSB7XG4gICAgLy8gY2FjaGUgdGhpcyB0byBlbnN1cmUgd2UgZG9uJ3QgdHJ5IHRvIHVwZGF0ZSB0aGUgc2FtZSB2aWV3IHR3aWNlXG4gICAgY2FjaGVkVmlld3MgPSBzb3VyY2VEQi5fY2FjaGVkVmlld3MgPSBzb3VyY2VEQi5fY2FjaGVkVmlld3MgfHwge307XG4gICAgaWYgKGNhY2hlZFZpZXdzW3ZpZXdTaWduYXR1cmVdKSB7XG4gICAgICByZXR1cm4gY2FjaGVkVmlld3Nbdmlld1NpZ25hdHVyZV07XG4gICAgfVxuICB9XG5cbiAgdmFyIHByb21pc2VGb3JWaWV3ID0gc291cmNlREIuaW5mbygpLnRoZW4oZnVuY3Rpb24gKGluZm8pIHtcblxuICAgIHZhciBkZXBEYk5hbWUgPSBpbmZvLmRiX25hbWUgKyAnLW1ydmlldy0nICtcbiAgICAgICh0ZW1wb3JhcnkgPyAndGVtcCcgOiBzdHJpbmdNZDUodmlld1NpZ25hdHVyZSkpO1xuXG4gICAgLy8gc2F2ZSB0aGUgdmlldyBuYW1lIGluIHRoZSBzb3VyY2UgZGIgc28gaXQgY2FuIGJlIGNsZWFuZWQgdXAgaWYgbmVjZXNzYXJ5XG4gICAgLy8gKGUuZy4gd2hlbiB0aGUgX2Rlc2lnbiBkb2MgaXMgZGVsZXRlZCwgcmVtb3ZlIGFsbCBhc3NvY2lhdGVkIHZpZXcgZGF0YSlcbiAgICBmdW5jdGlvbiBkaWZmRnVuY3Rpb24oZG9jKSB7XG4gICAgICBkb2Mudmlld3MgPSBkb2Mudmlld3MgfHwge307XG4gICAgICB2YXIgZnVsbFZpZXdOYW1lID0gdmlld05hbWU7XG4gICAgICBpZiAoZnVsbFZpZXdOYW1lLmluZGV4T2YoJy8nKSA9PT0gLTEpIHtcbiAgICAgICAgZnVsbFZpZXdOYW1lID0gdmlld05hbWUgKyAnLycgKyB2aWV3TmFtZTtcbiAgICAgIH1cbiAgICAgIHZhciBkZXBEYnMgPSBkb2Mudmlld3NbZnVsbFZpZXdOYW1lXSA9IGRvYy52aWV3c1tmdWxsVmlld05hbWVdIHx8IHt9O1xuICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgICBpZiAoZGVwRGJzW2RlcERiTmFtZV0pIHtcbiAgICAgICAgcmV0dXJuOyAvLyBubyB1cGRhdGUgbmVjZXNzYXJ5XG4gICAgICB9XG4gICAgICBkZXBEYnNbZGVwRGJOYW1lXSA9IHRydWU7XG4gICAgICByZXR1cm4gZG9jO1xuICAgIH1cbiAgICByZXR1cm4gdXBzZXJ0KHNvdXJjZURCLCAnX2xvY2FsL21ydmlld3MnLCBkaWZmRnVuY3Rpb24pLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHNvdXJjZURCLnJlZ2lzdGVyRGVwZW5kZW50RGF0YWJhc2UoZGVwRGJOYW1lKS50aGVuKGZ1bmN0aW9uIChyZXMpIHtcbiAgICAgICAgdmFyIGRiID0gcmVzLmRiO1xuICAgICAgICBkYi5hdXRvX2NvbXBhY3Rpb24gPSB0cnVlO1xuICAgICAgICB2YXIgdmlldyA9IHtcbiAgICAgICAgICBuYW1lOiBkZXBEYk5hbWUsXG4gICAgICAgICAgZGI6IGRiLFxuICAgICAgICAgIHNvdXJjZURCOiBzb3VyY2VEQixcbiAgICAgICAgICBhZGFwdGVyOiBzb3VyY2VEQi5hZGFwdGVyLFxuICAgICAgICAgIG1hcEZ1bjogbWFwRnVuLFxuICAgICAgICAgIHJlZHVjZUZ1bjogcmVkdWNlRnVuXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiB2aWV3LmRiLmdldCgnX2xvY2FsL2xhc3RTZXEnKS5jYXRjaChmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgICAgICAgaWYgKGVyci5zdGF0dXMgIT09IDQwNCkge1xuICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgIH1cbiAgICAgICAgfSkudGhlbihmdW5jdGlvbiAobGFzdFNlcURvYykge1xuICAgICAgICAgIHZpZXcuc2VxID0gbGFzdFNlcURvYyA/IGxhc3RTZXFEb2Muc2VxIDogMDtcbiAgICAgICAgICBpZiAoY2FjaGVkVmlld3MpIHtcbiAgICAgICAgICAgIHZpZXcuZGIub25jZSgnZGVzdHJveWVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICBkZWxldGUgY2FjaGVkVmlld3Nbdmlld1NpZ25hdHVyZV07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHZpZXc7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGlmIChjYWNoZWRWaWV3cykge1xuICAgIGNhY2hlZFZpZXdzW3ZpZXdTaWduYXR1cmVdID0gcHJvbWlzZUZvclZpZXc7XG4gIH1cbiAgcmV0dXJuIHByb21pc2VGb3JWaWV3O1xufVxuXG5mdW5jdGlvbiBRdWVyeVBhcnNlRXJyb3IobWVzc2FnZSkge1xuICB0aGlzLnN0YXR1cyA9IDQwMDtcbiAgdGhpcy5uYW1lID0gJ3F1ZXJ5X3BhcnNlX2Vycm9yJztcbiAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgdGhpcy5lcnJvciA9IHRydWU7XG4gIHRyeSB7XG4gICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgUXVlcnlQYXJzZUVycm9yKTtcbiAgfSBjYXRjaCAoZSkge31cbn1cblxuaW5oZXJpdHMoUXVlcnlQYXJzZUVycm9yLCBFcnJvcik7XG5cbmZ1bmN0aW9uIE5vdEZvdW5kRXJyb3IobWVzc2FnZSkge1xuICB0aGlzLnN0YXR1cyA9IDQwNDtcbiAgdGhpcy5uYW1lID0gJ25vdF9mb3VuZCc7XG4gIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gIHRoaXMuZXJyb3IgPSB0cnVlO1xuICB0cnkge1xuICAgIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIE5vdEZvdW5kRXJyb3IpO1xuICB9IGNhdGNoIChlKSB7fVxufVxuXG5pbmhlcml0cyhOb3RGb3VuZEVycm9yLCBFcnJvcik7XG5cbmZ1bmN0aW9uIEJ1aWx0SW5FcnJvcihtZXNzYWdlKSB7XG4gIHRoaXMuc3RhdHVzID0gNTAwO1xuICB0aGlzLm5hbWUgPSAnaW52YWxpZF92YWx1ZSc7XG4gIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gIHRoaXMuZXJyb3IgPSB0cnVlO1xuICB0cnkge1xuICAgIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIEJ1aWx0SW5FcnJvcik7XG4gIH0gY2F0Y2ggKGUpIHt9XG59XG5cbmluaGVyaXRzKEJ1aWx0SW5FcnJvciwgRXJyb3IpO1xuXG5mdW5jdGlvbiBjcmVhdGVCdWlsdEluRXJyb3IobmFtZSkge1xuICB2YXIgbWVzc2FnZSA9ICdidWlsdGluICcgKyBuYW1lICtcbiAgICAnIGZ1bmN0aW9uIHJlcXVpcmVzIG1hcCB2YWx1ZXMgdG8gYmUgbnVtYmVycycgK1xuICAgICcgb3IgbnVtYmVyIGFycmF5cyc7XG4gIHJldHVybiBuZXcgQnVpbHRJbkVycm9yKG1lc3NhZ2UpO1xufVxuXG5mdW5jdGlvbiBzdW0odmFsdWVzKSB7XG4gIHZhciByZXN1bHQgPSAwO1xuICBmb3IgKHZhciBpID0gMCwgbGVuID0gdmFsdWVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgdmFyIG51bSA9IHZhbHVlc1tpXTtcbiAgICBpZiAodHlwZW9mIG51bSAhPT0gJ251bWJlcicpIHtcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KG51bSkpIHtcbiAgICAgICAgLy8gbGlzdHMgb2YgbnVtYmVycyBhcmUgYWxzbyBhbGxvd2VkLCBzdW0gdGhlbSBzZXBhcmF0ZWx5XG4gICAgICAgIHJlc3VsdCA9IHR5cGVvZiByZXN1bHQgPT09ICdudW1iZXInID8gW3Jlc3VsdF0gOiByZXN1bHQ7XG4gICAgICAgIGZvciAodmFyIGogPSAwLCBqTGVuID0gbnVtLmxlbmd0aDsgaiA8IGpMZW47IGorKykge1xuICAgICAgICAgIHZhciBqTnVtID0gbnVtW2pdO1xuICAgICAgICAgIGlmICh0eXBlb2Ygak51bSAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIHRocm93IGNyZWF0ZUJ1aWx0SW5FcnJvcignX3N1bScpO1xuICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHJlc3VsdFtqXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKGpOdW0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHRbal0gKz0gak51bTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7IC8vIG5vdCBhcnJheS9udW1iZXJcbiAgICAgICAgdGhyb3cgY3JlYXRlQnVpbHRJbkVycm9yKCdfc3VtJyk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgcmVzdWx0ID09PSAnbnVtYmVyJykge1xuICAgICAgcmVzdWx0ICs9IG51bTtcbiAgICB9IGVsc2UgeyAvLyBhZGQgbnVtYmVyIHRvIGFycmF5XG4gICAgICByZXN1bHRbMF0gKz0gbnVtO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG52YXIgbG9nJDIgPSBndWFyZGVkQ29uc29sZS5iaW5kKG51bGwsICdsb2cnKTtcbnZhciBpc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbnZhciB0b0pTT04gPSBKU09OLnBhcnNlO1xuXG5mdW5jdGlvbiBldmFsRnVuY3Rpb25XaXRoRXZhbChmdW5jLCBlbWl0KSB7XG4gIHJldHVybiBzY29wZWRFdmFsKFxuICAgIFwicmV0dXJuIChcIiArIGZ1bmMucmVwbGFjZSgvO1xccyokLywgXCJcIikgKyBcIik7XCIsXG4gICAge1xuICAgICAgZW1pdDogZW1pdCxcbiAgICAgIHN1bTogc3VtLFxuICAgICAgbG9nOiBsb2ckMixcbiAgICAgIGlzQXJyYXk6IGlzQXJyYXksXG4gICAgICB0b0pTT046IHRvSlNPTlxuICAgIH1cbiAgKTtcbn1cblxudmFyIHByb21pc2VkQ2FsbGJhY2sgPSBmdW5jdGlvbiAocHJvbWlzZSwgY2FsbGJhY2spIHtcbiAgaWYgKGNhbGxiYWNrKSB7XG4gICAgcHJvbWlzZS50aGVuKGZ1bmN0aW9uIChyZXMpIHtcbiAgICAgIGltbWVkaWF0ZShmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIHJlcyk7XG4gICAgICB9KTtcbiAgICB9LCBmdW5jdGlvbiAocmVhc29uKSB7XG4gICAgICBpbW1lZGlhdGUoZnVuY3Rpb24gKCkge1xuICAgICAgICBjYWxsYmFjayhyZWFzb24pO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIHByb21pc2U7XG59O1xuXG52YXIgY2FsbGJhY2tpZnkgPSBmdW5jdGlvbiAoZnVuKSB7XG4gIHJldHVybiBnZXRBcmd1bWVudHMoZnVuY3Rpb24gKGFyZ3MpIHtcbiAgICB2YXIgY2IgPSBhcmdzLnBvcCgpO1xuICAgIHZhciBwcm9taXNlID0gZnVuLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgIGlmICh0eXBlb2YgY2IgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHByb21pc2VkQ2FsbGJhY2socHJvbWlzZSwgY2IpO1xuICAgIH1cbiAgICByZXR1cm4gcHJvbWlzZTtcbiAgfSk7XG59O1xuXG4vLyBQcm9taXNlIGZpbmFsbHkgdXRpbCBzaW1pbGFyIHRvIFEuZmluYWxseVxudmFyIGZpbiA9IGZ1bmN0aW9uIChwcm9taXNlLCBmaW5hbFByb21pc2VGYWN0b3J5KSB7XG4gIHJldHVybiBwcm9taXNlLnRoZW4oZnVuY3Rpb24gKHJlcykge1xuICAgIHJldHVybiBmaW5hbFByb21pc2VGYWN0b3J5KCkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gcmVzO1xuICAgIH0pO1xuICB9LCBmdW5jdGlvbiAocmVhc29uKSB7XG4gICAgcmV0dXJuIGZpbmFsUHJvbWlzZUZhY3RvcnkoKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHRocm93IHJlYXNvbjtcbiAgICB9KTtcbiAgfSk7XG59O1xuXG52YXIgc2VxdWVudGlhbGl6ZSA9IGZ1bmN0aW9uIChxdWV1ZSwgcHJvbWlzZUZhY3RvcnkpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICB2YXIgdGhhdCA9IHRoaXM7XG4gICAgcmV0dXJuIHF1ZXVlLmFkZChmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gcHJvbWlzZUZhY3RvcnkuYXBwbHkodGhhdCwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59O1xuXG4vLyB1bmlxIGFuIGFycmF5IG9mIHN0cmluZ3MsIG9yZGVyIG5vdCBndWFyYW50ZWVkXG4vLyBzaW1pbGFyIHRvIHVuZGVyc2NvcmUvbG9kYXNoIF8udW5pcVxudmFyIHVuaXEgPSBmdW5jdGlvbiAoYXJyKSB7XG4gIHZhciBtYXAgPSB7fTtcblxuICBmb3IgKHZhciBpID0gMCwgbGVuID0gYXJyLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgbWFwWyckJyArIGFycltpXV0gPSB0cnVlO1xuICB9XG5cbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhtYXApO1xuICB2YXIgb3V0cHV0ID0gbmV3IEFycmF5KGtleXMubGVuZ3RoKTtcblxuICBmb3IgKGkgPSAwLCBsZW4gPSBrZXlzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgb3V0cHV0W2ldID0ga2V5c1tpXS5zdWJzdHJpbmcoMSk7XG4gIH1cbiAgcmV0dXJuIG91dHB1dDtcbn07XG5cbnZhciBwZXJzaXN0ZW50UXVldWVzID0ge307XG52YXIgdGVtcFZpZXdRdWV1ZSA9IG5ldyBUYXNrUXVldWUkMSgpO1xudmFyIENIQU5HRVNfQkFUQ0hfU0laRSQxID0gNTA7XG5cbmZ1bmN0aW9uIHBhcnNlVmlld05hbWUobmFtZSkge1xuICAvLyBjYW4gYmUgZWl0aGVyICdkZG9jbmFtZS92aWV3bmFtZScgb3IganVzdCAndmlld25hbWUnXG4gIC8vICh3aGVyZSB0aGUgZGRvYyBuYW1lIGlzIHRoZSBzYW1lKVxuICByZXR1cm4gbmFtZS5pbmRleE9mKCcvJykgPT09IC0xID8gW25hbWUsIG5hbWVdIDogbmFtZS5zcGxpdCgnLycpO1xufVxuXG5mdW5jdGlvbiBpc0dlbk9uZShjaGFuZ2VzKSB7XG4gIC8vIG9ubHkgcmV0dXJuIHRydWUgaWYgdGhlIGN1cnJlbnQgY2hhbmdlIGlzIDEtXG4gIC8vIGFuZCB0aGVyZSBhcmUgbm8gb3RoZXIgbGVhZnNcbiAgcmV0dXJuIGNoYW5nZXMubGVuZ3RoID09PSAxICYmIC9eMS0vLnRlc3QoY2hhbmdlc1swXS5yZXYpO1xufVxuXG5mdW5jdGlvbiBlbWl0RXJyb3IoZGIsIGUpIHtcbiAgdHJ5IHtcbiAgICBkYi5lbWl0KCdlcnJvcicsIGUpO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBndWFyZGVkQ29uc29sZSgnZXJyb3InLFxuICAgICAgJ1RoZSB1c2VyXFwncyBtYXAvcmVkdWNlIGZ1bmN0aW9uIHRocmV3IGFuIHVuY2F1Z2h0IGVycm9yLlxcbicgK1xuICAgICAgJ1lvdSBjYW4gZGVidWcgdGhpcyBlcnJvciBieSBkb2luZzpcXG4nICtcbiAgICAgICdteURhdGFiYXNlLm9uKFxcJ2Vycm9yXFwnLCBmdW5jdGlvbiAoZXJyKSB7IGRlYnVnZ2VyOyB9KTtcXG4nICtcbiAgICAgICdQbGVhc2UgZG91YmxlLWNoZWNrIHlvdXIgbWFwL3JlZHVjZSBmdW5jdGlvbi4nKTtcbiAgICBndWFyZGVkQ29uc29sZSgnZXJyb3InLCBlKTtcbiAgfVxufVxuXG5mdW5jdGlvbiB0cnlDb2RlJDEoZGIsIGZ1biwgYXJncykge1xuICAvLyBlbWl0IGFuIGV2ZW50IGlmIHRoZXJlIHdhcyBhbiBlcnJvciB0aHJvd24gYnkgYSBtYXAvcmVkdWNlIGZ1bmN0aW9uLlxuICAvLyBwdXR0aW5nIHRyeS9jYXRjaGVzIGluIGEgc2luZ2xlIGZ1bmN0aW9uIGFsc28gYXZvaWRzIGRlb3B0aW1pemF0aW9ucy5cbiAgdHJ5IHtcbiAgICByZXR1cm4ge1xuICAgICAgb3V0cHV0IDogZnVuLmFwcGx5KG51bGwsIGFyZ3MpXG4gICAgfTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGVtaXRFcnJvcihkYiwgZSk7XG4gICAgcmV0dXJuIHtlcnJvcjogZX07XG4gIH1cbn1cblxuZnVuY3Rpb24gc29ydEJ5S2V5VGhlblZhbHVlKHgsIHkpIHtcbiAgdmFyIGtleUNvbXBhcmUgPSBjb2xsYXRlKHgua2V5LCB5LmtleSk7XG4gIHJldHVybiBrZXlDb21wYXJlICE9PSAwID8ga2V5Q29tcGFyZSA6IGNvbGxhdGUoeC52YWx1ZSwgeS52YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIHNsaWNlUmVzdWx0cyhyZXN1bHRzLCBsaW1pdCwgc2tpcCkge1xuICBza2lwID0gc2tpcCB8fCAwO1xuICBpZiAodHlwZW9mIGxpbWl0ID09PSAnbnVtYmVyJykge1xuICAgIHJldHVybiByZXN1bHRzLnNsaWNlKHNraXAsIGxpbWl0ICsgc2tpcCk7XG4gIH0gZWxzZSBpZiAoc2tpcCA+IDApIHtcbiAgICByZXR1cm4gcmVzdWx0cy5zbGljZShza2lwKTtcbiAgfVxuICByZXR1cm4gcmVzdWx0cztcbn1cblxuZnVuY3Rpb24gcm93VG9Eb2NJZChyb3cpIHtcbiAgdmFyIHZhbCA9IHJvdy52YWx1ZTtcbiAgLy8gVXNlcnMgY2FuIGV4cGxpY2l0bHkgc3BlY2lmeSBhIGpvaW5lZCBkb2MgX2lkLCBvciBpdFxuICAvLyBkZWZhdWx0cyB0byB0aGUgZG9jIF9pZCB0aGF0IGVtaXR0ZWQgdGhlIGtleS92YWx1ZS5cbiAgdmFyIGRvY0lkID0gKHZhbCAmJiB0eXBlb2YgdmFsID09PSAnb2JqZWN0JyAmJiB2YWwuX2lkKSB8fCByb3cuaWQ7XG4gIHJldHVybiBkb2NJZDtcbn1cblxuZnVuY3Rpb24gcmVhZEF0dGFjaG1lbnRzQXNCbG9iT3JCdWZmZXIkMShyZXMpIHtcbiAgcmVzLnJvd3MuZm9yRWFjaChmdW5jdGlvbiAocm93KSB7XG4gICAgdmFyIGF0dHMgPSByb3cuZG9jICYmIHJvdy5kb2MuX2F0dGFjaG1lbnRzO1xuICAgIGlmICghYXR0cykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBPYmplY3Qua2V5cyhhdHRzKS5mb3JFYWNoKGZ1bmN0aW9uIChmaWxlbmFtZSkge1xuICAgICAgdmFyIGF0dCA9IGF0dHNbZmlsZW5hbWVdO1xuICAgICAgYXR0c1tmaWxlbmFtZV0uZGF0YSA9IGI2NFRvQmx1ZmZlcihhdHQuZGF0YSwgYXR0LmNvbnRlbnRfdHlwZSk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBwb3N0cHJvY2Vzc0F0dGFjaG1lbnRzKG9wdHMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIChyZXMpIHtcbiAgICBpZiAob3B0cy5pbmNsdWRlX2RvY3MgJiYgb3B0cy5hdHRhY2htZW50cyAmJiBvcHRzLmJpbmFyeSkge1xuICAgICAgcmVhZEF0dGFjaG1lbnRzQXNCbG9iT3JCdWZmZXIkMShyZXMpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzO1xuICB9O1xufVxuXG52YXIgYnVpbHRJblJlZHVjZSA9IHtcbiAgX3N1bTogZnVuY3Rpb24gKGtleXMsIHZhbHVlcykge1xuICAgIHJldHVybiBzdW0odmFsdWVzKTtcbiAgfSxcblxuICBfY291bnQ6IGZ1bmN0aW9uIChrZXlzLCB2YWx1ZXMpIHtcbiAgICByZXR1cm4gdmFsdWVzLmxlbmd0aDtcbiAgfSxcblxuICBfc3RhdHM6IGZ1bmN0aW9uIChrZXlzLCB2YWx1ZXMpIHtcbiAgICAvLyBubyBuZWVkIHRvIGltcGxlbWVudCByZXJlZHVjZT10cnVlLCBiZWNhdXNlIFBvdWNoXG4gICAgLy8gd2lsbCBuZXZlciBjYWxsIGl0XG4gICAgZnVuY3Rpb24gc3Vtc3FyKHZhbHVlcykge1xuICAgICAgdmFyIF9zdW1zcXIgPSAwO1xuICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IHZhbHVlcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICB2YXIgbnVtID0gdmFsdWVzW2ldO1xuICAgICAgICBfc3Vtc3FyICs9IChudW0gKiBudW0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIF9zdW1zcXI7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBzdW0gICAgIDogc3VtKHZhbHVlcyksXG4gICAgICBtaW4gICAgIDogTWF0aC5taW4uYXBwbHkobnVsbCwgdmFsdWVzKSxcbiAgICAgIG1heCAgICAgOiBNYXRoLm1heC5hcHBseShudWxsLCB2YWx1ZXMpLFxuICAgICAgY291bnQgICA6IHZhbHVlcy5sZW5ndGgsXG4gICAgICBzdW1zcXIgOiBzdW1zcXIodmFsdWVzKVxuICAgIH07XG4gIH1cbn07XG5cbmZ1bmN0aW9uIGFkZEh0dHBQYXJhbShwYXJhbU5hbWUsIG9wdHMsIHBhcmFtcywgYXNKc29uKSB7XG4gIC8vIGFkZCBhbiBodHRwIHBhcmFtIGZyb20gb3B0cyB0byBwYXJhbXMsIG9wdGlvbmFsbHkganNvbi1lbmNvZGVkXG4gIHZhciB2YWwgPSBvcHRzW3BhcmFtTmFtZV07XG4gIGlmICh0eXBlb2YgdmFsICE9PSAndW5kZWZpbmVkJykge1xuICAgIGlmIChhc0pzb24pIHtcbiAgICAgIHZhbCA9IGVuY29kZVVSSUNvbXBvbmVudChKU09OLnN0cmluZ2lmeSh2YWwpKTtcbiAgICB9XG4gICAgcGFyYW1zLnB1c2gocGFyYW1OYW1lICsgJz0nICsgdmFsKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjb2VyY2VJbnRlZ2VyKGludGVnZXJDYW5kaWRhdGUpIHtcbiAgaWYgKHR5cGVvZiBpbnRlZ2VyQ2FuZGlkYXRlICE9PSAndW5kZWZpbmVkJykge1xuICAgIHZhciBhc051bWJlciA9IE51bWJlcihpbnRlZ2VyQ2FuZGlkYXRlKTtcbiAgICAvLyBwcmV2ZW50cyBlLmcuICcxZm9vJyBvciAnMS4xJyBiZWluZyBjb2VyY2VkIHRvIDFcbiAgICBpZiAoIWlzTmFOKGFzTnVtYmVyKSAmJiBhc051bWJlciA9PT0gcGFyc2VJbnQoaW50ZWdlckNhbmRpZGF0ZSwgMTApKSB7XG4gICAgICByZXR1cm4gYXNOdW1iZXI7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpbnRlZ2VyQ2FuZGlkYXRlO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBjb2VyY2VPcHRpb25zKG9wdHMpIHtcbiAgb3B0cy5ncm91cF9sZXZlbCA9IGNvZXJjZUludGVnZXIob3B0cy5ncm91cF9sZXZlbCk7XG4gIG9wdHMubGltaXQgPSBjb2VyY2VJbnRlZ2VyKG9wdHMubGltaXQpO1xuICBvcHRzLnNraXAgPSBjb2VyY2VJbnRlZ2VyKG9wdHMuc2tpcCk7XG4gIHJldHVybiBvcHRzO1xufVxuXG5mdW5jdGlvbiBjaGVja1Bvc2l0aXZlSW50ZWdlcihudW1iZXIpIHtcbiAgaWYgKG51bWJlcikge1xuICAgIGlmICh0eXBlb2YgbnVtYmVyICE9PSAnbnVtYmVyJykge1xuICAgICAgcmV0dXJuICBuZXcgUXVlcnlQYXJzZUVycm9yKCdJbnZhbGlkIHZhbHVlIGZvciBpbnRlZ2VyOiBcIicgK1xuICAgICAgbnVtYmVyICsgJ1wiJyk7XG4gICAgfVxuICAgIGlmIChudW1iZXIgPCAwKSB7XG4gICAgICByZXR1cm4gbmV3IFF1ZXJ5UGFyc2VFcnJvcignSW52YWxpZCB2YWx1ZSBmb3IgcG9zaXRpdmUgaW50ZWdlcjogJyArXG4gICAgICAgICdcIicgKyBudW1iZXIgKyAnXCInKTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gY2hlY2tRdWVyeVBhcnNlRXJyb3Iob3B0aW9ucywgZnVuKSB7XG4gIHZhciBzdGFydGtleU5hbWUgPSBvcHRpb25zLmRlc2NlbmRpbmcgPyAnZW5ka2V5JyA6ICdzdGFydGtleSc7XG4gIHZhciBlbmRrZXlOYW1lID0gb3B0aW9ucy5kZXNjZW5kaW5nID8gJ3N0YXJ0a2V5JyA6ICdlbmRrZXknO1xuXG4gIGlmICh0eXBlb2Ygb3B0aW9uc1tzdGFydGtleU5hbWVdICE9PSAndW5kZWZpbmVkJyAmJlxuICAgIHR5cGVvZiBvcHRpb25zW2VuZGtleU5hbWVdICE9PSAndW5kZWZpbmVkJyAmJlxuICAgIGNvbGxhdGUob3B0aW9uc1tzdGFydGtleU5hbWVdLCBvcHRpb25zW2VuZGtleU5hbWVdKSA+IDApIHtcbiAgICB0aHJvdyBuZXcgUXVlcnlQYXJzZUVycm9yKCdObyByb3dzIGNhbiBtYXRjaCB5b3VyIGtleSByYW5nZSwgJyArXG4gICAgJ3JldmVyc2UgeW91ciBzdGFydF9rZXkgYW5kIGVuZF9rZXkgb3Igc2V0IHtkZXNjZW5kaW5nIDogdHJ1ZX0nKTtcbiAgfSBlbHNlIGlmIChmdW4ucmVkdWNlICYmIG9wdGlvbnMucmVkdWNlICE9PSBmYWxzZSkge1xuICAgIGlmIChvcHRpb25zLmluY2x1ZGVfZG9jcykge1xuICAgICAgdGhyb3cgbmV3IFF1ZXJ5UGFyc2VFcnJvcigne2luY2x1ZGVfZG9jczp0cnVlfSBpcyBpbnZhbGlkIGZvciByZWR1Y2UnKTtcbiAgICB9IGVsc2UgaWYgKG9wdGlvbnMua2V5cyAmJiBvcHRpb25zLmtleXMubGVuZ3RoID4gMSAmJlxuICAgICAgICAhb3B0aW9ucy5ncm91cCAmJiAhb3B0aW9ucy5ncm91cF9sZXZlbCkge1xuICAgICAgdGhyb3cgbmV3IFF1ZXJ5UGFyc2VFcnJvcignTXVsdGkta2V5IGZldGNoZXMgZm9yIHJlZHVjZSB2aWV3cyBtdXN0IHVzZSAnICtcbiAgICAgICd7Z3JvdXA6IHRydWV9Jyk7XG4gICAgfVxuICB9XG4gIFsnZ3JvdXBfbGV2ZWwnLCAnbGltaXQnLCAnc2tpcCddLmZvckVhY2goZnVuY3Rpb24gKG9wdGlvbk5hbWUpIHtcbiAgICB2YXIgZXJyb3IgPSBjaGVja1Bvc2l0aXZlSW50ZWdlcihvcHRpb25zW29wdGlvbk5hbWVdKTtcbiAgICBpZiAoZXJyb3IpIHtcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGh0dHBRdWVyeShkYiwgZnVuLCBvcHRzKSB7XG4gIC8vIExpc3Qgb2YgcGFyYW1ldGVycyB0byBhZGQgdG8gdGhlIFBVVCByZXF1ZXN0XG4gIHZhciBwYXJhbXMgPSBbXTtcbiAgdmFyIGJvZHk7XG4gIHZhciBtZXRob2QgPSAnR0VUJztcblxuICAvLyBJZiBvcHRzLnJlZHVjZSBleGlzdHMgYW5kIGlzIGRlZmluZWQsIHRoZW4gYWRkIGl0IHRvIHRoZSBsaXN0XG4gIC8vIG9mIHBhcmFtZXRlcnMuXG4gIC8vIElmIHJlZHVjZT1mYWxzZSB0aGVuIHRoZSByZXN1bHRzIGFyZSB0aGF0IG9mIG9ubHkgdGhlIG1hcCBmdW5jdGlvblxuICAvLyBub3QgdGhlIGZpbmFsIHJlc3VsdCBvZiBtYXAgYW5kIHJlZHVjZS5cbiAgYWRkSHR0cFBhcmFtKCdyZWR1Y2UnLCBvcHRzLCBwYXJhbXMpO1xuICBhZGRIdHRwUGFyYW0oJ2luY2x1ZGVfZG9jcycsIG9wdHMsIHBhcmFtcyk7XG4gIGFkZEh0dHBQYXJhbSgnYXR0YWNobWVudHMnLCBvcHRzLCBwYXJhbXMpO1xuICBhZGRIdHRwUGFyYW0oJ2xpbWl0Jywgb3B0cywgcGFyYW1zKTtcbiAgYWRkSHR0cFBhcmFtKCdkZXNjZW5kaW5nJywgb3B0cywgcGFyYW1zKTtcbiAgYWRkSHR0cFBhcmFtKCdncm91cCcsIG9wdHMsIHBhcmFtcyk7XG4gIGFkZEh0dHBQYXJhbSgnZ3JvdXBfbGV2ZWwnLCBvcHRzLCBwYXJhbXMpO1xuICBhZGRIdHRwUGFyYW0oJ3NraXAnLCBvcHRzLCBwYXJhbXMpO1xuICBhZGRIdHRwUGFyYW0oJ3N0YWxlJywgb3B0cywgcGFyYW1zKTtcbiAgYWRkSHR0cFBhcmFtKCdjb25mbGljdHMnLCBvcHRzLCBwYXJhbXMpO1xuICBhZGRIdHRwUGFyYW0oJ3N0YXJ0a2V5Jywgb3B0cywgcGFyYW1zLCB0cnVlKTtcbiAgYWRkSHR0cFBhcmFtKCdzdGFydF9rZXknLCBvcHRzLCBwYXJhbXMsIHRydWUpO1xuICBhZGRIdHRwUGFyYW0oJ2VuZGtleScsIG9wdHMsIHBhcmFtcywgdHJ1ZSk7XG4gIGFkZEh0dHBQYXJhbSgnZW5kX2tleScsIG9wdHMsIHBhcmFtcywgdHJ1ZSk7XG4gIGFkZEh0dHBQYXJhbSgnaW5jbHVzaXZlX2VuZCcsIG9wdHMsIHBhcmFtcyk7XG4gIGFkZEh0dHBQYXJhbSgna2V5Jywgb3B0cywgcGFyYW1zLCB0cnVlKTtcblxuICAvLyBGb3JtYXQgdGhlIGxpc3Qgb2YgcGFyYW1ldGVycyBpbnRvIGEgdmFsaWQgVVJJIHF1ZXJ5IHN0cmluZ1xuICBwYXJhbXMgPSBwYXJhbXMuam9pbignJicpO1xuICBwYXJhbXMgPSBwYXJhbXMgPT09ICcnID8gJycgOiAnPycgKyBwYXJhbXM7XG5cbiAgLy8gSWYga2V5cyBhcmUgc3VwcGxpZWQsIGlzc3VlIGEgUE9TVCB0byBjaXJjdW12ZW50IEdFVCBxdWVyeSBzdHJpbmcgbGltaXRzXG4gIC8vIHNlZSBodHRwOi8vd2lraS5hcGFjaGUub3JnL2NvdWNoZGIvSFRUUF92aWV3X0FQSSNRdWVyeWluZ19PcHRpb25zXG4gIGlmICh0eXBlb2Ygb3B0cy5rZXlzICE9PSAndW5kZWZpbmVkJykge1xuICAgIHZhciBNQVhfVVJMX0xFTkdUSCA9IDIwMDA7XG4gICAgLy8gYWNjb3JkaW5nIHRvIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzQxNzE4NC82ODA3NDIsXG4gICAgLy8gdGhlIGRlIGZhY3RvIFVSTCBsZW5ndGggbGltaXQgaXMgMjAwMCBjaGFyYWN0ZXJzXG5cbiAgICB2YXIga2V5c0FzU3RyaW5nID1cbiAgICAgICdrZXlzPScgKyBlbmNvZGVVUklDb21wb25lbnQoSlNPTi5zdHJpbmdpZnkob3B0cy5rZXlzKSk7XG4gICAgaWYgKGtleXNBc1N0cmluZy5sZW5ndGggKyBwYXJhbXMubGVuZ3RoICsgMSA8PSBNQVhfVVJMX0xFTkdUSCkge1xuICAgICAgLy8gSWYgdGhlIGtleXMgYXJlIHNob3J0IGVub3VnaCwgZG8gYSBHRVQuIHdlIGRvIHRoaXMgdG8gd29yayBhcm91bmRcbiAgICAgIC8vIFNhZmFyaSBub3QgdW5kZXJzdGFuZGluZyAzMDRzIG9uIFBPU1RzIChzZWUgcG91Y2hkYi9wb3VjaGRiIzEyMzkpXG4gICAgICBwYXJhbXMgKz0gKHBhcmFtc1swXSA9PT0gJz8nID8gJyYnIDogJz8nKSArIGtleXNBc1N0cmluZztcbiAgICB9IGVsc2Uge1xuICAgICAgbWV0aG9kID0gJ1BPU1QnO1xuICAgICAgaWYgKHR5cGVvZiBmdW4gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGJvZHkgPSB7a2V5czogb3B0cy5rZXlzfTtcbiAgICAgIH0gZWxzZSB7IC8vIGZ1biBpcyB7bWFwIDogbWFwZnVufSwgc28gYXBwZW5kIHRvIHRoaXNcbiAgICAgICAgZnVuLmtleXMgPSBvcHRzLmtleXM7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gV2UgYXJlIHJlZmVyZW5jaW5nIGEgcXVlcnkgZGVmaW5lZCBpbiB0aGUgZGVzaWduIGRvY1xuICBpZiAodHlwZW9mIGZ1biA9PT0gJ3N0cmluZycpIHtcbiAgICB2YXIgcGFydHMgPSBwYXJzZVZpZXdOYW1lKGZ1bik7XG4gICAgcmV0dXJuIGRiLnJlcXVlc3Qoe1xuICAgICAgbWV0aG9kOiBtZXRob2QsXG4gICAgICB1cmw6ICdfZGVzaWduLycgKyBwYXJ0c1swXSArICcvX3ZpZXcvJyArIHBhcnRzWzFdICsgcGFyYW1zLFxuICAgICAgYm9keTogYm9keVxuICAgIH0pLnRoZW4ocG9zdHByb2Nlc3NBdHRhY2htZW50cyhvcHRzKSk7XG4gIH1cblxuICAvLyBXZSBhcmUgdXNpbmcgYSB0ZW1wb3JhcnkgdmlldywgdGVycmlibGUgZm9yIHBlcmZvcm1hbmNlLCBnb29kIGZvciB0ZXN0aW5nXG4gIGJvZHkgPSBib2R5IHx8IHt9O1xuICBPYmplY3Qua2V5cyhmdW4pLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGZ1bltrZXldKSkge1xuICAgICAgYm9keVtrZXldID0gZnVuW2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIGJvZHlba2V5XSA9IGZ1bltrZXldLnRvU3RyaW5nKCk7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIGRiLnJlcXVlc3Qoe1xuICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgIHVybDogJ190ZW1wX3ZpZXcnICsgcGFyYW1zLFxuICAgIGJvZHk6IGJvZHlcbiAgfSkudGhlbihwb3N0cHJvY2Vzc0F0dGFjaG1lbnRzKG9wdHMpKTtcbn1cblxuLy8gY3VzdG9tIGFkYXB0ZXJzIGNhbiBkZWZpbmUgdGhlaXIgb3duIGFwaS5fcXVlcnlcbi8vIGFuZCBvdmVycmlkZSB0aGUgZGVmYXVsdCBiZWhhdmlvclxuLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbmZ1bmN0aW9uIGN1c3RvbVF1ZXJ5KGRiLCBmdW4sIG9wdHMpIHtcbiAgcmV0dXJuIG5ldyBQb3VjaFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgIGRiLl9xdWVyeShmdW4sIG9wdHMsIGZ1bmN0aW9uIChlcnIsIHJlcykge1xuICAgICAgaWYgKGVycikge1xuICAgICAgICByZXR1cm4gcmVqZWN0KGVycik7XG4gICAgICB9XG4gICAgICByZXNvbHZlKHJlcyk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG4vLyBjdXN0b20gYWRhcHRlcnMgY2FuIGRlZmluZSB0aGVpciBvd24gYXBpLl92aWV3Q2xlYW51cFxuLy8gYW5kIG92ZXJyaWRlIHRoZSBkZWZhdWx0IGJlaGF2aW9yXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuZnVuY3Rpb24gY3VzdG9tVmlld0NsZWFudXAoZGIpIHtcbiAgcmV0dXJuIG5ldyBQb3VjaFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgIGRiLl92aWV3Q2xlYW51cChmdW5jdGlvbiAoZXJyLCByZXMpIHtcbiAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgcmV0dXJuIHJlamVjdChlcnIpO1xuICAgICAgfVxuICAgICAgcmVzb2x2ZShyZXMpO1xuICAgIH0pO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdHNUbyh2YWx1ZSkge1xuICByZXR1cm4gZnVuY3Rpb24gKHJlYXNvbikge1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgaWYgKHJlYXNvbi5zdGF0dXMgPT09IDQwNCkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyByZWFzb247XG4gICAgfVxuICB9O1xufVxuXG4vLyByZXR1cm5zIGEgcHJvbWlzZSBmb3IgYSBsaXN0IG9mIGRvY3MgdG8gdXBkYXRlLCBiYXNlZCBvbiB0aGUgaW5wdXQgZG9jSWQuXG4vLyB0aGUgb3JkZXIgZG9lc24ndCBtYXR0ZXIsIGJlY2F1c2UgcG9zdC0zLjIuMCwgYnVsa0RvY3Ncbi8vIGlzIGFuIGF0b21pYyBvcGVyYXRpb24gaW4gYWxsIHRocmVlIGFkYXB0ZXJzLlxuZnVuY3Rpb24gZ2V0RG9jc1RvUGVyc2lzdChkb2NJZCwgdmlldywgZG9jSWRzVG9DaGFuZ2VzQW5kRW1pdHMpIHtcbiAgdmFyIG1ldGFEb2NJZCA9ICdfbG9jYWwvZG9jXycgKyBkb2NJZDtcbiAgdmFyIGRlZmF1bHRNZXRhRG9jID0ge19pZDogbWV0YURvY0lkLCBrZXlzOiBbXX07XG4gIHZhciBkb2NEYXRhID0gZG9jSWRzVG9DaGFuZ2VzQW5kRW1pdHNbZG9jSWRdO1xuICB2YXIgaW5kZXhhYmxlS2V5c1RvS2V5VmFsdWVzID0gZG9jRGF0YS5pbmRleGFibGVLZXlzVG9LZXlWYWx1ZXM7XG4gIHZhciBjaGFuZ2VzID0gZG9jRGF0YS5jaGFuZ2VzO1xuXG4gIGZ1bmN0aW9uIGdldE1ldGFEb2MoKSB7XG4gICAgaWYgKGlzR2VuT25lKGNoYW5nZXMpKSB7XG4gICAgICAvLyBnZW5lcmF0aW9uIDEsIHNvIHdlIGNhbiBzYWZlbHkgYXNzdW1lIGluaXRpYWwgc3RhdGVcbiAgICAgIC8vIGZvciBwZXJmb3JtYW5jZSByZWFzb25zIChhdm9pZHMgdW5uZWNlc3NhcnkgR0VUcylcbiAgICAgIHJldHVybiBQb3VjaFByb21pc2UucmVzb2x2ZShkZWZhdWx0TWV0YURvYyk7XG4gICAgfVxuICAgIHJldHVybiB2aWV3LmRiLmdldChtZXRhRG9jSWQpLmNhdGNoKGRlZmF1bHRzVG8oZGVmYXVsdE1ldGFEb2MpKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldEtleVZhbHVlRG9jcyhtZXRhRG9jKSB7XG4gICAgaWYgKCFtZXRhRG9jLmtleXMubGVuZ3RoKSB7XG4gICAgICAvLyBubyBrZXlzLCBubyBuZWVkIGZvciBhIGxvb2t1cFxuICAgICAgcmV0dXJuIFBvdWNoUHJvbWlzZS5yZXNvbHZlKHtyb3dzOiBbXX0pO1xuICAgIH1cbiAgICByZXR1cm4gdmlldy5kYi5hbGxEb2NzKHtcbiAgICAgIGtleXM6IG1ldGFEb2Mua2V5cyxcbiAgICAgIGluY2x1ZGVfZG9jczogdHJ1ZVxuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gcHJvY2Vzc0t2RG9jcyhtZXRhRG9jLCBrdkRvY3NSZXMpIHtcbiAgICB2YXIga3ZEb2NzID0gW107XG4gICAgdmFyIG9sZEtleXNNYXAgPSB7fTtcblxuICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBrdkRvY3NSZXMucm93cy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgdmFyIHJvdyA9IGt2RG9jc1Jlcy5yb3dzW2ldO1xuICAgICAgdmFyIGRvYyA9IHJvdy5kb2M7XG4gICAgICBpZiAoIWRvYykgeyAvLyBkZWxldGVkXG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAga3ZEb2NzLnB1c2goZG9jKTtcbiAgICAgIG9sZEtleXNNYXBbZG9jLl9pZF0gPSB0cnVlO1xuICAgICAgZG9jLl9kZWxldGVkID0gIWluZGV4YWJsZUtleXNUb0tleVZhbHVlc1tkb2MuX2lkXTtcbiAgICAgIGlmICghZG9jLl9kZWxldGVkKSB7XG4gICAgICAgIHZhciBrZXlWYWx1ZSA9IGluZGV4YWJsZUtleXNUb0tleVZhbHVlc1tkb2MuX2lkXTtcbiAgICAgICAgaWYgKCd2YWx1ZScgaW4ga2V5VmFsdWUpIHtcbiAgICAgICAgICBkb2MudmFsdWUgPSBrZXlWYWx1ZS52YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBuZXdLZXlzID0gT2JqZWN0LmtleXMoaW5kZXhhYmxlS2V5c1RvS2V5VmFsdWVzKTtcbiAgICBuZXdLZXlzLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgaWYgKCFvbGRLZXlzTWFwW2tleV0pIHtcbiAgICAgICAgLy8gbmV3IGRvY1xuICAgICAgICB2YXIga3ZEb2MgPSB7XG4gICAgICAgICAgX2lkOiBrZXlcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGtleVZhbHVlID0gaW5kZXhhYmxlS2V5c1RvS2V5VmFsdWVzW2tleV07XG4gICAgICAgIGlmICgndmFsdWUnIGluIGtleVZhbHVlKSB7XG4gICAgICAgICAga3ZEb2MudmFsdWUgPSBrZXlWYWx1ZS52YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBrdkRvY3MucHVzaChrdkRvYyk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgbWV0YURvYy5rZXlzID0gdW5pcShuZXdLZXlzLmNvbmNhdChtZXRhRG9jLmtleXMpKTtcbiAgICBrdkRvY3MucHVzaChtZXRhRG9jKTtcblxuICAgIHJldHVybiBrdkRvY3M7XG4gIH1cblxuICByZXR1cm4gZ2V0TWV0YURvYygpLnRoZW4oZnVuY3Rpb24gKG1ldGFEb2MpIHtcbiAgICByZXR1cm4gZ2V0S2V5VmFsdWVEb2NzKG1ldGFEb2MpLnRoZW4oZnVuY3Rpb24gKGt2RG9jc1Jlcykge1xuICAgICAgcmV0dXJuIHByb2Nlc3NLdkRvY3MobWV0YURvYywga3ZEb2NzUmVzKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbi8vIHVwZGF0ZXMgYWxsIGVtaXR0ZWQga2V5L3ZhbHVlIGRvY3MgYW5kIG1ldGFEb2NzIGluIHRoZSBtcnZpZXcgZGF0YWJhc2Vcbi8vIGZvciB0aGUgZ2l2ZW4gYmF0Y2ggb2YgZG9jdW1lbnRzIGZyb20gdGhlIHNvdXJjZSBkYXRhYmFzZVxuZnVuY3Rpb24gc2F2ZUtleVZhbHVlcyh2aWV3LCBkb2NJZHNUb0NoYW5nZXNBbmRFbWl0cywgc2VxKSB7XG4gIHZhciBzZXFEb2NJZCA9ICdfbG9jYWwvbGFzdFNlcSc7XG4gIHJldHVybiB2aWV3LmRiLmdldChzZXFEb2NJZClcbiAgLmNhdGNoKGRlZmF1bHRzVG8oe19pZDogc2VxRG9jSWQsIHNlcTogMH0pKVxuICAudGhlbihmdW5jdGlvbiAobGFzdFNlcURvYykge1xuICAgIHZhciBkb2NJZHMgPSBPYmplY3Qua2V5cyhkb2NJZHNUb0NoYW5nZXNBbmRFbWl0cyk7XG4gICAgcmV0dXJuIFBvdWNoUHJvbWlzZS5hbGwoZG9jSWRzLm1hcChmdW5jdGlvbiAoZG9jSWQpIHtcbiAgICAgIHJldHVybiBnZXREb2NzVG9QZXJzaXN0KGRvY0lkLCB2aWV3LCBkb2NJZHNUb0NoYW5nZXNBbmRFbWl0cyk7XG4gICAgfSkpLnRoZW4oZnVuY3Rpb24gKGxpc3RPZkRvY3NUb1BlcnNpc3QpIHtcbiAgICAgIHZhciBkb2NzVG9QZXJzaXN0ID0gZmxhdHRlbihsaXN0T2ZEb2NzVG9QZXJzaXN0KTtcbiAgICAgIGxhc3RTZXFEb2Muc2VxID0gc2VxO1xuICAgICAgZG9jc1RvUGVyc2lzdC5wdXNoKGxhc3RTZXFEb2MpO1xuICAgICAgLy8gd3JpdGUgYWxsIGRvY3MgaW4gYSBzaW5nbGUgb3BlcmF0aW9uLCB1cGRhdGUgdGhlIHNlcSBvbmNlXG4gICAgICByZXR1cm4gdmlldy5kYi5idWxrRG9jcyh7ZG9jcyA6IGRvY3NUb1BlcnNpc3R9KTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdldFF1ZXVlKHZpZXcpIHtcbiAgdmFyIHZpZXdOYW1lID0gdHlwZW9mIHZpZXcgPT09ICdzdHJpbmcnID8gdmlldyA6IHZpZXcubmFtZTtcbiAgdmFyIHF1ZXVlID0gcGVyc2lzdGVudFF1ZXVlc1t2aWV3TmFtZV07XG4gIGlmICghcXVldWUpIHtcbiAgICBxdWV1ZSA9IHBlcnNpc3RlbnRRdWV1ZXNbdmlld05hbWVdID0gbmV3IFRhc2tRdWV1ZSQxKCk7XG4gIH1cbiAgcmV0dXJuIHF1ZXVlO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVWaWV3KHZpZXcpIHtcbiAgcmV0dXJuIHNlcXVlbnRpYWxpemUoZ2V0UXVldWUodmlldyksIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdXBkYXRlVmlld0luUXVldWUodmlldyk7XG4gIH0pKCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVZpZXdJblF1ZXVlKHZpZXcpIHtcbiAgLy8gYmluZCB0aGUgZW1pdCBmdW5jdGlvbiBvbmNlXG4gIHZhciBtYXBSZXN1bHRzO1xuICB2YXIgZG9jO1xuXG4gIGZ1bmN0aW9uIGVtaXQoa2V5LCB2YWx1ZSkge1xuICAgIHZhciBvdXRwdXQgPSB7aWQ6IGRvYy5faWQsIGtleTogbm9ybWFsaXplS2V5KGtleSl9O1xuICAgIC8vIERvbid0IGV4cGxpY2l0bHkgc3RvcmUgdGhlIHZhbHVlIHVubGVzcyBpdCdzIGRlZmluZWQgYW5kIG5vbi1udWxsLlxuICAgIC8vIFRoaXMgc2F2ZXMgb24gc3RvcmFnZSBzcGFjZSwgYmVjYXVzZSBvZnRlbiBwZW9wbGUgZG9uJ3QgdXNlIGl0LlxuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICd1bmRlZmluZWQnICYmIHZhbHVlICE9PSBudWxsKSB7XG4gICAgICBvdXRwdXQudmFsdWUgPSBub3JtYWxpemVLZXkodmFsdWUpO1xuICAgIH1cbiAgICBtYXBSZXN1bHRzLnB1c2gob3V0cHV0KTtcbiAgfVxuXG4gIHZhciBtYXBGdW47XG4gIC8vIGZvciB0ZW1wX3ZpZXdzIG9uZSBjYW4gdXNlIGVtaXQoZG9jLCBlbWl0KSwgc2VlICMzOFxuICBpZiAodHlwZW9mIHZpZXcubWFwRnVuID09PSBcImZ1bmN0aW9uXCIgJiYgdmlldy5tYXBGdW4ubGVuZ3RoID09PSAyKSB7XG4gICAgdmFyIG9yaWdNYXAgPSB2aWV3Lm1hcEZ1bjtcbiAgICBtYXBGdW4gPSBmdW5jdGlvbiAoZG9jKSB7XG4gICAgICByZXR1cm4gb3JpZ01hcChkb2MsIGVtaXQpO1xuICAgIH07XG4gIH0gZWxzZSB7XG4gICAgbWFwRnVuID0gZXZhbEZ1bmN0aW9uV2l0aEV2YWwodmlldy5tYXBGdW4udG9TdHJpbmcoKSwgZW1pdCk7XG4gIH1cblxuICB2YXIgY3VycmVudFNlcSA9IHZpZXcuc2VxIHx8IDA7XG5cbiAgZnVuY3Rpb24gcHJvY2Vzc0NoYW5nZShkb2NJZHNUb0NoYW5nZXNBbmRFbWl0cywgc2VxKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBzYXZlS2V5VmFsdWVzKHZpZXcsIGRvY0lkc1RvQ2hhbmdlc0FuZEVtaXRzLCBzZXEpO1xuICAgIH07XG4gIH1cblxuICB2YXIgcXVldWUgPSBuZXcgVGFza1F1ZXVlJDEoKTtcbiAgLy8gVE9ETyhuZW9qc2tpKTogaHR0cHM6Ly9naXRodWIuY29tL2RhbGVoYXJ2ZXkvcG91Y2hkYi9pc3N1ZXMvMTUyMVxuXG4gIHJldHVybiBuZXcgUG91Y2hQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcblxuICAgIGZ1bmN0aW9uIGNvbXBsZXRlKCkge1xuICAgICAgcXVldWUuZmluaXNoKCkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZpZXcuc2VxID0gY3VycmVudFNlcTtcbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcHJvY2Vzc05leHRCYXRjaCgpIHtcbiAgICAgIHZpZXcuc291cmNlREIuY2hhbmdlcyh7XG4gICAgICAgIGNvbmZsaWN0czogdHJ1ZSxcbiAgICAgICAgaW5jbHVkZV9kb2NzOiB0cnVlLFxuICAgICAgICBzdHlsZTogJ2FsbF9kb2NzJyxcbiAgICAgICAgc2luY2U6IGN1cnJlbnRTZXEsXG4gICAgICAgIGxpbWl0OiBDSEFOR0VTX0JBVENIX1NJWkUkMVxuICAgICAgfSkub24oJ2NvbXBsZXRlJywgZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgIHZhciByZXN1bHRzID0gcmVzcG9uc2UucmVzdWx0cztcbiAgICAgICAgaWYgKCFyZXN1bHRzLmxlbmd0aCkge1xuICAgICAgICAgIHJldHVybiBjb21wbGV0ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBkb2NJZHNUb0NoYW5nZXNBbmRFbWl0cyA9IHt9O1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IHJlc3VsdHMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgdmFyIGNoYW5nZSA9IHJlc3VsdHNbaV07XG4gICAgICAgICAgaWYgKGNoYW5nZS5kb2MuX2lkWzBdICE9PSAnXycpIHtcbiAgICAgICAgICAgIG1hcFJlc3VsdHMgPSBbXTtcbiAgICAgICAgICAgIGRvYyA9IGNoYW5nZS5kb2M7XG5cbiAgICAgICAgICAgIGlmICghZG9jLl9kZWxldGVkKSB7XG4gICAgICAgICAgICAgIHRyeUNvZGUkMSh2aWV3LnNvdXJjZURCLCBtYXBGdW4sIFtkb2NdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1hcFJlc3VsdHMuc29ydChzb3J0QnlLZXlUaGVuVmFsdWUpO1xuXG4gICAgICAgICAgICB2YXIgaW5kZXhhYmxlS2V5c1RvS2V5VmFsdWVzID0ge307XG4gICAgICAgICAgICB2YXIgbGFzdEtleTtcbiAgICAgICAgICAgIGZvciAodmFyIGogPSAwLCBqbCA9IG1hcFJlc3VsdHMubGVuZ3RoOyBqIDwgamw7IGorKykge1xuICAgICAgICAgICAgICB2YXIgb2JqID0gbWFwUmVzdWx0c1tqXTtcbiAgICAgICAgICAgICAgdmFyIGNvbXBsZXhLZXkgPSBbb2JqLmtleSwgb2JqLmlkXTtcbiAgICAgICAgICAgICAgaWYgKGNvbGxhdGUob2JqLmtleSwgbGFzdEtleSkgPT09IDApIHtcbiAgICAgICAgICAgICAgICBjb21wbGV4S2V5LnB1c2goaik7IC8vIGR1cCBrZXkraWQsIHNvIG1ha2UgaXQgdW5pcXVlXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgdmFyIGluZGV4YWJsZUtleSA9IHRvSW5kZXhhYmxlU3RyaW5nKGNvbXBsZXhLZXkpO1xuICAgICAgICAgICAgICBpbmRleGFibGVLZXlzVG9LZXlWYWx1ZXNbaW5kZXhhYmxlS2V5XSA9IG9iajtcbiAgICAgICAgICAgICAgbGFzdEtleSA9IG9iai5rZXk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkb2NJZHNUb0NoYW5nZXNBbmRFbWl0c1tjaGFuZ2UuZG9jLl9pZF0gPSB7XG4gICAgICAgICAgICAgIGluZGV4YWJsZUtleXNUb0tleVZhbHVlczogaW5kZXhhYmxlS2V5c1RvS2V5VmFsdWVzLFxuICAgICAgICAgICAgICBjaGFuZ2VzOiBjaGFuZ2UuY2hhbmdlc1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgICAgY3VycmVudFNlcSA9IGNoYW5nZS5zZXE7XG4gICAgICAgIH1cbiAgICAgICAgcXVldWUuYWRkKHByb2Nlc3NDaGFuZ2UoZG9jSWRzVG9DaGFuZ2VzQW5kRW1pdHMsIGN1cnJlbnRTZXEpKTtcbiAgICAgICAgaWYgKHJlc3VsdHMubGVuZ3RoIDwgQ0hBTkdFU19CQVRDSF9TSVpFJDEpIHtcbiAgICAgICAgICByZXR1cm4gY29tcGxldGUoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcHJvY2Vzc05leHRCYXRjaCgpO1xuICAgICAgfSkub24oJ2Vycm9yJywgb25FcnJvcik7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgZnVuY3Rpb24gb25FcnJvcihlcnIpIHtcbiAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcHJvY2Vzc05leHRCYXRjaCgpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gcmVkdWNlVmlldyh2aWV3LCByZXN1bHRzLCBvcHRpb25zKSB7XG4gIGlmIChvcHRpb25zLmdyb3VwX2xldmVsID09PSAwKSB7XG4gICAgZGVsZXRlIG9wdGlvbnMuZ3JvdXBfbGV2ZWw7XG4gIH1cblxuICB2YXIgc2hvdWxkR3JvdXAgPSBvcHRpb25zLmdyb3VwIHx8IG9wdGlvbnMuZ3JvdXBfbGV2ZWw7XG5cbiAgdmFyIHJlZHVjZUZ1bjtcbiAgaWYgKGJ1aWx0SW5SZWR1Y2Vbdmlldy5yZWR1Y2VGdW5dKSB7XG4gICAgcmVkdWNlRnVuID0gYnVpbHRJblJlZHVjZVt2aWV3LnJlZHVjZUZ1bl07XG4gIH0gZWxzZSB7XG4gICAgcmVkdWNlRnVuID0gZXZhbEZ1bmN0aW9uV2l0aEV2YWwodmlldy5yZWR1Y2VGdW4udG9TdHJpbmcoKSk7XG4gIH1cblxuICB2YXIgZ3JvdXBzID0gW107XG4gIHZhciBsdmwgPSBpc05hTihvcHRpb25zLmdyb3VwX2xldmVsKSA/IE51bWJlci5QT1NJVElWRV9JTkZJTklUWSA6XG4gICAgb3B0aW9ucy5ncm91cF9sZXZlbDtcbiAgcmVzdWx0cy5mb3JFYWNoKGZ1bmN0aW9uIChlKSB7XG4gICAgdmFyIGxhc3QgPSBncm91cHNbZ3JvdXBzLmxlbmd0aCAtIDFdO1xuICAgIHZhciBncm91cEtleSA9IHNob3VsZEdyb3VwID8gZS5rZXkgOiBudWxsO1xuXG4gICAgLy8gb25seSBzZXQgZ3JvdXBfbGV2ZWwgZm9yIGFycmF5IGtleXNcbiAgICBpZiAoc2hvdWxkR3JvdXAgJiYgQXJyYXkuaXNBcnJheShncm91cEtleSkpIHtcbiAgICAgIGdyb3VwS2V5ID0gZ3JvdXBLZXkuc2xpY2UoMCwgbHZsKTtcbiAgICB9XG5cbiAgICBpZiAobGFzdCAmJiBjb2xsYXRlKGxhc3QuZ3JvdXBLZXksIGdyb3VwS2V5KSA9PT0gMCkge1xuICAgICAgbGFzdC5rZXlzLnB1c2goW2Uua2V5LCBlLmlkXSk7XG4gICAgICBsYXN0LnZhbHVlcy5wdXNoKGUudmFsdWUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBncm91cHMucHVzaCh7XG4gICAgICBrZXlzOiBbW2Uua2V5LCBlLmlkXV0sXG4gICAgICB2YWx1ZXM6IFtlLnZhbHVlXSxcbiAgICAgIGdyb3VwS2V5OiBncm91cEtleVxuICAgIH0pO1xuICB9KTtcbiAgcmVzdWx0cyA9IFtdO1xuICBmb3IgKHZhciBpID0gMCwgbGVuID0gZ3JvdXBzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgdmFyIGUgPSBncm91cHNbaV07XG4gICAgdmFyIHJlZHVjZVRyeSA9IHRyeUNvZGUkMSh2aWV3LnNvdXJjZURCLCByZWR1Y2VGdW4sXG4gICAgICBbZS5rZXlzLCBlLnZhbHVlcywgZmFsc2VdKTtcbiAgICBpZiAocmVkdWNlVHJ5LmVycm9yICYmIHJlZHVjZVRyeS5lcnJvciBpbnN0YW5jZW9mIEJ1aWx0SW5FcnJvcikge1xuICAgICAgLy8gQ291Y2hEQiByZXR1cm5zIGFuIGVycm9yIGlmIGEgYnVpbHQtaW4gZXJyb3JzIG91dFxuICAgICAgdGhyb3cgcmVkdWNlVHJ5LmVycm9yO1xuICAgIH1cbiAgICByZXN1bHRzLnB1c2goe1xuICAgICAgLy8gQ291Y2hEQiBqdXN0IHNldHMgdGhlIHZhbHVlIHRvIG51bGwgaWYgYSBub24tYnVpbHQtaW4gZXJyb3JzIG91dFxuICAgICAgdmFsdWU6IHJlZHVjZVRyeS5lcnJvciA/IG51bGwgOiByZWR1Y2VUcnkub3V0cHV0LFxuICAgICAga2V5OiBlLmdyb3VwS2V5XG4gICAgfSk7XG4gIH1cbiAgLy8gbm8gdG90YWxfcm93cy9vZmZzZXQgd2hlbiByZWR1Y2luZ1xuICByZXR1cm4ge3Jvd3M6IHNsaWNlUmVzdWx0cyhyZXN1bHRzLCBvcHRpb25zLmxpbWl0LCBvcHRpb25zLnNraXApfTtcbn1cblxuZnVuY3Rpb24gcXVlcnlWaWV3KHZpZXcsIG9wdHMpIHtcbiAgcmV0dXJuIHNlcXVlbnRpYWxpemUoZ2V0UXVldWUodmlldyksIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gcXVlcnlWaWV3SW5RdWV1ZSh2aWV3LCBvcHRzKTtcbiAgfSkoKTtcbn1cblxuZnVuY3Rpb24gcXVlcnlWaWV3SW5RdWV1ZSh2aWV3LCBvcHRzKSB7XG4gIHZhciB0b3RhbFJvd3M7XG4gIHZhciBzaG91bGRSZWR1Y2UgPSB2aWV3LnJlZHVjZUZ1biAmJiBvcHRzLnJlZHVjZSAhPT0gZmFsc2U7XG4gIHZhciBza2lwID0gb3B0cy5za2lwIHx8IDA7XG4gIGlmICh0eXBlb2Ygb3B0cy5rZXlzICE9PSAndW5kZWZpbmVkJyAmJiAhb3B0cy5rZXlzLmxlbmd0aCkge1xuICAgIC8vIGVxdWl2YWxlbnQgcXVlcnlcbiAgICBvcHRzLmxpbWl0ID0gMDtcbiAgICBkZWxldGUgb3B0cy5rZXlzO1xuICB9XG5cbiAgZnVuY3Rpb24gZmV0Y2hGcm9tVmlldyh2aWV3T3B0cykge1xuICAgIHZpZXdPcHRzLmluY2x1ZGVfZG9jcyA9IHRydWU7XG4gICAgcmV0dXJuIHZpZXcuZGIuYWxsRG9jcyh2aWV3T3B0cykudGhlbihmdW5jdGlvbiAocmVzKSB7XG4gICAgICB0b3RhbFJvd3MgPSByZXMudG90YWxfcm93cztcbiAgICAgIHJldHVybiByZXMucm93cy5tYXAoZnVuY3Rpb24gKHJlc3VsdCkge1xuXG4gICAgICAgIC8vIGltcGxpY2l0IG1pZ3JhdGlvbiAtIGluIG9sZGVyIHZlcnNpb25zIG9mIFBvdWNoREIsXG4gICAgICAgIC8vIHdlIGV4cGxpY2l0bHkgc3RvcmVkIHRoZSBkb2MgYXMge2lkOiAuLi4sIGtleTogLi4uLCB2YWx1ZTogLi4ufVxuICAgICAgICAvLyB0aGlzIGlzIHRlc3RlZCBpbiBhIG1pZ3JhdGlvbiB0ZXN0XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICAgIGlmICgndmFsdWUnIGluIHJlc3VsdC5kb2MgJiYgdHlwZW9mIHJlc3VsdC5kb2MudmFsdWUgPT09ICdvYmplY3QnICYmXG4gICAgICAgICAgICByZXN1bHQuZG9jLnZhbHVlICE9PSBudWxsKSB7XG4gICAgICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhyZXN1bHQuZG9jLnZhbHVlKS5zb3J0KCk7XG4gICAgICAgICAgLy8gdGhpcyBkZXRlY3Rpb24gbWV0aG9kIGlzIG5vdCBwZXJmZWN0LCBidXQgaXQncyB1bmxpa2VseSB0aGUgdXNlclxuICAgICAgICAgIC8vIGVtaXR0ZWQgYSB2YWx1ZSB3aGljaCB3YXMgYW4gb2JqZWN0IHdpdGggdGhlc2UgMyBleGFjdCBrZXlzXG4gICAgICAgICAgdmFyIGV4cGVjdGVkS2V5cyA9IFsnaWQnLCAna2V5JywgJ3ZhbHVlJ107XG4gICAgICAgICAgaWYgKCEoa2V5cyA8IGV4cGVjdGVkS2V5cyB8fCBrZXlzID4gZXhwZWN0ZWRLZXlzKSkge1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC5kb2MudmFsdWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHBhcnNlZEtleUFuZERvY0lkID0gcGFyc2VJbmRleGFibGVTdHJpbmcocmVzdWx0LmRvYy5faWQpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGtleTogcGFyc2VkS2V5QW5kRG9jSWRbMF0sXG4gICAgICAgICAgaWQ6IHBhcnNlZEtleUFuZERvY0lkWzFdLFxuICAgICAgICAgIHZhbHVlOiAoJ3ZhbHVlJyBpbiByZXN1bHQuZG9jID8gcmVzdWx0LmRvYy52YWx1ZSA6IG51bGwpXG4gICAgICAgIH07XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIG9uTWFwUmVzdWx0c1JlYWR5KHJvd3MpIHtcbiAgICB2YXIgZmluYWxSZXN1bHRzO1xuICAgIGlmIChzaG91bGRSZWR1Y2UpIHtcbiAgICAgIGZpbmFsUmVzdWx0cyA9IHJlZHVjZVZpZXcodmlldywgcm93cywgb3B0cyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGZpbmFsUmVzdWx0cyA9IHtcbiAgICAgICAgdG90YWxfcm93czogdG90YWxSb3dzLFxuICAgICAgICBvZmZzZXQ6IHNraXAsXG4gICAgICAgIHJvd3M6IHJvd3NcbiAgICAgIH07XG4gICAgfVxuICAgIGlmIChvcHRzLmluY2x1ZGVfZG9jcykge1xuICAgICAgdmFyIGRvY0lkcyA9IHVuaXEocm93cy5tYXAocm93VG9Eb2NJZCkpO1xuXG4gICAgICByZXR1cm4gdmlldy5zb3VyY2VEQi5hbGxEb2NzKHtcbiAgICAgICAga2V5czogZG9jSWRzLFxuICAgICAgICBpbmNsdWRlX2RvY3M6IHRydWUsXG4gICAgICAgIGNvbmZsaWN0czogb3B0cy5jb25mbGljdHMsXG4gICAgICAgIGF0dGFjaG1lbnRzOiBvcHRzLmF0dGFjaG1lbnRzLFxuICAgICAgICBiaW5hcnk6IG9wdHMuYmluYXJ5XG4gICAgICB9KS50aGVuKGZ1bmN0aW9uIChhbGxEb2NzUmVzKSB7XG4gICAgICAgIHZhciBkb2NJZHNUb0RvY3MgPSB7fTtcbiAgICAgICAgYWxsRG9jc1Jlcy5yb3dzLmZvckVhY2goZnVuY3Rpb24gKHJvdykge1xuICAgICAgICAgIGlmIChyb3cuZG9jKSB7XG4gICAgICAgICAgICBkb2NJZHNUb0RvY3NbJyQnICsgcm93LmlkXSA9IHJvdy5kb2M7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcm93cy5mb3JFYWNoKGZ1bmN0aW9uIChyb3cpIHtcbiAgICAgICAgICB2YXIgZG9jSWQgPSByb3dUb0RvY0lkKHJvdyk7XG4gICAgICAgICAgdmFyIGRvYyA9IGRvY0lkc1RvRG9jc1snJCcgKyBkb2NJZF07XG4gICAgICAgICAgaWYgKGRvYykge1xuICAgICAgICAgICAgcm93LmRvYyA9IGRvYztcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gZmluYWxSZXN1bHRzO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBmaW5hbFJlc3VsdHM7XG4gICAgfVxuICB9XG5cbiAgaWYgKHR5cGVvZiBvcHRzLmtleXMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgdmFyIGtleXMgPSBvcHRzLmtleXM7XG4gICAgdmFyIGZldGNoUHJvbWlzZXMgPSBrZXlzLm1hcChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICB2YXIgdmlld09wdHMgPSB7XG4gICAgICAgIHN0YXJ0a2V5IDogdG9JbmRleGFibGVTdHJpbmcoW2tleV0pLFxuICAgICAgICBlbmRrZXkgICA6IHRvSW5kZXhhYmxlU3RyaW5nKFtrZXksIHt9XSlcbiAgICAgIH07XG4gICAgICByZXR1cm4gZmV0Y2hGcm9tVmlldyh2aWV3T3B0cyk7XG4gICAgfSk7XG4gICAgcmV0dXJuIFBvdWNoUHJvbWlzZS5hbGwoZmV0Y2hQcm9taXNlcykudGhlbihmbGF0dGVuKS50aGVuKG9uTWFwUmVzdWx0c1JlYWR5KTtcbiAgfSBlbHNlIHsgLy8gbm9ybWFsIHF1ZXJ5LCBubyAna2V5cydcbiAgICB2YXIgdmlld09wdHMgPSB7XG4gICAgICBkZXNjZW5kaW5nIDogb3B0cy5kZXNjZW5kaW5nXG4gICAgfTtcbiAgICBpZiAob3B0cy5zdGFydF9rZXkpIHtcbiAgICAgICAgb3B0cy5zdGFydGtleSA9IG9wdHMuc3RhcnRfa2V5O1xuICAgIH1cbiAgICBpZiAob3B0cy5lbmRfa2V5KSB7XG4gICAgICAgIG9wdHMuZW5ka2V5ID0gb3B0cy5lbmRfa2V5O1xuICAgIH1cbiAgICBpZiAodHlwZW9mIG9wdHMuc3RhcnRrZXkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB2aWV3T3B0cy5zdGFydGtleSA9IG9wdHMuZGVzY2VuZGluZyA/XG4gICAgICAgIHRvSW5kZXhhYmxlU3RyaW5nKFtvcHRzLnN0YXJ0a2V5LCB7fV0pIDpcbiAgICAgICAgdG9JbmRleGFibGVTdHJpbmcoW29wdHMuc3RhcnRrZXldKTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBvcHRzLmVuZGtleSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHZhciBpbmNsdXNpdmVFbmQgPSBvcHRzLmluY2x1c2l2ZV9lbmQgIT09IGZhbHNlO1xuICAgICAgaWYgKG9wdHMuZGVzY2VuZGluZykge1xuICAgICAgICBpbmNsdXNpdmVFbmQgPSAhaW5jbHVzaXZlRW5kO1xuICAgICAgfVxuXG4gICAgICB2aWV3T3B0cy5lbmRrZXkgPSB0b0luZGV4YWJsZVN0cmluZyhcbiAgICAgICAgaW5jbHVzaXZlRW5kID8gW29wdHMuZW5ka2V5LCB7fV0gOiBbb3B0cy5lbmRrZXldKTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBvcHRzLmtleSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHZhciBrZXlTdGFydCA9IHRvSW5kZXhhYmxlU3RyaW5nKFtvcHRzLmtleV0pO1xuICAgICAgdmFyIGtleUVuZCA9IHRvSW5kZXhhYmxlU3RyaW5nKFtvcHRzLmtleSwge31dKTtcbiAgICAgIGlmICh2aWV3T3B0cy5kZXNjZW5kaW5nKSB7XG4gICAgICAgIHZpZXdPcHRzLmVuZGtleSA9IGtleVN0YXJ0O1xuICAgICAgICB2aWV3T3B0cy5zdGFydGtleSA9IGtleUVuZDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZpZXdPcHRzLnN0YXJ0a2V5ID0ga2V5U3RhcnQ7XG4gICAgICAgIHZpZXdPcHRzLmVuZGtleSA9IGtleUVuZDtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFzaG91bGRSZWR1Y2UpIHtcbiAgICAgIGlmICh0eXBlb2Ygb3B0cy5saW1pdCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgdmlld09wdHMubGltaXQgPSBvcHRzLmxpbWl0O1xuICAgICAgfVxuICAgICAgdmlld09wdHMuc2tpcCA9IHNraXA7XG4gICAgfVxuICAgIHJldHVybiBmZXRjaEZyb21WaWV3KHZpZXdPcHRzKS50aGVuKG9uTWFwUmVzdWx0c1JlYWR5KTtcbiAgfVxufVxuXG5mdW5jdGlvbiBodHRwVmlld0NsZWFudXAoZGIpIHtcbiAgcmV0dXJuIGRiLnJlcXVlc3Qoe1xuICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgIHVybDogJ192aWV3X2NsZWFudXAnXG4gIH0pO1xufVxuXG5mdW5jdGlvbiBsb2NhbFZpZXdDbGVhbnVwKGRiKSB7XG4gIHJldHVybiBkYi5nZXQoJ19sb2NhbC9tcnZpZXdzJykudGhlbihmdW5jdGlvbiAobWV0YURvYykge1xuICAgIHZhciBkb2NzVG9WaWV3cyA9IHt9O1xuICAgIE9iamVjdC5rZXlzKG1ldGFEb2Mudmlld3MpLmZvckVhY2goZnVuY3Rpb24gKGZ1bGxWaWV3TmFtZSkge1xuICAgICAgdmFyIHBhcnRzID0gcGFyc2VWaWV3TmFtZShmdWxsVmlld05hbWUpO1xuICAgICAgdmFyIGRlc2lnbkRvY05hbWUgPSAnX2Rlc2lnbi8nICsgcGFydHNbMF07XG4gICAgICB2YXIgdmlld05hbWUgPSBwYXJ0c1sxXTtcbiAgICAgIGRvY3NUb1ZpZXdzW2Rlc2lnbkRvY05hbWVdID0gZG9jc1RvVmlld3NbZGVzaWduRG9jTmFtZV0gfHwge307XG4gICAgICBkb2NzVG9WaWV3c1tkZXNpZ25Eb2NOYW1lXVt2aWV3TmFtZV0gPSB0cnVlO1xuICAgIH0pO1xuICAgIHZhciBvcHRzID0ge1xuICAgICAga2V5cyA6IE9iamVjdC5rZXlzKGRvY3NUb1ZpZXdzKSxcbiAgICAgIGluY2x1ZGVfZG9jcyA6IHRydWVcbiAgICB9O1xuICAgIHJldHVybiBkYi5hbGxEb2NzKG9wdHMpLnRoZW4oZnVuY3Rpb24gKHJlcykge1xuICAgICAgdmFyIHZpZXdzVG9TdGF0dXMgPSB7fTtcbiAgICAgIHJlcy5yb3dzLmZvckVhY2goZnVuY3Rpb24gKHJvdykge1xuICAgICAgICB2YXIgZGRvY05hbWUgPSByb3cua2V5LnN1YnN0cmluZyg4KTtcbiAgICAgICAgT2JqZWN0LmtleXMoZG9jc1RvVmlld3Nbcm93LmtleV0pLmZvckVhY2goZnVuY3Rpb24gKHZpZXdOYW1lKSB7XG4gICAgICAgICAgdmFyIGZ1bGxWaWV3TmFtZSA9IGRkb2NOYW1lICsgJy8nICsgdmlld05hbWU7XG4gICAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgICAgICAgaWYgKCFtZXRhRG9jLnZpZXdzW2Z1bGxWaWV3TmFtZV0pIHtcbiAgICAgICAgICAgIC8vIG5ldyBmb3JtYXQsIHdpdGhvdXQgc2xhc2hlcywgdG8gc3VwcG9ydCBQb3VjaERCIDIuMi4wXG4gICAgICAgICAgICAvLyBtaWdyYXRpb24gdGVzdCBpbiBwb3VjaGRiJ3MgYnJvd3Nlci5taWdyYXRpb24uanMgdmVyaWZpZXMgdGhpc1xuICAgICAgICAgICAgZnVsbFZpZXdOYW1lID0gdmlld05hbWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhciB2aWV3REJOYW1lcyA9IE9iamVjdC5rZXlzKG1ldGFEb2Mudmlld3NbZnVsbFZpZXdOYW1lXSk7XG4gICAgICAgICAgLy8gZGVzaWduIGRvYyBkZWxldGVkLCBvciB2aWV3IGZ1bmN0aW9uIG5vbmV4aXN0ZW50XG4gICAgICAgICAgdmFyIHN0YXR1c0lzR29vZCA9IHJvdy5kb2MgJiYgcm93LmRvYy52aWV3cyAmJlxuICAgICAgICAgICAgcm93LmRvYy52aWV3c1t2aWV3TmFtZV07XG4gICAgICAgICAgdmlld0RCTmFtZXMuZm9yRWFjaChmdW5jdGlvbiAodmlld0RCTmFtZSkge1xuICAgICAgICAgICAgdmlld3NUb1N0YXR1c1t2aWV3REJOYW1lXSA9XG4gICAgICAgICAgICAgIHZpZXdzVG9TdGF0dXNbdmlld0RCTmFtZV0gfHwgc3RhdHVzSXNHb29kO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgICAgdmFyIGRic1RvRGVsZXRlID0gT2JqZWN0LmtleXModmlld3NUb1N0YXR1cykuZmlsdGVyKFxuICAgICAgICBmdW5jdGlvbiAodmlld0RCTmFtZSkgeyByZXR1cm4gIXZpZXdzVG9TdGF0dXNbdmlld0RCTmFtZV07IH0pO1xuICAgICAgdmFyIGRlc3Ryb3lQcm9taXNlcyA9IGRic1RvRGVsZXRlLm1hcChmdW5jdGlvbiAodmlld0RCTmFtZSkge1xuICAgICAgICByZXR1cm4gc2VxdWVudGlhbGl6ZShnZXRRdWV1ZSh2aWV3REJOYW1lKSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHJldHVybiBuZXcgZGIuY29uc3RydWN0b3Iodmlld0RCTmFtZSwgZGIuX19vcHRzKS5kZXN0cm95KCk7XG4gICAgICAgIH0pKCk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiBQb3VjaFByb21pc2UuYWxsKGRlc3Ryb3lQcm9taXNlcykudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7b2s6IHRydWV9O1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH0sIGRlZmF1bHRzVG8oe29rOiB0cnVlfSkpO1xufVxuXG52YXIgdmlld0NsZWFudXAgPSBjYWxsYmFja2lmeShmdW5jdGlvbiAoKSB7XG4gIHZhciBkYiA9IHRoaXM7XG4gIGlmIChkYi50eXBlKCkgPT09ICdodHRwJykge1xuICAgIHJldHVybiBodHRwVmlld0NsZWFudXAoZGIpO1xuICB9XG4gIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gIGlmICh0eXBlb2YgZGIuX3ZpZXdDbGVhbnVwID09PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIGN1c3RvbVZpZXdDbGVhbnVwKGRiKTtcbiAgfVxuICByZXR1cm4gbG9jYWxWaWV3Q2xlYW51cChkYik7XG59KTtcblxuZnVuY3Rpb24gcXVlcnlQcm9taXNlZChkYiwgZnVuLCBvcHRzKSB7XG4gIGlmIChkYi50eXBlKCkgPT09ICdodHRwJykge1xuICAgIHJldHVybiBodHRwUXVlcnkoZGIsIGZ1biwgb3B0cyk7XG4gIH1cblxuICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICBpZiAodHlwZW9mIGRiLl9xdWVyeSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHJldHVybiBjdXN0b21RdWVyeShkYiwgZnVuLCBvcHRzKTtcbiAgfVxuXG4gIGlmICh0eXBlb2YgZnVuICE9PSAnc3RyaW5nJykge1xuICAgIC8vIHRlbXBfdmlld1xuICAgIGNoZWNrUXVlcnlQYXJzZUVycm9yKG9wdHMsIGZ1bik7XG5cbiAgICB2YXIgY3JlYXRlVmlld09wdHMgPSB7XG4gICAgICBkYiA6IGRiLFxuICAgICAgdmlld05hbWUgOiAndGVtcF92aWV3L3RlbXBfdmlldycsXG4gICAgICBtYXAgOiBmdW4ubWFwLFxuICAgICAgcmVkdWNlIDogZnVuLnJlZHVjZSxcbiAgICAgIHRlbXBvcmFyeSA6IHRydWVcbiAgICB9O1xuICAgIHRlbXBWaWV3UXVldWUuYWRkKGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBjcmVhdGVWaWV3KGNyZWF0ZVZpZXdPcHRzKS50aGVuKGZ1bmN0aW9uICh2aWV3KSB7XG4gICAgICAgIGZ1bmN0aW9uIGNsZWFudXAoKSB7XG4gICAgICAgICAgcmV0dXJuIHZpZXcuZGIuZGVzdHJveSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmaW4odXBkYXRlVmlldyh2aWV3KS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICByZXR1cm4gcXVlcnlWaWV3KHZpZXcsIG9wdHMpO1xuICAgICAgICB9KSwgY2xlYW51cCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gdGVtcFZpZXdRdWV1ZS5maW5pc2goKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBwZXJzaXN0ZW50IHZpZXdcbiAgICB2YXIgZnVsbFZpZXdOYW1lID0gZnVuO1xuICAgIHZhciBwYXJ0cyA9IHBhcnNlVmlld05hbWUoZnVsbFZpZXdOYW1lKTtcbiAgICB2YXIgZGVzaWduRG9jTmFtZSA9IHBhcnRzWzBdO1xuICAgIHZhciB2aWV3TmFtZSA9IHBhcnRzWzFdO1xuICAgIHJldHVybiBkYi5nZXQoJ19kZXNpZ24vJyArIGRlc2lnbkRvY05hbWUpLnRoZW4oZnVuY3Rpb24gKGRvYykge1xuICAgICAgdmFyIGZ1biA9IGRvYy52aWV3cyAmJiBkb2Mudmlld3Nbdmlld05hbWVdO1xuXG4gICAgICBpZiAoIWZ1biB8fCB0eXBlb2YgZnVuLm1hcCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhyb3cgbmV3IE5vdEZvdW5kRXJyb3IoJ2Rkb2MgJyArIGRlc2lnbkRvY05hbWUgK1xuICAgICAgICAnIGhhcyBubyB2aWV3IG5hbWVkICcgKyB2aWV3TmFtZSk7XG4gICAgICB9XG4gICAgICBjaGVja1F1ZXJ5UGFyc2VFcnJvcihvcHRzLCBmdW4pO1xuXG4gICAgICB2YXIgY3JlYXRlVmlld09wdHMgPSB7XG4gICAgICAgIGRiIDogZGIsXG4gICAgICAgIHZpZXdOYW1lIDogZnVsbFZpZXdOYW1lLFxuICAgICAgICBtYXAgOiBmdW4ubWFwLFxuICAgICAgICByZWR1Y2UgOiBmdW4ucmVkdWNlXG4gICAgICB9O1xuICAgICAgcmV0dXJuIGNyZWF0ZVZpZXcoY3JlYXRlVmlld09wdHMpLnRoZW4oZnVuY3Rpb24gKHZpZXcpIHtcbiAgICAgICAgaWYgKG9wdHMuc3RhbGUgPT09ICdvaycgfHwgb3B0cy5zdGFsZSA9PT0gJ3VwZGF0ZV9hZnRlcicpIHtcbiAgICAgICAgICBpZiAob3B0cy5zdGFsZSA9PT0gJ3VwZGF0ZV9hZnRlcicpIHtcbiAgICAgICAgICAgIGltbWVkaWF0ZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgIHVwZGF0ZVZpZXcodmlldyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHF1ZXJ5Vmlldyh2aWV3LCBvcHRzKTtcbiAgICAgICAgfSBlbHNlIHsgLy8gc3RhbGUgbm90IG9rXG4gICAgICAgICAgcmV0dXJuIHVwZGF0ZVZpZXcodmlldykudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gcXVlcnlWaWV3KHZpZXcsIG9wdHMpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxufVxuXG52YXIgcXVlcnkgPSBmdW5jdGlvbiAoZnVuLCBvcHRzLCBjYWxsYmFjaykge1xuICBpZiAodHlwZW9mIG9wdHMgPT09ICdmdW5jdGlvbicpIHtcbiAgICBjYWxsYmFjayA9IG9wdHM7XG4gICAgb3B0cyA9IHt9O1xuICB9XG4gIG9wdHMgPSBvcHRzID8gY29lcmNlT3B0aW9ucyhvcHRzKSA6IHt9O1xuXG4gIGlmICh0eXBlb2YgZnVuID09PSAnZnVuY3Rpb24nKSB7XG4gICAgZnVuID0ge21hcCA6IGZ1bn07XG4gIH1cblxuICB2YXIgZGIgPSB0aGlzO1xuICB2YXIgcHJvbWlzZSA9IFBvdWNoUHJvbWlzZS5yZXNvbHZlKCkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHF1ZXJ5UHJvbWlzZWQoZGIsIGZ1biwgb3B0cyk7XG4gIH0pO1xuICBwcm9taXNlZENhbGxiYWNrKHByb21pc2UsIGNhbGxiYWNrKTtcbiAgcmV0dXJuIHByb21pc2U7XG59O1xuXG5cbnZhciBtYXByZWR1Y2UgPSB7XG4gIHF1ZXJ5OiBxdWVyeSxcbiAgdmlld0NsZWFudXA6IHZpZXdDbGVhbnVwXG59O1xuXG5mdW5jdGlvbiBpc0dlbk9uZSQxKHJldikge1xuICByZXR1cm4gL14xLS8udGVzdChyZXYpO1xufVxuXG5mdW5jdGlvbiBmaWxlSGFzQ2hhbmdlZChsb2NhbERvYywgcmVtb3RlRG9jLCBmaWxlbmFtZSkge1xuICByZXR1cm4gIWxvY2FsRG9jLl9hdHRhY2htZW50cyB8fFxuICAgICAgICAgIWxvY2FsRG9jLl9hdHRhY2htZW50c1tmaWxlbmFtZV0gfHxcbiAgICAgICAgIGxvY2FsRG9jLl9hdHRhY2htZW50c1tmaWxlbmFtZV0uZGlnZXN0ICE9PSByZW1vdGVEb2MuX2F0dGFjaG1lbnRzW2ZpbGVuYW1lXS5kaWdlc3Q7XG59XG5cbmZ1bmN0aW9uIGdldERvY0F0dGFjaG1lbnRzKGRiLCBkb2MpIHtcbiAgdmFyIGZpbGVuYW1lcyA9IE9iamVjdC5rZXlzKGRvYy5fYXR0YWNobWVudHMpO1xuICByZXR1cm4gUG91Y2hQcm9taXNlLmFsbChmaWxlbmFtZXMubWFwKGZ1bmN0aW9uIChmaWxlbmFtZSkge1xuICAgIHJldHVybiBkYi5nZXRBdHRhY2htZW50KGRvYy5faWQsIGZpbGVuYW1lLCB7cmV2OiBkb2MuX3Jldn0pO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGdldERvY0F0dGFjaG1lbnRzRnJvbVRhcmdldE9yU291cmNlKHRhcmdldCwgc3JjLCBkb2MpIHtcbiAgdmFyIGRvQ2hlY2tGb3JMb2NhbEF0dGFjaG1lbnRzID0gc3JjLnR5cGUoKSA9PT0gJ2h0dHAnICYmIHRhcmdldC50eXBlKCkgIT09ICdodHRwJztcbiAgdmFyIGZpbGVuYW1lcyA9IE9iamVjdC5rZXlzKGRvYy5fYXR0YWNobWVudHMpO1xuXG4gIGlmICghZG9DaGVja0ZvckxvY2FsQXR0YWNobWVudHMpIHtcbiAgICByZXR1cm4gZ2V0RG9jQXR0YWNobWVudHMoc3JjLCBkb2MpO1xuICB9XG5cbiAgcmV0dXJuIHRhcmdldC5nZXQoZG9jLl9pZCkudGhlbihmdW5jdGlvbiAobG9jYWxEb2MpIHtcbiAgICByZXR1cm4gUG91Y2hQcm9taXNlLmFsbChmaWxlbmFtZXMubWFwKGZ1bmN0aW9uIChmaWxlbmFtZSkge1xuICAgICAgaWYgKGZpbGVIYXNDaGFuZ2VkKGxvY2FsRG9jLCBkb2MsIGZpbGVuYW1lKSkge1xuICAgICAgICByZXR1cm4gc3JjLmdldEF0dGFjaG1lbnQoZG9jLl9pZCwgZmlsZW5hbWUpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGFyZ2V0LmdldEF0dGFjaG1lbnQobG9jYWxEb2MuX2lkLCBmaWxlbmFtZSk7XG4gICAgfSkpO1xuICB9KS5jYXRjaChmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICBpZiAoZXJyb3Iuc3RhdHVzICE9PSA0MDQpIHtcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cblxuICAgIHJldHVybiBnZXREb2NBdHRhY2htZW50cyhzcmMsIGRvYyk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVCdWxrR2V0T3B0cyhkaWZmcykge1xuICB2YXIgcmVxdWVzdHMgPSBbXTtcbiAgT2JqZWN0LmtleXMoZGlmZnMpLmZvckVhY2goZnVuY3Rpb24gKGlkKSB7XG4gICAgdmFyIG1pc3NpbmdSZXZzID0gZGlmZnNbaWRdLm1pc3Npbmc7XG4gICAgbWlzc2luZ1JldnMuZm9yRWFjaChmdW5jdGlvbiAobWlzc2luZ1Jldikge1xuICAgICAgcmVxdWVzdHMucHVzaCh7XG4gICAgICAgIGlkOiBpZCxcbiAgICAgICAgcmV2OiBtaXNzaW5nUmV2XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgcmV0dXJuIHtcbiAgICBkb2NzOiByZXF1ZXN0cyxcbiAgICByZXZzOiB0cnVlLFxuICAgIGxhdGVzdDogdHJ1ZVxuICB9O1xufVxuXG4vL1xuLy8gRmV0Y2ggYWxsIHRoZSBkb2N1bWVudHMgZnJvbSB0aGUgc3JjIGFzIGRlc2NyaWJlZCBpbiB0aGUgXCJkaWZmc1wiLFxuLy8gd2hpY2ggaXMgYSBtYXBwaW5nIG9mIGRvY3MgSURzIHRvIHJldmlzaW9ucy4gSWYgdGhlIHN0YXRlIGV2ZXJcbi8vIGNoYW5nZXMgdG8gXCJjYW5jZWxsZWRcIiwgdGhlbiB0aGUgcmV0dXJuZWQgcHJvbWlzZSB3aWxsIGJlIHJlamVjdGVkLlxuLy8gRWxzZSBpdCB3aWxsIGJlIHJlc29sdmVkIHdpdGggYSBsaXN0IG9mIGZldGNoZWQgZG9jdW1lbnRzLlxuLy9cbmZ1bmN0aW9uIGdldERvY3Moc3JjLCB0YXJnZXQsIGRpZmZzLCBzdGF0ZSkge1xuICBkaWZmcyA9IGNsb25lKGRpZmZzKTsgLy8gd2UgZG8gbm90IG5lZWQgdG8gbW9kaWZ5IHRoaXNcblxuICB2YXIgcmVzdWx0RG9jcyA9IFtdLFxuICAgICAgb2sgPSB0cnVlO1xuXG4gIGZ1bmN0aW9uIGdldEFsbERvY3MoKSB7XG5cbiAgICB2YXIgYnVsa0dldE9wdHMgPSBjcmVhdGVCdWxrR2V0T3B0cyhkaWZmcyk7XG5cbiAgICBpZiAoIWJ1bGtHZXRPcHRzLmRvY3MubGVuZ3RoKSB7IC8vIG9wdGltaXphdGlvbjogc2tpcCBlbXB0eSByZXF1ZXN0c1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHJldHVybiBzcmMuYnVsa0dldChidWxrR2V0T3B0cykudGhlbihmdW5jdGlvbiAoYnVsa0dldFJlc3BvbnNlKSB7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICAgIGlmIChzdGF0ZS5jYW5jZWxsZWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5jZWxsZWQnKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBQb3VjaFByb21pc2UuYWxsKGJ1bGtHZXRSZXNwb25zZS5yZXN1bHRzLm1hcChmdW5jdGlvbiAoYnVsa0dldEluZm8pIHtcbiAgICAgICAgcmV0dXJuIFBvdWNoUHJvbWlzZS5hbGwoYnVsa0dldEluZm8uZG9jcy5tYXAoZnVuY3Rpb24gKGRvYykge1xuICAgICAgICAgIHZhciByZW1vdGVEb2MgPSBkb2Mub2s7XG5cbiAgICAgICAgICBpZiAoZG9jLmVycm9yKSB7XG4gICAgICAgICAgICAvLyB3aGVuIEFVVE9fQ09NUEFDVElPTiBpcyBzZXQsIGRvY3MgY2FuIGJlIHJldHVybmVkIHdoaWNoIGxvb2tcbiAgICAgICAgICAgIC8vIGxpa2UgdGhpczoge1wibWlzc2luZ1wiOlwiMS03YzNhYzI1NmI2OTNjNDYyYWY4NDQyZjk5MmI4MzY5NlwifVxuICAgICAgICAgICAgb2sgPSBmYWxzZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoIXJlbW90ZURvYyB8fCAhcmVtb3RlRG9jLl9hdHRhY2htZW50cykge1xuICAgICAgICAgICAgcmV0dXJuIHJlbW90ZURvYztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gZ2V0RG9jQXR0YWNobWVudHNGcm9tVGFyZ2V0T3JTb3VyY2UodGFyZ2V0LCBzcmMsIHJlbW90ZURvYykudGhlbihmdW5jdGlvbiAoYXR0YWNobWVudHMpIHtcbiAgICAgICAgICAgIHZhciBmaWxlbmFtZXMgPSBPYmplY3Qua2V5cyhyZW1vdGVEb2MuX2F0dGFjaG1lbnRzKTtcbiAgICAgICAgICAgIGF0dGFjaG1lbnRzLmZvckVhY2goZnVuY3Rpb24gKGF0dGFjaG1lbnQsIGkpIHtcbiAgICAgICAgICAgICAgdmFyIGF0dCA9IHJlbW90ZURvYy5fYXR0YWNobWVudHNbZmlsZW5hbWVzW2ldXTtcbiAgICAgICAgICAgICAgZGVsZXRlIGF0dC5zdHViO1xuICAgICAgICAgICAgICBkZWxldGUgYXR0Lmxlbmd0aDtcbiAgICAgICAgICAgICAgYXR0LmRhdGEgPSBhdHRhY2htZW50O1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHJldHVybiByZW1vdGVEb2M7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pKTtcbiAgICAgIH0pKVxuXG4gICAgICAudGhlbihmdW5jdGlvbiAocmVzdWx0cykge1xuICAgICAgICByZXN1bHREb2NzID0gcmVzdWx0RG9jcy5jb25jYXQoZmxhdHRlbihyZXN1bHRzKS5maWx0ZXIoQm9vbGVhbikpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBoYXNBdHRhY2htZW50cyhkb2MpIHtcbiAgICByZXR1cm4gZG9jLl9hdHRhY2htZW50cyAmJiBPYmplY3Qua2V5cyhkb2MuX2F0dGFjaG1lbnRzKS5sZW5ndGggPiAwO1xuICB9XG5cbiAgZnVuY3Rpb24gaGFzQ29uZmxpY3RzKGRvYykge1xuICAgIHJldHVybiBkb2MuX2NvbmZsaWN0cyAmJiBkb2MuX2NvbmZsaWN0cy5sZW5ndGggPiAwO1xuICB9XG5cbiAgZnVuY3Rpb24gZmV0Y2hSZXZpc2lvbk9uZURvY3MoaWRzKSB7XG4gICAgLy8gT3B0aW1pemF0aW9uOiBmZXRjaCBnZW4tMSBkb2NzIGFuZCBhdHRhY2htZW50cyBpblxuICAgIC8vIGEgc2luZ2xlIHJlcXVlc3QgdXNpbmcgX2FsbF9kb2NzXG4gICAgcmV0dXJuIHNyYy5hbGxEb2NzKHtcbiAgICAgIGtleXM6IGlkcyxcbiAgICAgIGluY2x1ZGVfZG9jczogdHJ1ZSxcbiAgICAgIGNvbmZsaWN0czogdHJ1ZVxuICAgIH0pLnRoZW4oZnVuY3Rpb24gKHJlcykge1xuICAgICAgaWYgKHN0YXRlLmNhbmNlbGxlZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2NhbmNlbGxlZCcpO1xuICAgICAgfVxuICAgICAgcmVzLnJvd3MuZm9yRWFjaChmdW5jdGlvbiAocm93KSB7XG4gICAgICAgIGlmIChyb3cuZGVsZXRlZCB8fCAhcm93LmRvYyB8fCAhaXNHZW5PbmUkMShyb3cudmFsdWUucmV2KSB8fFxuICAgICAgICAgICAgaGFzQXR0YWNobWVudHMocm93LmRvYykgfHwgaGFzQ29uZmxpY3RzKHJvdy5kb2MpKSB7XG4gICAgICAgICAgLy8gaWYgYW55IG9mIHRoZXNlIGNvbmRpdGlvbnMgYXBwbHksIHdlIG5lZWQgdG8gZmV0Y2ggdXNpbmcgZ2V0KClcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzdHJpcCBfY29uZmxpY3RzIGFycmF5IHRvIGFwcGVhc2UgQ1NHICgjNTc5MylcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgICAgIGlmIChyb3cuZG9jLl9jb25mbGljdHMpIHtcbiAgICAgICAgICBkZWxldGUgcm93LmRvYy5fY29uZmxpY3RzO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdGhlIGRvYyB3ZSBnb3QgYmFjayBmcm9tIGFsbERvY3MoKSBpcyBzdWZmaWNpZW50XG4gICAgICAgIHJlc3VsdERvY3MucHVzaChyb3cuZG9jKTtcbiAgICAgICAgZGVsZXRlIGRpZmZzW3Jvdy5pZF07XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldFJldmlzaW9uT25lRG9jcygpIHtcbiAgICAvLyBmaWx0ZXIgb3V0IHRoZSBnZW5lcmF0aW9uIDEgZG9jcyBhbmQgZ2V0IHRoZW1cbiAgICAvLyBsZWF2aW5nIHRoZSBub24tZ2VuZXJhdGlvbiBvbmUgZG9jcyB0byBiZSBnb3Qgb3RoZXJ3aXNlXG4gICAgdmFyIGlkcyA9IE9iamVjdC5rZXlzKGRpZmZzKS5maWx0ZXIoZnVuY3Rpb24gKGlkKSB7XG4gICAgICB2YXIgbWlzc2luZyA9IGRpZmZzW2lkXS5taXNzaW5nO1xuICAgICAgcmV0dXJuIG1pc3NpbmcubGVuZ3RoID09PSAxICYmIGlzR2VuT25lJDEobWlzc2luZ1swXSk7XG4gICAgfSk7XG4gICAgaWYgKGlkcy5sZW5ndGggPiAwKSB7XG4gICAgICByZXR1cm4gZmV0Y2hSZXZpc2lvbk9uZURvY3MoaWRzKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiByZXR1cm5SZXN1bHQoKSB7XG4gICAgcmV0dXJuIHsgb2s6b2ssIGRvY3M6cmVzdWx0RG9jcyB9O1xuICB9XG5cbiAgcmV0dXJuIFBvdWNoUHJvbWlzZS5yZXNvbHZlKClcbiAgICAudGhlbihnZXRSZXZpc2lvbk9uZURvY3MpXG4gICAgLnRoZW4oZ2V0QWxsRG9jcylcbiAgICAudGhlbihyZXR1cm5SZXN1bHQpO1xufVxuXG52YXIgQ0hFQ0tQT0lOVF9WRVJTSU9OID0gMTtcbnZhciBSRVBMSUNBVE9SID0gXCJwb3VjaGRiXCI7XG4vLyBUaGlzIGlzIGFuIGFyYml0cmFyeSBudW1iZXIgdG8gbGltaXQgdGhlXG4vLyBhbW91bnQgb2YgcmVwbGljYXRpb24gaGlzdG9yeSB3ZSBzYXZlIGluIHRoZSBjaGVja3BvaW50LlxuLy8gSWYgd2Ugc2F2ZSB0b28gbXVjaCwgdGhlIGNoZWNrcG9pbmcgZG9jcyB3aWxsIGJlY29tZSB2ZXJ5IGJpZyxcbi8vIGlmIHdlIHNhdmUgZmV3ZXIsIHdlJ2xsIHJ1biBhIGdyZWF0ZXIgcmlzayBvZiBoYXZpbmcgdG9cbi8vIHJlYWQgYWxsIHRoZSBjaGFuZ2VzIGZyb20gMCB3aGVuIGNoZWNrcG9pbnQgUFVUcyBmYWlsXG4vLyBDb3VjaERCIDIuMCBoYXMgYSBtb3JlIGludm9sdmVkIGhpc3RvcnkgcHJ1bmluZyxcbi8vIGJ1dCBsZXQncyBnbyBmb3IgdGhlIHNpbXBsZSB2ZXJzaW9uIGZvciBub3cuXG52YXIgQ0hFQ0tQT0lOVF9ISVNUT1JZX1NJWkUgPSA1O1xudmFyIExPV0VTVF9TRVEgPSAwO1xuXG5mdW5jdGlvbiB1cGRhdGVDaGVja3BvaW50KGRiLCBpZCwgY2hlY2twb2ludCwgc2Vzc2lvbiwgcmV0dXJuVmFsdWUpIHtcbiAgcmV0dXJuIGRiLmdldChpZCkuY2F0Y2goZnVuY3Rpb24gKGVycikge1xuICAgIGlmIChlcnIuc3RhdHVzID09PSA0MDQpIHtcbiAgICAgIGlmIChkYi50eXBlKCkgPT09ICdodHRwJykge1xuICAgICAgICBleHBsYWluRXJyb3IoXG4gICAgICAgICAgNDA0LCAnUG91Y2hEQiBpcyBqdXN0IGNoZWNraW5nIGlmIGEgcmVtb3RlIGNoZWNrcG9pbnQgZXhpc3RzLidcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHNlc3Npb25faWQ6IHNlc3Npb24sXG4gICAgICAgIF9pZDogaWQsXG4gICAgICAgIGhpc3Rvcnk6IFtdLFxuICAgICAgICByZXBsaWNhdG9yOiBSRVBMSUNBVE9SLFxuICAgICAgICB2ZXJzaW9uOiBDSEVDS1BPSU5UX1ZFUlNJT05cbiAgICAgIH07XG4gICAgfVxuICAgIHRocm93IGVycjtcbiAgfSkudGhlbihmdW5jdGlvbiAoZG9jKSB7XG4gICAgaWYgKHJldHVyblZhbHVlLmNhbmNlbGxlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZSBjaGVja3BvaW50IGhhcyBub3QgY2hhbmdlZCwgZG8gbm90IHVwZGF0ZVxuICAgIGlmIChkb2MubGFzdF9zZXEgPT09IGNoZWNrcG9pbnQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBGaWx0ZXIgb3V0IGN1cnJlbnQgZW50cnkgZm9yIHRoaXMgcmVwbGljYXRpb25cbiAgICBkb2MuaGlzdG9yeSA9IChkb2MuaGlzdG9yeSB8fCBbXSkuZmlsdGVyKGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgICByZXR1cm4gaXRlbS5zZXNzaW9uX2lkICE9PSBzZXNzaW9uO1xuICAgIH0pO1xuXG4gICAgLy8gQWRkIHRoZSBsYXRlc3QgY2hlY2twb2ludCB0byBoaXN0b3J5XG4gICAgZG9jLmhpc3RvcnkudW5zaGlmdCh7XG4gICAgICBsYXN0X3NlcTogY2hlY2twb2ludCxcbiAgICAgIHNlc3Npb25faWQ6IHNlc3Npb25cbiAgICB9KTtcblxuICAgIC8vIEp1c3QgdGFrZSB0aGUgbGFzdCBwaWVjZXMgaW4gaGlzdG9yeSwgdG9cbiAgICAvLyBhdm9pZCByZWFsbHkgYmlnIGNoZWNrcG9pbnQgZG9jcy5cbiAgICAvLyBzZWUgY29tbWVudCBvbiBoaXN0b3J5IHNpemUgYWJvdmVcbiAgICBkb2MuaGlzdG9yeSA9IGRvYy5oaXN0b3J5LnNsaWNlKDAsIENIRUNLUE9JTlRfSElTVE9SWV9TSVpFKTtcblxuICAgIGRvYy52ZXJzaW9uID0gQ0hFQ0tQT0lOVF9WRVJTSU9OO1xuICAgIGRvYy5yZXBsaWNhdG9yID0gUkVQTElDQVRPUjtcblxuICAgIGRvYy5zZXNzaW9uX2lkID0gc2Vzc2lvbjtcbiAgICBkb2MubGFzdF9zZXEgPSBjaGVja3BvaW50O1xuXG4gICAgcmV0dXJuIGRiLnB1dChkb2MpLmNhdGNoKGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgIGlmIChlcnIuc3RhdHVzID09PSA0MDkpIHtcbiAgICAgICAgLy8gcmV0cnk7IHNvbWVvbmUgaXMgdHJ5aW5nIHRvIHdyaXRlIGEgY2hlY2twb2ludCBzaW11bHRhbmVvdXNseVxuICAgICAgICByZXR1cm4gdXBkYXRlQ2hlY2twb2ludChkYiwgaWQsIGNoZWNrcG9pbnQsIHNlc3Npb24sIHJldHVyblZhbHVlKTtcbiAgICAgIH1cbiAgICAgIHRocm93IGVycjtcbiAgICB9KTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIENoZWNrcG9pbnRlcihzcmMsIHRhcmdldCwgaWQsIHJldHVyblZhbHVlKSB7XG4gIHRoaXMuc3JjID0gc3JjO1xuICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgdGhpcy5pZCA9IGlkO1xuICB0aGlzLnJldHVyblZhbHVlID0gcmV0dXJuVmFsdWU7XG59XG5cbkNoZWNrcG9pbnRlci5wcm90b3R5cGUud3JpdGVDaGVja3BvaW50ID0gZnVuY3Rpb24gKGNoZWNrcG9pbnQsIHNlc3Npb24pIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICByZXR1cm4gdGhpcy51cGRhdGVUYXJnZXQoY2hlY2twb2ludCwgc2Vzc2lvbikudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHNlbGYudXBkYXRlU291cmNlKGNoZWNrcG9pbnQsIHNlc3Npb24pO1xuICB9KTtcbn07XG5cbkNoZWNrcG9pbnRlci5wcm90b3R5cGUudXBkYXRlVGFyZ2V0ID0gZnVuY3Rpb24gKGNoZWNrcG9pbnQsIHNlc3Npb24pIHtcbiAgcmV0dXJuIHVwZGF0ZUNoZWNrcG9pbnQodGhpcy50YXJnZXQsIHRoaXMuaWQsIGNoZWNrcG9pbnQsXG4gICAgc2Vzc2lvbiwgdGhpcy5yZXR1cm5WYWx1ZSk7XG59O1xuXG5DaGVja3BvaW50ZXIucHJvdG90eXBlLnVwZGF0ZVNvdXJjZSA9IGZ1bmN0aW9uIChjaGVja3BvaW50LCBzZXNzaW9uKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgaWYgKHRoaXMucmVhZE9ubHlTb3VyY2UpIHtcbiAgICByZXR1cm4gUG91Y2hQcm9taXNlLnJlc29sdmUodHJ1ZSk7XG4gIH1cbiAgcmV0dXJuIHVwZGF0ZUNoZWNrcG9pbnQodGhpcy5zcmMsIHRoaXMuaWQsIGNoZWNrcG9pbnQsXG4gICAgc2Vzc2lvbiwgdGhpcy5yZXR1cm5WYWx1ZSlcbiAgICAuY2F0Y2goZnVuY3Rpb24gKGVycikge1xuICAgICAgaWYgKGlzRm9yYmlkZGVuRXJyb3IoZXJyKSkge1xuICAgICAgICBzZWxmLnJlYWRPbmx5U291cmNlID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfSk7XG59O1xuXG52YXIgY29tcGFyaXNvbnMgPSB7XG4gIFwidW5kZWZpbmVkXCI6IGZ1bmN0aW9uICh0YXJnZXREb2MsIHNvdXJjZURvYykge1xuICAgIC8vIFRoaXMgaXMgdGhlIHByZXZpb3VzIGNvbXBhcmlzb24gZnVuY3Rpb25cbiAgICBpZiAoY29sbGF0ZSh0YXJnZXREb2MubGFzdF9zZXEsIHNvdXJjZURvYy5sYXN0X3NlcSkgPT09IDApIHtcbiAgICAgIHJldHVybiBzb3VyY2VEb2MubGFzdF9zZXE7XG4gICAgfVxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgcmV0dXJuIDA7XG4gIH0sXG4gIFwiMVwiOiBmdW5jdGlvbiAodGFyZ2V0RG9jLCBzb3VyY2VEb2MpIHtcbiAgICAvLyBUaGlzIGlzIHRoZSBjb21wYXJpc29uIGZ1bmN0aW9uIHBvcnRlZCBmcm9tIENvdWNoREJcbiAgICByZXR1cm4gY29tcGFyZVJlcGxpY2F0aW9uTG9ncyhzb3VyY2VEb2MsIHRhcmdldERvYykubGFzdF9zZXE7XG4gIH1cbn07XG5cbkNoZWNrcG9pbnRlci5wcm90b3R5cGUuZ2V0Q2hlY2twb2ludCA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICByZXR1cm4gc2VsZi50YXJnZXQuZ2V0KHNlbGYuaWQpLnRoZW4oZnVuY3Rpb24gKHRhcmdldERvYykge1xuICAgIGlmIChzZWxmLnJlYWRPbmx5U291cmNlKSB7XG4gICAgICByZXR1cm4gUG91Y2hQcm9taXNlLnJlc29sdmUodGFyZ2V0RG9jLmxhc3Rfc2VxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc2VsZi5zcmMuZ2V0KHNlbGYuaWQpLnRoZW4oZnVuY3Rpb24gKHNvdXJjZURvYykge1xuICAgICAgLy8gU2luY2Ugd2UgY2FuJ3QgbWlncmF0ZSBhbiBvbGQgdmVyc2lvbiBkb2MgdG8gYSBuZXcgb25lXG4gICAgICAvLyAobm8gc2Vzc2lvbiBpZCksIHdlIGp1c3QgZ28gd2l0aCB0aGUgbG93ZXN0IHNlcSBpbiB0aGlzIGNhc2VcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgICAgaWYgKHRhcmdldERvYy52ZXJzaW9uICE9PSBzb3VyY2VEb2MudmVyc2lvbikge1xuICAgICAgICByZXR1cm4gTE9XRVNUX1NFUTtcbiAgICAgIH1cblxuICAgICAgdmFyIHZlcnNpb247XG4gICAgICBpZiAodGFyZ2V0RG9jLnZlcnNpb24pIHtcbiAgICAgICAgdmVyc2lvbiA9IHRhcmdldERvYy52ZXJzaW9uLnRvU3RyaW5nKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2ZXJzaW9uID0gXCJ1bmRlZmluZWRcIjtcbiAgICAgIH1cblxuICAgICAgaWYgKHZlcnNpb24gaW4gY29tcGFyaXNvbnMpIHtcbiAgICAgICAgcmV0dXJuIGNvbXBhcmlzb25zW3ZlcnNpb25dKHRhcmdldERvYywgc291cmNlRG9jKTtcbiAgICAgIH1cbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICByZXR1cm4gTE9XRVNUX1NFUTtcbiAgICB9LCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICBpZiAoZXJyLnN0YXR1cyA9PT0gNDA0ICYmIHRhcmdldERvYy5sYXN0X3NlcSkge1xuICAgICAgICByZXR1cm4gc2VsZi5zcmMucHV0KHtcbiAgICAgICAgICBfaWQ6IHNlbGYuaWQsXG4gICAgICAgICAgbGFzdF9zZXE6IExPV0VTVF9TRVFcbiAgICAgICAgfSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgcmV0dXJuIExPV0VTVF9TRVE7XG4gICAgICAgIH0sIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICBpZiAoaXNGb3JiaWRkZW5FcnJvcihlcnIpKSB7XG4gICAgICAgICAgICBzZWxmLnJlYWRPbmx5U291cmNlID0gdHJ1ZTtcbiAgICAgICAgICAgIHJldHVybiB0YXJnZXREb2MubGFzdF9zZXE7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICAgICAgcmV0dXJuIExPV0VTVF9TRVE7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgdGhyb3cgZXJyO1xuICAgIH0pO1xuICB9KS5jYXRjaChmdW5jdGlvbiAoZXJyKSB7XG4gICAgaWYgKGVyci5zdGF0dXMgIT09IDQwNCkge1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH1cbiAgICByZXR1cm4gTE9XRVNUX1NFUTtcbiAgfSk7XG59O1xuLy8gVGhpcyBjaGVja3BvaW50IGNvbXBhcmlzb24gaXMgcG9ydGVkIGZyb20gQ291Y2hEQnMgc291cmNlXG4vLyB0aGV5IGNvbWUgZnJvbSBoZXJlOlxuLy8gaHR0cHM6Ly9naXRodWIuY29tL2FwYWNoZS9jb3VjaGRiLWNvdWNoLXJlcGxpY2F0b3IvYmxvYi9tYXN0ZXIvc3JjL2NvdWNoX3JlcGxpY2F0b3IuZXJsI0w4NjMtTDkwNlxuXG5mdW5jdGlvbiBjb21wYXJlUmVwbGljYXRpb25Mb2dzKHNyY0RvYywgdGd0RG9jKSB7XG4gIGlmIChzcmNEb2Muc2Vzc2lvbl9pZCA9PT0gdGd0RG9jLnNlc3Npb25faWQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbGFzdF9zZXE6IHNyY0RvYy5sYXN0X3NlcSxcbiAgICAgIGhpc3Rvcnk6IHNyY0RvYy5oaXN0b3J5XG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBjb21wYXJlUmVwbGljYXRpb25IaXN0b3J5KHNyY0RvYy5oaXN0b3J5LCB0Z3REb2MuaGlzdG9yeSk7XG59XG5cbmZ1bmN0aW9uIGNvbXBhcmVSZXBsaWNhdGlvbkhpc3Rvcnkoc291cmNlSGlzdG9yeSwgdGFyZ2V0SGlzdG9yeSkge1xuICAvLyB0aGUgZXJsYW5nIGxvb3AgdmlhIGZ1bmN0aW9uIGFyZ3VtZW50cyBpcyBub3Qgc28gZWFzeSB0byByZXBlYXQgaW4gSlNcbiAgLy8gdGhlcmVmb3JlLCBkb2luZyB0aGlzIGFzIHJlY3Vyc2lvblxuICB2YXIgUyA9IHNvdXJjZUhpc3RvcnlbMF07XG4gIHZhciBzb3VyY2VSZXN0ID0gc291cmNlSGlzdG9yeS5zbGljZSgxKTtcbiAgdmFyIFQgPSB0YXJnZXRIaXN0b3J5WzBdO1xuICB2YXIgdGFyZ2V0UmVzdCA9IHRhcmdldEhpc3Rvcnkuc2xpY2UoMSk7XG5cbiAgaWYgKCFTIHx8IHRhcmdldEhpc3RvcnkubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGxhc3Rfc2VxOiBMT1dFU1RfU0VRLFxuICAgICAgaGlzdG9yeTogW11cbiAgICB9O1xuICB9XG5cbiAgdmFyIHNvdXJjZUlkID0gUy5zZXNzaW9uX2lkO1xuICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgaWYgKGhhc1Nlc3Npb25JZChzb3VyY2VJZCwgdGFyZ2V0SGlzdG9yeSkpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbGFzdF9zZXE6IFMubGFzdF9zZXEsXG4gICAgICBoaXN0b3J5OiBzb3VyY2VIaXN0b3J5XG4gICAgfTtcbiAgfVxuXG4gIHZhciB0YXJnZXRJZCA9IFQuc2Vzc2lvbl9pZDtcbiAgaWYgKGhhc1Nlc3Npb25JZCh0YXJnZXRJZCwgc291cmNlUmVzdCkpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbGFzdF9zZXE6IFQubGFzdF9zZXEsXG4gICAgICBoaXN0b3J5OiB0YXJnZXRSZXN0XG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBjb21wYXJlUmVwbGljYXRpb25IaXN0b3J5KHNvdXJjZVJlc3QsIHRhcmdldFJlc3QpO1xufVxuXG5mdW5jdGlvbiBoYXNTZXNzaW9uSWQoc2Vzc2lvbklkLCBoaXN0b3J5KSB7XG4gIHZhciBwcm9wcyA9IGhpc3RvcnlbMF07XG4gIHZhciByZXN0ID0gaGlzdG9yeS5zbGljZSgxKTtcblxuICBpZiAoIXNlc3Npb25JZCB8fCBoaXN0b3J5Lmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmIChzZXNzaW9uSWQgPT09IHByb3BzLnNlc3Npb25faWQpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHJldHVybiBoYXNTZXNzaW9uSWQoc2Vzc2lvbklkLCByZXN0KTtcbn1cblxuZnVuY3Rpb24gaXNGb3JiaWRkZW5FcnJvcihlcnIpIHtcbiAgcmV0dXJuIHR5cGVvZiBlcnIuc3RhdHVzID09PSAnbnVtYmVyJyAmJiBNYXRoLmZsb29yKGVyci5zdGF0dXMgLyAxMDApID09PSA0O1xufVxuXG52YXIgU1RBUlRJTkdfQkFDS19PRkYgPSAwO1xuXG5mdW5jdGlvbiBiYWNrT2ZmKG9wdHMsIHJldHVyblZhbHVlLCBlcnJvciwgY2FsbGJhY2spIHtcbiAgaWYgKG9wdHMucmV0cnkgPT09IGZhbHNlKSB7XG4gICAgcmV0dXJuVmFsdWUuZW1pdCgnZXJyb3InLCBlcnJvcik7XG4gICAgcmV0dXJuVmFsdWUucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmICh0eXBlb2Ygb3B0cy5iYWNrX29mZl9mdW5jdGlvbiAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIG9wdHMuYmFja19vZmZfZnVuY3Rpb24gPSBkZWZhdWx0QmFja09mZjtcbiAgfVxuICByZXR1cm5WYWx1ZS5lbWl0KCdyZXF1ZXN0RXJyb3InLCBlcnJvcik7XG4gIGlmIChyZXR1cm5WYWx1ZS5zdGF0ZSA9PT0gJ2FjdGl2ZScgfHwgcmV0dXJuVmFsdWUuc3RhdGUgPT09ICdwZW5kaW5nJykge1xuICAgIHJldHVyblZhbHVlLmVtaXQoJ3BhdXNlZCcsIGVycm9yKTtcbiAgICByZXR1cm5WYWx1ZS5zdGF0ZSA9ICdzdG9wcGVkJztcbiAgICB2YXIgYmFja09mZlNldCA9IGZ1bmN0aW9uIGJhY2tvZmZUaW1lU2V0KCkge1xuICAgICAgb3B0cy5jdXJyZW50X2JhY2tfb2ZmID0gU1RBUlRJTkdfQkFDS19PRkY7XG4gICAgfTtcbiAgICB2YXIgcmVtb3ZlQmFja09mZlNldHRlciA9IGZ1bmN0aW9uIHJlbW92ZUJhY2tPZmZUaW1lU2V0KCkge1xuICAgICAgcmV0dXJuVmFsdWUucmVtb3ZlTGlzdGVuZXIoJ2FjdGl2ZScsIGJhY2tPZmZTZXQpO1xuICAgIH07XG4gICAgcmV0dXJuVmFsdWUub25jZSgncGF1c2VkJywgcmVtb3ZlQmFja09mZlNldHRlcik7XG4gICAgcmV0dXJuVmFsdWUub25jZSgnYWN0aXZlJywgYmFja09mZlNldCk7XG4gIH1cblxuICBvcHRzLmN1cnJlbnRfYmFja19vZmYgPSBvcHRzLmN1cnJlbnRfYmFja19vZmYgfHwgU1RBUlRJTkdfQkFDS19PRkY7XG4gIG9wdHMuY3VycmVudF9iYWNrX29mZiA9IG9wdHMuYmFja19vZmZfZnVuY3Rpb24ob3B0cy5jdXJyZW50X2JhY2tfb2ZmKTtcbiAgc2V0VGltZW91dChjYWxsYmFjaywgb3B0cy5jdXJyZW50X2JhY2tfb2ZmKTtcbn1cblxuZnVuY3Rpb24gc29ydE9iamVjdFByb3BlcnRpZXNCeUtleShxdWVyeVBhcmFtcykge1xuICByZXR1cm4gT2JqZWN0LmtleXMocXVlcnlQYXJhbXMpLnNvcnQoY29sbGF0ZSkucmVkdWNlKGZ1bmN0aW9uIChyZXN1bHQsIGtleSkge1xuICAgIHJlc3VsdFtrZXldID0gcXVlcnlQYXJhbXNba2V5XTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LCB7fSk7XG59XG5cbi8vIEdlbmVyYXRlIGEgdW5pcXVlIGlkIHBhcnRpY3VsYXIgdG8gdGhpcyByZXBsaWNhdGlvbi5cbi8vIE5vdCBndWFyYW50ZWVkIHRvIGFsaWduIHBlcmZlY3RseSB3aXRoIENvdWNoREIncyByZXAgaWRzLlxuZnVuY3Rpb24gZ2VuZXJhdGVSZXBsaWNhdGlvbklkKHNyYywgdGFyZ2V0LCBvcHRzKSB7XG4gIHZhciBkb2NJZHMgPSBvcHRzLmRvY19pZHMgPyBvcHRzLmRvY19pZHMuc29ydChjb2xsYXRlKSA6ICcnO1xuICB2YXIgZmlsdGVyRnVuID0gb3B0cy5maWx0ZXIgPyBvcHRzLmZpbHRlci50b1N0cmluZygpIDogJyc7XG4gIHZhciBxdWVyeVBhcmFtcyA9ICcnO1xuICB2YXIgZmlsdGVyVmlld05hbWUgPSAgJyc7XG5cbiAgaWYgKG9wdHMuZmlsdGVyICYmIG9wdHMucXVlcnlfcGFyYW1zKSB7XG4gICAgcXVlcnlQYXJhbXMgPSBKU09OLnN0cmluZ2lmeShzb3J0T2JqZWN0UHJvcGVydGllc0J5S2V5KG9wdHMucXVlcnlfcGFyYW1zKSk7XG4gIH1cblxuICBpZiAob3B0cy5maWx0ZXIgJiYgb3B0cy5maWx0ZXIgPT09ICdfdmlldycpIHtcbiAgICBmaWx0ZXJWaWV3TmFtZSA9IG9wdHMudmlldy50b1N0cmluZygpO1xuICB9XG5cbiAgcmV0dXJuIFBvdWNoUHJvbWlzZS5hbGwoW3NyYy5pZCgpLCB0YXJnZXQuaWQoKV0pLnRoZW4oZnVuY3Rpb24gKHJlcykge1xuICAgIHZhciBxdWVyeURhdGEgPSByZXNbMF0gKyByZXNbMV0gKyBmaWx0ZXJGdW4gKyBmaWx0ZXJWaWV3TmFtZSArXG4gICAgICBxdWVyeVBhcmFtcyArIGRvY0lkcztcbiAgICByZXR1cm4gbmV3IFBvdWNoUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSkge1xuICAgICAgYmluYXJ5TWQ1KHF1ZXJ5RGF0YSwgcmVzb2x2ZSk7XG4gICAgfSk7XG4gIH0pLnRoZW4oZnVuY3Rpb24gKG1kNXN1bSkge1xuICAgIC8vIGNhbid0IHVzZSBzdHJhaWdodC11cCBtZDUgYWxwaGFiZXQsIGJlY2F1c2VcbiAgICAvLyB0aGUgY2hhciAnLycgaXMgaW50ZXJwcmV0ZWQgYXMgYmVpbmcgZm9yIGF0dGFjaG1lbnRzLFxuICAgIC8vIGFuZCArIGlzIGFsc28gbm90IHVybC1zYWZlXG4gICAgbWQ1c3VtID0gbWQ1c3VtLnJlcGxhY2UoL1xcLy9nLCAnLicpLnJlcGxhY2UoL1xcKy9nLCAnXycpO1xuICAgIHJldHVybiAnX2xvY2FsLycgKyBtZDVzdW07XG4gIH0pO1xufVxuXG5mdW5jdGlvbiByZXBsaWNhdGUkMShzcmMsIHRhcmdldCwgb3B0cywgcmV0dXJuVmFsdWUsIHJlc3VsdCkge1xuICB2YXIgYmF0Y2hlcyA9IFtdOyAgICAgICAgICAgICAgIC8vIGxpc3Qgb2YgYmF0Y2hlcyB0byBiZSBwcm9jZXNzZWRcbiAgdmFyIGN1cnJlbnRCYXRjaDsgICAgICAgICAgICAgICAvLyB0aGUgYmF0Y2ggY3VycmVudGx5IGJlaW5nIHByb2Nlc3NlZFxuICB2YXIgcGVuZGluZ0JhdGNoID0ge1xuICAgIHNlcTogMCxcbiAgICBjaGFuZ2VzOiBbXSxcbiAgICBkb2NzOiBbXVxuICB9OyAvLyBuZXh0IGJhdGNoLCBub3QgeWV0IHJlYWR5IHRvIGJlIHByb2Nlc3NlZFxuICB2YXIgd3JpdGluZ0NoZWNrcG9pbnQgPSBmYWxzZTsgIC8vIHRydWUgd2hpbGUgY2hlY2twb2ludCBpcyBiZWluZyB3cml0dGVuXG4gIHZhciBjaGFuZ2VzQ29tcGxldGVkID0gZmFsc2U7ICAgLy8gdHJ1ZSB3aGVuIGFsbCBjaGFuZ2VzIHJlY2VpdmVkXG4gIHZhciByZXBsaWNhdGlvbkNvbXBsZXRlZCA9IGZhbHNlOyAvLyB0cnVlIHdoZW4gcmVwbGljYXRpb24gaGFzIGNvbXBsZXRlZFxuICB2YXIgbGFzdF9zZXEgPSAwO1xuICB2YXIgY29udGludW91cyA9IG9wdHMuY29udGludW91cyB8fCBvcHRzLmxpdmUgfHwgZmFsc2U7XG4gIHZhciBiYXRjaF9zaXplID0gb3B0cy5iYXRjaF9zaXplIHx8IDEwMDtcbiAgdmFyIGJhdGNoZXNfbGltaXQgPSBvcHRzLmJhdGNoZXNfbGltaXQgfHwgMTA7XG4gIHZhciBjaGFuZ2VzUGVuZGluZyA9IGZhbHNlOyAgICAgLy8gdHJ1ZSB3aGlsZSBzcmMuY2hhbmdlcyBpcyBydW5uaW5nXG4gIHZhciBkb2NfaWRzID0gb3B0cy5kb2NfaWRzO1xuICB2YXIgcmVwSWQ7XG4gIHZhciBjaGVja3BvaW50ZXI7XG4gIHZhciBjaGFuZ2VkRG9jcyA9IFtdO1xuICAvLyBMaWtlIGNvdWNoZGIsIGV2ZXJ5IHJlcGxpY2F0aW9uIGdldHMgYSB1bmlxdWUgc2Vzc2lvbiBpZFxuICB2YXIgc2Vzc2lvbiA9IHV1aWQoKTtcblxuICByZXN1bHQgPSByZXN1bHQgfHwge1xuICAgIG9rOiB0cnVlLFxuICAgIHN0YXJ0X3RpbWU6IG5ldyBEYXRlKCksXG4gICAgZG9jc19yZWFkOiAwLFxuICAgIGRvY3Nfd3JpdHRlbjogMCxcbiAgICBkb2Nfd3JpdGVfZmFpbHVyZXM6IDAsXG4gICAgZXJyb3JzOiBbXVxuICB9O1xuXG4gIHZhciBjaGFuZ2VzT3B0cyA9IHt9O1xuICByZXR1cm5WYWx1ZS5yZWFkeShzcmMsIHRhcmdldCk7XG5cbiAgZnVuY3Rpb24gaW5pdENoZWNrcG9pbnRlcigpIHtcbiAgICBpZiAoY2hlY2twb2ludGVyKSB7XG4gICAgICByZXR1cm4gUG91Y2hQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG4gICAgcmV0dXJuIGdlbmVyYXRlUmVwbGljYXRpb25JZChzcmMsIHRhcmdldCwgb3B0cykudGhlbihmdW5jdGlvbiAocmVzKSB7XG4gICAgICByZXBJZCA9IHJlcztcbiAgICAgIGNoZWNrcG9pbnRlciA9IG5ldyBDaGVja3BvaW50ZXIoc3JjLCB0YXJnZXQsIHJlcElkLCByZXR1cm5WYWx1ZSk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiB3cml0ZURvY3MoKSB7XG4gICAgY2hhbmdlZERvY3MgPSBbXTtcblxuICAgIGlmIChjdXJyZW50QmF0Y2guZG9jcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIGRvY3MgPSBjdXJyZW50QmF0Y2guZG9jcztcbiAgICB2YXIgYnVsa09wdHMgPSB7dGltZW91dDogb3B0cy50aW1lb3V0fTtcbiAgICByZXR1cm4gdGFyZ2V0LmJ1bGtEb2NzKHtkb2NzOiBkb2NzLCBuZXdfZWRpdHM6IGZhbHNlfSwgYnVsa09wdHMpLnRoZW4oZnVuY3Rpb24gKHJlcykge1xuICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgICBpZiAocmV0dXJuVmFsdWUuY2FuY2VsbGVkKSB7XG4gICAgICAgIGNvbXBsZXRlUmVwbGljYXRpb24oKTtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5jZWxsZWQnKTtcbiAgICAgIH1cblxuICAgICAgLy8gYHJlc2AgZG9lc24ndCBpbmNsdWRlIGZ1bGwgZG9jdW1lbnRzICh3aGljaCBsaXZlIGluIGBkb2NzYCksIHNvIHdlIGNyZWF0ZSBhIG1hcCBvZiBcbiAgICAgIC8vIChpZCAtPiBlcnJvciksIGFuZCBjaGVjayBmb3IgZXJyb3JzIHdoaWxlIGl0ZXJhdGluZyBvdmVyIGBkb2NzYFxuICAgICAgdmFyIGVycm9yc0J5SWQgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgICAgcmVzLmZvckVhY2goZnVuY3Rpb24gKHJlcykge1xuICAgICAgICBpZiAocmVzLmVycm9yKSB7XG4gICAgICAgICAgZXJyb3JzQnlJZFtyZXMuaWRdID0gcmVzO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgdmFyIGVycm9yc05vID0gT2JqZWN0LmtleXMoZXJyb3JzQnlJZCkubGVuZ3RoO1xuICAgICAgcmVzdWx0LmRvY193cml0ZV9mYWlsdXJlcyArPSBlcnJvcnNObztcbiAgICAgIHJlc3VsdC5kb2NzX3dyaXR0ZW4gKz0gZG9jcy5sZW5ndGggLSBlcnJvcnNObztcblxuICAgICAgZG9jcy5mb3JFYWNoKGZ1bmN0aW9uIChkb2MpIHtcbiAgICAgICAgdmFyIGVycm9yID0gZXJyb3JzQnlJZFtkb2MuX2lkXTtcbiAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgcmVzdWx0LmVycm9ycy5wdXNoKGVycm9yKTtcbiAgICAgICAgICBpZiAoZXJyb3IubmFtZSA9PT0gJ3VuYXV0aG9yaXplZCcgfHwgZXJyb3IubmFtZSA9PT0gJ2ZvcmJpZGRlbicpIHtcbiAgICAgICAgICAgIHJldHVyblZhbHVlLmVtaXQoJ2RlbmllZCcsIGNsb25lKGVycm9yKSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjaGFuZ2VkRG9jcy5wdXNoKGRvYyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgfSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgcmVzdWx0LmRvY193cml0ZV9mYWlsdXJlcyArPSBkb2NzLmxlbmd0aDtcbiAgICAgIHRocm93IGVycjtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZpbmlzaEJhdGNoKCkge1xuICAgIGlmIChjdXJyZW50QmF0Y2guZXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhlcmUgd2FzIGEgcHJvYmxlbSBnZXR0aW5nIGRvY3MuJyk7XG4gICAgfVxuICAgIHJlc3VsdC5sYXN0X3NlcSA9IGxhc3Rfc2VxID0gY3VycmVudEJhdGNoLnNlcTtcbiAgICB2YXIgb3V0UmVzdWx0ID0gY2xvbmUocmVzdWx0KTtcbiAgICBpZiAoY2hhbmdlZERvY3MubGVuZ3RoKSB7XG4gICAgICBvdXRSZXN1bHQuZG9jcyA9IGNoYW5nZWREb2NzO1xuICAgICAgcmV0dXJuVmFsdWUuZW1pdCgnY2hhbmdlJywgb3V0UmVzdWx0KTtcbiAgICB9XG4gICAgd3JpdGluZ0NoZWNrcG9pbnQgPSB0cnVlO1xuICAgIHJldHVybiBjaGVja3BvaW50ZXIud3JpdGVDaGVja3BvaW50KGN1cnJlbnRCYXRjaC5zZXEsXG4gICAgICAgIHNlc3Npb24pLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgd3JpdGluZ0NoZWNrcG9pbnQgPSBmYWxzZTtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgICAgaWYgKHJldHVyblZhbHVlLmNhbmNlbGxlZCkge1xuICAgICAgICBjb21wbGV0ZVJlcGxpY2F0aW9uKCk7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignY2FuY2VsbGVkJyk7XG4gICAgICB9XG4gICAgICBjdXJyZW50QmF0Y2ggPSB1bmRlZmluZWQ7XG4gICAgICBnZXRDaGFuZ2VzKCk7XG4gICAgfSkuY2F0Y2goZnVuY3Rpb24gKGVycikge1xuICAgICAgb25DaGVja3BvaW50RXJyb3IoZXJyKTtcbiAgICAgIHRocm93IGVycjtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldERpZmZzKCkge1xuICAgIHZhciBkaWZmID0ge307XG4gICAgY3VycmVudEJhdGNoLmNoYW5nZXMuZm9yRWFjaChmdW5jdGlvbiAoY2hhbmdlKSB7XG4gICAgICAvLyBDb3VjaGJhc2UgU3luYyBHYXRld2F5IGVtaXRzIHRoZXNlLCBidXQgd2UgY2FuIGlnbm9yZSB0aGVtXG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICAgIGlmIChjaGFuZ2UuaWQgPT09IFwiX3VzZXIvXCIpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgZGlmZltjaGFuZ2UuaWRdID0gY2hhbmdlLmNoYW5nZXMubWFwKGZ1bmN0aW9uICh4KSB7XG4gICAgICAgIHJldHVybiB4LnJldjtcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIHJldHVybiB0YXJnZXQucmV2c0RpZmYoZGlmZikudGhlbihmdW5jdGlvbiAoZGlmZnMpIHtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgICAgaWYgKHJldHVyblZhbHVlLmNhbmNlbGxlZCkge1xuICAgICAgICBjb21wbGV0ZVJlcGxpY2F0aW9uKCk7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignY2FuY2VsbGVkJyk7XG4gICAgICB9XG4gICAgICAvLyBjdXJyZW50QmF0Y2guZGlmZnMgZWxlbWVudHMgYXJlIGRlbGV0ZWQgYXMgdGhlIGRvY3VtZW50cyBhcmUgd3JpdHRlblxuICAgICAgY3VycmVudEJhdGNoLmRpZmZzID0gZGlmZnM7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRCYXRjaERvY3MoKSB7XG4gICAgcmV0dXJuIGdldERvY3Moc3JjLCB0YXJnZXQsIGN1cnJlbnRCYXRjaC5kaWZmcywgcmV0dXJuVmFsdWUpLnRoZW4oZnVuY3Rpb24gKGdvdCkge1xuICAgICAgY3VycmVudEJhdGNoLmVycm9yID0gIWdvdC5vaztcbiAgICAgIGdvdC5kb2NzLmZvckVhY2goZnVuY3Rpb24gKGRvYykge1xuICAgICAgICBkZWxldGUgY3VycmVudEJhdGNoLmRpZmZzW2RvYy5faWRdO1xuICAgICAgICByZXN1bHQuZG9jc19yZWFkKys7XG4gICAgICAgIGN1cnJlbnRCYXRjaC5kb2NzLnB1c2goZG9jKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgZnVuY3Rpb24gc3RhcnROZXh0QmF0Y2goKSB7XG4gICAgaWYgKHJldHVyblZhbHVlLmNhbmNlbGxlZCB8fCBjdXJyZW50QmF0Y2gpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKGJhdGNoZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICBwcm9jZXNzUGVuZGluZ0JhdGNoKHRydWUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjdXJyZW50QmF0Y2ggPSBiYXRjaGVzLnNoaWZ0KCk7XG4gICAgZ2V0RGlmZnMoKVxuICAgICAgLnRoZW4oZ2V0QmF0Y2hEb2NzKVxuICAgICAgLnRoZW4od3JpdGVEb2NzKVxuICAgICAgLnRoZW4oZmluaXNoQmF0Y2gpXG4gICAgICAudGhlbihzdGFydE5leHRCYXRjaClcbiAgICAgIC5jYXRjaChmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgIGFib3J0UmVwbGljYXRpb24oJ2JhdGNoIHByb2Nlc3NpbmcgdGVybWluYXRlZCB3aXRoIGVycm9yJywgZXJyKTtcbiAgICAgIH0pO1xuICB9XG5cblxuICBmdW5jdGlvbiBwcm9jZXNzUGVuZGluZ0JhdGNoKGltbWVkaWF0ZSkge1xuICAgIGlmIChwZW5kaW5nQmF0Y2guY2hhbmdlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIGlmIChiYXRjaGVzLmxlbmd0aCA9PT0gMCAmJiAhY3VycmVudEJhdGNoKSB7XG4gICAgICAgIGlmICgoY29udGludW91cyAmJiBjaGFuZ2VzT3B0cy5saXZlKSB8fCBjaGFuZ2VzQ29tcGxldGVkKSB7XG4gICAgICAgICAgcmV0dXJuVmFsdWUuc3RhdGUgPSAncGVuZGluZyc7XG4gICAgICAgICAgcmV0dXJuVmFsdWUuZW1pdCgncGF1c2VkJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNoYW5nZXNDb21wbGV0ZWQpIHtcbiAgICAgICAgICBjb21wbGV0ZVJlcGxpY2F0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKFxuICAgICAgaW1tZWRpYXRlIHx8XG4gICAgICBjaGFuZ2VzQ29tcGxldGVkIHx8XG4gICAgICBwZW5kaW5nQmF0Y2guY2hhbmdlcy5sZW5ndGggPj0gYmF0Y2hfc2l6ZVxuICAgICkge1xuICAgICAgYmF0Y2hlcy5wdXNoKHBlbmRpbmdCYXRjaCk7XG4gICAgICBwZW5kaW5nQmF0Y2ggPSB7XG4gICAgICAgIHNlcTogMCxcbiAgICAgICAgY2hhbmdlczogW10sXG4gICAgICAgIGRvY3M6IFtdXG4gICAgICB9O1xuICAgICAgaWYgKHJldHVyblZhbHVlLnN0YXRlID09PSAncGVuZGluZycgfHwgcmV0dXJuVmFsdWUuc3RhdGUgPT09ICdzdG9wcGVkJykge1xuICAgICAgICByZXR1cm5WYWx1ZS5zdGF0ZSA9ICdhY3RpdmUnO1xuICAgICAgICByZXR1cm5WYWx1ZS5lbWl0KCdhY3RpdmUnKTtcbiAgICAgIH1cbiAgICAgIHN0YXJ0TmV4dEJhdGNoKCk7XG4gICAgfVxuICB9XG5cblxuICBmdW5jdGlvbiBhYm9ydFJlcGxpY2F0aW9uKHJlYXNvbiwgZXJyKSB7XG4gICAgaWYgKHJlcGxpY2F0aW9uQ29tcGxldGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghZXJyLm1lc3NhZ2UpIHtcbiAgICAgIGVyci5tZXNzYWdlID0gcmVhc29uO1xuICAgIH1cbiAgICByZXN1bHQub2sgPSBmYWxzZTtcbiAgICByZXN1bHQuc3RhdHVzID0gJ2Fib3J0aW5nJztcbiAgICBiYXRjaGVzID0gW107XG4gICAgcGVuZGluZ0JhdGNoID0ge1xuICAgICAgc2VxOiAwLFxuICAgICAgY2hhbmdlczogW10sXG4gICAgICBkb2NzOiBbXVxuICAgIH07XG4gICAgY29tcGxldGVSZXBsaWNhdGlvbihlcnIpO1xuICB9XG5cblxuICBmdW5jdGlvbiBjb21wbGV0ZVJlcGxpY2F0aW9uKGZhdGFsRXJyb3IpIHtcbiAgICBpZiAocmVwbGljYXRpb25Db21wbGV0ZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgaWYgKHJldHVyblZhbHVlLmNhbmNlbGxlZCkge1xuICAgICAgcmVzdWx0LnN0YXR1cyA9ICdjYW5jZWxsZWQnO1xuICAgICAgaWYgKHdyaXRpbmdDaGVja3BvaW50KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG4gICAgcmVzdWx0LnN0YXR1cyA9IHJlc3VsdC5zdGF0dXMgfHwgJ2NvbXBsZXRlJztcbiAgICByZXN1bHQuZW5kX3RpbWUgPSBuZXcgRGF0ZSgpO1xuICAgIHJlc3VsdC5sYXN0X3NlcSA9IGxhc3Rfc2VxO1xuICAgIHJlcGxpY2F0aW9uQ29tcGxldGVkID0gdHJ1ZTtcblxuICAgIGlmIChmYXRhbEVycm9yKSB7XG4gICAgICBmYXRhbEVycm9yLnJlc3VsdCA9IHJlc3VsdDtcblxuICAgICAgaWYgKGZhdGFsRXJyb3IubmFtZSA9PT0gJ3VuYXV0aG9yaXplZCcgfHwgZmF0YWxFcnJvci5uYW1lID09PSAnZm9yYmlkZGVuJykge1xuICAgICAgICByZXR1cm5WYWx1ZS5lbWl0KCdlcnJvcicsIGZhdGFsRXJyb3IpO1xuICAgICAgICByZXR1cm5WYWx1ZS5yZW1vdmVBbGxMaXN0ZW5lcnMoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJhY2tPZmYob3B0cywgcmV0dXJuVmFsdWUsIGZhdGFsRXJyb3IsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICByZXBsaWNhdGUkMShzcmMsIHRhcmdldCwgb3B0cywgcmV0dXJuVmFsdWUpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuVmFsdWUuZW1pdCgnY29tcGxldGUnLCByZXN1bHQpO1xuICAgICAgcmV0dXJuVmFsdWUucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgfVxuICB9XG5cblxuICBmdW5jdGlvbiBvbkNoYW5nZShjaGFuZ2UpIHtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICBpZiAocmV0dXJuVmFsdWUuY2FuY2VsbGVkKSB7XG4gICAgICByZXR1cm4gY29tcGxldGVSZXBsaWNhdGlvbigpO1xuICAgIH1cbiAgICB2YXIgZmlsdGVyID0gZmlsdGVyQ2hhbmdlKG9wdHMpKGNoYW5nZSk7XG4gICAgaWYgKCFmaWx0ZXIpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgcGVuZGluZ0JhdGNoLnNlcSA9IGNoYW5nZS5zZXE7XG4gICAgcGVuZGluZ0JhdGNoLmNoYW5nZXMucHVzaChjaGFuZ2UpO1xuICAgIHByb2Nlc3NQZW5kaW5nQmF0Y2goYmF0Y2hlcy5sZW5ndGggPT09IDAgJiYgY2hhbmdlc09wdHMubGl2ZSk7XG4gIH1cblxuXG4gIGZ1bmN0aW9uIG9uQ2hhbmdlc0NvbXBsZXRlKGNoYW5nZXMpIHtcbiAgICBjaGFuZ2VzUGVuZGluZyA9IGZhbHNlO1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgIGlmIChyZXR1cm5WYWx1ZS5jYW5jZWxsZWQpIHtcbiAgICAgIHJldHVybiBjb21wbGV0ZVJlcGxpY2F0aW9uKCk7XG4gICAgfVxuXG4gICAgLy8gaWYgbm8gcmVzdWx0cyB3ZXJlIHJldHVybmVkIHRoZW4gd2UncmUgZG9uZSxcbiAgICAvLyBlbHNlIGZldGNoIG1vcmVcbiAgICBpZiAoY2hhbmdlcy5yZXN1bHRzLmxlbmd0aCA+IDApIHtcbiAgICAgIGNoYW5nZXNPcHRzLnNpbmNlID0gY2hhbmdlcy5sYXN0X3NlcTtcbiAgICAgIGdldENoYW5nZXMoKTtcbiAgICAgIHByb2Nlc3NQZW5kaW5nQmF0Y2godHJ1ZSk7XG4gICAgfSBlbHNlIHtcblxuICAgICAgdmFyIGNvbXBsZXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoY29udGludW91cykge1xuICAgICAgICAgIGNoYW5nZXNPcHRzLmxpdmUgPSB0cnVlO1xuICAgICAgICAgIGdldENoYW5nZXMoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjaGFuZ2VzQ29tcGxldGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBwcm9jZXNzUGVuZGluZ0JhdGNoKHRydWUpO1xuICAgICAgfTtcblxuICAgICAgLy8gdXBkYXRlIHRoZSBjaGVja3BvaW50IHNvIHdlIHN0YXJ0IGZyb20gdGhlIHJpZ2h0IHNlcSBuZXh0IHRpbWVcbiAgICAgIGlmICghY3VycmVudEJhdGNoICYmIGNoYW5nZXMucmVzdWx0cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgd3JpdGluZ0NoZWNrcG9pbnQgPSB0cnVlO1xuICAgICAgICBjaGVja3BvaW50ZXIud3JpdGVDaGVja3BvaW50KGNoYW5nZXMubGFzdF9zZXEsXG4gICAgICAgICAgICBzZXNzaW9uKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICB3cml0aW5nQ2hlY2twb2ludCA9IGZhbHNlO1xuICAgICAgICAgIHJlc3VsdC5sYXN0X3NlcSA9IGxhc3Rfc2VxID0gY2hhbmdlcy5sYXN0X3NlcTtcbiAgICAgICAgICBjb21wbGV0ZSgpO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2gob25DaGVja3BvaW50RXJyb3IpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29tcGxldGUoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuXG4gIGZ1bmN0aW9uIG9uQ2hhbmdlc0Vycm9yKGVycikge1xuICAgIGNoYW5nZXNQZW5kaW5nID0gZmFsc2U7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgaWYgKHJldHVyblZhbHVlLmNhbmNlbGxlZCkge1xuICAgICAgcmV0dXJuIGNvbXBsZXRlUmVwbGljYXRpb24oKTtcbiAgICB9XG4gICAgYWJvcnRSZXBsaWNhdGlvbignY2hhbmdlcyByZWplY3RlZCcsIGVycik7XG4gIH1cblxuXG4gIGZ1bmN0aW9uIGdldENoYW5nZXMoKSB7XG4gICAgaWYgKCEoXG4gICAgICAhY2hhbmdlc1BlbmRpbmcgJiZcbiAgICAgICFjaGFuZ2VzQ29tcGxldGVkICYmXG4gICAgICBiYXRjaGVzLmxlbmd0aCA8IGJhdGNoZXNfbGltaXRcbiAgICAgICkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY2hhbmdlc1BlbmRpbmcgPSB0cnVlO1xuICAgIGZ1bmN0aW9uIGFib3J0Q2hhbmdlcygpIHtcbiAgICAgIGNoYW5nZXMuY2FuY2VsKCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKCkge1xuICAgICAgcmV0dXJuVmFsdWUucmVtb3ZlTGlzdGVuZXIoJ2NhbmNlbCcsIGFib3J0Q2hhbmdlcyk7XG4gICAgfVxuXG4gICAgaWYgKHJldHVyblZhbHVlLl9jaGFuZ2VzKSB7IC8vIHJlbW92ZSBvbGQgY2hhbmdlcygpIGFuZCBsaXN0ZW5lcnNcbiAgICAgIHJldHVyblZhbHVlLnJlbW92ZUxpc3RlbmVyKCdjYW5jZWwnLCByZXR1cm5WYWx1ZS5fYWJvcnRDaGFuZ2VzKTtcbiAgICAgIHJldHVyblZhbHVlLl9jaGFuZ2VzLmNhbmNlbCgpO1xuICAgIH1cbiAgICByZXR1cm5WYWx1ZS5vbmNlKCdjYW5jZWwnLCBhYm9ydENoYW5nZXMpO1xuXG4gICAgdmFyIGNoYW5nZXMgPSBzcmMuY2hhbmdlcyhjaGFuZ2VzT3B0cylcbiAgICAgIC5vbignY2hhbmdlJywgb25DaGFuZ2UpO1xuICAgIGNoYW5nZXMudGhlbihyZW1vdmVMaXN0ZW5lciwgcmVtb3ZlTGlzdGVuZXIpO1xuICAgIGNoYW5nZXMudGhlbihvbkNoYW5nZXNDb21wbGV0ZSlcbiAgICAgIC5jYXRjaChvbkNoYW5nZXNFcnJvcik7XG5cbiAgICBpZiAob3B0cy5yZXRyeSkge1xuICAgICAgLy8gc2F2ZSBmb3IgbGF0ZXIgc28gd2UgY2FuIGNhbmNlbCBpZiBuZWNlc3NhcnlcbiAgICAgIHJldHVyblZhbHVlLl9jaGFuZ2VzID0gY2hhbmdlcztcbiAgICAgIHJldHVyblZhbHVlLl9hYm9ydENoYW5nZXMgPSBhYm9ydENoYW5nZXM7XG4gICAgfVxuICB9XG5cblxuICBmdW5jdGlvbiBzdGFydENoYW5nZXMoKSB7XG4gICAgaW5pdENoZWNrcG9pbnRlcigpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgICBpZiAocmV0dXJuVmFsdWUuY2FuY2VsbGVkKSB7XG4gICAgICAgIGNvbXBsZXRlUmVwbGljYXRpb24oKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGNoZWNrcG9pbnRlci5nZXRDaGVja3BvaW50KCkudGhlbihmdW5jdGlvbiAoY2hlY2twb2ludCkge1xuICAgICAgICBsYXN0X3NlcSA9IGNoZWNrcG9pbnQ7XG4gICAgICAgIGNoYW5nZXNPcHRzID0ge1xuICAgICAgICAgIHNpbmNlOiBsYXN0X3NlcSxcbiAgICAgICAgICBsaW1pdDogYmF0Y2hfc2l6ZSxcbiAgICAgICAgICBiYXRjaF9zaXplOiBiYXRjaF9zaXplLFxuICAgICAgICAgIHN0eWxlOiAnYWxsX2RvY3MnLFxuICAgICAgICAgIGRvY19pZHM6IGRvY19pZHMsXG4gICAgICAgICAgcmV0dXJuX2RvY3M6IHRydWUgLy8gcmVxdWlyZWQgc28gd2Uga25vdyB3aGVuIHdlJ3JlIGRvbmVcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKG9wdHMuZmlsdGVyKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBvcHRzLmZpbHRlciAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIC8vIHJlcXVpcmVkIGZvciB0aGUgY2xpZW50LXNpZGUgZmlsdGVyIGluIG9uQ2hhbmdlXG4gICAgICAgICAgICBjaGFuZ2VzT3B0cy5pbmNsdWRlX2RvY3MgPSB0cnVlO1xuICAgICAgICAgIH0gZWxzZSB7IC8vIGRkb2MgZmlsdGVyXG4gICAgICAgICAgICBjaGFuZ2VzT3B0cy5maWx0ZXIgPSBvcHRzLmZpbHRlcjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCdoZWFydGJlYXQnIGluIG9wdHMpIHtcbiAgICAgICAgICBjaGFuZ2VzT3B0cy5oZWFydGJlYXQgPSBvcHRzLmhlYXJ0YmVhdDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoJ3RpbWVvdXQnIGluIG9wdHMpIHtcbiAgICAgICAgICBjaGFuZ2VzT3B0cy50aW1lb3V0ID0gb3B0cy50aW1lb3V0O1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRzLnF1ZXJ5X3BhcmFtcykge1xuICAgICAgICAgIGNoYW5nZXNPcHRzLnF1ZXJ5X3BhcmFtcyA9IG9wdHMucXVlcnlfcGFyYW1zO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRzLnZpZXcpIHtcbiAgICAgICAgICBjaGFuZ2VzT3B0cy52aWV3ID0gb3B0cy52aWV3O1xuICAgICAgICB9XG4gICAgICAgIGdldENoYW5nZXMoKTtcbiAgICAgIH0pO1xuICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgIGFib3J0UmVwbGljYXRpb24oJ2dldENoZWNrcG9pbnQgcmVqZWN0ZWQgd2l0aCAnLCBlcnIpO1xuICAgIH0pO1xuICB9XG5cbiAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgZnVuY3Rpb24gb25DaGVja3BvaW50RXJyb3IoZXJyKSB7XG4gICAgd3JpdGluZ0NoZWNrcG9pbnQgPSBmYWxzZTtcbiAgICBhYm9ydFJlcGxpY2F0aW9uKCd3cml0ZUNoZWNrcG9pbnQgY29tcGxldGVkIHdpdGggZXJyb3InLCBlcnIpO1xuICB9XG5cbiAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gIGlmIChyZXR1cm5WYWx1ZS5jYW5jZWxsZWQpIHsgLy8gY2FuY2VsbGVkIGltbWVkaWF0ZWx5XG4gICAgY29tcGxldGVSZXBsaWNhdGlvbigpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmICghcmV0dXJuVmFsdWUuX2FkZGVkTGlzdGVuZXJzKSB7XG4gICAgcmV0dXJuVmFsdWUub25jZSgnY2FuY2VsJywgY29tcGxldGVSZXBsaWNhdGlvbik7XG5cbiAgICBpZiAodHlwZW9mIG9wdHMuY29tcGxldGUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVyblZhbHVlLm9uY2UoJ2Vycm9yJywgb3B0cy5jb21wbGV0ZSk7XG4gICAgICByZXR1cm5WYWx1ZS5vbmNlKCdjb21wbGV0ZScsIGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgb3B0cy5jb21wbGV0ZShudWxsLCByZXN1bHQpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVyblZhbHVlLl9hZGRlZExpc3RlbmVycyA9IHRydWU7XG4gIH1cblxuICBpZiAodHlwZW9mIG9wdHMuc2luY2UgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgc3RhcnRDaGFuZ2VzKCk7XG4gIH0gZWxzZSB7XG4gICAgaW5pdENoZWNrcG9pbnRlcigpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgd3JpdGluZ0NoZWNrcG9pbnQgPSB0cnVlO1xuICAgICAgcmV0dXJuIGNoZWNrcG9pbnRlci53cml0ZUNoZWNrcG9pbnQob3B0cy5zaW5jZSwgc2Vzc2lvbik7XG4gICAgfSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICB3cml0aW5nQ2hlY2twb2ludCA9IGZhbHNlO1xuICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgICBpZiAocmV0dXJuVmFsdWUuY2FuY2VsbGVkKSB7XG4gICAgICAgIGNvbXBsZXRlUmVwbGljYXRpb24oKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgbGFzdF9zZXEgPSBvcHRzLnNpbmNlO1xuICAgICAgc3RhcnRDaGFuZ2VzKCk7XG4gICAgfSkuY2F0Y2gob25DaGVja3BvaW50RXJyb3IpO1xuICB9XG59XG5cbi8vIFdlIGNyZWF0ZSBhIGJhc2ljIHByb21pc2Ugc28gdGhlIGNhbGxlciBjYW4gY2FuY2VsIHRoZSByZXBsaWNhdGlvbiBwb3NzaWJseVxuLy8gYmVmb3JlIHdlIGhhdmUgYWN0dWFsbHkgc3RhcnRlZCBsaXN0ZW5pbmcgdG8gY2hhbmdlcyBldGNcbmluaGVyaXRzKFJlcGxpY2F0aW9uLCBldmVudHMuRXZlbnRFbWl0dGVyKTtcbmZ1bmN0aW9uIFJlcGxpY2F0aW9uKCkge1xuICBldmVudHMuRXZlbnRFbWl0dGVyLmNhbGwodGhpcyk7XG4gIHRoaXMuY2FuY2VsbGVkID0gZmFsc2U7XG4gIHRoaXMuc3RhdGUgPSAncGVuZGluZyc7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIHByb21pc2UgPSBuZXcgUG91Y2hQcm9taXNlKGZ1bmN0aW9uIChmdWxmaWxsLCByZWplY3QpIHtcbiAgICBzZWxmLm9uY2UoJ2NvbXBsZXRlJywgZnVsZmlsbCk7XG4gICAgc2VsZi5vbmNlKCdlcnJvcicsIHJlamVjdCk7XG4gIH0pO1xuICBzZWxmLnRoZW4gPSBmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgcmV0dXJuIHByb21pc2UudGhlbihyZXNvbHZlLCByZWplY3QpO1xuICB9O1xuICBzZWxmLmNhdGNoID0gZnVuY3Rpb24gKHJlamVjdCkge1xuICAgIHJldHVybiBwcm9taXNlLmNhdGNoKHJlamVjdCk7XG4gIH07XG4gIC8vIEFzIHdlIGFsbG93IGVycm9yIGhhbmRsaW5nIHZpYSBcImVycm9yXCIgZXZlbnQgYXMgd2VsbCxcbiAgLy8gcHV0IGEgc3R1YiBpbiBoZXJlIHNvIHRoYXQgcmVqZWN0aW5nIG5ldmVyIHRocm93cyBVbmhhbmRsZWRFcnJvci5cbiAgc2VsZi5jYXRjaChmdW5jdGlvbiAoKSB7fSk7XG59XG5cblJlcGxpY2F0aW9uLnByb3RvdHlwZS5jYW5jZWwgPSBmdW5jdGlvbiAoKSB7XG4gIHRoaXMuY2FuY2VsbGVkID0gdHJ1ZTtcbiAgdGhpcy5zdGF0ZSA9ICdjYW5jZWxsZWQnO1xuICB0aGlzLmVtaXQoJ2NhbmNlbCcpO1xufTtcblxuUmVwbGljYXRpb24ucHJvdG90eXBlLnJlYWR5ID0gZnVuY3Rpb24gKHNyYywgdGFyZ2V0KSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgaWYgKHNlbGYuX3JlYWR5Q2FsbGVkKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHNlbGYuX3JlYWR5Q2FsbGVkID0gdHJ1ZTtcblxuICBmdW5jdGlvbiBvbkRlc3Ryb3koKSB7XG4gICAgc2VsZi5jYW5jZWwoKTtcbiAgfVxuICBzcmMub25jZSgnZGVzdHJveWVkJywgb25EZXN0cm95KTtcbiAgdGFyZ2V0Lm9uY2UoJ2Rlc3Ryb3llZCcsIG9uRGVzdHJveSk7XG4gIGZ1bmN0aW9uIGNsZWFudXAoKSB7XG4gICAgc3JjLnJlbW92ZUxpc3RlbmVyKCdkZXN0cm95ZWQnLCBvbkRlc3Ryb3kpO1xuICAgIHRhcmdldC5yZW1vdmVMaXN0ZW5lcignZGVzdHJveWVkJywgb25EZXN0cm95KTtcbiAgfVxuICBzZWxmLm9uY2UoJ2NvbXBsZXRlJywgY2xlYW51cCk7XG59O1xuXG5mdW5jdGlvbiB0b1BvdWNoKGRiLCBvcHRzKSB7XG4gIHZhciBQb3VjaENvbnN0cnVjdG9yID0gb3B0cy5Qb3VjaENvbnN0cnVjdG9yO1xuICBpZiAodHlwZW9mIGRiID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiBuZXcgUG91Y2hDb25zdHJ1Y3RvcihkYiwgb3B0cyk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGRiO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlcGxpY2F0ZShzcmMsIHRhcmdldCwgb3B0cywgY2FsbGJhY2spIHtcblxuICBpZiAodHlwZW9mIG9wdHMgPT09ICdmdW5jdGlvbicpIHtcbiAgICBjYWxsYmFjayA9IG9wdHM7XG4gICAgb3B0cyA9IHt9O1xuICB9XG4gIGlmICh0eXBlb2Ygb3B0cyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBvcHRzID0ge307XG4gIH1cblxuICBpZiAob3B0cy5kb2NfaWRzICYmICFBcnJheS5pc0FycmF5KG9wdHMuZG9jX2lkcykpIHtcbiAgICB0aHJvdyBjcmVhdGVFcnJvcihCQURfUkVRVUVTVCxcbiAgICAgICAgICAgICAgICAgICAgICAgXCJgZG9jX2lkc2AgZmlsdGVyIHBhcmFtZXRlciBpcyBub3QgYSBsaXN0LlwiKTtcbiAgfVxuXG4gIG9wdHMuY29tcGxldGUgPSBjYWxsYmFjaztcbiAgb3B0cyA9IGNsb25lKG9wdHMpO1xuICBvcHRzLmNvbnRpbnVvdXMgPSBvcHRzLmNvbnRpbnVvdXMgfHwgb3B0cy5saXZlO1xuICBvcHRzLnJldHJ5ID0gKCdyZXRyeScgaW4gb3B0cykgPyBvcHRzLnJldHJ5IDogZmFsc2U7XG4gIC8qanNoaW50IHZhbGlkdGhpczp0cnVlICovXG4gIG9wdHMuUG91Y2hDb25zdHJ1Y3RvciA9IG9wdHMuUG91Y2hDb25zdHJ1Y3RvciB8fCB0aGlzO1xuICB2YXIgcmVwbGljYXRlUmV0ID0gbmV3IFJlcGxpY2F0aW9uKG9wdHMpO1xuICB2YXIgc3JjUG91Y2ggPSB0b1BvdWNoKHNyYywgb3B0cyk7XG4gIHZhciB0YXJnZXRQb3VjaCA9IHRvUG91Y2godGFyZ2V0LCBvcHRzKTtcbiAgcmVwbGljYXRlJDEoc3JjUG91Y2gsIHRhcmdldFBvdWNoLCBvcHRzLCByZXBsaWNhdGVSZXQpO1xuICByZXR1cm4gcmVwbGljYXRlUmV0O1xufVxuXG5pbmhlcml0cyhTeW5jLCBldmVudHMuRXZlbnRFbWl0dGVyKTtcbmZ1bmN0aW9uIHN5bmMoc3JjLCB0YXJnZXQsIG9wdHMsIGNhbGxiYWNrKSB7XG4gIGlmICh0eXBlb2Ygb3B0cyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIGNhbGxiYWNrID0gb3B0cztcbiAgICBvcHRzID0ge307XG4gIH1cbiAgaWYgKHR5cGVvZiBvcHRzID09PSAndW5kZWZpbmVkJykge1xuICAgIG9wdHMgPSB7fTtcbiAgfVxuICBvcHRzID0gY2xvbmUob3B0cyk7XG4gIC8qanNoaW50IHZhbGlkdGhpczp0cnVlICovXG4gIG9wdHMuUG91Y2hDb25zdHJ1Y3RvciA9IG9wdHMuUG91Y2hDb25zdHJ1Y3RvciB8fCB0aGlzO1xuICBzcmMgPSB0b1BvdWNoKHNyYywgb3B0cyk7XG4gIHRhcmdldCA9IHRvUG91Y2godGFyZ2V0LCBvcHRzKTtcbiAgcmV0dXJuIG5ldyBTeW5jKHNyYywgdGFyZ2V0LCBvcHRzLCBjYWxsYmFjayk7XG59XG5cbmZ1bmN0aW9uIFN5bmMoc3JjLCB0YXJnZXQsIG9wdHMsIGNhbGxiYWNrKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdGhpcy5jYW5jZWxlZCA9IGZhbHNlO1xuXG4gIHZhciBvcHRzUHVzaCA9IG9wdHMucHVzaCA/IGV4dGVuZCQxKHt9LCBvcHRzLCBvcHRzLnB1c2gpIDogb3B0cztcbiAgdmFyIG9wdHNQdWxsID0gb3B0cy5wdWxsID8gZXh0ZW5kJDEoe30sIG9wdHMsIG9wdHMucHVsbCkgOiBvcHRzO1xuXG4gIHRoaXMucHVzaCA9IHJlcGxpY2F0ZShzcmMsIHRhcmdldCwgb3B0c1B1c2gpO1xuICB0aGlzLnB1bGwgPSByZXBsaWNhdGUodGFyZ2V0LCBzcmMsIG9wdHNQdWxsKTtcblxuICB0aGlzLnB1c2hQYXVzZWQgPSB0cnVlO1xuICB0aGlzLnB1bGxQYXVzZWQgPSB0cnVlO1xuXG4gIGZ1bmN0aW9uIHB1bGxDaGFuZ2UoY2hhbmdlKSB7XG4gICAgc2VsZi5lbWl0KCdjaGFuZ2UnLCB7XG4gICAgICBkaXJlY3Rpb246ICdwdWxsJyxcbiAgICAgIGNoYW5nZTogY2hhbmdlXG4gICAgfSk7XG4gIH1cbiAgZnVuY3Rpb24gcHVzaENoYW5nZShjaGFuZ2UpIHtcbiAgICBzZWxmLmVtaXQoJ2NoYW5nZScsIHtcbiAgICAgIGRpcmVjdGlvbjogJ3B1c2gnLFxuICAgICAgY2hhbmdlOiBjaGFuZ2VcbiAgICB9KTtcbiAgfVxuICBmdW5jdGlvbiBwdXNoRGVuaWVkKGRvYykge1xuICAgIHNlbGYuZW1pdCgnZGVuaWVkJywge1xuICAgICAgZGlyZWN0aW9uOiAncHVzaCcsXG4gICAgICBkb2M6IGRvY1xuICAgIH0pO1xuICB9XG4gIGZ1bmN0aW9uIHB1bGxEZW5pZWQoZG9jKSB7XG4gICAgc2VsZi5lbWl0KCdkZW5pZWQnLCB7XG4gICAgICBkaXJlY3Rpb246ICdwdWxsJyxcbiAgICAgIGRvYzogZG9jXG4gICAgfSk7XG4gIH1cbiAgZnVuY3Rpb24gcHVzaFBhdXNlZCgpIHtcbiAgICBzZWxmLnB1c2hQYXVzZWQgPSB0cnVlO1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgIGlmIChzZWxmLnB1bGxQYXVzZWQpIHtcbiAgICAgIHNlbGYuZW1pdCgncGF1c2VkJyk7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIHB1bGxQYXVzZWQoKSB7XG4gICAgc2VsZi5wdWxsUGF1c2VkID0gdHJ1ZTtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICBpZiAoc2VsZi5wdXNoUGF1c2VkKSB7XG4gICAgICBzZWxmLmVtaXQoJ3BhdXNlZCcpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBwdXNoQWN0aXZlKCkge1xuICAgIHNlbGYucHVzaFBhdXNlZCA9IGZhbHNlO1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgIGlmIChzZWxmLnB1bGxQYXVzZWQpIHtcbiAgICAgIHNlbGYuZW1pdCgnYWN0aXZlJywge1xuICAgICAgICBkaXJlY3Rpb246ICdwdXNoJ1xuICAgICAgfSk7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIHB1bGxBY3RpdmUoKSB7XG4gICAgc2VsZi5wdWxsUGF1c2VkID0gZmFsc2U7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgaWYgKHNlbGYucHVzaFBhdXNlZCkge1xuICAgICAgc2VsZi5lbWl0KCdhY3RpdmUnLCB7XG4gICAgICAgIGRpcmVjdGlvbjogJ3B1bGwnXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICB2YXIgcmVtb3ZlZCA9IHt9O1xuXG4gIGZ1bmN0aW9uIHJlbW92ZUFsbCh0eXBlKSB7IC8vIHR5cGUgaXMgJ3B1c2gnIG9yICdwdWxsJ1xuICAgIHJldHVybiBmdW5jdGlvbiAoZXZlbnQsIGZ1bmMpIHtcbiAgICAgIHZhciBpc0NoYW5nZSA9IGV2ZW50ID09PSAnY2hhbmdlJyAmJlxuICAgICAgICAoZnVuYyA9PT0gcHVsbENoYW5nZSB8fCBmdW5jID09PSBwdXNoQ2hhbmdlKTtcbiAgICAgIHZhciBpc0RlbmllZCA9IGV2ZW50ID09PSAnZGVuaWVkJyAmJlxuICAgICAgICAoZnVuYyA9PT0gcHVsbERlbmllZCB8fCBmdW5jID09PSBwdXNoRGVuaWVkKTtcbiAgICAgIHZhciBpc1BhdXNlZCA9IGV2ZW50ID09PSAncGF1c2VkJyAmJlxuICAgICAgICAoZnVuYyA9PT0gcHVsbFBhdXNlZCB8fCBmdW5jID09PSBwdXNoUGF1c2VkKTtcbiAgICAgIHZhciBpc0FjdGl2ZSA9IGV2ZW50ID09PSAnYWN0aXZlJyAmJlxuICAgICAgICAoZnVuYyA9PT0gcHVsbEFjdGl2ZSB8fCBmdW5jID09PSBwdXNoQWN0aXZlKTtcblxuICAgICAgaWYgKGlzQ2hhbmdlIHx8IGlzRGVuaWVkIHx8IGlzUGF1c2VkIHx8IGlzQWN0aXZlKSB7XG4gICAgICAgIGlmICghKGV2ZW50IGluIHJlbW92ZWQpKSB7XG4gICAgICAgICAgcmVtb3ZlZFtldmVudF0gPSB7fTtcbiAgICAgICAgfVxuICAgICAgICByZW1vdmVkW2V2ZW50XVt0eXBlXSA9IHRydWU7XG4gICAgICAgIGlmIChPYmplY3Qua2V5cyhyZW1vdmVkW2V2ZW50XSkubGVuZ3RoID09PSAyKSB7XG4gICAgICAgICAgLy8gYm90aCBwdXNoIGFuZCBwdWxsIGhhdmUgYXNrZWQgdG8gYmUgcmVtb3ZlZFxuICAgICAgICAgIHNlbGYucmVtb3ZlQWxsTGlzdGVuZXJzKGV2ZW50KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG4gIH1cblxuICBpZiAob3B0cy5saXZlKSB7XG4gICAgdGhpcy5wdXNoLm9uKCdjb21wbGV0ZScsIHNlbGYucHVsbC5jYW5jZWwuYmluZChzZWxmLnB1bGwpKTtcbiAgICB0aGlzLnB1bGwub24oJ2NvbXBsZXRlJywgc2VsZi5wdXNoLmNhbmNlbC5iaW5kKHNlbGYucHVzaCkpO1xuICB9XG5cbiAgZnVuY3Rpb24gYWRkT25lTGlzdGVuZXIoZWUsIGV2ZW50LCBsaXN0ZW5lcikge1xuICAgIGlmIChlZS5saXN0ZW5lcnMoZXZlbnQpLmluZGV4T2YobGlzdGVuZXIpID09IC0xKSB7XG4gICAgICBlZS5vbihldmVudCwgbGlzdGVuZXIpO1xuICAgIH1cbiAgfVxuXG4gIHRoaXMub24oJ25ld0xpc3RlbmVyJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgaWYgKGV2ZW50ID09PSAnY2hhbmdlJykge1xuICAgICAgYWRkT25lTGlzdGVuZXIoc2VsZi5wdWxsLCAnY2hhbmdlJywgcHVsbENoYW5nZSk7XG4gICAgICBhZGRPbmVMaXN0ZW5lcihzZWxmLnB1c2gsICdjaGFuZ2UnLCBwdXNoQ2hhbmdlKTtcbiAgICB9IGVsc2UgaWYgKGV2ZW50ID09PSAnZGVuaWVkJykge1xuICAgICAgYWRkT25lTGlzdGVuZXIoc2VsZi5wdWxsLCAnZGVuaWVkJywgcHVsbERlbmllZCk7XG4gICAgICBhZGRPbmVMaXN0ZW5lcihzZWxmLnB1c2gsICdkZW5pZWQnLCBwdXNoRGVuaWVkKTtcbiAgICB9IGVsc2UgaWYgKGV2ZW50ID09PSAnYWN0aXZlJykge1xuICAgICAgYWRkT25lTGlzdGVuZXIoc2VsZi5wdWxsLCAnYWN0aXZlJywgcHVsbEFjdGl2ZSk7XG4gICAgICBhZGRPbmVMaXN0ZW5lcihzZWxmLnB1c2gsICdhY3RpdmUnLCBwdXNoQWN0aXZlKTtcbiAgICB9IGVsc2UgaWYgKGV2ZW50ID09PSAncGF1c2VkJykge1xuICAgICAgYWRkT25lTGlzdGVuZXIoc2VsZi5wdWxsLCAncGF1c2VkJywgcHVsbFBhdXNlZCk7XG4gICAgICBhZGRPbmVMaXN0ZW5lcihzZWxmLnB1c2gsICdwYXVzZWQnLCBwdXNoUGF1c2VkKTtcbiAgICB9XG4gIH0pO1xuXG4gIHRoaXMub24oJ3JlbW92ZUxpc3RlbmVyJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgaWYgKGV2ZW50ID09PSAnY2hhbmdlJykge1xuICAgICAgc2VsZi5wdWxsLnJlbW92ZUxpc3RlbmVyKCdjaGFuZ2UnLCBwdWxsQ2hhbmdlKTtcbiAgICAgIHNlbGYucHVzaC5yZW1vdmVMaXN0ZW5lcignY2hhbmdlJywgcHVzaENoYW5nZSk7XG4gICAgfSBlbHNlIGlmIChldmVudCA9PT0gJ2RlbmllZCcpIHtcbiAgICAgIHNlbGYucHVsbC5yZW1vdmVMaXN0ZW5lcignZGVuaWVkJywgcHVsbERlbmllZCk7XG4gICAgICBzZWxmLnB1c2gucmVtb3ZlTGlzdGVuZXIoJ2RlbmllZCcsIHB1c2hEZW5pZWQpO1xuICAgIH0gZWxzZSBpZiAoZXZlbnQgPT09ICdhY3RpdmUnKSB7XG4gICAgICBzZWxmLnB1bGwucmVtb3ZlTGlzdGVuZXIoJ2FjdGl2ZScsIHB1bGxBY3RpdmUpO1xuICAgICAgc2VsZi5wdXNoLnJlbW92ZUxpc3RlbmVyKCdhY3RpdmUnLCBwdXNoQWN0aXZlKTtcbiAgICB9IGVsc2UgaWYgKGV2ZW50ID09PSAncGF1c2VkJykge1xuICAgICAgc2VsZi5wdWxsLnJlbW92ZUxpc3RlbmVyKCdwYXVzZWQnLCBwdWxsUGF1c2VkKTtcbiAgICAgIHNlbGYucHVzaC5yZW1vdmVMaXN0ZW5lcigncGF1c2VkJywgcHVzaFBhdXNlZCk7XG4gICAgfVxuICB9KTtcblxuICB0aGlzLnB1bGwub24oJ3JlbW92ZUxpc3RlbmVyJywgcmVtb3ZlQWxsKCdwdWxsJykpO1xuICB0aGlzLnB1c2gub24oJ3JlbW92ZUxpc3RlbmVyJywgcmVtb3ZlQWxsKCdwdXNoJykpO1xuXG4gIHZhciBwcm9taXNlID0gUG91Y2hQcm9taXNlLmFsbChbXG4gICAgdGhpcy5wdXNoLFxuICAgIHRoaXMucHVsbFxuICBdKS50aGVuKGZ1bmN0aW9uIChyZXNwKSB7XG4gICAgdmFyIG91dCA9IHtcbiAgICAgIHB1c2g6IHJlc3BbMF0sXG4gICAgICBwdWxsOiByZXNwWzFdXG4gICAgfTtcbiAgICBzZWxmLmVtaXQoJ2NvbXBsZXRlJywgb3V0KTtcbiAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgIGNhbGxiYWNrKG51bGwsIG91dCk7XG4gICAgfVxuICAgIHNlbGYucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgcmV0dXJuIG91dDtcbiAgfSwgZnVuY3Rpb24gKGVycikge1xuICAgIHNlbGYuY2FuY2VsKCk7XG4gICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAvLyBpZiB0aGVyZSdzIGEgY2FsbGJhY2ssIHRoZW4gdGhlIGNhbGxiYWNrIGNhbiByZWNlaXZlXG4gICAgICAvLyB0aGUgZXJyb3IgZXZlbnRcbiAgICAgIGNhbGxiYWNrKGVycik7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGlmIHRoZXJlJ3Mgbm8gY2FsbGJhY2ssIHRoZW4gd2UncmUgc2FmZSB0byBlbWl0IGFuIGVycm9yXG4gICAgICAvLyBldmVudCwgd2hpY2ggd291bGQgb3RoZXJ3aXNlIHRocm93IGFuIHVuaGFuZGxlZCBlcnJvclxuICAgICAgLy8gZHVlIHRvICdlcnJvcicgYmVpbmcgYSBzcGVjaWFsIGV2ZW50IGluIEV2ZW50RW1pdHRlcnNcbiAgICAgIHNlbGYuZW1pdCgnZXJyb3InLCBlcnIpO1xuICAgIH1cbiAgICBzZWxmLnJlbW92ZUFsbExpc3RlbmVycygpO1xuICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgLy8gbm8gc2Vuc2UgdGhyb3dpbmcgaWYgd2UncmUgYWxyZWFkeSBlbWl0dGluZyBhbiAnZXJyb3InIGV2ZW50XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICB9KTtcblxuICB0aGlzLnRoZW4gPSBmdW5jdGlvbiAoc3VjY2VzcywgZXJyKSB7XG4gICAgcmV0dXJuIHByb21pc2UudGhlbihzdWNjZXNzLCBlcnIpO1xuICB9O1xuXG4gIHRoaXMuY2F0Y2ggPSBmdW5jdGlvbiAoZXJyKSB7XG4gICAgcmV0dXJuIHByb21pc2UuY2F0Y2goZXJyKTtcbiAgfTtcbn1cblxuU3luYy5wcm90b3R5cGUuY2FuY2VsID0gZnVuY3Rpb24gKCkge1xuICBpZiAoIXRoaXMuY2FuY2VsZWQpIHtcbiAgICB0aGlzLmNhbmNlbGVkID0gdHJ1ZTtcbiAgICB0aGlzLnB1c2guY2FuY2VsKCk7XG4gICAgdGhpcy5wdWxsLmNhbmNlbCgpO1xuICB9XG59O1xuXG5mdW5jdGlvbiByZXBsaWNhdGlvbihQb3VjaERCKSB7XG4gIFBvdWNoREIucmVwbGljYXRlID0gcmVwbGljYXRlO1xuICBQb3VjaERCLnN5bmMgPSBzeW5jO1xuXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShQb3VjaERCLnByb3RvdHlwZSwgJ3JlcGxpY2F0ZScsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGZyb206IGZ1bmN0aW9uIChvdGhlciwgb3B0cywgY2FsbGJhY2spIHtcbiAgICAgICAgICByZXR1cm4gc2VsZi5jb25zdHJ1Y3Rvci5yZXBsaWNhdGUob3RoZXIsIHNlbGYsIG9wdHMsIGNhbGxiYWNrKTtcbiAgICAgICAgfSxcbiAgICAgICAgdG86IGZ1bmN0aW9uIChvdGhlciwgb3B0cywgY2FsbGJhY2spIHtcbiAgICAgICAgICByZXR1cm4gc2VsZi5jb25zdHJ1Y3Rvci5yZXBsaWNhdGUoc2VsZiwgb3RoZXIsIG9wdHMsIGNhbGxiYWNrKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG4gIH0pO1xuXG4gIFBvdWNoREIucHJvdG90eXBlLnN5bmMgPSBmdW5jdGlvbiAoZGJOYW1lLCBvcHRzLCBjYWxsYmFjaykge1xuICAgIHJldHVybiB0aGlzLmNvbnN0cnVjdG9yLnN5bmModGhpcywgZGJOYW1lLCBvcHRzLCBjYWxsYmFjayk7XG4gIH07XG59XG5cblBvdWNoREIucGx1Z2luKElEQlBvdWNoKVxuICAucGx1Z2luKFdlYlNxbFBvdWNoKVxuICAucGx1Z2luKEh0dHBQb3VjaCQxKVxuICAucGx1Z2luKG1hcHJlZHVjZSlcbiAgLnBsdWdpbihyZXBsaWNhdGlvbik7XG5cbi8vIFB1bGwgZnJvbSBzcmMgYmVjYXVzZSBwb3VjaGRiLW5vZGUvcG91Y2hkYi1icm93c2VyIHRoZW1zZWx2ZXNcbi8vIGFyZSBhZ2dyZXNzaXZlbHkgb3B0aW1pemVkIGFuZCBqc25leHQ6bWFpbiB3b3VsZCBub3JtYWxseSBnaXZlIHVzIHRoaXNcbi8vIGFnZ3Jlc3NpdmUgYnVuZGxlLlxuXG5tb2R1bGUuZXhwb3J0cyA9IFBvdWNoREI7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L3BvdWNoZGIvbGliL2luZGV4LWJyb3dzZXIuanNcbi8vIG1vZHVsZSBpZCA9IDg5XG4vLyBtb2R1bGUgY2h1bmtzID0gMCJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 90 */
- /***/ function(module, exports, __webpack_require__) {
- eval("'use strict';\nvar immediate = __webpack_require__(91);\n\n/* istanbul ignore next */\nfunction INTERNAL() {}\n\nvar handlers = {};\n\nvar REJECTED = ['REJECTED'];\nvar FULFILLED = ['FULFILLED'];\nvar PENDING = ['PENDING'];\n\nmodule.exports = Promise;\n\nfunction Promise(resolver) {\n if (typeof resolver !== 'function') {\n throw new TypeError('resolver must be a function');\n }\n this.state = PENDING;\n this.queue = [];\n this.outcome = void 0;\n if (resolver !== INTERNAL) {\n safelyResolveThenable(this, resolver);\n }\n}\n\nPromise.prototype[\"catch\"] = function (onRejected) {\n return this.then(null, onRejected);\n};\nPromise.prototype.then = function (onFulfilled, onRejected) {\n if (typeof onFulfilled !== 'function' && this.state === FULFILLED ||\n typeof onRejected !== 'function' && this.state === REJECTED) {\n return this;\n }\n var promise = new this.constructor(INTERNAL);\n if (this.state !== PENDING) {\n var resolver = this.state === FULFILLED ? onFulfilled : onRejected;\n unwrap(promise, resolver, this.outcome);\n } else {\n this.queue.push(new QueueItem(promise, onFulfilled, onRejected));\n }\n\n return promise;\n};\nfunction QueueItem(promise, onFulfilled, onRejected) {\n this.promise = promise;\n if (typeof onFulfilled === 'function') {\n this.onFulfilled = onFulfilled;\n this.callFulfilled = this.otherCallFulfilled;\n }\n if (typeof onRejected === 'function') {\n this.onRejected = onRejected;\n this.callRejected = this.otherCallRejected;\n }\n}\nQueueItem.prototype.callFulfilled = function (value) {\n handlers.resolve(this.promise, value);\n};\nQueueItem.prototype.otherCallFulfilled = function (value) {\n unwrap(this.promise, this.onFulfilled, value);\n};\nQueueItem.prototype.callRejected = function (value) {\n handlers.reject(this.promise, value);\n};\nQueueItem.prototype.otherCallRejected = function (value) {\n unwrap(this.promise, this.onRejected, value);\n};\n\nfunction unwrap(promise, func, value) {\n immediate(function () {\n var returnValue;\n try {\n returnValue = func(value);\n } catch (e) {\n return handlers.reject(promise, e);\n }\n if (returnValue === promise) {\n handlers.reject(promise, new TypeError('Cannot resolve promise with itself'));\n } else {\n handlers.resolve(promise, returnValue);\n }\n });\n}\n\nhandlers.resolve = function (self, value) {\n var result = tryCatch(getThen, value);\n if (result.status === 'error') {\n return handlers.reject(self, result.value);\n }\n var thenable = result.value;\n\n if (thenable) {\n safelyResolveThenable(self, thenable);\n } else {\n self.state = FULFILLED;\n self.outcome = value;\n var i = -1;\n var len = self.queue.length;\n while (++i < len) {\n self.queue[i].callFulfilled(value);\n }\n }\n return self;\n};\nhandlers.reject = function (self, error) {\n self.state = REJECTED;\n self.outcome = error;\n var i = -1;\n var len = self.queue.length;\n while (++i < len) {\n self.queue[i].callRejected(error);\n }\n return self;\n};\n\nfunction getThen(obj) {\n // Make sure we only access the accessor once as required by the spec\n var then = obj && obj.then;\n if (obj && typeof obj === 'object' && typeof then === 'function') {\n return function appyThen() {\n then.apply(obj, arguments);\n };\n }\n}\n\nfunction safelyResolveThenable(self, thenable) {\n // Either fulfill, reject or reject with error\n var called = false;\n function onError(value) {\n if (called) {\n return;\n }\n called = true;\n handlers.reject(self, value);\n }\n\n function onSuccess(value) {\n if (called) {\n return;\n }\n called = true;\n handlers.resolve(self, value);\n }\n\n function tryToUnwrap() {\n thenable(onSuccess, onError);\n }\n\n var result = tryCatch(tryToUnwrap);\n if (result.status === 'error') {\n onError(result.value);\n }\n}\n\nfunction tryCatch(func, value) {\n var out = {};\n try {\n out.value = func(value);\n out.status = 'success';\n } catch (e) {\n out.status = 'error';\n out.value = e;\n }\n return out;\n}\n\nPromise.resolve = resolve;\nfunction resolve(value) {\n if (value instanceof this) {\n return value;\n }\n return handlers.resolve(new this(INTERNAL), value);\n}\n\nPromise.reject = reject;\nfunction reject(reason) {\n var promise = new this(INTERNAL);\n return handlers.reject(promise, reason);\n}\n\nPromise.all = all;\nfunction all(iterable) {\n var self = this;\n if (Object.prototype.toString.call(iterable) !== '[object Array]') {\n return this.reject(new TypeError('must be an array'));\n }\n\n var len = iterable.length;\n var called = false;\n if (!len) {\n return this.resolve([]);\n }\n\n var values = new Array(len);\n var resolved = 0;\n var i = -1;\n var promise = new this(INTERNAL);\n\n while (++i < len) {\n allResolver(iterable[i], i);\n }\n return promise;\n function allResolver(value, i) {\n self.resolve(value).then(resolveFromAll, function (error) {\n if (!called) {\n called = true;\n handlers.reject(promise, error);\n }\n });\n function resolveFromAll(outValue) {\n values[i] = outValue;\n if (++resolved === len && !called) {\n called = true;\n handlers.resolve(promise, values);\n }\n }\n }\n}\n\nPromise.race = race;\nfunction race(iterable) {\n var self = this;\n if (Object.prototype.toString.call(iterable) !== '[object Array]') {\n return this.reject(new TypeError('must be an array'));\n }\n\n var len = iterable.length;\n var called = false;\n if (!len) {\n return this.resolve([]);\n }\n\n var i = -1;\n var promise = new this(INTERNAL);\n\n while (++i < len) {\n resolver(iterable[i]);\n }\n return promise;\n function resolver(value) {\n self.resolve(value).then(function (response) {\n if (!called) {\n called = true;\n handlers.resolve(promise, response);\n }\n }, function (error) {\n if (!called) {\n called = true;\n handlers.reject(promise, error);\n }\n });\n }\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiOTAuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2xpZS9saWIvYnJvd3Nlci5qcz83MGFhIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcbnZhciBpbW1lZGlhdGUgPSByZXF1aXJlKCdpbW1lZGlhdGUnKTtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbmZ1bmN0aW9uIElOVEVSTkFMKCkge31cblxudmFyIGhhbmRsZXJzID0ge307XG5cbnZhciBSRUpFQ1RFRCA9IFsnUkVKRUNURUQnXTtcbnZhciBGVUxGSUxMRUQgPSBbJ0ZVTEZJTExFRCddO1xudmFyIFBFTkRJTkcgPSBbJ1BFTkRJTkcnXTtcblxubW9kdWxlLmV4cG9ydHMgPSBQcm9taXNlO1xuXG5mdW5jdGlvbiBQcm9taXNlKHJlc29sdmVyKSB7XG4gIGlmICh0eXBlb2YgcmVzb2x2ZXIgIT09ICdmdW5jdGlvbicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdyZXNvbHZlciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgfVxuICB0aGlzLnN0YXRlID0gUEVORElORztcbiAgdGhpcy5xdWV1ZSA9IFtdO1xuICB0aGlzLm91dGNvbWUgPSB2b2lkIDA7XG4gIGlmIChyZXNvbHZlciAhPT0gSU5URVJOQUwpIHtcbiAgICBzYWZlbHlSZXNvbHZlVGhlbmFibGUodGhpcywgcmVzb2x2ZXIpO1xuICB9XG59XG5cblByb21pc2UucHJvdG90eXBlW1wiY2F0Y2hcIl0gPSBmdW5jdGlvbiAob25SZWplY3RlZCkge1xuICByZXR1cm4gdGhpcy50aGVuKG51bGwsIG9uUmVqZWN0ZWQpO1xufTtcblByb21pc2UucHJvdG90eXBlLnRoZW4gPSBmdW5jdGlvbiAob25GdWxmaWxsZWQsIG9uUmVqZWN0ZWQpIHtcbiAgaWYgKHR5cGVvZiBvbkZ1bGZpbGxlZCAhPT0gJ2Z1bmN0aW9uJyAmJiB0aGlzLnN0YXRlID09PSBGVUxGSUxMRUQgfHxcbiAgICB0eXBlb2Ygb25SZWplY3RlZCAhPT0gJ2Z1bmN0aW9uJyAmJiB0aGlzLnN0YXRlID09PSBSRUpFQ1RFRCkge1xuICAgIHJldHVybiB0aGlzO1xuICB9XG4gIHZhciBwcm9taXNlID0gbmV3IHRoaXMuY29uc3RydWN0b3IoSU5URVJOQUwpO1xuICBpZiAodGhpcy5zdGF0ZSAhPT0gUEVORElORykge1xuICAgIHZhciByZXNvbHZlciA9IHRoaXMuc3RhdGUgPT09IEZVTEZJTExFRCA/IG9uRnVsZmlsbGVkIDogb25SZWplY3RlZDtcbiAgICB1bndyYXAocHJvbWlzZSwgcmVzb2x2ZXIsIHRoaXMub3V0Y29tZSk7XG4gIH0gZWxzZSB7XG4gICAgdGhpcy5xdWV1ZS5wdXNoKG5ldyBRdWV1ZUl0ZW0ocHJvbWlzZSwgb25GdWxmaWxsZWQsIG9uUmVqZWN0ZWQpKTtcbiAgfVxuXG4gIHJldHVybiBwcm9taXNlO1xufTtcbmZ1bmN0aW9uIFF1ZXVlSXRlbShwcm9taXNlLCBvbkZ1bGZpbGxlZCwgb25SZWplY3RlZCkge1xuICB0aGlzLnByb21pc2UgPSBwcm9taXNlO1xuICBpZiAodHlwZW9mIG9uRnVsZmlsbGVkID09PSAnZnVuY3Rpb24nKSB7XG4gICAgdGhpcy5vbkZ1bGZpbGxlZCA9IG9uRnVsZmlsbGVkO1xuICAgIHRoaXMuY2FsbEZ1bGZpbGxlZCA9IHRoaXMub3RoZXJDYWxsRnVsZmlsbGVkO1xuICB9XG4gIGlmICh0eXBlb2Ygb25SZWplY3RlZCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHRoaXMub25SZWplY3RlZCA9IG9uUmVqZWN0ZWQ7XG4gICAgdGhpcy5jYWxsUmVqZWN0ZWQgPSB0aGlzLm90aGVyQ2FsbFJlamVjdGVkO1xuICB9XG59XG5RdWV1ZUl0ZW0ucHJvdG90eXBlLmNhbGxGdWxmaWxsZWQgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgaGFuZGxlcnMucmVzb2x2ZSh0aGlzLnByb21pc2UsIHZhbHVlKTtcbn07XG5RdWV1ZUl0ZW0ucHJvdG90eXBlLm90aGVyQ2FsbEZ1bGZpbGxlZCA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICB1bndyYXAodGhpcy5wcm9taXNlLCB0aGlzLm9uRnVsZmlsbGVkLCB2YWx1ZSk7XG59O1xuUXVldWVJdGVtLnByb3RvdHlwZS5jYWxsUmVqZWN0ZWQgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgaGFuZGxlcnMucmVqZWN0KHRoaXMucHJvbWlzZSwgdmFsdWUpO1xufTtcblF1ZXVlSXRlbS5wcm90b3R5cGUub3RoZXJDYWxsUmVqZWN0ZWQgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgdW53cmFwKHRoaXMucHJvbWlzZSwgdGhpcy5vblJlamVjdGVkLCB2YWx1ZSk7XG59O1xuXG5mdW5jdGlvbiB1bndyYXAocHJvbWlzZSwgZnVuYywgdmFsdWUpIHtcbiAgaW1tZWRpYXRlKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcmV0dXJuVmFsdWU7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVyblZhbHVlID0gZnVuYyh2YWx1ZSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIGhhbmRsZXJzLnJlamVjdChwcm9taXNlLCBlKTtcbiAgICB9XG4gICAgaWYgKHJldHVyblZhbHVlID09PSBwcm9taXNlKSB7XG4gICAgICBoYW5kbGVycy5yZWplY3QocHJvbWlzZSwgbmV3IFR5cGVFcnJvcignQ2Fubm90IHJlc29sdmUgcHJvbWlzZSB3aXRoIGl0c2VsZicpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaGFuZGxlcnMucmVzb2x2ZShwcm9taXNlLCByZXR1cm5WYWx1ZSk7XG4gICAgfVxuICB9KTtcbn1cblxuaGFuZGxlcnMucmVzb2x2ZSA9IGZ1bmN0aW9uIChzZWxmLCB2YWx1ZSkge1xuICB2YXIgcmVzdWx0ID0gdHJ5Q2F0Y2goZ2V0VGhlbiwgdmFsdWUpO1xuICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gJ2Vycm9yJykge1xuICAgIHJldHVybiBoYW5kbGVycy5yZWplY3Qoc2VsZiwgcmVzdWx0LnZhbHVlKTtcbiAgfVxuICB2YXIgdGhlbmFibGUgPSByZXN1bHQudmFsdWU7XG5cbiAgaWYgKHRoZW5hYmxlKSB7XG4gICAgc2FmZWx5UmVzb2x2ZVRoZW5hYmxlKHNlbGYsIHRoZW5hYmxlKTtcbiAgfSBlbHNlIHtcbiAgICBzZWxmLnN0YXRlID0gRlVMRklMTEVEO1xuICAgIHNlbGYub3V0Y29tZSA9IHZhbHVlO1xuICAgIHZhciBpID0gLTE7XG4gICAgdmFyIGxlbiA9IHNlbGYucXVldWUubGVuZ3RoO1xuICAgIHdoaWxlICgrK2kgPCBsZW4pIHtcbiAgICAgIHNlbGYucXVldWVbaV0uY2FsbEZ1bGZpbGxlZCh2YWx1ZSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBzZWxmO1xufTtcbmhhbmRsZXJzLnJlamVjdCA9IGZ1bmN0aW9uIChzZWxmLCBlcnJvcikge1xuICBzZWxmLnN0YXRlID0gUkVKRUNURUQ7XG4gIHNlbGYub3V0Y29tZSA9IGVycm9yO1xuICB2YXIgaSA9IC0xO1xuICB2YXIgbGVuID0gc2VsZi5xdWV1ZS5sZW5ndGg7XG4gIHdoaWxlICgrK2kgPCBsZW4pIHtcbiAgICBzZWxmLnF1ZXVlW2ldLmNhbGxSZWplY3RlZChlcnJvcik7XG4gIH1cbiAgcmV0dXJuIHNlbGY7XG59O1xuXG5mdW5jdGlvbiBnZXRUaGVuKG9iaikge1xuICAvLyBNYWtlIHN1cmUgd2Ugb25seSBhY2Nlc3MgdGhlIGFjY2Vzc29yIG9uY2UgYXMgcmVxdWlyZWQgYnkgdGhlIHNwZWNcbiAgdmFyIHRoZW4gPSBvYmogJiYgb2JqLnRoZW47XG4gIGlmIChvYmogJiYgdHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIHRoZW4gPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gYXBweVRoZW4oKSB7XG4gICAgICB0aGVuLmFwcGx5KG9iaiwgYXJndW1lbnRzKTtcbiAgICB9O1xuICB9XG59XG5cbmZ1bmN0aW9uIHNhZmVseVJlc29sdmVUaGVuYWJsZShzZWxmLCB0aGVuYWJsZSkge1xuICAvLyBFaXRoZXIgZnVsZmlsbCwgcmVqZWN0IG9yIHJlamVjdCB3aXRoIGVycm9yXG4gIHZhciBjYWxsZWQgPSBmYWxzZTtcbiAgZnVuY3Rpb24gb25FcnJvcih2YWx1ZSkge1xuICAgIGlmIChjYWxsZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY2FsbGVkID0gdHJ1ZTtcbiAgICBoYW5kbGVycy5yZWplY3Qoc2VsZiwgdmFsdWUpO1xuICB9XG5cbiAgZnVuY3Rpb24gb25TdWNjZXNzKHZhbHVlKSB7XG4gICAgaWYgKGNhbGxlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjYWxsZWQgPSB0cnVlO1xuICAgIGhhbmRsZXJzLnJlc29sdmUoc2VsZiwgdmFsdWUpO1xuICB9XG5cbiAgZnVuY3Rpb24gdHJ5VG9VbndyYXAoKSB7XG4gICAgdGhlbmFibGUob25TdWNjZXNzLCBvbkVycm9yKTtcbiAgfVxuXG4gIHZhciByZXN1bHQgPSB0cnlDYXRjaCh0cnlUb1Vud3JhcCk7XG4gIGlmIChyZXN1bHQuc3RhdHVzID09PSAnZXJyb3InKSB7XG4gICAgb25FcnJvcihyZXN1bHQudmFsdWUpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRyeUNhdGNoKGZ1bmMsIHZhbHVlKSB7XG4gIHZhciBvdXQgPSB7fTtcbiAgdHJ5IHtcbiAgICBvdXQudmFsdWUgPSBmdW5jKHZhbHVlKTtcbiAgICBvdXQuc3RhdHVzID0gJ3N1Y2Nlc3MnO1xuICB9IGNhdGNoIChlKSB7XG4gICAgb3V0LnN0YXR1cyA9ICdlcnJvcic7XG4gICAgb3V0LnZhbHVlID0gZTtcbiAgfVxuICByZXR1cm4gb3V0O1xufVxuXG5Qcm9taXNlLnJlc29sdmUgPSByZXNvbHZlO1xuZnVuY3Rpb24gcmVzb2x2ZSh2YWx1ZSkge1xuICBpZiAodmFsdWUgaW5zdGFuY2VvZiB0aGlzKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG4gIHJldHVybiBoYW5kbGVycy5yZXNvbHZlKG5ldyB0aGlzKElOVEVSTkFMKSwgdmFsdWUpO1xufVxuXG5Qcm9taXNlLnJlamVjdCA9IHJlamVjdDtcbmZ1bmN0aW9uIHJlamVjdChyZWFzb24pIHtcbiAgdmFyIHByb21pc2UgPSBuZXcgdGhpcyhJTlRFUk5BTCk7XG4gIHJldHVybiBoYW5kbGVycy5yZWplY3QocHJvbWlzZSwgcmVhc29uKTtcbn1cblxuUHJvbWlzZS5hbGwgPSBhbGw7XG5mdW5jdGlvbiBhbGwoaXRlcmFibGUpIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGl0ZXJhYmxlKSAhPT0gJ1tvYmplY3QgQXJyYXldJykge1xuICAgIHJldHVybiB0aGlzLnJlamVjdChuZXcgVHlwZUVycm9yKCdtdXN0IGJlIGFuIGFycmF5JykpO1xuICB9XG5cbiAgdmFyIGxlbiA9IGl0ZXJhYmxlLmxlbmd0aDtcbiAgdmFyIGNhbGxlZCA9IGZhbHNlO1xuICBpZiAoIWxlbikge1xuICAgIHJldHVybiB0aGlzLnJlc29sdmUoW10pO1xuICB9XG5cbiAgdmFyIHZhbHVlcyA9IG5ldyBBcnJheShsZW4pO1xuICB2YXIgcmVzb2x2ZWQgPSAwO1xuICB2YXIgaSA9IC0xO1xuICB2YXIgcHJvbWlzZSA9IG5ldyB0aGlzKElOVEVSTkFMKTtcblxuICB3aGlsZSAoKytpIDwgbGVuKSB7XG4gICAgYWxsUmVzb2x2ZXIoaXRlcmFibGVbaV0sIGkpO1xuICB9XG4gIHJldHVybiBwcm9taXNlO1xuICBmdW5jdGlvbiBhbGxSZXNvbHZlcih2YWx1ZSwgaSkge1xuICAgIHNlbGYucmVzb2x2ZSh2YWx1ZSkudGhlbihyZXNvbHZlRnJvbUFsbCwgZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICBpZiAoIWNhbGxlZCkge1xuICAgICAgICBjYWxsZWQgPSB0cnVlO1xuICAgICAgICBoYW5kbGVycy5yZWplY3QocHJvbWlzZSwgZXJyb3IpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGZ1bmN0aW9uIHJlc29sdmVGcm9tQWxsKG91dFZhbHVlKSB7XG4gICAgICB2YWx1ZXNbaV0gPSBvdXRWYWx1ZTtcbiAgICAgIGlmICgrK3Jlc29sdmVkID09PSBsZW4gJiYgIWNhbGxlZCkge1xuICAgICAgICBjYWxsZWQgPSB0cnVlO1xuICAgICAgICBoYW5kbGVycy5yZXNvbHZlKHByb21pc2UsIHZhbHVlcyk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cblByb21pc2UucmFjZSA9IHJhY2U7XG5mdW5jdGlvbiByYWNlKGl0ZXJhYmxlKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChpdGVyYWJsZSkgIT09ICdbb2JqZWN0IEFycmF5XScpIHtcbiAgICByZXR1cm4gdGhpcy5yZWplY3QobmV3IFR5cGVFcnJvcignbXVzdCBiZSBhbiBhcnJheScpKTtcbiAgfVxuXG4gIHZhciBsZW4gPSBpdGVyYWJsZS5sZW5ndGg7XG4gIHZhciBjYWxsZWQgPSBmYWxzZTtcbiAgaWYgKCFsZW4pIHtcbiAgICByZXR1cm4gdGhpcy5yZXNvbHZlKFtdKTtcbiAgfVxuXG4gIHZhciBpID0gLTE7XG4gIHZhciBwcm9taXNlID0gbmV3IHRoaXMoSU5URVJOQUwpO1xuXG4gIHdoaWxlICgrK2kgPCBsZW4pIHtcbiAgICByZXNvbHZlcihpdGVyYWJsZVtpXSk7XG4gIH1cbiAgcmV0dXJuIHByb21pc2U7XG4gIGZ1bmN0aW9uIHJlc29sdmVyKHZhbHVlKSB7XG4gICAgc2VsZi5yZXNvbHZlKHZhbHVlKS50aGVuKGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgaWYgKCFjYWxsZWQpIHtcbiAgICAgICAgY2FsbGVkID0gdHJ1ZTtcbiAgICAgICAgaGFuZGxlcnMucmVzb2x2ZShwcm9taXNlLCByZXNwb25zZSk7XG4gICAgICB9XG4gICAgfSwgZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICBpZiAoIWNhbGxlZCkge1xuICAgICAgICBjYWxsZWQgPSB0cnVlO1xuICAgICAgICBoYW5kbGVycy5yZWplY3QocHJvbWlzZSwgZXJyb3IpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG59XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vbGllL2xpYi9icm93c2VyLmpzXG4vLyBtb2R1bGUgaWQgPSA5MFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOyIsInNvdXJjZVJvb3QiOiIifQ==");
- /***/ },
- /* 91 */
- /***/ function(module, exports) {
- eval("/* WEBPACK VAR INJECTION */(function(global) {'use strict';\nvar Mutation = global.MutationObserver || global.WebKitMutationObserver;\n\nvar scheduleDrain;\n\n{\n if (Mutation) {\n var called = 0;\n var observer = new Mutation(nextTick);\n var element = global.document.createTextNode('');\n observer.observe(element, {\n characterData: true\n });\n scheduleDrain = function () {\n element.data = (called = ++called % 2);\n };\n } else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') {\n var channel = new global.MessageChannel();\n channel.port1.onmessage = nextTick;\n scheduleDrain = function () {\n channel.port2.postMessage(0);\n };\n } else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) {\n scheduleDrain = function () {\n\n // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted\n // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.\n var scriptEl = global.document.createElement('script');\n scriptEl.onreadystatechange = function () {\n nextTick();\n\n scriptEl.onreadystatechange = null;\n scriptEl.parentNode.removeChild(scriptEl);\n scriptEl = null;\n };\n global.document.documentElement.appendChild(scriptEl);\n };\n } else {\n scheduleDrain = function () {\n setTimeout(nextTick, 0);\n };\n }\n}\n\nvar draining;\nvar queue = [];\n//named nextTick for less confusing stack traces\nfunction nextTick() {\n draining = true;\n var i, oldQueue;\n var len = queue.length;\n while (len) {\n oldQueue = queue;\n queue = [];\n i = -1;\n while (++i < len) {\n oldQueue[i]();\n }\n len = queue.length;\n }\n draining = false;\n}\n\nmodule.exports = immediate;\nfunction immediate(task) {\n if (queue.push(task) === 1 && !draining) {\n scheduleDrain();\n }\n}\n\n/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiOTEuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2ltbWVkaWF0ZS9saWIvYnJvd3Nlci5qcz81MDBlIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcbnZhciBNdXRhdGlvbiA9IGdsb2JhbC5NdXRhdGlvbk9ic2VydmVyIHx8IGdsb2JhbC5XZWJLaXRNdXRhdGlvbk9ic2VydmVyO1xuXG52YXIgc2NoZWR1bGVEcmFpbjtcblxue1xuICBpZiAoTXV0YXRpb24pIHtcbiAgICB2YXIgY2FsbGVkID0gMDtcbiAgICB2YXIgb2JzZXJ2ZXIgPSBuZXcgTXV0YXRpb24obmV4dFRpY2spO1xuICAgIHZhciBlbGVtZW50ID0gZ2xvYmFsLmRvY3VtZW50LmNyZWF0ZVRleHROb2RlKCcnKTtcbiAgICBvYnNlcnZlci5vYnNlcnZlKGVsZW1lbnQsIHtcbiAgICAgIGNoYXJhY3RlckRhdGE6IHRydWVcbiAgICB9KTtcbiAgICBzY2hlZHVsZURyYWluID0gZnVuY3Rpb24gKCkge1xuICAgICAgZWxlbWVudC5kYXRhID0gKGNhbGxlZCA9ICsrY2FsbGVkICUgMik7XG4gICAgfTtcbiAgfSBlbHNlIGlmICghZ2xvYmFsLnNldEltbWVkaWF0ZSAmJiB0eXBlb2YgZ2xvYmFsLk1lc3NhZ2VDaGFubmVsICE9PSAndW5kZWZpbmVkJykge1xuICAgIHZhciBjaGFubmVsID0gbmV3IGdsb2JhbC5NZXNzYWdlQ2hhbm5lbCgpO1xuICAgIGNoYW5uZWwucG9ydDEub25tZXNzYWdlID0gbmV4dFRpY2s7XG4gICAgc2NoZWR1bGVEcmFpbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIGNoYW5uZWwucG9ydDIucG9zdE1lc3NhZ2UoMCk7XG4gICAgfTtcbiAgfSBlbHNlIGlmICgnZG9jdW1lbnQnIGluIGdsb2JhbCAmJiAnb25yZWFkeXN0YXRlY2hhbmdlJyBpbiBnbG9iYWwuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0JykpIHtcbiAgICBzY2hlZHVsZURyYWluID0gZnVuY3Rpb24gKCkge1xuXG4gICAgICAvLyBDcmVhdGUgYSA8c2NyaXB0PiBlbGVtZW50OyBpdHMgcmVhZHlzdGF0ZWNoYW5nZSBldmVudCB3aWxsIGJlIGZpcmVkIGFzeW5jaHJvbm91c2x5IG9uY2UgaXQgaXMgaW5zZXJ0ZWRcbiAgICAgIC8vIGludG8gdGhlIGRvY3VtZW50LiBEbyBzbywgdGh1cyBxdWV1aW5nIHVwIHRoZSB0YXNrLiBSZW1lbWJlciB0byBjbGVhbiB1cCBvbmNlIGl0J3MgYmVlbiBjYWxsZWQuXG4gICAgICB2YXIgc2NyaXB0RWwgPSBnbG9iYWwuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jyk7XG4gICAgICBzY3JpcHRFbC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIG5leHRUaWNrKCk7XG5cbiAgICAgICAgc2NyaXB0RWwub25yZWFkeXN0YXRlY2hhbmdlID0gbnVsbDtcbiAgICAgICAgc2NyaXB0RWwucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChzY3JpcHRFbCk7XG4gICAgICAgIHNjcmlwdEVsID0gbnVsbDtcbiAgICAgIH07XG4gICAgICBnbG9iYWwuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmFwcGVuZENoaWxkKHNjcmlwdEVsKTtcbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIHNjaGVkdWxlRHJhaW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgICBzZXRUaW1lb3V0KG5leHRUaWNrLCAwKTtcbiAgICB9O1xuICB9XG59XG5cbnZhciBkcmFpbmluZztcbnZhciBxdWV1ZSA9IFtdO1xuLy9uYW1lZCBuZXh0VGljayBmb3IgbGVzcyBjb25mdXNpbmcgc3RhY2sgdHJhY2VzXG5mdW5jdGlvbiBuZXh0VGljaygpIHtcbiAgZHJhaW5pbmcgPSB0cnVlO1xuICB2YXIgaSwgb2xkUXVldWU7XG4gIHZhciBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gIHdoaWxlIChsZW4pIHtcbiAgICBvbGRRdWV1ZSA9IHF1ZXVlO1xuICAgIHF1ZXVlID0gW107XG4gICAgaSA9IC0xO1xuICAgIHdoaWxlICgrK2kgPCBsZW4pIHtcbiAgICAgIG9sZFF1ZXVlW2ldKCk7XG4gICAgfVxuICAgIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgfVxuICBkcmFpbmluZyA9IGZhbHNlO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGltbWVkaWF0ZTtcbmZ1bmN0aW9uIGltbWVkaWF0ZSh0YXNrKSB7XG4gIGlmIChxdWV1ZS5wdXNoKHRhc2spID09PSAxICYmICFkcmFpbmluZykge1xuICAgIHNjaGVkdWxlRHJhaW4oKTtcbiAgfVxufVxuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2ltbWVkaWF0ZS9saWIvYnJvd3Nlci5qc1xuLy8gbW9kdWxlIGlkID0gOTFcbi8vIG1vZHVsZSBjaHVua3MgPSAwIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 92 */
- /***/ function(module, exports) {
- eval("'use strict';\n\nmodule.exports = argsArray;\n\nfunction argsArray(fun) {\n return function () {\n var len = arguments.length;\n if (len) {\n var args = [];\n var i = -1;\n while (++i < len) {\n args[i] = arguments[i];\n }\n return fun.call(this, args);\n } else {\n return fun.call(this, []);\n }\n };\n}//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiOTIuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2FyZ3NhcnJheS9pbmRleC5qcz9mMjdmIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBhcmdzQXJyYXk7XG5cbmZ1bmN0aW9uIGFyZ3NBcnJheShmdW4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgbGVuID0gYXJndW1lbnRzLmxlbmd0aDtcbiAgICBpZiAobGVuKSB7XG4gICAgICB2YXIgYXJncyA9IFtdO1xuICAgICAgdmFyIGkgPSAtMTtcbiAgICAgIHdoaWxlICgrK2kgPCBsZW4pIHtcbiAgICAgICAgYXJnc1tpXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmdW4uY2FsbCh0aGlzLCBhcmdzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGZ1bi5jYWxsKHRoaXMsIFtdKTtcbiAgICB9XG4gIH07XG59XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L2FyZ3NhcnJheS9pbmRleC5qc1xuLy8gbW9kdWxlIGlkID0gOTJcbi8vIG1vZHVsZSBjaHVua3MgPSAwIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZVJvb3QiOiIifQ==");
- /***/ },
- /* 93 */
- /***/ function(module, exports, __webpack_require__) {
- eval("/* WEBPACK VAR INJECTION */(function(process) {\n/**\n * This is the web browser implementation of `debug()`.\n *\n * Expose `debug()` as the module.\n */\n\nexports = module.exports = __webpack_require__(94);\nexports.log = log;\nexports.formatArgs = formatArgs;\nexports.save = save;\nexports.load = load;\nexports.useColors = useColors;\nexports.storage = 'undefined' != typeof chrome\n && 'undefined' != typeof chrome.storage\n ? chrome.storage.local\n : localstorage();\n\n/**\n * Colors.\n */\n\nexports.colors = [\n 'lightseagreen',\n 'forestgreen',\n 'goldenrod',\n 'dodgerblue',\n 'darkorchid',\n 'crimson'\n];\n\n/**\n * Currently only WebKit-based Web Inspectors, Firefox >= v31,\n * and the Firebug extension (any Firefox version) are known\n * to support \"%c\" CSS customizations.\n *\n * TODO: add a `localStorage` variable to explicitly enable/disable colors\n */\n\nfunction useColors() {\n // is webkit? http://stackoverflow.com/a/16459606/376773\n // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632\n return (typeof document !== 'undefined' && 'WebkitAppearance' in document.documentElement.style) ||\n // is firebug? http://stackoverflow.com/a/398120/376773\n (window.console && (console.firebug || (console.exception && console.table))) ||\n // is firefox >= v31?\n // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages\n (navigator.userAgent.toLowerCase().match(/firefox\\/(\\d+)/) && parseInt(RegExp.$1, 10) >= 31);\n}\n\n/**\n * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.\n */\n\nexports.formatters.j = function(v) {\n return JSON.stringify(v);\n};\n\n\n/**\n * Colorize log arguments if enabled.\n *\n * @api public\n */\n\nfunction formatArgs() {\n var args = arguments;\n var useColors = this.useColors;\n\n args[0] = (useColors ? '%c' : '')\n + this.namespace\n + (useColors ? ' %c' : ' ')\n + args[0]\n + (useColors ? '%c ' : ' ')\n + '+' + exports.humanize(this.diff);\n\n if (!useColors) return args;\n\n var c = 'color: ' + this.color;\n args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1));\n\n // the final \"%c\" is somewhat tricky, because there could be other\n // arguments passed either before or after the %c, so we need to\n // figure out the correct index to insert the CSS into\n var index = 0;\n var lastC = 0;\n args[0].replace(/%[a-z%]/g, function(match) {\n if ('%%' === match) return;\n index++;\n if ('%c' === match) {\n // we only are interested in the *last* %c\n // (the user may have provided their own)\n lastC = index;\n }\n });\n\n args.splice(lastC, 0, c);\n return args;\n}\n\n/**\n * Invokes `console.log()` when available.\n * No-op when `console.log` is not a \"function\".\n *\n * @api public\n */\n\nfunction log() {\n // this hackery is required for IE8/9, where\n // the `console.log` function doesn't have 'apply'\n return 'object' === typeof console\n && console.log\n && Function.prototype.apply.call(console.log, console, arguments);\n}\n\n/**\n * Save `namespaces`.\n *\n * @param {String} namespaces\n * @api private\n */\n\nfunction save(namespaces) {\n try {\n if (null == namespaces) {\n exports.storage.removeItem('debug');\n } else {\n exports.storage.debug = namespaces;\n }\n } catch(e) {}\n}\n\n/**\n * Load `namespaces`.\n *\n * @return {String} returns the previously persisted debug modes\n * @api private\n */\n\nfunction load() {\n var r;\n try {\n r = exports.storage.debug;\n } catch(e) {}\n\n // If debug isn't set in LS, and we're in Electron, try to load $DEBUG\n if ('env' in (typeof process === 'undefined' ? {} : process)) {\n r = process.env.DEBUG;\n }\n \n return r;\n}\n\n/**\n * Enable namespaces listed in `localStorage.debug` initially.\n */\n\nexports.enable(load());\n\n/**\n * Localstorage attempts to return the localstorage.\n *\n * This is necessary because safari throws\n * when a user disables cookies/localstorage\n * and you attempt to access it.\n *\n * @return {LocalStorage}\n * @api private\n */\n\nfunction localstorage(){\n try {\n return window.localStorage;\n } catch (e) {}\n}\n\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiOTMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L3BvdWNoZGIvfi9kZWJ1Zy9icm93c2VyLmpzPzE2MWMiXSwic291cmNlc0NvbnRlbnQiOlsiXG4vKipcbiAqIFRoaXMgaXMgdGhlIHdlYiBicm93c2VyIGltcGxlbWVudGF0aW9uIG9mIGBkZWJ1ZygpYC5cbiAqXG4gKiBFeHBvc2UgYGRlYnVnKClgIGFzIHRoZSBtb2R1bGUuXG4gKi9cblxuZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9kZWJ1ZycpO1xuZXhwb3J0cy5sb2cgPSBsb2c7XG5leHBvcnRzLmZvcm1hdEFyZ3MgPSBmb3JtYXRBcmdzO1xuZXhwb3J0cy5zYXZlID0gc2F2ZTtcbmV4cG9ydHMubG9hZCA9IGxvYWQ7XG5leHBvcnRzLnVzZUNvbG9ycyA9IHVzZUNvbG9ycztcbmV4cG9ydHMuc3RvcmFnZSA9ICd1bmRlZmluZWQnICE9IHR5cGVvZiBjaHJvbWVcbiAgICAgICAgICAgICAgICYmICd1bmRlZmluZWQnICE9IHR5cGVvZiBjaHJvbWUuc3RvcmFnZVxuICAgICAgICAgICAgICAgICAgPyBjaHJvbWUuc3RvcmFnZS5sb2NhbFxuICAgICAgICAgICAgICAgICAgOiBsb2NhbHN0b3JhZ2UoKTtcblxuLyoqXG4gKiBDb2xvcnMuXG4gKi9cblxuZXhwb3J0cy5jb2xvcnMgPSBbXG4gICdsaWdodHNlYWdyZWVuJyxcbiAgJ2ZvcmVzdGdyZWVuJyxcbiAgJ2dvbGRlbnJvZCcsXG4gICdkb2RnZXJibHVlJyxcbiAgJ2RhcmtvcmNoaWQnLFxuICAnY3JpbXNvbidcbl07XG5cbi8qKlxuICogQ3VycmVudGx5IG9ubHkgV2ViS2l0LWJhc2VkIFdlYiBJbnNwZWN0b3JzLCBGaXJlZm94ID49IHYzMSxcbiAqIGFuZCB0aGUgRmlyZWJ1ZyBleHRlbnNpb24gKGFueSBGaXJlZm94IHZlcnNpb24pIGFyZSBrbm93blxuICogdG8gc3VwcG9ydCBcIiVjXCIgQ1NTIGN1c3RvbWl6YXRpb25zLlxuICpcbiAqIFRPRE86IGFkZCBhIGBsb2NhbFN0b3JhZ2VgIHZhcmlhYmxlIHRvIGV4cGxpY2l0bHkgZW5hYmxlL2Rpc2FibGUgY29sb3JzXG4gKi9cblxuZnVuY3Rpb24gdXNlQ29sb3JzKCkge1xuICAvLyBpcyB3ZWJraXQ/IGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzE2NDU5NjA2LzM3Njc3M1xuICAvLyBkb2N1bWVudCBpcyB1bmRlZmluZWQgaW4gcmVhY3QtbmF0aXZlOiBodHRwczovL2dpdGh1Yi5jb20vZmFjZWJvb2svcmVhY3QtbmF0aXZlL3B1bGwvMTYzMlxuICByZXR1cm4gKHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgJ1dlYmtpdEFwcGVhcmFuY2UnIGluIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZSkgfHxcbiAgICAvLyBpcyBmaXJlYnVnPyBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8zOTgxMjAvMzc2NzczXG4gICAgKHdpbmRvdy5jb25zb2xlICYmIChjb25zb2xlLmZpcmVidWcgfHwgKGNvbnNvbGUuZXhjZXB0aW9uICYmIGNvbnNvbGUudGFibGUpKSkgfHxcbiAgICAvLyBpcyBmaXJlZm94ID49IHYzMT9cbiAgICAvLyBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1Rvb2xzL1dlYl9Db25zb2xlI1N0eWxpbmdfbWVzc2FnZXNcbiAgICAobmF2aWdhdG9yLnVzZXJBZ2VudC50b0xvd2VyQ2FzZSgpLm1hdGNoKC9maXJlZm94XFwvKFxcZCspLykgJiYgcGFyc2VJbnQoUmVnRXhwLiQxLCAxMCkgPj0gMzEpO1xufVxuXG4vKipcbiAqIE1hcCAlaiB0byBgSlNPTi5zdHJpbmdpZnkoKWAsIHNpbmNlIG5vIFdlYiBJbnNwZWN0b3JzIGRvIHRoYXQgYnkgZGVmYXVsdC5cbiAqL1xuXG5leHBvcnRzLmZvcm1hdHRlcnMuaiA9IGZ1bmN0aW9uKHYpIHtcbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHYpO1xufTtcblxuXG4vKipcbiAqIENvbG9yaXplIGxvZyBhcmd1bWVudHMgaWYgZW5hYmxlZC5cbiAqXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmZ1bmN0aW9uIGZvcm1hdEFyZ3MoKSB7XG4gIHZhciBhcmdzID0gYXJndW1lbnRzO1xuICB2YXIgdXNlQ29sb3JzID0gdGhpcy51c2VDb2xvcnM7XG5cbiAgYXJnc1swXSA9ICh1c2VDb2xvcnMgPyAnJWMnIDogJycpXG4gICAgKyB0aGlzLm5hbWVzcGFjZVxuICAgICsgKHVzZUNvbG9ycyA/ICcgJWMnIDogJyAnKVxuICAgICsgYXJnc1swXVxuICAgICsgKHVzZUNvbG9ycyA/ICclYyAnIDogJyAnKVxuICAgICsgJysnICsgZXhwb3J0cy5odW1hbml6ZSh0aGlzLmRpZmYpO1xuXG4gIGlmICghdXNlQ29sb3JzKSByZXR1cm4gYXJncztcblxuICB2YXIgYyA9ICdjb2xvcjogJyArIHRoaXMuY29sb3I7XG4gIGFyZ3MgPSBbYXJnc1swXSwgYywgJ2NvbG9yOiBpbmhlcml0J10uY29uY2F0KEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3MsIDEpKTtcblxuICAvLyB0aGUgZmluYWwgXCIlY1wiIGlzIHNvbWV3aGF0IHRyaWNreSwgYmVjYXVzZSB0aGVyZSBjb3VsZCBiZSBvdGhlclxuICAvLyBhcmd1bWVudHMgcGFzc2VkIGVpdGhlciBiZWZvcmUgb3IgYWZ0ZXIgdGhlICVjLCBzbyB3ZSBuZWVkIHRvXG4gIC8vIGZpZ3VyZSBvdXQgdGhlIGNvcnJlY3QgaW5kZXggdG8gaW5zZXJ0IHRoZSBDU1MgaW50b1xuICB2YXIgaW5kZXggPSAwO1xuICB2YXIgbGFzdEMgPSAwO1xuICBhcmdzWzBdLnJlcGxhY2UoLyVbYS16JV0vZywgZnVuY3Rpb24obWF0Y2gpIHtcbiAgICBpZiAoJyUlJyA9PT0gbWF0Y2gpIHJldHVybjtcbiAgICBpbmRleCsrO1xuICAgIGlmICgnJWMnID09PSBtYXRjaCkge1xuICAgICAgLy8gd2Ugb25seSBhcmUgaW50ZXJlc3RlZCBpbiB0aGUgKmxhc3QqICVjXG4gICAgICAvLyAodGhlIHVzZXIgbWF5IGhhdmUgcHJvdmlkZWQgdGhlaXIgb3duKVxuICAgICAgbGFzdEMgPSBpbmRleDtcbiAgICB9XG4gIH0pO1xuXG4gIGFyZ3Muc3BsaWNlKGxhc3RDLCAwLCBjKTtcbiAgcmV0dXJuIGFyZ3M7XG59XG5cbi8qKlxuICogSW52b2tlcyBgY29uc29sZS5sb2coKWAgd2hlbiBhdmFpbGFibGUuXG4gKiBOby1vcCB3aGVuIGBjb25zb2xlLmxvZ2AgaXMgbm90IGEgXCJmdW5jdGlvblwiLlxuICpcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuZnVuY3Rpb24gbG9nKCkge1xuICAvLyB0aGlzIGhhY2tlcnkgaXMgcmVxdWlyZWQgZm9yIElFOC85LCB3aGVyZVxuICAvLyB0aGUgYGNvbnNvbGUubG9nYCBmdW5jdGlvbiBkb2Vzbid0IGhhdmUgJ2FwcGx5J1xuICByZXR1cm4gJ29iamVjdCcgPT09IHR5cGVvZiBjb25zb2xlXG4gICAgJiYgY29uc29sZS5sb2dcbiAgICAmJiBGdW5jdGlvbi5wcm90b3R5cGUuYXBwbHkuY2FsbChjb25zb2xlLmxvZywgY29uc29sZSwgYXJndW1lbnRzKTtcbn1cblxuLyoqXG4gKiBTYXZlIGBuYW1lc3BhY2VzYC5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZXNwYWNlc1xuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gc2F2ZShuYW1lc3BhY2VzKSB7XG4gIHRyeSB7XG4gICAgaWYgKG51bGwgPT0gbmFtZXNwYWNlcykge1xuICAgICAgZXhwb3J0cy5zdG9yYWdlLnJlbW92ZUl0ZW0oJ2RlYnVnJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGV4cG9ydHMuc3RvcmFnZS5kZWJ1ZyA9IG5hbWVzcGFjZXM7XG4gICAgfVxuICB9IGNhdGNoKGUpIHt9XG59XG5cbi8qKlxuICogTG9hZCBgbmFtZXNwYWNlc2AuXG4gKlxuICogQHJldHVybiB7U3RyaW5nfSByZXR1cm5zIHRoZSBwcmV2aW91c2x5IHBlcnNpc3RlZCBkZWJ1ZyBtb2Rlc1xuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gbG9hZCgpIHtcbiAgdmFyIHI7XG4gIHRyeSB7XG4gICAgciA9IGV4cG9ydHMuc3RvcmFnZS5kZWJ1ZztcbiAgfSBjYXRjaChlKSB7fVxuXG4gIC8vIElmIGRlYnVnIGlzbid0IHNldCBpbiBMUywgYW5kIHdlJ3JlIGluIEVsZWN0cm9uLCB0cnkgdG8gbG9hZCAkREVCVUdcbiAgaWYgKCdlbnYnIGluICh0eXBlb2YgcHJvY2VzcyA9PT0gJ3VuZGVmaW5lZCcgPyB7fSA6IHByb2Nlc3MpKSB7XG4gICAgciA9IHByb2Nlc3MuZW52LkRFQlVHO1xuICB9XG4gIFxuICByZXR1cm4gcjtcbn1cblxuLyoqXG4gKiBFbmFibGUgbmFtZXNwYWNlcyBsaXN0ZWQgaW4gYGxvY2FsU3RvcmFnZS5kZWJ1Z2AgaW5pdGlhbGx5LlxuICovXG5cbmV4cG9ydHMuZW5hYmxlKGxvYWQoKSk7XG5cbi8qKlxuICogTG9jYWxzdG9yYWdlIGF0dGVtcHRzIHRvIHJldHVybiB0aGUgbG9jYWxzdG9yYWdlLlxuICpcbiAqIFRoaXMgaXMgbmVjZXNzYXJ5IGJlY2F1c2Ugc2FmYXJpIHRocm93c1xuICogd2hlbiBhIHVzZXIgZGlzYWJsZXMgY29va2llcy9sb2NhbHN0b3JhZ2VcbiAqIGFuZCB5b3UgYXR0ZW1wdCB0byBhY2Nlc3MgaXQuXG4gKlxuICogQHJldHVybiB7TG9jYWxTdG9yYWdlfVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gbG9jYWxzdG9yYWdlKCl7XG4gIHRyeSB7XG4gICAgcmV0dXJuIHdpbmRvdy5sb2NhbFN0b3JhZ2U7XG4gIH0gY2F0Y2ggKGUpIHt9XG59XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vcG91Y2hkYi9+L2RlYnVnL2Jyb3dzZXIuanNcbi8vIG1vZHVsZSBpZCA9IDkzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 94 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\n/**\n * This is the common logic for both the Node.js and web browser\n * implementations of `debug()`.\n *\n * Expose `debug()` as the module.\n */\n\nexports = module.exports = debug.debug = debug;\nexports.coerce = coerce;\nexports.disable = disable;\nexports.enable = enable;\nexports.enabled = enabled;\nexports.humanize = __webpack_require__(95);\n\n/**\n * The currently active debug mode names, and names to skip.\n */\n\nexports.names = [];\nexports.skips = [];\n\n/**\n * Map of special \"%n\" handling functions, for the debug \"format\" argument.\n *\n * Valid key names are a single, lowercased letter, i.e. \"n\".\n */\n\nexports.formatters = {};\n\n/**\n * Previously assigned color.\n */\n\nvar prevColor = 0;\n\n/**\n * Previous log timestamp.\n */\n\nvar prevTime;\n\n/**\n * Select a color.\n *\n * @return {Number}\n * @api private\n */\n\nfunction selectColor() {\n return exports.colors[prevColor++ % exports.colors.length];\n}\n\n/**\n * Create a debugger with the given `namespace`.\n *\n * @param {String} namespace\n * @return {Function}\n * @api public\n */\n\nfunction debug(namespace) {\n\n // define the `disabled` version\n function disabled() {\n }\n disabled.enabled = false;\n\n // define the `enabled` version\n function enabled() {\n\n var self = enabled;\n\n // set `diff` timestamp\n var curr = +new Date();\n var ms = curr - (prevTime || curr);\n self.diff = ms;\n self.prev = prevTime;\n self.curr = curr;\n prevTime = curr;\n\n // add the `color` if not set\n if (null == self.useColors) self.useColors = exports.useColors();\n if (null == self.color && self.useColors) self.color = selectColor();\n\n var args = new Array(arguments.length);\n for (var i = 0; i < args.length; i++) {\n args[i] = arguments[i];\n }\n\n args[0] = exports.coerce(args[0]);\n\n if ('string' !== typeof args[0]) {\n // anything else let's inspect with %o\n args = ['%o'].concat(args);\n }\n\n // apply any `formatters` transformations\n var index = 0;\n args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {\n // if we encounter an escaped % then don't increase the array index\n if (match === '%%') return match;\n index++;\n var formatter = exports.formatters[format];\n if ('function' === typeof formatter) {\n var val = args[index];\n match = formatter.call(self, val);\n\n // now we need to remove `args[index]` since it's inlined in the `format`\n args.splice(index, 1);\n index--;\n }\n return match;\n });\n\n // apply env-specific formatting\n args = exports.formatArgs.apply(self, args);\n\n var logFn = enabled.log || exports.log || console.log.bind(console);\n logFn.apply(self, args);\n }\n enabled.enabled = true;\n\n var fn = exports.enabled(namespace) ? enabled : disabled;\n\n fn.namespace = namespace;\n\n return fn;\n}\n\n/**\n * Enables a debug mode by namespaces. This can include modes\n * separated by a colon and wildcards.\n *\n * @param {String} namespaces\n * @api public\n */\n\nfunction enable(namespaces) {\n exports.save(namespaces);\n\n var split = (namespaces || '').split(/[\\s,]+/);\n var len = split.length;\n\n for (var i = 0; i < len; i++) {\n if (!split[i]) continue; // ignore empty strings\n namespaces = split[i].replace(/[\\\\^$+?.()|[\\]{}]/g, '\\\\$&').replace(/\\*/g, '.*?');\n if (namespaces[0] === '-') {\n exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));\n } else {\n exports.names.push(new RegExp('^' + namespaces + '$'));\n }\n }\n}\n\n/**\n * Disable debug output.\n *\n * @api public\n */\n\nfunction disable() {\n exports.enable('');\n}\n\n/**\n * Returns true if the given mode name is enabled, false otherwise.\n *\n * @param {String} name\n * @return {Boolean}\n * @api public\n */\n\nfunction enabled(name) {\n var i, len;\n for (i = 0, len = exports.skips.length; i < len; i++) {\n if (exports.skips[i].test(name)) {\n return false;\n }\n }\n for (i = 0, len = exports.names.length; i < len; i++) {\n if (exports.names[i].test(name)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Coerce `val`.\n *\n * @param {Mixed} val\n * @return {Mixed}\n * @api private\n */\n\nfunction coerce(val) {\n if (val instanceof Error) return val.stack || val.message;\n return val;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiOTQuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L3BvdWNoZGIvfi9kZWJ1Zy9kZWJ1Zy5qcz8zNDFlIl0sInNvdXJjZXNDb250ZW50IjpbIlxuLyoqXG4gKiBUaGlzIGlzIHRoZSBjb21tb24gbG9naWMgZm9yIGJvdGggdGhlIE5vZGUuanMgYW5kIHdlYiBicm93c2VyXG4gKiBpbXBsZW1lbnRhdGlvbnMgb2YgYGRlYnVnKClgLlxuICpcbiAqIEV4cG9zZSBgZGVidWcoKWAgYXMgdGhlIG1vZHVsZS5cbiAqL1xuXG5leHBvcnRzID0gbW9kdWxlLmV4cG9ydHMgPSBkZWJ1Zy5kZWJ1ZyA9IGRlYnVnO1xuZXhwb3J0cy5jb2VyY2UgPSBjb2VyY2U7XG5leHBvcnRzLmRpc2FibGUgPSBkaXNhYmxlO1xuZXhwb3J0cy5lbmFibGUgPSBlbmFibGU7XG5leHBvcnRzLmVuYWJsZWQgPSBlbmFibGVkO1xuZXhwb3J0cy5odW1hbml6ZSA9IHJlcXVpcmUoJ21zJyk7XG5cbi8qKlxuICogVGhlIGN1cnJlbnRseSBhY3RpdmUgZGVidWcgbW9kZSBuYW1lcywgYW5kIG5hbWVzIHRvIHNraXAuXG4gKi9cblxuZXhwb3J0cy5uYW1lcyA9IFtdO1xuZXhwb3J0cy5za2lwcyA9IFtdO1xuXG4vKipcbiAqIE1hcCBvZiBzcGVjaWFsIFwiJW5cIiBoYW5kbGluZyBmdW5jdGlvbnMsIGZvciB0aGUgZGVidWcgXCJmb3JtYXRcIiBhcmd1bWVudC5cbiAqXG4gKiBWYWxpZCBrZXkgbmFtZXMgYXJlIGEgc2luZ2xlLCBsb3dlcmNhc2VkIGxldHRlciwgaS5lLiBcIm5cIi5cbiAqL1xuXG5leHBvcnRzLmZvcm1hdHRlcnMgPSB7fTtcblxuLyoqXG4gKiBQcmV2aW91c2x5IGFzc2lnbmVkIGNvbG9yLlxuICovXG5cbnZhciBwcmV2Q29sb3IgPSAwO1xuXG4vKipcbiAqIFByZXZpb3VzIGxvZyB0aW1lc3RhbXAuXG4gKi9cblxudmFyIHByZXZUaW1lO1xuXG4vKipcbiAqIFNlbGVjdCBhIGNvbG9yLlxuICpcbiAqIEByZXR1cm4ge051bWJlcn1cbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbmZ1bmN0aW9uIHNlbGVjdENvbG9yKCkge1xuICByZXR1cm4gZXhwb3J0cy5jb2xvcnNbcHJldkNvbG9yKysgJSBleHBvcnRzLmNvbG9ycy5sZW5ndGhdO1xufVxuXG4vKipcbiAqIENyZWF0ZSBhIGRlYnVnZ2VyIHdpdGggdGhlIGdpdmVuIGBuYW1lc3BhY2VgLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lc3BhY2VcbiAqIEByZXR1cm4ge0Z1bmN0aW9ufVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5mdW5jdGlvbiBkZWJ1ZyhuYW1lc3BhY2UpIHtcblxuICAvLyBkZWZpbmUgdGhlIGBkaXNhYmxlZGAgdmVyc2lvblxuICBmdW5jdGlvbiBkaXNhYmxlZCgpIHtcbiAgfVxuICBkaXNhYmxlZC5lbmFibGVkID0gZmFsc2U7XG5cbiAgLy8gZGVmaW5lIHRoZSBgZW5hYmxlZGAgdmVyc2lvblxuICBmdW5jdGlvbiBlbmFibGVkKCkge1xuXG4gICAgdmFyIHNlbGYgPSBlbmFibGVkO1xuXG4gICAgLy8gc2V0IGBkaWZmYCB0aW1lc3RhbXBcbiAgICB2YXIgY3VyciA9ICtuZXcgRGF0ZSgpO1xuICAgIHZhciBtcyA9IGN1cnIgLSAocHJldlRpbWUgfHwgY3Vycik7XG4gICAgc2VsZi5kaWZmID0gbXM7XG4gICAgc2VsZi5wcmV2ID0gcHJldlRpbWU7XG4gICAgc2VsZi5jdXJyID0gY3VycjtcbiAgICBwcmV2VGltZSA9IGN1cnI7XG5cbiAgICAvLyBhZGQgdGhlIGBjb2xvcmAgaWYgbm90IHNldFxuICAgIGlmIChudWxsID09IHNlbGYudXNlQ29sb3JzKSBzZWxmLnVzZUNvbG9ycyA9IGV4cG9ydHMudXNlQ29sb3JzKCk7XG4gICAgaWYgKG51bGwgPT0gc2VsZi5jb2xvciAmJiBzZWxmLnVzZUNvbG9ycykgc2VsZi5jb2xvciA9IHNlbGVjdENvbG9yKCk7XG5cbiAgICB2YXIgYXJncyA9IG5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgIGFyZ3NbaV0gPSBhcmd1bWVudHNbaV07XG4gICAgfVxuXG4gICAgYXJnc1swXSA9IGV4cG9ydHMuY29lcmNlKGFyZ3NbMF0pO1xuXG4gICAgaWYgKCdzdHJpbmcnICE9PSB0eXBlb2YgYXJnc1swXSkge1xuICAgICAgLy8gYW55dGhpbmcgZWxzZSBsZXQncyBpbnNwZWN0IHdpdGggJW9cbiAgICAgIGFyZ3MgPSBbJyVvJ10uY29uY2F0KGFyZ3MpO1xuICAgIH1cblxuICAgIC8vIGFwcGx5IGFueSBgZm9ybWF0dGVyc2AgdHJhbnNmb3JtYXRpb25zXG4gICAgdmFyIGluZGV4ID0gMDtcbiAgICBhcmdzWzBdID0gYXJnc1swXS5yZXBsYWNlKC8lKFthLXolXSkvZywgZnVuY3Rpb24obWF0Y2gsIGZvcm1hdCkge1xuICAgICAgLy8gaWYgd2UgZW5jb3VudGVyIGFuIGVzY2FwZWQgJSB0aGVuIGRvbid0IGluY3JlYXNlIHRoZSBhcnJheSBpbmRleFxuICAgICAgaWYgKG1hdGNoID09PSAnJSUnKSByZXR1cm4gbWF0Y2g7XG4gICAgICBpbmRleCsrO1xuICAgICAgdmFyIGZvcm1hdHRlciA9IGV4cG9ydHMuZm9ybWF0dGVyc1tmb3JtYXRdO1xuICAgICAgaWYgKCdmdW5jdGlvbicgPT09IHR5cGVvZiBmb3JtYXR0ZXIpIHtcbiAgICAgICAgdmFyIHZhbCA9IGFyZ3NbaW5kZXhdO1xuICAgICAgICBtYXRjaCA9IGZvcm1hdHRlci5jYWxsKHNlbGYsIHZhbCk7XG5cbiAgICAgICAgLy8gbm93IHdlIG5lZWQgdG8gcmVtb3ZlIGBhcmdzW2luZGV4XWAgc2luY2UgaXQncyBpbmxpbmVkIGluIHRoZSBgZm9ybWF0YFxuICAgICAgICBhcmdzLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgIGluZGV4LS07XG4gICAgICB9XG4gICAgICByZXR1cm4gbWF0Y2g7XG4gICAgfSk7XG5cbiAgICAvLyBhcHBseSBlbnYtc3BlY2lmaWMgZm9ybWF0dGluZ1xuICAgIGFyZ3MgPSBleHBvcnRzLmZvcm1hdEFyZ3MuYXBwbHkoc2VsZiwgYXJncyk7XG5cbiAgICB2YXIgbG9nRm4gPSBlbmFibGVkLmxvZyB8fCBleHBvcnRzLmxvZyB8fCBjb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUpO1xuICAgIGxvZ0ZuLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICB9XG4gIGVuYWJsZWQuZW5hYmxlZCA9IHRydWU7XG5cbiAgdmFyIGZuID0gZXhwb3J0cy5lbmFibGVkKG5hbWVzcGFjZSkgPyBlbmFibGVkIDogZGlzYWJsZWQ7XG5cbiAgZm4ubmFtZXNwYWNlID0gbmFtZXNwYWNlO1xuXG4gIHJldHVybiBmbjtcbn1cblxuLyoqXG4gKiBFbmFibGVzIGEgZGVidWcgbW9kZSBieSBuYW1lc3BhY2VzLiBUaGlzIGNhbiBpbmNsdWRlIG1vZGVzXG4gKiBzZXBhcmF0ZWQgYnkgYSBjb2xvbiBhbmQgd2lsZGNhcmRzLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lc3BhY2VzXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmZ1bmN0aW9uIGVuYWJsZShuYW1lc3BhY2VzKSB7XG4gIGV4cG9ydHMuc2F2ZShuYW1lc3BhY2VzKTtcblxuICB2YXIgc3BsaXQgPSAobmFtZXNwYWNlcyB8fCAnJykuc3BsaXQoL1tcXHMsXSsvKTtcbiAgdmFyIGxlbiA9IHNwbGl0Lmxlbmd0aDtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgaWYgKCFzcGxpdFtpXSkgY29udGludWU7IC8vIGlnbm9yZSBlbXB0eSBzdHJpbmdzXG4gICAgbmFtZXNwYWNlcyA9IHNwbGl0W2ldLnJlcGxhY2UoL1tcXFxcXiQrPy4oKXxbXFxde31dL2csICdcXFxcJCYnKS5yZXBsYWNlKC9cXCovZywgJy4qPycpO1xuICAgIGlmIChuYW1lc3BhY2VzWzBdID09PSAnLScpIHtcbiAgICAgIGV4cG9ydHMuc2tpcHMucHVzaChuZXcgUmVnRXhwKCdeJyArIG5hbWVzcGFjZXMuc3Vic3RyKDEpICsgJyQnKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGV4cG9ydHMubmFtZXMucHVzaChuZXcgUmVnRXhwKCdeJyArIG5hbWVzcGFjZXMgKyAnJCcpKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBEaXNhYmxlIGRlYnVnIG91dHB1dC5cbiAqXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmZ1bmN0aW9uIGRpc2FibGUoKSB7XG4gIGV4cG9ydHMuZW5hYmxlKCcnKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlIGdpdmVuIG1vZGUgbmFtZSBpcyBlbmFibGVkLCBmYWxzZSBvdGhlcndpc2UuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAqIEByZXR1cm4ge0Jvb2xlYW59XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmZ1bmN0aW9uIGVuYWJsZWQobmFtZSkge1xuICB2YXIgaSwgbGVuO1xuICBmb3IgKGkgPSAwLCBsZW4gPSBleHBvcnRzLnNraXBzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgaWYgKGV4cG9ydHMuc2tpcHNbaV0udGVzdChuYW1lKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuICBmb3IgKGkgPSAwLCBsZW4gPSBleHBvcnRzLm5hbWVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgaWYgKGV4cG9ydHMubmFtZXNbaV0udGVzdChuYW1lKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuLyoqXG4gKiBDb2VyY2UgYHZhbGAuXG4gKlxuICogQHBhcmFtIHtNaXhlZH0gdmFsXG4gKiBAcmV0dXJuIHtNaXhlZH1cbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbmZ1bmN0aW9uIGNvZXJjZSh2YWwpIHtcbiAgaWYgKHZhbCBpbnN0YW5jZW9mIEVycm9yKSByZXR1cm4gdmFsLnN0YWNrIHx8IHZhbC5tZXNzYWdlO1xuICByZXR1cm4gdmFsO1xufVxuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L3BvdWNoZGIvfi9kZWJ1Zy9kZWJ1Zy5qc1xuLy8gbW9kdWxlIGlkID0gOTRcbi8vIG1vZHVsZSBjaHVua3MgPSAwIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOyIsInNvdXJjZVJvb3QiOiIifQ==");
- /***/ },
- /* 95 */
- /***/ function(module, exports) {
- eval("/**\n * Helpers.\n */\n\nvar s = 1000\nvar m = s * 60\nvar h = m * 60\nvar d = h * 24\nvar y = d * 365.25\n\n/**\n * Parse or format the given `val`.\n *\n * Options:\n *\n * - `long` verbose formatting [false]\n *\n * @param {String|Number} val\n * @param {Object} options\n * @throws {Error} throw an error if val is not a non-empty string or a number\n * @return {String|Number}\n * @api public\n */\n\nmodule.exports = function (val, options) {\n options = options || {}\n var type = typeof val\n if (type === 'string' && val.length > 0) {\n return parse(val)\n } else if (type === 'number' && isNaN(val) === false) {\n return options.long ?\n\t\t\tfmtLong(val) :\n\t\t\tfmtShort(val)\n }\n throw new Error('val is not a non-empty string or a valid number. val=' + JSON.stringify(val))\n}\n\n/**\n * Parse the given `str` and return milliseconds.\n *\n * @param {String} str\n * @return {Number}\n * @api private\n */\n\nfunction parse(str) {\n str = String(str)\n if (str.length > 10000) {\n return\n }\n var match = /^((?:\\d+)?\\.?\\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str)\n if (!match) {\n return\n }\n var n = parseFloat(match[1])\n var type = (match[2] || 'ms').toLowerCase()\n switch (type) {\n case 'years':\n case 'year':\n case 'yrs':\n case 'yr':\n case 'y':\n return n * y\n case 'days':\n case 'day':\n case 'd':\n return n * d\n case 'hours':\n case 'hour':\n case 'hrs':\n case 'hr':\n case 'h':\n return n * h\n case 'minutes':\n case 'minute':\n case 'mins':\n case 'min':\n case 'm':\n return n * m\n case 'seconds':\n case 'second':\n case 'secs':\n case 'sec':\n case 's':\n return n * s\n case 'milliseconds':\n case 'millisecond':\n case 'msecs':\n case 'msec':\n case 'ms':\n return n\n default:\n return undefined\n }\n}\n\n/**\n * Short format for `ms`.\n *\n * @param {Number} ms\n * @return {String}\n * @api private\n */\n\nfunction fmtShort(ms) {\n if (ms >= d) {\n return Math.round(ms / d) + 'd'\n }\n if (ms >= h) {\n return Math.round(ms / h) + 'h'\n }\n if (ms >= m) {\n return Math.round(ms / m) + 'm'\n }\n if (ms >= s) {\n return Math.round(ms / s) + 's'\n }\n return ms + 'ms'\n}\n\n/**\n * Long format for `ms`.\n *\n * @param {Number} ms\n * @return {String}\n * @api private\n */\n\nfunction fmtLong(ms) {\n return plural(ms, d, 'day') ||\n plural(ms, h, 'hour') ||\n plural(ms, m, 'minute') ||\n plural(ms, s, 'second') ||\n ms + ' ms'\n}\n\n/**\n * Pluralization helper.\n */\n\nfunction plural(ms, n, name) {\n if (ms < n) {\n return\n }\n if (ms < n * 1.5) {\n return Math.floor(ms / n) + ' ' + name\n }\n return Math.ceil(ms / n) + ' ' + name + 's'\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiOTUuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L21zL2luZGV4LmpzPzZkMzYiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBIZWxwZXJzLlxuICovXG5cbnZhciBzID0gMTAwMFxudmFyIG0gPSBzICogNjBcbnZhciBoID0gbSAqIDYwXG52YXIgZCA9IGggKiAyNFxudmFyIHkgPSBkICogMzY1LjI1XG5cbi8qKlxuICogUGFyc2Ugb3IgZm9ybWF0IHRoZSBnaXZlbiBgdmFsYC5cbiAqXG4gKiBPcHRpb25zOlxuICpcbiAqICAtIGBsb25nYCB2ZXJib3NlIGZvcm1hdHRpbmcgW2ZhbHNlXVxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfE51bWJlcn0gdmFsXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICogQHRocm93cyB7RXJyb3J9IHRocm93IGFuIGVycm9yIGlmIHZhbCBpcyBub3QgYSBub24tZW1wdHkgc3RyaW5nIG9yIGEgbnVtYmVyXG4gKiBAcmV0dXJuIHtTdHJpbmd8TnVtYmVyfVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICh2YWwsIG9wdGlvbnMpIHtcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cbiAgdmFyIHR5cGUgPSB0eXBlb2YgdmFsXG4gIGlmICh0eXBlID09PSAnc3RyaW5nJyAmJiB2YWwubGVuZ3RoID4gMCkge1xuICAgIHJldHVybiBwYXJzZSh2YWwpXG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ251bWJlcicgJiYgaXNOYU4odmFsKSA9PT0gZmFsc2UpIHtcbiAgICByZXR1cm4gb3B0aW9ucy5sb25nID9cblx0XHRcdGZtdExvbmcodmFsKSA6XG5cdFx0XHRmbXRTaG9ydCh2YWwpXG4gIH1cbiAgdGhyb3cgbmV3IEVycm9yKCd2YWwgaXMgbm90IGEgbm9uLWVtcHR5IHN0cmluZyBvciBhIHZhbGlkIG51bWJlci4gdmFsPScgKyBKU09OLnN0cmluZ2lmeSh2YWwpKVxufVxuXG4vKipcbiAqIFBhcnNlIHRoZSBnaXZlbiBgc3RyYCBhbmQgcmV0dXJuIG1pbGxpc2Vjb25kcy5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gc3RyXG4gKiBAcmV0dXJuIHtOdW1iZXJ9XG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5mdW5jdGlvbiBwYXJzZShzdHIpIHtcbiAgc3RyID0gU3RyaW5nKHN0cilcbiAgaWYgKHN0ci5sZW5ndGggPiAxMDAwMCkge1xuICAgIHJldHVyblxuICB9XG4gIHZhciBtYXRjaCA9IC9eKCg/OlxcZCspP1xcLj9cXGQrKSAqKG1pbGxpc2Vjb25kcz98bXNlY3M/fG1zfHNlY29uZHM/fHNlY3M/fHN8bWludXRlcz98bWlucz98bXxob3Vycz98aHJzP3xofGRheXM/fGR8eWVhcnM/fHlycz98eSk/JC9pLmV4ZWMoc3RyKVxuICBpZiAoIW1hdGNoKSB7XG4gICAgcmV0dXJuXG4gIH1cbiAgdmFyIG4gPSBwYXJzZUZsb2F0KG1hdGNoWzFdKVxuICB2YXIgdHlwZSA9IChtYXRjaFsyXSB8fCAnbXMnKS50b0xvd2VyQ2FzZSgpXG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2UgJ3llYXJzJzpcbiAgICBjYXNlICd5ZWFyJzpcbiAgICBjYXNlICd5cnMnOlxuICAgIGNhc2UgJ3lyJzpcbiAgICBjYXNlICd5JzpcbiAgICAgIHJldHVybiBuICogeVxuICAgIGNhc2UgJ2RheXMnOlxuICAgIGNhc2UgJ2RheSc6XG4gICAgY2FzZSAnZCc6XG4gICAgICByZXR1cm4gbiAqIGRcbiAgICBjYXNlICdob3Vycyc6XG4gICAgY2FzZSAnaG91cic6XG4gICAgY2FzZSAnaHJzJzpcbiAgICBjYXNlICdocic6XG4gICAgY2FzZSAnaCc6XG4gICAgICByZXR1cm4gbiAqIGhcbiAgICBjYXNlICdtaW51dGVzJzpcbiAgICBjYXNlICdtaW51dGUnOlxuICAgIGNhc2UgJ21pbnMnOlxuICAgIGNhc2UgJ21pbic6XG4gICAgY2FzZSAnbSc6XG4gICAgICByZXR1cm4gbiAqIG1cbiAgICBjYXNlICdzZWNvbmRzJzpcbiAgICBjYXNlICdzZWNvbmQnOlxuICAgIGNhc2UgJ3NlY3MnOlxuICAgIGNhc2UgJ3NlYyc6XG4gICAgY2FzZSAncyc6XG4gICAgICByZXR1cm4gbiAqIHNcbiAgICBjYXNlICdtaWxsaXNlY29uZHMnOlxuICAgIGNhc2UgJ21pbGxpc2Vjb25kJzpcbiAgICBjYXNlICdtc2Vjcyc6XG4gICAgY2FzZSAnbXNlYyc6XG4gICAgY2FzZSAnbXMnOlxuICAgICAgcmV0dXJuIG5cbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIHVuZGVmaW5lZFxuICB9XG59XG5cbi8qKlxuICogU2hvcnQgZm9ybWF0IGZvciBgbXNgLlxuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSBtc1xuICogQHJldHVybiB7U3RyaW5nfVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gZm10U2hvcnQobXMpIHtcbiAgaWYgKG1zID49IGQpIHtcbiAgICByZXR1cm4gTWF0aC5yb3VuZChtcyAvIGQpICsgJ2QnXG4gIH1cbiAgaWYgKG1zID49IGgpIHtcbiAgICByZXR1cm4gTWF0aC5yb3VuZChtcyAvIGgpICsgJ2gnXG4gIH1cbiAgaWYgKG1zID49IG0pIHtcbiAgICByZXR1cm4gTWF0aC5yb3VuZChtcyAvIG0pICsgJ20nXG4gIH1cbiAgaWYgKG1zID49IHMpIHtcbiAgICByZXR1cm4gTWF0aC5yb3VuZChtcyAvIHMpICsgJ3MnXG4gIH1cbiAgcmV0dXJuIG1zICsgJ21zJ1xufVxuXG4vKipcbiAqIExvbmcgZm9ybWF0IGZvciBgbXNgLlxuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSBtc1xuICogQHJldHVybiB7U3RyaW5nfVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gZm10TG9uZyhtcykge1xuICByZXR1cm4gcGx1cmFsKG1zLCBkLCAnZGF5JykgfHxcbiAgICBwbHVyYWwobXMsIGgsICdob3VyJykgfHxcbiAgICBwbHVyYWwobXMsIG0sICdtaW51dGUnKSB8fFxuICAgIHBsdXJhbChtcywgcywgJ3NlY29uZCcpIHx8XG4gICAgbXMgKyAnIG1zJ1xufVxuXG4vKipcbiAqIFBsdXJhbGl6YXRpb24gaGVscGVyLlxuICovXG5cbmZ1bmN0aW9uIHBsdXJhbChtcywgbiwgbmFtZSkge1xuICBpZiAobXMgPCBuKSB7XG4gICAgcmV0dXJuXG4gIH1cbiAgaWYgKG1zIDwgbiAqIDEuNSkge1xuICAgIHJldHVybiBNYXRoLmZsb29yKG1zIC8gbikgKyAnICcgKyBuYW1lXG4gIH1cbiAgcmV0dXJuIE1hdGguY2VpbChtcyAvIG4pICsgJyAnICsgbmFtZSArICdzJ1xufVxuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L21zL2luZGV4LmpzXG4vLyBtb2R1bGUgaWQgPSA5NVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 96 */
- /***/ function(module, exports) {
- eval("// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nfunction EventEmitter() {\n this._events = this._events || {};\n this._maxListeners = this._maxListeners || undefined;\n}\nmodule.exports = EventEmitter;\n\n// Backwards-compat with node 0.10.x\nEventEmitter.EventEmitter = EventEmitter;\n\nEventEmitter.prototype._events = undefined;\nEventEmitter.prototype._maxListeners = undefined;\n\n// By default EventEmitters will print a warning if more than 10 listeners are\n// added to it. This is a useful default which helps finding memory leaks.\nEventEmitter.defaultMaxListeners = 10;\n\n// Obviously not all Emitters should be limited to 10. This function allows\n// that to be increased. Set to zero for unlimited.\nEventEmitter.prototype.setMaxListeners = function(n) {\n if (!isNumber(n) || n < 0 || isNaN(n))\n throw TypeError('n must be a positive number');\n this._maxListeners = n;\n return this;\n};\n\nEventEmitter.prototype.emit = function(type) {\n var er, handler, len, args, i, listeners;\n\n if (!this._events)\n this._events = {};\n\n // If there is no 'error' event listener then throw.\n if (type === 'error') {\n if (!this._events.error ||\n (isObject(this._events.error) && !this._events.error.length)) {\n er = arguments[1];\n if (er instanceof Error) {\n throw er; // Unhandled 'error' event\n } else {\n // At least give some kind of context to the user\n var err = new Error('Uncaught, unspecified \"error\" event. (' + er + ')');\n err.context = er;\n throw err;\n }\n }\n }\n\n handler = this._events[type];\n\n if (isUndefined(handler))\n return false;\n\n if (isFunction(handler)) {\n switch (arguments.length) {\n // fast cases\n case 1:\n handler.call(this);\n break;\n case 2:\n handler.call(this, arguments[1]);\n break;\n case 3:\n handler.call(this, arguments[1], arguments[2]);\n break;\n // slower\n default:\n args = Array.prototype.slice.call(arguments, 1);\n handler.apply(this, args);\n }\n } else if (isObject(handler)) {\n args = Array.prototype.slice.call(arguments, 1);\n listeners = handler.slice();\n len = listeners.length;\n for (i = 0; i < len; i++)\n listeners[i].apply(this, args);\n }\n\n return true;\n};\n\nEventEmitter.prototype.addListener = function(type, listener) {\n var m;\n\n if (!isFunction(listener))\n throw TypeError('listener must be a function');\n\n if (!this._events)\n this._events = {};\n\n // To avoid recursion in the case that type === \"newListener\"! Before\n // adding it to the listeners, first emit \"newListener\".\n if (this._events.newListener)\n this.emit('newListener', type,\n isFunction(listener.listener) ?\n listener.listener : listener);\n\n if (!this._events[type])\n // Optimize the case of one listener. Don't need the extra array object.\n this._events[type] = listener;\n else if (isObject(this._events[type]))\n // If we've already got an array, just append.\n this._events[type].push(listener);\n else\n // Adding the second element, need to change to array.\n this._events[type] = [this._events[type], listener];\n\n // Check for listener leak\n if (isObject(this._events[type]) && !this._events[type].warned) {\n if (!isUndefined(this._maxListeners)) {\n m = this._maxListeners;\n } else {\n m = EventEmitter.defaultMaxListeners;\n }\n\n if (m && m > 0 && this._events[type].length > m) {\n this._events[type].warned = true;\n console.error('(node) warning: possible EventEmitter memory ' +\n 'leak detected. %d listeners added. ' +\n 'Use emitter.setMaxListeners() to increase limit.',\n this._events[type].length);\n if (typeof console.trace === 'function') {\n // not supported in IE 10\n console.trace();\n }\n }\n }\n\n return this;\n};\n\nEventEmitter.prototype.on = EventEmitter.prototype.addListener;\n\nEventEmitter.prototype.once = function(type, listener) {\n if (!isFunction(listener))\n throw TypeError('listener must be a function');\n\n var fired = false;\n\n function g() {\n this.removeListener(type, g);\n\n if (!fired) {\n fired = true;\n listener.apply(this, arguments);\n }\n }\n\n g.listener = listener;\n this.on(type, g);\n\n return this;\n};\n\n// emits a 'removeListener' event iff the listener was removed\nEventEmitter.prototype.removeListener = function(type, listener) {\n var list, position, length, i;\n\n if (!isFunction(listener))\n throw TypeError('listener must be a function');\n\n if (!this._events || !this._events[type])\n return this;\n\n list = this._events[type];\n length = list.length;\n position = -1;\n\n if (list === listener ||\n (isFunction(list.listener) && list.listener === listener)) {\n delete this._events[type];\n if (this._events.removeListener)\n this.emit('removeListener', type, listener);\n\n } else if (isObject(list)) {\n for (i = length; i-- > 0;) {\n if (list[i] === listener ||\n (list[i].listener && list[i].listener === listener)) {\n position = i;\n break;\n }\n }\n\n if (position < 0)\n return this;\n\n if (list.length === 1) {\n list.length = 0;\n delete this._events[type];\n } else {\n list.splice(position, 1);\n }\n\n if (this._events.removeListener)\n this.emit('removeListener', type, listener);\n }\n\n return this;\n};\n\nEventEmitter.prototype.removeAllListeners = function(type) {\n var key, listeners;\n\n if (!this._events)\n return this;\n\n // not listening for removeListener, no need to emit\n if (!this._events.removeListener) {\n if (arguments.length === 0)\n this._events = {};\n else if (this._events[type])\n delete this._events[type];\n return this;\n }\n\n // emit removeListener for all listeners on all events\n if (arguments.length === 0) {\n for (key in this._events) {\n if (key === 'removeListener') continue;\n this.removeAllListeners(key);\n }\n this.removeAllListeners('removeListener');\n this._events = {};\n return this;\n }\n\n listeners = this._events[type];\n\n if (isFunction(listeners)) {\n this.removeListener(type, listeners);\n } else if (listeners) {\n // LIFO order\n while (listeners.length)\n this.removeListener(type, listeners[listeners.length - 1]);\n }\n delete this._events[type];\n\n return this;\n};\n\nEventEmitter.prototype.listeners = function(type) {\n var ret;\n if (!this._events || !this._events[type])\n ret = [];\n else if (isFunction(this._events[type]))\n ret = [this._events[type]];\n else\n ret = this._events[type].slice();\n return ret;\n};\n\nEventEmitter.prototype.listenerCount = function(type) {\n if (this._events) {\n var evlistener = this._events[type];\n\n if (isFunction(evlistener))\n return 1;\n else if (evlistener)\n return evlistener.length;\n }\n return 0;\n};\n\nEventEmitter.listenerCount = function(emitter, type) {\n return emitter.listenerCount(type);\n};\n\nfunction isFunction(arg) {\n return typeof arg === 'function';\n}\n\nfunction isNumber(arg) {\n return typeof arg === 'number';\n}\n\nfunction isObject(arg) {\n return typeof arg === 'object' && arg !== null;\n}\n\nfunction isUndefined(arg) {\n return arg === void 0;\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiOTYuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2V2ZW50cy9ldmVudHMuanM/N2M3MSJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxuZnVuY3Rpb24gRXZlbnRFbWl0dGVyKCkge1xuICB0aGlzLl9ldmVudHMgPSB0aGlzLl9ldmVudHMgfHwge307XG4gIHRoaXMuX21heExpc3RlbmVycyA9IHRoaXMuX21heExpc3RlbmVycyB8fCB1bmRlZmluZWQ7XG59XG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcblxuLy8gQmFja3dhcmRzLWNvbXBhdCB3aXRoIG5vZGUgMC4xMC54XG5FdmVudEVtaXR0ZXIuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9ldmVudHMgPSB1bmRlZmluZWQ7XG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9tYXhMaXN0ZW5lcnMgPSB1bmRlZmluZWQ7XG5cbi8vIEJ5IGRlZmF1bHQgRXZlbnRFbWl0dGVycyB3aWxsIHByaW50IGEgd2FybmluZyBpZiBtb3JlIHRoYW4gMTAgbGlzdGVuZXJzIGFyZVxuLy8gYWRkZWQgdG8gaXQuIFRoaXMgaXMgYSB1c2VmdWwgZGVmYXVsdCB3aGljaCBoZWxwcyBmaW5kaW5nIG1lbW9yeSBsZWFrcy5cbkV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzID0gMTA7XG5cbi8vIE9idmlvdXNseSBub3QgYWxsIEVtaXR0ZXJzIHNob3VsZCBiZSBsaW1pdGVkIHRvIDEwLiBUaGlzIGZ1bmN0aW9uIGFsbG93c1xuLy8gdGhhdCB0byBiZSBpbmNyZWFzZWQuIFNldCB0byB6ZXJvIGZvciB1bmxpbWl0ZWQuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnNldE1heExpc3RlbmVycyA9IGZ1bmN0aW9uKG4pIHtcbiAgaWYgKCFpc051bWJlcihuKSB8fCBuIDwgMCB8fCBpc05hTihuKSlcbiAgICB0aHJvdyBUeXBlRXJyb3IoJ24gbXVzdCBiZSBhIHBvc2l0aXZlIG51bWJlcicpO1xuICB0aGlzLl9tYXhMaXN0ZW5lcnMgPSBuO1xuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uKHR5cGUpIHtcbiAgdmFyIGVyLCBoYW5kbGVyLCBsZW4sIGFyZ3MsIGksIGxpc3RlbmVycztcblxuICBpZiAoIXRoaXMuX2V2ZW50cylcbiAgICB0aGlzLl9ldmVudHMgPSB7fTtcblxuICAvLyBJZiB0aGVyZSBpcyBubyAnZXJyb3InIGV2ZW50IGxpc3RlbmVyIHRoZW4gdGhyb3cuXG4gIGlmICh0eXBlID09PSAnZXJyb3InKSB7XG4gICAgaWYgKCF0aGlzLl9ldmVudHMuZXJyb3IgfHxcbiAgICAgICAgKGlzT2JqZWN0KHRoaXMuX2V2ZW50cy5lcnJvcikgJiYgIXRoaXMuX2V2ZW50cy5lcnJvci5sZW5ndGgpKSB7XG4gICAgICBlciA9IGFyZ3VtZW50c1sxXTtcbiAgICAgIGlmIChlciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHRocm93IGVyOyAvLyBVbmhhbmRsZWQgJ2Vycm9yJyBldmVudFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gQXQgbGVhc3QgZ2l2ZSBzb21lIGtpbmQgb2YgY29udGV4dCB0byB0aGUgdXNlclxuICAgICAgICB2YXIgZXJyID0gbmV3IEVycm9yKCdVbmNhdWdodCwgdW5zcGVjaWZpZWQgXCJlcnJvclwiIGV2ZW50LiAoJyArIGVyICsgJyknKTtcbiAgICAgICAgZXJyLmNvbnRleHQgPSBlcjtcbiAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGhhbmRsZXIgPSB0aGlzLl9ldmVudHNbdHlwZV07XG5cbiAgaWYgKGlzVW5kZWZpbmVkKGhhbmRsZXIpKVxuICAgIHJldHVybiBmYWxzZTtcblxuICBpZiAoaXNGdW5jdGlvbihoYW5kbGVyKSkge1xuICAgIHN3aXRjaCAoYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgLy8gZmFzdCBjYXNlc1xuICAgICAgY2FzZSAxOlxuICAgICAgICBoYW5kbGVyLmNhbGwodGhpcyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAyOlxuICAgICAgICBoYW5kbGVyLmNhbGwodGhpcywgYXJndW1lbnRzWzFdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIGhhbmRsZXIuY2FsbCh0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgLy8gc2xvd2VyXG4gICAgICBkZWZhdWx0OlxuICAgICAgICBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgaGFuZGxlci5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoaXNPYmplY3QoaGFuZGxlcikpIHtcbiAgICBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICBsaXN0ZW5lcnMgPSBoYW5kbGVyLnNsaWNlKCk7XG4gICAgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspXG4gICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkodGhpcywgYXJncyk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuYWRkTGlzdGVuZXIgPSBmdW5jdGlvbih0eXBlLCBsaXN0ZW5lcikge1xuICB2YXIgbTtcblxuICBpZiAoIWlzRnVuY3Rpb24obGlzdGVuZXIpKVxuICAgIHRocm93IFR5cGVFcnJvcignbGlzdGVuZXIgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgaWYgKCF0aGlzLl9ldmVudHMpXG4gICAgdGhpcy5fZXZlbnRzID0ge307XG5cbiAgLy8gVG8gYXZvaWQgcmVjdXJzaW9uIGluIHRoZSBjYXNlIHRoYXQgdHlwZSA9PT0gXCJuZXdMaXN0ZW5lclwiISBCZWZvcmVcbiAgLy8gYWRkaW5nIGl0IHRvIHRoZSBsaXN0ZW5lcnMsIGZpcnN0IGVtaXQgXCJuZXdMaXN0ZW5lclwiLlxuICBpZiAodGhpcy5fZXZlbnRzLm5ld0xpc3RlbmVyKVxuICAgIHRoaXMuZW1pdCgnbmV3TGlzdGVuZXInLCB0eXBlLFxuICAgICAgICAgICAgICBpc0Z1bmN0aW9uKGxpc3RlbmVyLmxpc3RlbmVyKSA/XG4gICAgICAgICAgICAgIGxpc3RlbmVyLmxpc3RlbmVyIDogbGlzdGVuZXIpO1xuXG4gIGlmICghdGhpcy5fZXZlbnRzW3R5cGVdKVxuICAgIC8vIE9wdGltaXplIHRoZSBjYXNlIG9mIG9uZSBsaXN0ZW5lci4gRG9uJ3QgbmVlZCB0aGUgZXh0cmEgYXJyYXkgb2JqZWN0LlxuICAgIHRoaXMuX2V2ZW50c1t0eXBlXSA9IGxpc3RlbmVyO1xuICBlbHNlIGlmIChpc09iamVjdCh0aGlzLl9ldmVudHNbdHlwZV0pKVxuICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgZ290IGFuIGFycmF5LCBqdXN0IGFwcGVuZC5cbiAgICB0aGlzLl9ldmVudHNbdHlwZV0ucHVzaChsaXN0ZW5lcik7XG4gIGVsc2VcbiAgICAvLyBBZGRpbmcgdGhlIHNlY29uZCBlbGVtZW50LCBuZWVkIHRvIGNoYW5nZSB0byBhcnJheS5cbiAgICB0aGlzLl9ldmVudHNbdHlwZV0gPSBbdGhpcy5fZXZlbnRzW3R5cGVdLCBsaXN0ZW5lcl07XG5cbiAgLy8gQ2hlY2sgZm9yIGxpc3RlbmVyIGxlYWtcbiAgaWYgKGlzT2JqZWN0KHRoaXMuX2V2ZW50c1t0eXBlXSkgJiYgIXRoaXMuX2V2ZW50c1t0eXBlXS53YXJuZWQpIHtcbiAgICBpZiAoIWlzVW5kZWZpbmVkKHRoaXMuX21heExpc3RlbmVycykpIHtcbiAgICAgIG0gPSB0aGlzLl9tYXhMaXN0ZW5lcnM7XG4gICAgfSBlbHNlIHtcbiAgICAgIG0gPSBFdmVudEVtaXR0ZXIuZGVmYXVsdE1heExpc3RlbmVycztcbiAgICB9XG5cbiAgICBpZiAobSAmJiBtID4gMCAmJiB0aGlzLl9ldmVudHNbdHlwZV0ubGVuZ3RoID4gbSkge1xuICAgICAgdGhpcy5fZXZlbnRzW3R5cGVdLndhcm5lZCA9IHRydWU7XG4gICAgICBjb25zb2xlLmVycm9yKCcobm9kZSkgd2FybmluZzogcG9zc2libGUgRXZlbnRFbWl0dGVyIG1lbW9yeSAnICtcbiAgICAgICAgICAgICAgICAgICAgJ2xlYWsgZGV0ZWN0ZWQuICVkIGxpc3RlbmVycyBhZGRlZC4gJyArXG4gICAgICAgICAgICAgICAgICAgICdVc2UgZW1pdHRlci5zZXRNYXhMaXN0ZW5lcnMoKSB0byBpbmNyZWFzZSBsaW1pdC4nLFxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9ldmVudHNbdHlwZV0ubGVuZ3RoKTtcbiAgICAgIGlmICh0eXBlb2YgY29uc29sZS50cmFjZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAvLyBub3Qgc3VwcG9ydGVkIGluIElFIDEwXG4gICAgICAgIGNvbnNvbGUudHJhY2UoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub24gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbih0eXBlLCBsaXN0ZW5lcikge1xuICBpZiAoIWlzRnVuY3Rpb24obGlzdGVuZXIpKVxuICAgIHRocm93IFR5cGVFcnJvcignbGlzdGVuZXIgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgdmFyIGZpcmVkID0gZmFsc2U7XG5cbiAgZnVuY3Rpb24gZygpIHtcbiAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGcpO1xuXG4gICAgaWYgKCFmaXJlZCkge1xuICAgICAgZmlyZWQgPSB0cnVlO1xuICAgICAgbGlzdGVuZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBnLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gIHRoaXMub24odHlwZSwgZyk7XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vLyBlbWl0cyBhICdyZW1vdmVMaXN0ZW5lcicgZXZlbnQgaWZmIHRoZSBsaXN0ZW5lciB3YXMgcmVtb3ZlZFxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lciA9IGZ1bmN0aW9uKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBsaXN0LCBwb3NpdGlvbiwgbGVuZ3RoLCBpO1xuXG4gIGlmICghaXNGdW5jdGlvbihsaXN0ZW5lcikpXG4gICAgdGhyb3cgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcblxuICBpZiAoIXRoaXMuX2V2ZW50cyB8fCAhdGhpcy5fZXZlbnRzW3R5cGVdKVxuICAgIHJldHVybiB0aGlzO1xuXG4gIGxpc3QgPSB0aGlzLl9ldmVudHNbdHlwZV07XG4gIGxlbmd0aCA9IGxpc3QubGVuZ3RoO1xuICBwb3NpdGlvbiA9IC0xO1xuXG4gIGlmIChsaXN0ID09PSBsaXN0ZW5lciB8fFxuICAgICAgKGlzRnVuY3Rpb24obGlzdC5saXN0ZW5lcikgJiYgbGlzdC5saXN0ZW5lciA9PT0gbGlzdGVuZXIpKSB7XG4gICAgZGVsZXRlIHRoaXMuX2V2ZW50c1t0eXBlXTtcbiAgICBpZiAodGhpcy5fZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgdGhpcy5lbWl0KCdyZW1vdmVMaXN0ZW5lcicsIHR5cGUsIGxpc3RlbmVyKTtcblxuICB9IGVsc2UgaWYgKGlzT2JqZWN0KGxpc3QpKSB7XG4gICAgZm9yIChpID0gbGVuZ3RoOyBpLS0gPiAwOykge1xuICAgICAgaWYgKGxpc3RbaV0gPT09IGxpc3RlbmVyIHx8XG4gICAgICAgICAgKGxpc3RbaV0ubGlzdGVuZXIgJiYgbGlzdFtpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpKSB7XG4gICAgICAgIHBvc2l0aW9uID0gaTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHBvc2l0aW9uIDwgMClcbiAgICAgIHJldHVybiB0aGlzO1xuXG4gICAgaWYgKGxpc3QubGVuZ3RoID09PSAxKSB7XG4gICAgICBsaXN0Lmxlbmd0aCA9IDA7XG4gICAgICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuICAgIH0gZWxzZSB7XG4gICAgICBsaXN0LnNwbGljZShwb3NpdGlvbiwgMSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX2V2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBsaXN0ZW5lcik7XG4gIH1cblxuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucmVtb3ZlQWxsTGlzdGVuZXJzID0gZnVuY3Rpb24odHlwZSkge1xuICB2YXIga2V5LCBsaXN0ZW5lcnM7XG5cbiAgaWYgKCF0aGlzLl9ldmVudHMpXG4gICAgcmV0dXJuIHRoaXM7XG5cbiAgLy8gbm90IGxpc3RlbmluZyBmb3IgcmVtb3ZlTGlzdGVuZXIsIG5vIG5lZWQgdG8gZW1pdFxuICBpZiAoIXRoaXMuX2V2ZW50cy5yZW1vdmVMaXN0ZW5lcikge1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKVxuICAgICAgdGhpcy5fZXZlbnRzID0ge307XG4gICAgZWxzZSBpZiAodGhpcy5fZXZlbnRzW3R5cGVdKVxuICAgICAgZGVsZXRlIHRoaXMuX2V2ZW50c1t0eXBlXTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8vIGVtaXQgcmVtb3ZlTGlzdGVuZXIgZm9yIGFsbCBsaXN0ZW5lcnMgb24gYWxsIGV2ZW50c1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgIGZvciAoa2V5IGluIHRoaXMuX2V2ZW50cykge1xuICAgICAgaWYgKGtleSA9PT0gJ3JlbW92ZUxpc3RlbmVyJykgY29udGludWU7XG4gICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhrZXkpO1xuICAgIH1cbiAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycygncmVtb3ZlTGlzdGVuZXInKTtcbiAgICB0aGlzLl9ldmVudHMgPSB7fTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIGxpc3RlbmVycyA9IHRoaXMuX2V2ZW50c1t0eXBlXTtcblxuICBpZiAoaXNGdW5jdGlvbihsaXN0ZW5lcnMpKSB7XG4gICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnMpO1xuICB9IGVsc2UgaWYgKGxpc3RlbmVycykge1xuICAgIC8vIExJRk8gb3JkZXJcbiAgICB3aGlsZSAobGlzdGVuZXJzLmxlbmd0aClcbiAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXJzW2xpc3RlbmVycy5sZW5ndGggLSAxXSk7XG4gIH1cbiAgZGVsZXRlIHRoaXMuX2V2ZW50c1t0eXBlXTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJzID0gZnVuY3Rpb24odHlwZSkge1xuICB2YXIgcmV0O1xuICBpZiAoIXRoaXMuX2V2ZW50cyB8fCAhdGhpcy5fZXZlbnRzW3R5cGVdKVxuICAgIHJldCA9IFtdO1xuICBlbHNlIGlmIChpc0Z1bmN0aW9uKHRoaXMuX2V2ZW50c1t0eXBlXSkpXG4gICAgcmV0ID0gW3RoaXMuX2V2ZW50c1t0eXBlXV07XG4gIGVsc2VcbiAgICByZXQgPSB0aGlzLl9ldmVudHNbdHlwZV0uc2xpY2UoKTtcbiAgcmV0dXJuIHJldDtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKHR5cGUpIHtcbiAgaWYgKHRoaXMuX2V2ZW50cykge1xuICAgIHZhciBldmxpc3RlbmVyID0gdGhpcy5fZXZlbnRzW3R5cGVdO1xuXG4gICAgaWYgKGlzRnVuY3Rpb24oZXZsaXN0ZW5lcikpXG4gICAgICByZXR1cm4gMTtcbiAgICBlbHNlIGlmIChldmxpc3RlbmVyKVxuICAgICAgcmV0dXJuIGV2bGlzdGVuZXIubGVuZ3RoO1xuICB9XG4gIHJldHVybiAwO1xufTtcblxuRXZlbnRFbWl0dGVyLmxpc3RlbmVyQ291bnQgPSBmdW5jdGlvbihlbWl0dGVyLCB0eXBlKSB7XG4gIHJldHVybiBlbWl0dGVyLmxpc3RlbmVyQ291bnQodHlwZSk7XG59O1xuXG5mdW5jdGlvbiBpc0Z1bmN0aW9uKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ2Z1bmN0aW9uJztcbn1cblxuZnVuY3Rpb24gaXNOdW1iZXIoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNPYmplY3QoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnb2JqZWN0JyAmJiBhcmcgIT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzVW5kZWZpbmVkKGFyZykge1xuICByZXR1cm4gYXJnID09PSB2b2lkIDA7XG59XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vZXZlbnRzL2V2ZW50cy5qc1xuLy8gbW9kdWxlIGlkID0gOTZcbi8vIG1vZHVsZSBjaHVua3MgPSAwIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOyIsInNvdXJjZVJvb3QiOiIifQ==");
- /***/ },
- /* 97 */
- /***/ function(module, exports) {
- eval("if (typeof Object.create === 'function') {\n // implementation from standard node.js 'util' module\n module.exports = function inherits(ctor, superCtor) {\n ctor.super_ = superCtor\n ctor.prototype = Object.create(superCtor.prototype, {\n constructor: {\n value: ctor,\n enumerable: false,\n writable: true,\n configurable: true\n }\n });\n };\n} else {\n // old school shim for old browsers\n module.exports = function inherits(ctor, superCtor) {\n ctor.super_ = superCtor\n var TempCtor = function () {}\n TempCtor.prototype = superCtor.prototype\n ctor.prototype = new TempCtor()\n ctor.prototype.constructor = ctor\n }\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiOTcuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L2luaGVyaXRzL2luaGVyaXRzX2Jyb3dzZXIuanM/N2Q0OCJdLCJzb3VyY2VzQ29udGVudCI6WyJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gIH1cbn1cblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vfi9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzXG4vLyBtb2R1bGUgaWQgPSA5N1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 98 */
- /***/ function(module, exports) {
- eval("// Generated by CoffeeScript 1.9.2\n(function() {\n var hasProp = {}.hasOwnProperty,\n slice = [].slice;\n\n module.exports = function(source, scope) {\n var key, keys, value, values;\n keys = [];\n values = [];\n for (key in scope) {\n if (!hasProp.call(scope, key)) continue;\n value = scope[key];\n if (key === 'this') {\n continue;\n }\n keys.push(key);\n values.push(value);\n }\n return Function.apply(null, slice.call(keys).concat([source])).apply(scope[\"this\"], values);\n };\n\n}).call(this);\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiOTguanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L3Njb3BlLWV2YWwvc2NvcGVfZXZhbC5qcz82YzljIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIEdlbmVyYXRlZCBieSBDb2ZmZWVTY3JpcHQgMS45LjJcbihmdW5jdGlvbigpIHtcbiAgdmFyIGhhc1Byb3AgPSB7fS5oYXNPd25Qcm9wZXJ0eSxcbiAgICBzbGljZSA9IFtdLnNsaWNlO1xuXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oc291cmNlLCBzY29wZSkge1xuICAgIHZhciBrZXksIGtleXMsIHZhbHVlLCB2YWx1ZXM7XG4gICAga2V5cyA9IFtdO1xuICAgIHZhbHVlcyA9IFtdO1xuICAgIGZvciAoa2V5IGluIHNjb3BlKSB7XG4gICAgICBpZiAoIWhhc1Byb3AuY2FsbChzY29wZSwga2V5KSkgY29udGludWU7XG4gICAgICB2YWx1ZSA9IHNjb3BlW2tleV07XG4gICAgICBpZiAoa2V5ID09PSAndGhpcycpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBrZXlzLnB1c2goa2V5KTtcbiAgICAgIHZhbHVlcy5wdXNoKHZhbHVlKTtcbiAgICB9XG4gICAgcmV0dXJuIEZ1bmN0aW9uLmFwcGx5KG51bGwsIHNsaWNlLmNhbGwoa2V5cykuY29uY2F0KFtzb3VyY2VdKSkuYXBwbHkoc2NvcGVbXCJ0aGlzXCJdLCB2YWx1ZXMpO1xuICB9O1xuXG59KS5jYWxsKHRoaXMpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L3Njb3BlLWV2YWwvc2NvcGVfZXZhbC5qc1xuLy8gbW9kdWxlIGlkID0gOThcbi8vIG1vZHVsZSBjaHVua3MgPSAwIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ },
- /* 99 */
- /***/ function(module, exports, __webpack_require__) {
- eval("(function (factory) {\n if (true) {\n // Node/CommonJS\n module.exports = factory();\n } else if (typeof define === 'function' && define.amd) {\n // AMD\n define(factory);\n } else {\n // Browser globals (with support for web workers)\n var glob;\n\n try {\n glob = window;\n } catch (e) {\n glob = self;\n }\n\n glob.SparkMD5 = factory();\n }\n}(function (undefined) {\n\n 'use strict';\n\n /*\n * Fastest md5 implementation around (JKM md5).\n * Credits: Joseph Myers\n *\n * @see http://www.myersdaily.org/joseph/javascript/md5-text.html\n * @see http://jsperf.com/md5-shootout/7\n */\n\n /* this function is much faster,\n so if possible we use it. Some IEs\n are the only ones I know of that\n need the idiotic second function,\n generated by an if clause. */\n var add32 = function (a, b) {\n return (a + b) & 0xFFFFFFFF;\n },\n hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];\n\n\n function cmn(q, a, b, x, s, t) {\n a = add32(add32(a, q), add32(x, t));\n return add32((a << s) | (a >>> (32 - s)), b);\n }\n\n function md5cycle(x, k) {\n var a = x[0],\n b = x[1],\n c = x[2],\n d = x[3];\n\n a += (b & c | ~b & d) + k[0] - 680876936 | 0;\n a = (a << 7 | a >>> 25) + b | 0;\n d += (a & b | ~a & c) + k[1] - 389564586 | 0;\n d = (d << 12 | d >>> 20) + a | 0;\n c += (d & a | ~d & b) + k[2] + 606105819 | 0;\n c = (c << 17 | c >>> 15) + d | 0;\n b += (c & d | ~c & a) + k[3] - 1044525330 | 0;\n b = (b << 22 | b >>> 10) + c | 0;\n a += (b & c | ~b & d) + k[4] - 176418897 | 0;\n a = (a << 7 | a >>> 25) + b | 0;\n d += (a & b | ~a & c) + k[5] + 1200080426 | 0;\n d = (d << 12 | d >>> 20) + a | 0;\n c += (d & a | ~d & b) + k[6] - 1473231341 | 0;\n c = (c << 17 | c >>> 15) + d | 0;\n b += (c & d | ~c & a) + k[7] - 45705983 | 0;\n b = (b << 22 | b >>> 10) + c | 0;\n a += (b & c | ~b & d) + k[8] + 1770035416 | 0;\n a = (a << 7 | a >>> 25) + b | 0;\n d += (a & b | ~a & c) + k[9] - 1958414417 | 0;\n d = (d << 12 | d >>> 20) + a | 0;\n c += (d & a | ~d & b) + k[10] - 42063 | 0;\n c = (c << 17 | c >>> 15) + d | 0;\n b += (c & d | ~c & a) + k[11] - 1990404162 | 0;\n b = (b << 22 | b >>> 10) + c | 0;\n a += (b & c | ~b & d) + k[12] + 1804603682 | 0;\n a = (a << 7 | a >>> 25) + b | 0;\n d += (a & b | ~a & c) + k[13] - 40341101 | 0;\n d = (d << 12 | d >>> 20) + a | 0;\n c += (d & a | ~d & b) + k[14] - 1502002290 | 0;\n c = (c << 17 | c >>> 15) + d | 0;\n b += (c & d | ~c & a) + k[15] + 1236535329 | 0;\n b = (b << 22 | b >>> 10) + c | 0;\n\n a += (b & d | c & ~d) + k[1] - 165796510 | 0;\n a = (a << 5 | a >>> 27) + b | 0;\n d += (a & c | b & ~c) + k[6] - 1069501632 | 0;\n d = (d << 9 | d >>> 23) + a | 0;\n c += (d & b | a & ~b) + k[11] + 643717713 | 0;\n c = (c << 14 | c >>> 18) + d | 0;\n b += (c & a | d & ~a) + k[0] - 373897302 | 0;\n b = (b << 20 | b >>> 12) + c | 0;\n a += (b & d | c & ~d) + k[5] - 701558691 | 0;\n a = (a << 5 | a >>> 27) + b | 0;\n d += (a & c | b & ~c) + k[10] + 38016083 | 0;\n d = (d << 9 | d >>> 23) + a | 0;\n c += (d & b | a & ~b) + k[15] - 660478335 | 0;\n c = (c << 14 | c >>> 18) + d | 0;\n b += (c & a | d & ~a) + k[4] - 405537848 | 0;\n b = (b << 20 | b >>> 12) + c | 0;\n a += (b & d | c & ~d) + k[9] + 568446438 | 0;\n a = (a << 5 | a >>> 27) + b | 0;\n d += (a & c | b & ~c) + k[14] - 1019803690 | 0;\n d = (d << 9 | d >>> 23) + a | 0;\n c += (d & b | a & ~b) + k[3] - 187363961 | 0;\n c = (c << 14 | c >>> 18) + d | 0;\n b += (c & a | d & ~a) + k[8] + 1163531501 | 0;\n b = (b << 20 | b >>> 12) + c | 0;\n a += (b & d | c & ~d) + k[13] - 1444681467 | 0;\n a = (a << 5 | a >>> 27) + b | 0;\n d += (a & c | b & ~c) + k[2] - 51403784 | 0;\n d = (d << 9 | d >>> 23) + a | 0;\n c += (d & b | a & ~b) + k[7] + 1735328473 | 0;\n c = (c << 14 | c >>> 18) + d | 0;\n b += (c & a | d & ~a) + k[12] - 1926607734 | 0;\n b = (b << 20 | b >>> 12) + c | 0;\n\n a += (b ^ c ^ d) + k[5] - 378558 | 0;\n a = (a << 4 | a >>> 28) + b | 0;\n d += (a ^ b ^ c) + k[8] - 2022574463 | 0;\n d = (d << 11 | d >>> 21) + a | 0;\n c += (d ^ a ^ b) + k[11] + 1839030562 | 0;\n c = (c << 16 | c >>> 16) + d | 0;\n b += (c ^ d ^ a) + k[14] - 35309556 | 0;\n b = (b << 23 | b >>> 9) + c | 0;\n a += (b ^ c ^ d) + k[1] - 1530992060 | 0;\n a = (a << 4 | a >>> 28) + b | 0;\n d += (a ^ b ^ c) + k[4] + 1272893353 | 0;\n d = (d << 11 | d >>> 21) + a | 0;\n c += (d ^ a ^ b) + k[7] - 155497632 | 0;\n c = (c << 16 | c >>> 16) + d | 0;\n b += (c ^ d ^ a) + k[10] - 1094730640 | 0;\n b = (b << 23 | b >>> 9) + c | 0;\n a += (b ^ c ^ d) + k[13] + 681279174 | 0;\n a = (a << 4 | a >>> 28) + b | 0;\n d += (a ^ b ^ c) + k[0] - 358537222 | 0;\n d = (d << 11 | d >>> 21) + a | 0;\n c += (d ^ a ^ b) + k[3] - 722521979 | 0;\n c = (c << 16 | c >>> 16) + d | 0;\n b += (c ^ d ^ a) + k[6] + 76029189 | 0;\n b = (b << 23 | b >>> 9) + c | 0;\n a += (b ^ c ^ d) + k[9] - 640364487 | 0;\n a = (a << 4 | a >>> 28) + b | 0;\n d += (a ^ b ^ c) + k[12] - 421815835 | 0;\n d = (d << 11 | d >>> 21) + a | 0;\n c += (d ^ a ^ b) + k[15] + 530742520 | 0;\n c = (c << 16 | c >>> 16) + d | 0;\n b += (c ^ d ^ a) + k[2] - 995338651 | 0;\n b = (b << 23 | b >>> 9) + c | 0;\n\n a += (c ^ (b | ~d)) + k[0] - 198630844 | 0;\n a = (a << 6 | a >>> 26) + b | 0;\n d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0;\n d = (d << 10 | d >>> 22) + a | 0;\n c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0;\n c = (c << 15 | c >>> 17) + d | 0;\n b += (d ^ (c | ~a)) + k[5] - 57434055 | 0;\n b = (b << 21 |b >>> 11) + c | 0;\n a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0;\n a = (a << 6 | a >>> 26) + b | 0;\n d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0;\n d = (d << 10 | d >>> 22) + a | 0;\n c += (a ^ (d | ~b)) + k[10] - 1051523 | 0;\n c = (c << 15 | c >>> 17) + d | 0;\n b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0;\n b = (b << 21 |b >>> 11) + c | 0;\n a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0;\n a = (a << 6 | a >>> 26) + b | 0;\n d += (b ^ (a | ~c)) + k[15] - 30611744 | 0;\n d = (d << 10 | d >>> 22) + a | 0;\n c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0;\n c = (c << 15 | c >>> 17) + d | 0;\n b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0;\n b = (b << 21 |b >>> 11) + c | 0;\n a += (c ^ (b | ~d)) + k[4] - 145523070 | 0;\n a = (a << 6 | a >>> 26) + b | 0;\n d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0;\n d = (d << 10 | d >>> 22) + a | 0;\n c += (a ^ (d | ~b)) + k[2] + 718787259 | 0;\n c = (c << 15 | c >>> 17) + d | 0;\n b += (d ^ (c | ~a)) + k[9] - 343485551 | 0;\n b = (b << 21 | b >>> 11) + c | 0;\n\n x[0] = a + x[0] | 0;\n x[1] = b + x[1] | 0;\n x[2] = c + x[2] | 0;\n x[3] = d + x[3] | 0;\n }\n\n function md5blk(s) {\n var md5blks = [],\n i; /* Andy King said do it this way. */\n\n for (i = 0; i < 64; i += 4) {\n md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);\n }\n return md5blks;\n }\n\n function md5blk_array(a) {\n var md5blks = [],\n i; /* Andy King said do it this way. */\n\n for (i = 0; i < 64; i += 4) {\n md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);\n }\n return md5blks;\n }\n\n function md51(s) {\n var n = s.length,\n state = [1732584193, -271733879, -1732584194, 271733878],\n i,\n length,\n tail,\n tmp,\n lo,\n hi;\n\n for (i = 64; i <= n; i += 64) {\n md5cycle(state, md5blk(s.substring(i - 64, i)));\n }\n s = s.substring(i - 64);\n length = s.length;\n tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n for (i = 0; i < length; i += 1) {\n tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);\n }\n tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n if (i > 55) {\n md5cycle(state, tail);\n for (i = 0; i < 16; i += 1) {\n tail[i] = 0;\n }\n }\n\n // Beware that the final length might not fit in 32 bits so we take care of that\n tmp = n * 8;\n tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n lo = parseInt(tmp[2], 16);\n hi = parseInt(tmp[1], 16) || 0;\n\n tail[14] = lo;\n tail[15] = hi;\n\n md5cycle(state, tail);\n return state;\n }\n\n function md51_array(a) {\n var n = a.length,\n state = [1732584193, -271733879, -1732584194, 271733878],\n i,\n length,\n tail,\n tmp,\n lo,\n hi;\n\n for (i = 64; i <= n; i += 64) {\n md5cycle(state, md5blk_array(a.subarray(i - 64, i)));\n }\n\n // Not sure if it is a bug, however IE10 will always produce a sub array of length 1\n // containing the last element of the parent array if the sub array specified starts\n // beyond the length of the parent array - weird.\n // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue\n a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0);\n\n length = a.length;\n tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n for (i = 0; i < length; i += 1) {\n tail[i >> 2] |= a[i] << ((i % 4) << 3);\n }\n\n tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n if (i > 55) {\n md5cycle(state, tail);\n for (i = 0; i < 16; i += 1) {\n tail[i] = 0;\n }\n }\n\n // Beware that the final length might not fit in 32 bits so we take care of that\n tmp = n * 8;\n tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n lo = parseInt(tmp[2], 16);\n hi = parseInt(tmp[1], 16) || 0;\n\n tail[14] = lo;\n tail[15] = hi;\n\n md5cycle(state, tail);\n\n return state;\n }\n\n function rhex(n) {\n var s = '',\n j;\n for (j = 0; j < 4; j += 1) {\n s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F];\n }\n return s;\n }\n\n function hex(x) {\n var i;\n for (i = 0; i < x.length; i += 1) {\n x[i] = rhex(x[i]);\n }\n return x.join('');\n }\n\n // In some cases the fast add32 function cannot be used..\n if (hex(md51('hello')) !== '5d41402abc4b2a76b9719d911017c592') {\n add32 = function (x, y) {\n var lsw = (x & 0xFFFF) + (y & 0xFFFF),\n msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n return (msw << 16) | (lsw & 0xFFFF);\n };\n }\n\n // ---------------------------------------------------\n\n /**\n * ArrayBuffer slice polyfill.\n *\n * @see https://github.com/ttaubert/node-arraybuffer-slice\n */\n\n if (typeof ArrayBuffer !== 'undefined' && !ArrayBuffer.prototype.slice) {\n (function () {\n function clamp(val, length) {\n val = (val | 0) || 0;\n\n if (val < 0) {\n return Math.max(val + length, 0);\n }\n\n return Math.min(val, length);\n }\n\n ArrayBuffer.prototype.slice = function (from, to) {\n var length = this.byteLength,\n begin = clamp(from, length),\n end = length,\n num,\n target,\n targetArray,\n sourceArray;\n\n if (to !== undefined) {\n end = clamp(to, length);\n }\n\n if (begin > end) {\n return new ArrayBuffer(0);\n }\n\n num = end - begin;\n target = new ArrayBuffer(num);\n targetArray = new Uint8Array(target);\n\n sourceArray = new Uint8Array(this, begin, num);\n targetArray.set(sourceArray);\n\n return target;\n };\n })();\n }\n\n // ---------------------------------------------------\n\n /**\n * Helpers.\n */\n\n function toUtf8(str) {\n if (/[\\u0080-\\uFFFF]/.test(str)) {\n str = unescape(encodeURIComponent(str));\n }\n\n return str;\n }\n\n function utf8Str2ArrayBuffer(str, returnUInt8Array) {\n var length = str.length,\n buff = new ArrayBuffer(length),\n arr = new Uint8Array(buff),\n i;\n\n for (i = 0; i < length; i += 1) {\n arr[i] = str.charCodeAt(i);\n }\n\n return returnUInt8Array ? arr : buff;\n }\n\n function arrayBuffer2Utf8Str(buff) {\n return String.fromCharCode.apply(null, new Uint8Array(buff));\n }\n\n function concatenateArrayBuffers(first, second, returnUInt8Array) {\n var result = new Uint8Array(first.byteLength + second.byteLength);\n\n result.set(new Uint8Array(first));\n result.set(new Uint8Array(second), first.byteLength);\n\n return returnUInt8Array ? result : result.buffer;\n }\n\n function hexToBinaryString(hex) {\n var bytes = [],\n length = hex.length,\n x;\n\n for (x = 0; x < length - 1; x += 2) {\n bytes.push(parseInt(hex.substr(x, 2), 16));\n }\n\n return String.fromCharCode.apply(String, bytes);\n }\n\n // ---------------------------------------------------\n\n /**\n * SparkMD5 OOP implementation.\n *\n * Use this class to perform an incremental md5, otherwise use the\n * static methods instead.\n */\n\n function SparkMD5() {\n // call reset to init the instance\n this.reset();\n }\n\n /**\n * Appends a string.\n * A conversion will be applied if an utf8 string is detected.\n *\n * @param {String} str The string to be appended\n *\n * @return {SparkMD5} The instance itself\n */\n SparkMD5.prototype.append = function (str) {\n // Converts the string to utf8 bytes if necessary\n // Then append as binary\n this.appendBinary(toUtf8(str));\n\n return this;\n };\n\n /**\n * Appends a binary string.\n *\n * @param {String} contents The binary string to be appended\n *\n * @return {SparkMD5} The instance itself\n */\n SparkMD5.prototype.appendBinary = function (contents) {\n this._buff += contents;\n this._length += contents.length;\n\n var length = this._buff.length,\n i;\n\n for (i = 64; i <= length; i += 64) {\n md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i)));\n }\n\n this._buff = this._buff.substring(i - 64);\n\n return this;\n };\n\n /**\n * Finishes the incremental computation, reseting the internal state and\n * returning the result.\n *\n * @param {Boolean} raw True to get the raw string, false to get the hex string\n *\n * @return {String} The result\n */\n SparkMD5.prototype.end = function (raw) {\n var buff = this._buff,\n length = buff.length,\n i,\n tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n ret;\n\n for (i = 0; i < length; i += 1) {\n tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3);\n }\n\n this._finish(tail, length);\n ret = hex(this._hash);\n\n if (raw) {\n ret = hexToBinaryString(ret);\n }\n\n this.reset();\n\n return ret;\n };\n\n /**\n * Resets the internal state of the computation.\n *\n * @return {SparkMD5} The instance itself\n */\n SparkMD5.prototype.reset = function () {\n this._buff = '';\n this._length = 0;\n this._hash = [1732584193, -271733879, -1732584194, 271733878];\n\n return this;\n };\n\n /**\n * Gets the internal state of the computation.\n *\n * @return {Object} The state\n */\n SparkMD5.prototype.getState = function () {\n return {\n buff: this._buff,\n length: this._length,\n hash: this._hash\n };\n };\n\n /**\n * Gets the internal state of the computation.\n *\n * @param {Object} state The state\n *\n * @return {SparkMD5} The instance itself\n */\n SparkMD5.prototype.setState = function (state) {\n this._buff = state.buff;\n this._length = state.length;\n this._hash = state.hash;\n\n return this;\n };\n\n /**\n * Releases memory used by the incremental buffer and other additional\n * resources. If you plan to use the instance again, use reset instead.\n */\n SparkMD5.prototype.destroy = function () {\n delete this._hash;\n delete this._buff;\n delete this._length;\n };\n\n /**\n * Finish the final calculation based on the tail.\n *\n * @param {Array} tail The tail (will be modified)\n * @param {Number} length The length of the remaining buffer\n */\n SparkMD5.prototype._finish = function (tail, length) {\n var i = length,\n tmp,\n lo,\n hi;\n\n tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n if (i > 55) {\n md5cycle(this._hash, tail);\n for (i = 0; i < 16; i += 1) {\n tail[i] = 0;\n }\n }\n\n // Do the final computation based on the tail and length\n // Beware that the final length may not fit in 32 bits so we take care of that\n tmp = this._length * 8;\n tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n lo = parseInt(tmp[2], 16);\n hi = parseInt(tmp[1], 16) || 0;\n\n tail[14] = lo;\n tail[15] = hi;\n md5cycle(this._hash, tail);\n };\n\n /**\n * Performs the md5 hash on a string.\n * A conversion will be applied if utf8 string is detected.\n *\n * @param {String} str The string\n * @param {Boolean} raw True to get the raw string, false to get the hex string\n *\n * @return {String} The result\n */\n SparkMD5.hash = function (str, raw) {\n // Converts the string to utf8 bytes if necessary\n // Then compute it using the binary function\n return SparkMD5.hashBinary(toUtf8(str), raw);\n };\n\n /**\n * Performs the md5 hash on a binary string.\n *\n * @param {String} content The binary string\n * @param {Boolean} raw True to get the raw string, false to get the hex string\n *\n * @return {String} The result\n */\n SparkMD5.hashBinary = function (content, raw) {\n var hash = md51(content),\n ret = hex(hash);\n\n return raw ? hexToBinaryString(ret) : ret;\n };\n\n // ---------------------------------------------------\n\n /**\n * SparkMD5 OOP implementation for array buffers.\n *\n * Use this class to perform an incremental md5 ONLY for array buffers.\n */\n SparkMD5.ArrayBuffer = function () {\n // call reset to init the instance\n this.reset();\n };\n\n /**\n * Appends an array buffer.\n *\n * @param {ArrayBuffer} arr The array to be appended\n *\n * @return {SparkMD5.ArrayBuffer} The instance itself\n */\n SparkMD5.ArrayBuffer.prototype.append = function (arr) {\n var buff = concatenateArrayBuffers(this._buff.buffer, arr, true),\n length = buff.length,\n i;\n\n this._length += arr.byteLength;\n\n for (i = 64; i <= length; i += 64) {\n md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i)));\n }\n\n this._buff = (i - 64) < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0);\n\n return this;\n };\n\n /**\n * Finishes the incremental computation, reseting the internal state and\n * returning the result.\n *\n * @param {Boolean} raw True to get the raw string, false to get the hex string\n *\n * @return {String} The result\n */\n SparkMD5.ArrayBuffer.prototype.end = function (raw) {\n var buff = this._buff,\n length = buff.length,\n tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n i,\n ret;\n\n for (i = 0; i < length; i += 1) {\n tail[i >> 2] |= buff[i] << ((i % 4) << 3);\n }\n\n this._finish(tail, length);\n ret = hex(this._hash);\n\n if (raw) {\n ret = hexToBinaryString(ret);\n }\n\n this.reset();\n\n return ret;\n };\n\n /**\n * Resets the internal state of the computation.\n *\n * @return {SparkMD5.ArrayBuffer} The instance itself\n */\n SparkMD5.ArrayBuffer.prototype.reset = function () {\n this._buff = new Uint8Array(0);\n this._length = 0;\n this._hash = [1732584193, -271733879, -1732584194, 271733878];\n\n return this;\n };\n\n /**\n * Gets the internal state of the computation.\n *\n * @return {Object} The state\n */\n SparkMD5.ArrayBuffer.prototype.getState = function () {\n var state = SparkMD5.prototype.getState.call(this);\n\n // Convert buffer to a string\n state.buff = arrayBuffer2Utf8Str(state.buff);\n\n return state;\n };\n\n /**\n * Gets the internal state of the computation.\n *\n * @param {Object} state The state\n *\n * @return {SparkMD5.ArrayBuffer} The instance itself\n */\n SparkMD5.ArrayBuffer.prototype.setState = function (state) {\n // Convert string to buffer\n state.buff = utf8Str2ArrayBuffer(state.buff, true);\n\n return SparkMD5.prototype.setState.call(this, state);\n };\n\n SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;\n\n SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;\n\n /**\n * Performs the md5 hash on an array buffer.\n *\n * @param {ArrayBuffer} arr The array buffer\n * @param {Boolean} raw True to get the raw string, false to get the hex one\n *\n * @return {String} The result\n */\n SparkMD5.ArrayBuffer.hash = function (arr, raw) {\n var hash = md51_array(new Uint8Array(arr)),\n ret = hex(hash);\n\n return raw ? hexToBinaryString(ret) : ret;\n };\n\n return SparkMD5;\n}));\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiOTkuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9+L3NwYXJrLW1kNS9zcGFyay1tZDUuanM/NzgyMiJdLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gKGZhY3RvcnkpIHtcbiAgICBpZiAodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIC8vIE5vZGUvQ29tbW9uSlNcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgLy8gQU1EXG4gICAgICAgIGRlZmluZShmYWN0b3J5KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBCcm93c2VyIGdsb2JhbHMgKHdpdGggc3VwcG9ydCBmb3Igd2ViIHdvcmtlcnMpXG4gICAgICAgIHZhciBnbG9iO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBnbG9iID0gd2luZG93O1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBnbG9iID0gc2VsZjtcbiAgICAgICAgfVxuXG4gICAgICAgIGdsb2IuU3BhcmtNRDUgPSBmYWN0b3J5KCk7XG4gICAgfVxufShmdW5jdGlvbiAodW5kZWZpbmVkKSB7XG5cbiAgICAndXNlIHN0cmljdCc7XG5cbiAgICAvKlxuICAgICAqIEZhc3Rlc3QgbWQ1IGltcGxlbWVudGF0aW9uIGFyb3VuZCAoSktNIG1kNSkuXG4gICAgICogQ3JlZGl0czogSm9zZXBoIE15ZXJzXG4gICAgICpcbiAgICAgKiBAc2VlIGh0dHA6Ly93d3cubXllcnNkYWlseS5vcmcvam9zZXBoL2phdmFzY3JpcHQvbWQ1LXRleHQuaHRtbFxuICAgICAqIEBzZWUgaHR0cDovL2pzcGVyZi5jb20vbWQ1LXNob290b3V0LzdcbiAgICAgKi9cblxuICAgIC8qIHRoaXMgZnVuY3Rpb24gaXMgbXVjaCBmYXN0ZXIsXG4gICAgICBzbyBpZiBwb3NzaWJsZSB3ZSB1c2UgaXQuIFNvbWUgSUVzXG4gICAgICBhcmUgdGhlIG9ubHkgb25lcyBJIGtub3cgb2YgdGhhdFxuICAgICAgbmVlZCB0aGUgaWRpb3RpYyBzZWNvbmQgZnVuY3Rpb24sXG4gICAgICBnZW5lcmF0ZWQgYnkgYW4gaWYgY2xhdXNlLiAgKi9cbiAgICB2YXIgYWRkMzIgPSBmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICByZXR1cm4gKGEgKyBiKSAmIDB4RkZGRkZGRkY7XG4gICAgfSxcbiAgICAgICAgaGV4X2NociA9IFsnMCcsICcxJywgJzInLCAnMycsICc0JywgJzUnLCAnNicsICc3JywgJzgnLCAnOScsICdhJywgJ2InLCAnYycsICdkJywgJ2UnLCAnZiddO1xuXG5cbiAgICBmdW5jdGlvbiBjbW4ocSwgYSwgYiwgeCwgcywgdCkge1xuICAgICAgICBhID0gYWRkMzIoYWRkMzIoYSwgcSksIGFkZDMyKHgsIHQpKTtcbiAgICAgICAgcmV0dXJuIGFkZDMyKChhIDw8IHMpIHwgKGEgPj4+ICgzMiAtIHMpKSwgYik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWQ1Y3ljbGUoeCwgaykge1xuICAgICAgICB2YXIgYSA9IHhbMF0sXG4gICAgICAgICAgICBiID0geFsxXSxcbiAgICAgICAgICAgIGMgPSB4WzJdLFxuICAgICAgICAgICAgZCA9IHhbM107XG5cbiAgICAgICAgYSArPSAoYiAmIGMgfCB+YiAmIGQpICsga1swXSAtIDY4MDg3NjkzNiB8IDA7XG4gICAgICAgIGEgID0gKGEgPDwgNyB8IGEgPj4+IDI1KSArIGIgfCAwO1xuICAgICAgICBkICs9IChhICYgYiB8IH5hICYgYykgKyBrWzFdIC0gMzg5NTY0NTg2IHwgMDtcbiAgICAgICAgZCAgPSAoZCA8PCAxMiB8IGQgPj4+IDIwKSArIGEgfCAwO1xuICAgICAgICBjICs9IChkICYgYSB8IH5kICYgYikgKyBrWzJdICsgNjA2MTA1ODE5IHwgMDtcbiAgICAgICAgYyAgPSAoYyA8PCAxNyB8IGMgPj4+IDE1KSArIGQgfCAwO1xuICAgICAgICBiICs9IChjICYgZCB8IH5jICYgYSkgKyBrWzNdIC0gMTA0NDUyNTMzMCB8IDA7XG4gICAgICAgIGIgID0gKGIgPDwgMjIgfCBiID4+PiAxMCkgKyBjIHwgMDtcbiAgICAgICAgYSArPSAoYiAmIGMgfCB+YiAmIGQpICsga1s0XSAtIDE3NjQxODg5NyB8IDA7XG4gICAgICAgIGEgID0gKGEgPDwgNyB8IGEgPj4+IDI1KSArIGIgfCAwO1xuICAgICAgICBkICs9IChhICYgYiB8IH5hICYgYykgKyBrWzVdICsgMTIwMDA4MDQyNiB8IDA7XG4gICAgICAgIGQgID0gKGQgPDwgMTIgfCBkID4+PiAyMCkgKyBhIHwgMDtcbiAgICAgICAgYyArPSAoZCAmIGEgfCB+ZCAmIGIpICsga1s2XSAtIDE0NzMyMzEzNDEgfCAwO1xuICAgICAgICBjICA9IChjIDw8IDE3IHwgYyA+Pj4gMTUpICsgZCB8IDA7XG4gICAgICAgIGIgKz0gKGMgJiBkIHwgfmMgJiBhKSArIGtbN10gLSA0NTcwNTk4MyB8IDA7XG4gICAgICAgIGIgID0gKGIgPDwgMjIgfCBiID4+PiAxMCkgKyBjIHwgMDtcbiAgICAgICAgYSArPSAoYiAmIGMgfCB+YiAmIGQpICsga1s4XSArIDE3NzAwMzU0MTYgfCAwO1xuICAgICAgICBhICA9IChhIDw8IDcgfCBhID4+PiAyNSkgKyBiIHwgMDtcbiAgICAgICAgZCArPSAoYSAmIGIgfCB+YSAmIGMpICsga1s5XSAtIDE5NTg0MTQ0MTcgfCAwO1xuICAgICAgICBkICA9IChkIDw8IDEyIHwgZCA+Pj4gMjApICsgYSB8IDA7XG4gICAgICAgIGMgKz0gKGQgJiBhIHwgfmQgJiBiKSArIGtbMTBdIC0gNDIwNjMgfCAwO1xuICAgICAgICBjICA9IChjIDw8IDE3IHwgYyA+Pj4gMTUpICsgZCB8IDA7XG4gICAgICAgIGIgKz0gKGMgJiBkIHwgfmMgJiBhKSArIGtbMTFdIC0gMTk5MDQwNDE2MiB8IDA7XG4gICAgICAgIGIgID0gKGIgPDwgMjIgfCBiID4+PiAxMCkgKyBjIHwgMDtcbiAgICAgICAgYSArPSAoYiAmIGMgfCB+YiAmIGQpICsga1sxMl0gKyAxODA0NjAzNjgyIHwgMDtcbiAgICAgICAgYSAgPSAoYSA8PCA3IHwgYSA+Pj4gMjUpICsgYiB8IDA7XG4gICAgICAgIGQgKz0gKGEgJiBiIHwgfmEgJiBjKSArIGtbMTNdIC0gNDAzNDExMDEgfCAwO1xuICAgICAgICBkICA9IChkIDw8IDEyIHwgZCA+Pj4gMjApICsgYSB8IDA7XG4gICAgICAgIGMgKz0gKGQgJiBhIHwgfmQgJiBiKSArIGtbMTRdIC0gMTUwMjAwMjI5MCB8IDA7XG4gICAgICAgIGMgID0gKGMgPDwgMTcgfCBjID4+PiAxNSkgKyBkIHwgMDtcbiAgICAgICAgYiArPSAoYyAmIGQgfCB+YyAmIGEpICsga1sxNV0gKyAxMjM2NTM1MzI5IHwgMDtcbiAgICAgICAgYiAgPSAoYiA8PCAyMiB8IGIgPj4+IDEwKSArIGMgfCAwO1xuXG4gICAgICAgIGEgKz0gKGIgJiBkIHwgYyAmIH5kKSArIGtbMV0gLSAxNjU3OTY1MTAgfCAwO1xuICAgICAgICBhICA9IChhIDw8IDUgfCBhID4+PiAyNykgKyBiIHwgMDtcbiAgICAgICAgZCArPSAoYSAmIGMgfCBiICYgfmMpICsga1s2XSAtIDEwNjk1MDE2MzIgfCAwO1xuICAgICAgICBkICA9IChkIDw8IDkgfCBkID4+PiAyMykgKyBhIHwgMDtcbiAgICAgICAgYyArPSAoZCAmIGIgfCBhICYgfmIpICsga1sxMV0gKyA2NDM3MTc3MTMgfCAwO1xuICAgICAgICBjICA9IChjIDw8IDE0IHwgYyA+Pj4gMTgpICsgZCB8IDA7XG4gICAgICAgIGIgKz0gKGMgJiBhIHwgZCAmIH5hKSArIGtbMF0gLSAzNzM4OTczMDIgfCAwO1xuICAgICAgICBiICA9IChiIDw8IDIwIHwgYiA+Pj4gMTIpICsgYyB8IDA7XG4gICAgICAgIGEgKz0gKGIgJiBkIHwgYyAmIH5kKSArIGtbNV0gLSA3MDE1NTg2OTEgfCAwO1xuICAgICAgICBhICA9IChhIDw8IDUgfCBhID4+PiAyNykgKyBiIHwgMDtcbiAgICAgICAgZCArPSAoYSAmIGMgfCBiICYgfmMpICsga1sxMF0gKyAzODAxNjA4MyB8IDA7XG4gICAgICAgIGQgID0gKGQgPDwgOSB8IGQgPj4+IDIzKSArIGEgfCAwO1xuICAgICAgICBjICs9IChkICYgYiB8IGEgJiB+YikgKyBrWzE1XSAtIDY2MDQ3ODMzNSB8IDA7XG4gICAgICAgIGMgID0gKGMgPDwgMTQgfCBjID4+PiAxOCkgKyBkIHwgMDtcbiAgICAgICAgYiArPSAoYyAmIGEgfCBkICYgfmEpICsga1s0XSAtIDQwNTUzNzg0OCB8IDA7XG4gICAgICAgIGIgID0gKGIgPDwgMjAgfCBiID4+PiAxMikgKyBjIHwgMDtcbiAgICAgICAgYSArPSAoYiAmIGQgfCBjICYgfmQpICsga1s5XSArIDU2ODQ0NjQzOCB8IDA7XG4gICAgICAgIGEgID0gKGEgPDwgNSB8IGEgPj4+IDI3KSArIGIgfCAwO1xuICAgICAgICBkICs9IChhICYgYyB8IGIgJiB+YykgKyBrWzE0XSAtIDEwMTk4MDM2OTAgfCAwO1xuICAgICAgICBkICA9IChkIDw8IDkgfCBkID4+PiAyMykgKyBhIHwgMDtcbiAgICAgICAgYyArPSAoZCAmIGIgfCBhICYgfmIpICsga1szXSAtIDE4NzM2Mzk2MSB8IDA7XG4gICAgICAgIGMgID0gKGMgPDwgMTQgfCBjID4+PiAxOCkgKyBkIHwgMDtcbiAgICAgICAgYiArPSAoYyAmIGEgfCBkICYgfmEpICsga1s4XSArIDExNjM1MzE1MDEgfCAwO1xuICAgICAgICBiICA9IChiIDw8IDIwIHwgYiA+Pj4gMTIpICsgYyB8IDA7XG4gICAgICAgIGEgKz0gKGIgJiBkIHwgYyAmIH5kKSArIGtbMTNdIC0gMTQ0NDY4MTQ2NyB8IDA7XG4gICAgICAgIGEgID0gKGEgPDwgNSB8IGEgPj4+IDI3KSArIGIgfCAwO1xuICAgICAgICBkICs9IChhICYgYyB8IGIgJiB+YykgKyBrWzJdIC0gNTE0MDM3ODQgfCAwO1xuICAgICAgICBkICA9IChkIDw8IDkgfCBkID4+PiAyMykgKyBhIHwgMDtcbiAgICAgICAgYyArPSAoZCAmIGIgfCBhICYgfmIpICsga1s3XSArIDE3MzUzMjg0NzMgfCAwO1xuICAgICAgICBjICA9IChjIDw8IDE0IHwgYyA+Pj4gMTgpICsgZCB8IDA7XG4gICAgICAgIGIgKz0gKGMgJiBhIHwgZCAmIH5hKSArIGtbMTJdIC0gMTkyNjYwNzczNCB8IDA7XG4gICAgICAgIGIgID0gKGIgPDwgMjAgfCBiID4+PiAxMikgKyBjIHwgMDtcblxuICAgICAgICBhICs9IChiIF4gYyBeIGQpICsga1s1XSAtIDM3ODU1OCB8IDA7XG4gICAgICAgIGEgID0gKGEgPDwgNCB8IGEgPj4+IDI4KSArIGIgfCAwO1xuICAgICAgICBkICs9IChhIF4gYiBeIGMpICsga1s4XSAtIDIwMjI1NzQ0NjMgfCAwO1xuICAgICAgICBkICA9IChkIDw8IDExIHwgZCA+Pj4gMjEpICsgYSB8IDA7XG4gICAgICAgIGMgKz0gKGQgXiBhIF4gYikgKyBrWzExXSArIDE4MzkwMzA1NjIgfCAwO1xuICAgICAgICBjICA9IChjIDw8IDE2IHwgYyA+Pj4gMTYpICsgZCB8IDA7XG4gICAgICAgIGIgKz0gKGMgXiBkIF4gYSkgKyBrWzE0XSAtIDM1MzA5NTU2IHwgMDtcbiAgICAgICAgYiAgPSAoYiA8PCAyMyB8IGIgPj4+IDkpICsgYyB8IDA7XG4gICAgICAgIGEgKz0gKGIgXiBjIF4gZCkgKyBrWzFdIC0gMTUzMDk5MjA2MCB8IDA7XG4gICAgICAgIGEgID0gKGEgPDwgNCB8IGEgPj4+IDI4KSArIGIgfCAwO1xuICAgICAgICBkICs9IChhIF4gYiBeIGMpICsga1s0XSArIDEyNzI4OTMzNTMgfCAwO1xuICAgICAgICBkICA9IChkIDw8IDExIHwgZCA+Pj4gMjEpICsgYSB8IDA7XG4gICAgICAgIGMgKz0gKGQgXiBhIF4gYikgKyBrWzddIC0gMTU1NDk3NjMyIHwgMDtcbiAgICAgICAgYyAgPSAoYyA8PCAxNiB8IGMgPj4+IDE2KSArIGQgfCAwO1xuICAgICAgICBiICs9IChjIF4gZCBeIGEpICsga1sxMF0gLSAxMDk0NzMwNjQwIHwgMDtcbiAgICAgICAgYiAgPSAoYiA8PCAyMyB8IGIgPj4+IDkpICsgYyB8IDA7XG4gICAgICAgIGEgKz0gKGIgXiBjIF4gZCkgKyBrWzEzXSArIDY4MTI3OTE3NCB8IDA7XG4gICAgICAgIGEgID0gKGEgPDwgNCB8IGEgPj4+IDI4KSArIGIgfCAwO1xuICAgICAgICBkICs9IChhIF4gYiBeIGMpICsga1swXSAtIDM1ODUzNzIyMiB8IDA7XG4gICAgICAgIGQgID0gKGQgPDwgMTEgfCBkID4+PiAyMSkgKyBhIHwgMDtcbiAgICAgICAgYyArPSAoZCBeIGEgXiBiKSArIGtbM10gLSA3MjI1MjE5NzkgfCAwO1xuICAgICAgICBjICA9IChjIDw8IDE2IHwgYyA+Pj4gMTYpICsgZCB8IDA7XG4gICAgICAgIGIgKz0gKGMgXiBkIF4gYSkgKyBrWzZdICsgNzYwMjkxODkgfCAwO1xuICAgICAgICBiICA9IChiIDw8IDIzIHwgYiA+Pj4gOSkgKyBjIHwgMDtcbiAgICAgICAgYSArPSAoYiBeIGMgXiBkKSArIGtbOV0gLSA2NDAzNjQ0ODcgfCAwO1xuICAgICAgICBhICA9IChhIDw8IDQgfCBhID4+PiAyOCkgKyBiIHwgMDtcbiAgICAgICAgZCArPSAoYSBeIGIgXiBjKSArIGtbMTJdIC0gNDIxODE1ODM1IHwgMDtcbiAgICAgICAgZCAgPSAoZCA8PCAxMSB8IGQgPj4+IDIxKSArIGEgfCAwO1xuICAgICAgICBjICs9IChkIF4gYSBeIGIpICsga1sxNV0gKyA1MzA3NDI1MjAgfCAwO1xuICAgICAgICBjICA9IChjIDw8IDE2IHwgYyA+Pj4gMTYpICsgZCB8IDA7XG4gICAgICAgIGIgKz0gKGMgXiBkIF4gYSkgKyBrWzJdIC0gOTk1MzM4NjUxIHwgMDtcbiAgICAgICAgYiAgPSAoYiA8PCAyMyB8IGIgPj4+IDkpICsgYyB8IDA7XG5cbiAgICAgICAgYSArPSAoYyBeIChiIHwgfmQpKSArIGtbMF0gLSAxOTg2MzA4NDQgfCAwO1xuICAgICAgICBhICA9IChhIDw8IDYgfCBhID4+PiAyNikgKyBiIHwgMDtcbiAgICAgICAgZCArPSAoYiBeIChhIHwgfmMpKSArIGtbN10gKyAxMTI2ODkxNDE1IHwgMDtcbiAgICAgICAgZCAgPSAoZCA8PCAxMCB8IGQgPj4+IDIyKSArIGEgfCAwO1xuICAgICAgICBjICs9IChhIF4gKGQgfCB+YikpICsga1sxNF0gLSAxNDE2MzU0OTA1IHwgMDtcbiAgICAgICAgYyAgPSAoYyA8PCAxNSB8IGMgPj4+IDE3KSArIGQgfCAwO1xuICAgICAgICBiICs9IChkIF4gKGMgfCB+YSkpICsga1s1XSAtIDU3NDM0MDU1IHwgMDtcbiAgICAgICAgYiAgPSAoYiA8PCAyMSB8YiA+Pj4gMTEpICsgYyB8IDA7XG4gICAgICAgIGEgKz0gKGMgXiAoYiB8IH5kKSkgKyBrWzEyXSArIDE3MDA0ODU1NzEgfCAwO1xuICAgICAgICBhICA9IChhIDw8IDYgfCBhID4+PiAyNikgKyBiIHwgMDtcbiAgICAgICAgZCArPSAoYiBeIChhIHwgfmMpKSArIGtbM10gLSAxODk0OTg2NjA2IHwgMDtcbiAgICAgICAgZCAgPSAoZCA8PCAxMCB8IGQgPj4+IDIyKSArIGEgfCAwO1xuICAgICAgICBjICs9IChhIF4gKGQgfCB+YikpICsga1sxMF0gLSAxMDUxNTIzIHwgMDtcbiAgICAgICAgYyAgPSAoYyA8PCAxNSB8IGMgPj4+IDE3KSArIGQgfCAwO1xuICAgICAgICBiICs9IChkIF4gKGMgfCB+YSkpICsga1sxXSAtIDIwNTQ5MjI3OTkgfCAwO1xuICAgICAgICBiICA9IChiIDw8IDIxIHxiID4+PiAxMSkgKyBjIHwgMDtcbiAgICAgICAgYSArPSAoYyBeIChiIHwgfmQpKSArIGtbOF0gKyAxODczMzEzMzU5IHwgMDtcbiAgICAgICAgYSAgPSAoYSA8PCA2IHwgYSA+Pj4gMjYpICsgYiB8IDA7XG4gICAgICAgIGQgKz0gKGIgXiAoYSB8IH5jKSkgKyBrWzE1XSAtIDMwNjExNzQ0IHwgMDtcbiAgICAgICAgZCAgPSAoZCA8PCAxMCB8IGQgPj4+IDIyKSArIGEgfCAwO1xuICAgICAgICBjICs9IChhIF4gKGQgfCB+YikpICsga1s2XSAtIDE1NjAxOTgzODAgfCAwO1xuICAgICAgICBjICA9IChjIDw8IDE1IHwgYyA+Pj4gMTcpICsgZCB8IDA7XG4gICAgICAgIGIgKz0gKGQgXiAoYyB8IH5hKSkgKyBrWzEzXSArIDEzMDkxNTE2NDkgfCAwO1xuICAgICAgICBiICA9IChiIDw8IDIxIHxiID4+PiAxMSkgKyBjIHwgMDtcbiAgICAgICAgYSArPSAoYyBeIChiIHwgfmQpKSArIGtbNF0gLSAxNDU1MjMwNzAgfCAwO1xuICAgICAgICBhICA9IChhIDw8IDYgfCBhID4+PiAyNikgKyBiIHwgMDtcbiAgICAgICAgZCArPSAoYiBeIChhIHwgfmMpKSArIGtbMTFdIC0gMTEyMDIxMDM3OSB8IDA7XG4gICAgICAgIGQgID0gKGQgPDwgMTAgfCBkID4+PiAyMikgKyBhIHwgMDtcbiAgICAgICAgYyArPSAoYSBeIChkIHwgfmIpKSArIGtbMl0gKyA3MTg3ODcyNTkgfCAwO1xuICAgICAgICBjICA9IChjIDw8IDE1IHwgYyA+Pj4gMTcpICsgZCB8IDA7XG4gICAgICAgIGIgKz0gKGQgXiAoYyB8IH5hKSkgKyBrWzldIC0gMzQzNDg1NTUxIHwgMDtcbiAgICAgICAgYiAgPSAoYiA8PCAyMSB8IGIgPj4+IDExKSArIGMgfCAwO1xuXG4gICAgICAgIHhbMF0gPSBhICsgeFswXSB8IDA7XG4gICAgICAgIHhbMV0gPSBiICsgeFsxXSB8IDA7XG4gICAgICAgIHhbMl0gPSBjICsgeFsyXSB8IDA7XG4gICAgICAgIHhbM10gPSBkICsgeFszXSB8IDA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWQ1YmxrKHMpIHtcbiAgICAgICAgdmFyIG1kNWJsa3MgPSBbXSxcbiAgICAgICAgICAgIGk7IC8qIEFuZHkgS2luZyBzYWlkIGRvIGl0IHRoaXMgd2F5LiAqL1xuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCA2NDsgaSArPSA0KSB7XG4gICAgICAgICAgICBtZDVibGtzW2kgPj4gMl0gPSBzLmNoYXJDb2RlQXQoaSkgKyAocy5jaGFyQ29kZUF0KGkgKyAxKSA8PCA4KSArIChzLmNoYXJDb2RlQXQoaSArIDIpIDw8IDE2KSArIChzLmNoYXJDb2RlQXQoaSArIDMpIDw8IDI0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWQ1YmxrcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtZDVibGtfYXJyYXkoYSkge1xuICAgICAgICB2YXIgbWQ1YmxrcyA9IFtdLFxuICAgICAgICAgICAgaTsgLyogQW5keSBLaW5nIHNhaWQgZG8gaXQgdGhpcyB3YXkuICovXG5cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IDY0OyBpICs9IDQpIHtcbiAgICAgICAgICAgIG1kNWJsa3NbaSA+PiAyXSA9IGFbaV0gKyAoYVtpICsgMV0gPDwgOCkgKyAoYVtpICsgMl0gPDwgMTYpICsgKGFbaSArIDNdIDw8IDI0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWQ1YmxrcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtZDUxKHMpIHtcbiAgICAgICAgdmFyIG4gPSBzLmxlbmd0aCxcbiAgICAgICAgICAgIHN0YXRlID0gWzE3MzI1ODQxOTMsIC0yNzE3MzM4NzksIC0xNzMyNTg0MTk0LCAyNzE3MzM4NzhdLFxuICAgICAgICAgICAgaSxcbiAgICAgICAgICAgIGxlbmd0aCxcbiAgICAgICAgICAgIHRhaWwsXG4gICAgICAgICAgICB0bXAsXG4gICAgICAgICAgICBsbyxcbiAgICAgICAgICAgIGhpO1xuXG4gICAgICAgIGZvciAoaSA9IDY0OyBpIDw9IG47IGkgKz0gNjQpIHtcbiAgICAgICAgICAgIG1kNWN5Y2xlKHN0YXRlLCBtZDVibGsocy5zdWJzdHJpbmcoaSAtIDY0LCBpKSkpO1xuICAgICAgICB9XG4gICAgICAgIHMgPSBzLnN1YnN0cmluZyhpIC0gNjQpO1xuICAgICAgICBsZW5ndGggPSBzLmxlbmd0aDtcbiAgICAgICAgdGFpbCA9IFswLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwXTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICB0YWlsW2kgPj4gMl0gfD0gcy5jaGFyQ29kZUF0KGkpIDw8ICgoaSAlIDQpIDw8IDMpO1xuICAgICAgICB9XG4gICAgICAgIHRhaWxbaSA+PiAyXSB8PSAweDgwIDw8ICgoaSAlIDQpIDw8IDMpO1xuICAgICAgICBpZiAoaSA+IDU1KSB7XG4gICAgICAgICAgICBtZDVjeWNsZShzdGF0ZSwgdGFpbCk7XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMTY7IGkgKz0gMSkge1xuICAgICAgICAgICAgICAgIHRhaWxbaV0gPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQmV3YXJlIHRoYXQgdGhlIGZpbmFsIGxlbmd0aCBtaWdodCBub3QgZml0IGluIDMyIGJpdHMgc28gd2UgdGFrZSBjYXJlIG9mIHRoYXRcbiAgICAgICAgdG1wID0gbiAqIDg7XG4gICAgICAgIHRtcCA9IHRtcC50b1N0cmluZygxNikubWF0Y2goLyguKj8pKC57MCw4fSkkLyk7XG4gICAgICAgIGxvID0gcGFyc2VJbnQodG1wWzJdLCAxNik7XG4gICAgICAgIGhpID0gcGFyc2VJbnQodG1wWzFdLCAxNikgfHwgMDtcblxuICAgICAgICB0YWlsWzE0XSA9IGxvO1xuICAgICAgICB0YWlsWzE1XSA9IGhpO1xuXG4gICAgICAgIG1kNWN5Y2xlKHN0YXRlLCB0YWlsKTtcbiAgICAgICAgcmV0dXJuIHN0YXRlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1kNTFfYXJyYXkoYSkge1xuICAgICAgICB2YXIgbiA9IGEubGVuZ3RoLFxuICAgICAgICAgICAgc3RhdGUgPSBbMTczMjU4NDE5MywgLTI3MTczMzg3OSwgLTE3MzI1ODQxOTQsIDI3MTczMzg3OF0sXG4gICAgICAgICAgICBpLFxuICAgICAgICAgICAgbGVuZ3RoLFxuICAgICAgICAgICAgdGFpbCxcbiAgICAgICAgICAgIHRtcCxcbiAgICAgICAgICAgIGxvLFxuICAgICAgICAgICAgaGk7XG5cbiAgICAgICAgZm9yIChpID0gNjQ7IGkgPD0gbjsgaSArPSA2NCkge1xuICAgICAgICAgICAgbWQ1Y3ljbGUoc3RhdGUsIG1kNWJsa19hcnJheShhLnN1YmFycmF5KGkgLSA2NCwgaSkpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE5vdCBzdXJlIGlmIGl0IGlzIGEgYnVnLCBob3dldmVyIElFMTAgd2lsbCBhbHdheXMgcHJvZHVjZSBhIHN1YiBhcnJheSBvZiBsZW5ndGggMVxuICAgICAgICAvLyBjb250YWluaW5nIHRoZSBsYXN0IGVsZW1lbnQgb2YgdGhlIHBhcmVudCBhcnJheSBpZiB0aGUgc3ViIGFycmF5IHNwZWNpZmllZCBzdGFydHNcbiAgICAgICAgLy8gYmV5b25kIHRoZSBsZW5ndGggb2YgdGhlIHBhcmVudCBhcnJheSAtIHdlaXJkLlxuICAgICAgICAvLyBodHRwczovL2Nvbm5lY3QubWljcm9zb2Z0LmNvbS9JRS9mZWVkYmFjay9kZXRhaWxzLzc3MTQ1Mi90eXBlZC1hcnJheS1zdWJhcnJheS1pc3N1ZVxuICAgICAgICBhID0gKGkgLSA2NCkgPCBuID8gYS5zdWJhcnJheShpIC0gNjQpIDogbmV3IFVpbnQ4QXJyYXkoMCk7XG5cbiAgICAgICAgbGVuZ3RoID0gYS5sZW5ndGg7XG4gICAgICAgIHRhaWwgPSBbMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMF07XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgdGFpbFtpID4+IDJdIHw9IGFbaV0gPDwgKChpICUgNCkgPDwgMyk7XG4gICAgICAgIH1cblxuICAgICAgICB0YWlsW2kgPj4gMl0gfD0gMHg4MCA8PCAoKGkgJSA0KSA8PCAzKTtcbiAgICAgICAgaWYgKGkgPiA1NSkge1xuICAgICAgICAgICAgbWQ1Y3ljbGUoc3RhdGUsIHRhaWwpO1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IDE2OyBpICs9IDEpIHtcbiAgICAgICAgICAgICAgICB0YWlsW2ldID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEJld2FyZSB0aGF0IHRoZSBmaW5hbCBsZW5ndGggbWlnaHQgbm90IGZpdCBpbiAzMiBiaXRzIHNvIHdlIHRha2UgY2FyZSBvZiB0aGF0XG4gICAgICAgIHRtcCA9IG4gKiA4O1xuICAgICAgICB0bXAgPSB0bXAudG9TdHJpbmcoMTYpLm1hdGNoKC8oLio/KSguezAsOH0pJC8pO1xuICAgICAgICBsbyA9IHBhcnNlSW50KHRtcFsyXSwgMTYpO1xuICAgICAgICBoaSA9IHBhcnNlSW50KHRtcFsxXSwgMTYpIHx8IDA7XG5cbiAgICAgICAgdGFpbFsxNF0gPSBsbztcbiAgICAgICAgdGFpbFsxNV0gPSBoaTtcblxuICAgICAgICBtZDVjeWNsZShzdGF0ZSwgdGFpbCk7XG5cbiAgICAgICAgcmV0dXJuIHN0YXRlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJoZXgobikge1xuICAgICAgICB2YXIgcyA9ICcnLFxuICAgICAgICAgICAgajtcbiAgICAgICAgZm9yIChqID0gMDsgaiA8IDQ7IGogKz0gMSkge1xuICAgICAgICAgICAgcyArPSBoZXhfY2hyWyhuID4+IChqICogOCArIDQpKSAmIDB4MEZdICsgaGV4X2NoclsobiA+PiAoaiAqIDgpKSAmIDB4MEZdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGhleCh4KSB7XG4gICAgICAgIHZhciBpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgeC5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgeFtpXSA9IHJoZXgoeFtpXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHguam9pbignJyk7XG4gICAgfVxuXG4gICAgLy8gSW4gc29tZSBjYXNlcyB0aGUgZmFzdCBhZGQzMiBmdW5jdGlvbiBjYW5ub3QgYmUgdXNlZC4uXG4gICAgaWYgKGhleChtZDUxKCdoZWxsbycpKSAhPT0gJzVkNDE0MDJhYmM0YjJhNzZiOTcxOWQ5MTEwMTdjNTkyJykge1xuICAgICAgICBhZGQzMiA9IGZ1bmN0aW9uICh4LCB5KSB7XG4gICAgICAgICAgICB2YXIgbHN3ID0gKHggJiAweEZGRkYpICsgKHkgJiAweEZGRkYpLFxuICAgICAgICAgICAgICAgIG1zdyA9ICh4ID4+IDE2KSArICh5ID4+IDE2KSArIChsc3cgPj4gMTYpO1xuICAgICAgICAgICAgcmV0dXJuIChtc3cgPDwgMTYpIHwgKGxzdyAmIDB4RkZGRik7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgICAvKipcbiAgICAgKiBBcnJheUJ1ZmZlciBzbGljZSBwb2x5ZmlsbC5cbiAgICAgKlxuICAgICAqIEBzZWUgaHR0cHM6Ly9naXRodWIuY29tL3R0YXViZXJ0L25vZGUtYXJyYXlidWZmZXItc2xpY2VcbiAgICAgKi9cblxuICAgIGlmICh0eXBlb2YgQXJyYXlCdWZmZXIgIT09ICd1bmRlZmluZWQnICYmICFBcnJheUJ1ZmZlci5wcm90b3R5cGUuc2xpY2UpIHtcbiAgICAgICAgKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGZ1bmN0aW9uIGNsYW1wKHZhbCwgbGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdmFsID0gKHZhbCB8IDApIHx8IDA7XG5cbiAgICAgICAgICAgICAgICBpZiAodmFsIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gTWF0aC5tYXgodmFsICsgbGVuZ3RoLCAwKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gTWF0aC5taW4odmFsLCBsZW5ndGgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBBcnJheUJ1ZmZlci5wcm90b3R5cGUuc2xpY2UgPSBmdW5jdGlvbiAoZnJvbSwgdG8pIHtcbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gdGhpcy5ieXRlTGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICBiZWdpbiA9IGNsYW1wKGZyb20sIGxlbmd0aCksXG4gICAgICAgICAgICAgICAgICAgIGVuZCA9IGxlbmd0aCxcbiAgICAgICAgICAgICAgICAgICAgbnVtLFxuICAgICAgICAgICAgICAgICAgICB0YXJnZXQsXG4gICAgICAgICAgICAgICAgICAgIHRhcmdldEFycmF5LFxuICAgICAgICAgICAgICAgICAgICBzb3VyY2VBcnJheTtcblxuICAgICAgICAgICAgICAgIGlmICh0byAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGVuZCA9IGNsYW1wKHRvLCBsZW5ndGgpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChiZWdpbiA+IGVuZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEFycmF5QnVmZmVyKDApO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIG51bSA9IGVuZCAtIGJlZ2luO1xuICAgICAgICAgICAgICAgIHRhcmdldCA9IG5ldyBBcnJheUJ1ZmZlcihudW0pO1xuICAgICAgICAgICAgICAgIHRhcmdldEFycmF5ID0gbmV3IFVpbnQ4QXJyYXkodGFyZ2V0KTtcblxuICAgICAgICAgICAgICAgIHNvdXJjZUFycmF5ID0gbmV3IFVpbnQ4QXJyYXkodGhpcywgYmVnaW4sIG51bSk7XG4gICAgICAgICAgICAgICAgdGFyZ2V0QXJyYXkuc2V0KHNvdXJjZUFycmF5KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0YXJnZXQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9KSgpO1xuICAgIH1cblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gICAgLyoqXG4gICAgICogSGVscGVycy5cbiAgICAgKi9cblxuICAgIGZ1bmN0aW9uIHRvVXRmOChzdHIpIHtcbiAgICAgICAgaWYgKC9bXFx1MDA4MC1cXHVGRkZGXS8udGVzdChzdHIpKSB7XG4gICAgICAgICAgICBzdHIgPSB1bmVzY2FwZShlbmNvZGVVUklDb21wb25lbnQoc3RyKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc3RyO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHV0ZjhTdHIyQXJyYXlCdWZmZXIoc3RyLCByZXR1cm5VSW50OEFycmF5KSB7XG4gICAgICAgIHZhciBsZW5ndGggPSBzdHIubGVuZ3RoLFxuICAgICAgICAgICBidWZmID0gbmV3IEFycmF5QnVmZmVyKGxlbmd0aCksXG4gICAgICAgICAgIGFyciA9IG5ldyBVaW50OEFycmF5KGJ1ZmYpLFxuICAgICAgICAgICBpO1xuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgYXJyW2ldID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmV0dXJuVUludDhBcnJheSA/IGFyciA6IGJ1ZmY7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYXJyYXlCdWZmZXIyVXRmOFN0cihidWZmKSB7XG4gICAgICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsIG5ldyBVaW50OEFycmF5KGJ1ZmYpKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb25jYXRlbmF0ZUFycmF5QnVmZmVycyhmaXJzdCwgc2Vjb25kLCByZXR1cm5VSW50OEFycmF5KSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBuZXcgVWludDhBcnJheShmaXJzdC5ieXRlTGVuZ3RoICsgc2Vjb25kLmJ5dGVMZW5ndGgpO1xuXG4gICAgICAgIHJlc3VsdC5zZXQobmV3IFVpbnQ4QXJyYXkoZmlyc3QpKTtcbiAgICAgICAgcmVzdWx0LnNldChuZXcgVWludDhBcnJheShzZWNvbmQpLCBmaXJzdC5ieXRlTGVuZ3RoKTtcblxuICAgICAgICByZXR1cm4gcmV0dXJuVUludDhBcnJheSA/IHJlc3VsdCA6IHJlc3VsdC5idWZmZXI7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaGV4VG9CaW5hcnlTdHJpbmcoaGV4KSB7XG4gICAgICAgIHZhciBieXRlcyA9IFtdLFxuICAgICAgICAgICAgbGVuZ3RoID0gaGV4Lmxlbmd0aCxcbiAgICAgICAgICAgIHg7XG5cbiAgICAgICAgZm9yICh4ID0gMDsgeCA8IGxlbmd0aCAtIDE7IHggKz0gMikge1xuICAgICAgICAgICAgYnl0ZXMucHVzaChwYXJzZUludChoZXguc3Vic3RyKHgsIDIpLCAxNikpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoU3RyaW5nLCBieXRlcyk7XG4gICAgfVxuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgICAvKipcbiAgICAgKiBTcGFya01ENSBPT1AgaW1wbGVtZW50YXRpb24uXG4gICAgICpcbiAgICAgKiBVc2UgdGhpcyBjbGFzcyB0byBwZXJmb3JtIGFuIGluY3JlbWVudGFsIG1kNSwgb3RoZXJ3aXNlIHVzZSB0aGVcbiAgICAgKiBzdGF0aWMgbWV0aG9kcyBpbnN0ZWFkLlxuICAgICAqL1xuXG4gICAgZnVuY3Rpb24gU3BhcmtNRDUoKSB7XG4gICAgICAgIC8vIGNhbGwgcmVzZXQgdG8gaW5pdCB0aGUgaW5zdGFuY2VcbiAgICAgICAgdGhpcy5yZXNldCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFwcGVuZHMgYSBzdHJpbmcuXG4gICAgICogQSBjb252ZXJzaW9uIHdpbGwgYmUgYXBwbGllZCBpZiBhbiB1dGY4IHN0cmluZyBpcyBkZXRlY3RlZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgVGhlIHN0cmluZyB0byBiZSBhcHBlbmRlZFxuICAgICAqXG4gICAgICogQHJldHVybiB7U3BhcmtNRDV9IFRoZSBpbnN0YW5jZSBpdHNlbGZcbiAgICAgKi9cbiAgICBTcGFya01ENS5wcm90b3R5cGUuYXBwZW5kID0gZnVuY3Rpb24gKHN0cikge1xuICAgICAgICAvLyBDb252ZXJ0cyB0aGUgc3RyaW5nIHRvIHV0ZjggYnl0ZXMgaWYgbmVjZXNzYXJ5XG4gICAgICAgIC8vIFRoZW4gYXBwZW5kIGFzIGJpbmFyeVxuICAgICAgICB0aGlzLmFwcGVuZEJpbmFyeSh0b1V0Zjgoc3RyKSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFwcGVuZHMgYSBiaW5hcnkgc3RyaW5nLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGNvbnRlbnRzIFRoZSBiaW5hcnkgc3RyaW5nIHRvIGJlIGFwcGVuZGVkXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtTcGFya01ENX0gVGhlIGluc3RhbmNlIGl0c2VsZlxuICAgICAqL1xuICAgIFNwYXJrTUQ1LnByb3RvdHlwZS5hcHBlbmRCaW5hcnkgPSBmdW5jdGlvbiAoY29udGVudHMpIHtcbiAgICAgICAgdGhpcy5fYnVmZiArPSBjb250ZW50cztcbiAgICAgICAgdGhpcy5fbGVuZ3RoICs9IGNvbnRlbnRzLmxlbmd0aDtcblxuICAgICAgICB2YXIgbGVuZ3RoID0gdGhpcy5fYnVmZi5sZW5ndGgsXG4gICAgICAgICAgICBpO1xuXG4gICAgICAgIGZvciAoaSA9IDY0OyBpIDw9IGxlbmd0aDsgaSArPSA2NCkge1xuICAgICAgICAgICAgbWQ1Y3ljbGUodGhpcy5faGFzaCwgbWQ1YmxrKHRoaXMuX2J1ZmYuc3Vic3RyaW5nKGkgLSA2NCwgaSkpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2J1ZmYgPSB0aGlzLl9idWZmLnN1YnN0cmluZyhpIC0gNjQpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGaW5pc2hlcyB0aGUgaW5jcmVtZW50YWwgY29tcHV0YXRpb24sIHJlc2V0aW5nIHRoZSBpbnRlcm5hbCBzdGF0ZSBhbmRcbiAgICAgKiByZXR1cm5pbmcgdGhlIHJlc3VsdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gcmF3IFRydWUgdG8gZ2V0IHRoZSByYXcgc3RyaW5nLCBmYWxzZSB0byBnZXQgdGhlIGhleCBzdHJpbmdcbiAgICAgKlxuICAgICAqIEByZXR1cm4ge1N0cmluZ30gVGhlIHJlc3VsdFxuICAgICAqL1xuICAgIFNwYXJrTUQ1LnByb3RvdHlwZS5lbmQgPSBmdW5jdGlvbiAocmF3KSB7XG4gICAgICAgIHZhciBidWZmID0gdGhpcy5fYnVmZixcbiAgICAgICAgICAgIGxlbmd0aCA9IGJ1ZmYubGVuZ3RoLFxuICAgICAgICAgICAgaSxcbiAgICAgICAgICAgIHRhaWwgPSBbMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMF0sXG4gICAgICAgICAgICByZXQ7XG5cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICB0YWlsW2kgPj4gMl0gfD0gYnVmZi5jaGFyQ29kZUF0KGkpIDw8ICgoaSAlIDQpIDw8IDMpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fZmluaXNoKHRhaWwsIGxlbmd0aCk7XG4gICAgICAgIHJldCA9IGhleCh0aGlzLl9oYXNoKTtcblxuICAgICAgICBpZiAocmF3KSB7XG4gICAgICAgICAgICByZXQgPSBoZXhUb0JpbmFyeVN0cmluZyhyZXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5yZXNldCgpO1xuXG4gICAgICAgIHJldHVybiByZXQ7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlc2V0cyB0aGUgaW50ZXJuYWwgc3RhdGUgb2YgdGhlIGNvbXB1dGF0aW9uLlxuICAgICAqXG4gICAgICogQHJldHVybiB7U3BhcmtNRDV9IFRoZSBpbnN0YW5jZSBpdHNlbGZcbiAgICAgKi9cbiAgICBTcGFya01ENS5wcm90b3R5cGUucmVzZXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuX2J1ZmYgPSAnJztcbiAgICAgICAgdGhpcy5fbGVuZ3RoID0gMDtcbiAgICAgICAgdGhpcy5faGFzaCA9IFsxNzMyNTg0MTkzLCAtMjcxNzMzODc5LCAtMTczMjU4NDE5NCwgMjcxNzMzODc4XTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgaW50ZXJuYWwgc3RhdGUgb2YgdGhlIGNvbXB1dGF0aW9uLlxuICAgICAqXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBUaGUgc3RhdGVcbiAgICAgKi9cbiAgICBTcGFya01ENS5wcm90b3R5cGUuZ2V0U3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBidWZmOiB0aGlzLl9idWZmLFxuICAgICAgICAgICAgbGVuZ3RoOiB0aGlzLl9sZW5ndGgsXG4gICAgICAgICAgICBoYXNoOiB0aGlzLl9oYXNoXG4gICAgICAgIH07XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGludGVybmFsIHN0YXRlIG9mIHRoZSBjb21wdXRhdGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzdGF0ZSBUaGUgc3RhdGVcbiAgICAgKlxuICAgICAqIEByZXR1cm4ge1NwYXJrTUQ1fSBUaGUgaW5zdGFuY2UgaXRzZWxmXG4gICAgICovXG4gICAgU3BhcmtNRDUucHJvdG90eXBlLnNldFN0YXRlID0gZnVuY3Rpb24gKHN0YXRlKSB7XG4gICAgICAgIHRoaXMuX2J1ZmYgPSBzdGF0ZS5idWZmO1xuICAgICAgICB0aGlzLl9sZW5ndGggPSBzdGF0ZS5sZW5ndGg7XG4gICAgICAgIHRoaXMuX2hhc2ggPSBzdGF0ZS5oYXNoO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZWxlYXNlcyBtZW1vcnkgdXNlZCBieSB0aGUgaW5jcmVtZW50YWwgYnVmZmVyIGFuZCBvdGhlciBhZGRpdGlvbmFsXG4gICAgICogcmVzb3VyY2VzLiBJZiB5b3UgcGxhbiB0byB1c2UgdGhlIGluc3RhbmNlIGFnYWluLCB1c2UgcmVzZXQgaW5zdGVhZC5cbiAgICAgKi9cbiAgICBTcGFya01ENS5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZGVsZXRlIHRoaXMuX2hhc2g7XG4gICAgICAgIGRlbGV0ZSB0aGlzLl9idWZmO1xuICAgICAgICBkZWxldGUgdGhpcy5fbGVuZ3RoO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGaW5pc2ggdGhlIGZpbmFsIGNhbGN1bGF0aW9uIGJhc2VkIG9uIHRoZSB0YWlsLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtBcnJheX0gIHRhaWwgICBUaGUgdGFpbCAod2lsbCBiZSBtb2RpZmllZClcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbGVuZ3RoIFRoZSBsZW5ndGggb2YgdGhlIHJlbWFpbmluZyBidWZmZXJcbiAgICAgKi9cbiAgICBTcGFya01ENS5wcm90b3R5cGUuX2ZpbmlzaCA9IGZ1bmN0aW9uICh0YWlsLCBsZW5ndGgpIHtcbiAgICAgICAgdmFyIGkgPSBsZW5ndGgsXG4gICAgICAgICAgICB0bXAsXG4gICAgICAgICAgICBsbyxcbiAgICAgICAgICAgIGhpO1xuXG4gICAgICAgIHRhaWxbaSA+PiAyXSB8PSAweDgwIDw8ICgoaSAlIDQpIDw8IDMpO1xuICAgICAgICBpZiAoaSA+IDU1KSB7XG4gICAgICAgICAgICBtZDVjeWNsZSh0aGlzLl9oYXNoLCB0YWlsKTtcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCAxNjsgaSArPSAxKSB7XG4gICAgICAgICAgICAgICAgdGFpbFtpXSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEbyB0aGUgZmluYWwgY29tcHV0YXRpb24gYmFzZWQgb24gdGhlIHRhaWwgYW5kIGxlbmd0aFxuICAgICAgICAvLyBCZXdhcmUgdGhhdCB0aGUgZmluYWwgbGVuZ3RoIG1heSBub3QgZml0IGluIDMyIGJpdHMgc28gd2UgdGFrZSBjYXJlIG9mIHRoYXRcbiAgICAgICAgdG1wID0gdGhpcy5fbGVuZ3RoICogODtcbiAgICAgICAgdG1wID0gdG1wLnRvU3RyaW5nKDE2KS5tYXRjaCgvKC4qPykoLnswLDh9KSQvKTtcbiAgICAgICAgbG8gPSBwYXJzZUludCh0bXBbMl0sIDE2KTtcbiAgICAgICAgaGkgPSBwYXJzZUludCh0bXBbMV0sIDE2KSB8fCAwO1xuXG4gICAgICAgIHRhaWxbMTRdID0gbG87XG4gICAgICAgIHRhaWxbMTVdID0gaGk7XG4gICAgICAgIG1kNWN5Y2xlKHRoaXMuX2hhc2gsIHRhaWwpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBQZXJmb3JtcyB0aGUgbWQ1IGhhc2ggb24gYSBzdHJpbmcuXG4gICAgICogQSBjb252ZXJzaW9uIHdpbGwgYmUgYXBwbGllZCBpZiB1dGY4IHN0cmluZyBpcyBkZXRlY3RlZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSAgc3RyIFRoZSBzdHJpbmdcbiAgICAgKiBAcGFyYW0ge0Jvb2xlYW59IHJhdyBUcnVlIHRvIGdldCB0aGUgcmF3IHN0cmluZywgZmFsc2UgdG8gZ2V0IHRoZSBoZXggc3RyaW5nXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtTdHJpbmd9IFRoZSByZXN1bHRcbiAgICAgKi9cbiAgICBTcGFya01ENS5oYXNoID0gZnVuY3Rpb24gKHN0ciwgcmF3KSB7XG4gICAgICAgIC8vIENvbnZlcnRzIHRoZSBzdHJpbmcgdG8gdXRmOCBieXRlcyBpZiBuZWNlc3NhcnlcbiAgICAgICAgLy8gVGhlbiBjb21wdXRlIGl0IHVzaW5nIHRoZSBiaW5hcnkgZnVuY3Rpb25cbiAgICAgICAgcmV0dXJuIFNwYXJrTUQ1Lmhhc2hCaW5hcnkodG9VdGY4KHN0ciksIHJhdyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFBlcmZvcm1zIHRoZSBtZDUgaGFzaCBvbiBhIGJpbmFyeSBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gIGNvbnRlbnQgVGhlIGJpbmFyeSBzdHJpbmdcbiAgICAgKiBAcGFyYW0ge0Jvb2xlYW59IHJhdyAgICAgVHJ1ZSB0byBnZXQgdGhlIHJhdyBzdHJpbmcsIGZhbHNlIHRvIGdldCB0aGUgaGV4IHN0cmluZ1xuICAgICAqXG4gICAgICogQHJldHVybiB7U3RyaW5nfSBUaGUgcmVzdWx0XG4gICAgICovXG4gICAgU3BhcmtNRDUuaGFzaEJpbmFyeSA9IGZ1bmN0aW9uIChjb250ZW50LCByYXcpIHtcbiAgICAgICAgdmFyIGhhc2ggPSBtZDUxKGNvbnRlbnQpLFxuICAgICAgICAgICAgcmV0ID0gaGV4KGhhc2gpO1xuXG4gICAgICAgIHJldHVybiByYXcgPyBoZXhUb0JpbmFyeVN0cmluZyhyZXQpIDogcmV0O1xuICAgIH07XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICAgIC8qKlxuICAgICAqIFNwYXJrTUQ1IE9PUCBpbXBsZW1lbnRhdGlvbiBmb3IgYXJyYXkgYnVmZmVycy5cbiAgICAgKlxuICAgICAqIFVzZSB0aGlzIGNsYXNzIHRvIHBlcmZvcm0gYW4gaW5jcmVtZW50YWwgbWQ1IE9OTFkgZm9yIGFycmF5IGJ1ZmZlcnMuXG4gICAgICovXG4gICAgU3BhcmtNRDUuQXJyYXlCdWZmZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIGNhbGwgcmVzZXQgdG8gaW5pdCB0aGUgaW5zdGFuY2VcbiAgICAgICAgdGhpcy5yZXNldCgpO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBcHBlbmRzIGFuIGFycmF5IGJ1ZmZlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7QXJyYXlCdWZmZXJ9IGFyciBUaGUgYXJyYXkgdG8gYmUgYXBwZW5kZWRcbiAgICAgKlxuICAgICAqIEByZXR1cm4ge1NwYXJrTUQ1LkFycmF5QnVmZmVyfSBUaGUgaW5zdGFuY2UgaXRzZWxmXG4gICAgICovXG4gICAgU3BhcmtNRDUuQXJyYXlCdWZmZXIucHJvdG90eXBlLmFwcGVuZCA9IGZ1bmN0aW9uIChhcnIpIHtcbiAgICAgICAgdmFyIGJ1ZmYgPSBjb25jYXRlbmF0ZUFycmF5QnVmZmVycyh0aGlzLl9idWZmLmJ1ZmZlciwgYXJyLCB0cnVlKSxcbiAgICAgICAgICAgIGxlbmd0aCA9IGJ1ZmYubGVuZ3RoLFxuICAgICAgICAgICAgaTtcblxuICAgICAgICB0aGlzLl9sZW5ndGggKz0gYXJyLmJ5dGVMZW5ndGg7XG5cbiAgICAgICAgZm9yIChpID0gNjQ7IGkgPD0gbGVuZ3RoOyBpICs9IDY0KSB7XG4gICAgICAgICAgICBtZDVjeWNsZSh0aGlzLl9oYXNoLCBtZDVibGtfYXJyYXkoYnVmZi5zdWJhcnJheShpIC0gNjQsIGkpKSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9idWZmID0gKGkgLSA2NCkgPCBsZW5ndGggPyBuZXcgVWludDhBcnJheShidWZmLmJ1ZmZlci5zbGljZShpIC0gNjQpKSA6IG5ldyBVaW50OEFycmF5KDApO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGaW5pc2hlcyB0aGUgaW5jcmVtZW50YWwgY29tcHV0YXRpb24sIHJlc2V0aW5nIHRoZSBpbnRlcm5hbCBzdGF0ZSBhbmRcbiAgICAgKiByZXR1cm5pbmcgdGhlIHJlc3VsdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gcmF3IFRydWUgdG8gZ2V0IHRoZSByYXcgc3RyaW5nLCBmYWxzZSB0byBnZXQgdGhlIGhleCBzdHJpbmdcbiAgICAgKlxuICAgICAqIEByZXR1cm4ge1N0cmluZ30gVGhlIHJlc3VsdFxuICAgICAqL1xuICAgIFNwYXJrTUQ1LkFycmF5QnVmZmVyLnByb3RvdHlwZS5lbmQgPSBmdW5jdGlvbiAocmF3KSB7XG4gICAgICAgIHZhciBidWZmID0gdGhpcy5fYnVmZixcbiAgICAgICAgICAgIGxlbmd0aCA9IGJ1ZmYubGVuZ3RoLFxuICAgICAgICAgICAgdGFpbCA9IFswLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwXSxcbiAgICAgICAgICAgIGksXG4gICAgICAgICAgICByZXQ7XG5cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICB0YWlsW2kgPj4gMl0gfD0gYnVmZltpXSA8PCAoKGkgJSA0KSA8PCAzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2ZpbmlzaCh0YWlsLCBsZW5ndGgpO1xuICAgICAgICByZXQgPSBoZXgodGhpcy5faGFzaCk7XG5cbiAgICAgICAgaWYgKHJhdykge1xuICAgICAgICAgICAgcmV0ID0gaGV4VG9CaW5hcnlTdHJpbmcocmV0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucmVzZXQoKTtcblxuICAgICAgICByZXR1cm4gcmV0O1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBSZXNldHMgdGhlIGludGVybmFsIHN0YXRlIG9mIHRoZSBjb21wdXRhdGlvbi5cbiAgICAgKlxuICAgICAqIEByZXR1cm4ge1NwYXJrTUQ1LkFycmF5QnVmZmVyfSBUaGUgaW5zdGFuY2UgaXRzZWxmXG4gICAgICovXG4gICAgU3BhcmtNRDUuQXJyYXlCdWZmZXIucHJvdG90eXBlLnJlc2V0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLl9idWZmID0gbmV3IFVpbnQ4QXJyYXkoMCk7XG4gICAgICAgIHRoaXMuX2xlbmd0aCA9IDA7XG4gICAgICAgIHRoaXMuX2hhc2ggPSBbMTczMjU4NDE5MywgLTI3MTczMzg3OSwgLTE3MzI1ODQxOTQsIDI3MTczMzg3OF07XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGludGVybmFsIHN0YXRlIG9mIHRoZSBjb21wdXRhdGlvbi5cbiAgICAgKlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gVGhlIHN0YXRlXG4gICAgICovXG4gICAgU3BhcmtNRDUuQXJyYXlCdWZmZXIucHJvdG90eXBlLmdldFN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc3RhdGUgPSBTcGFya01ENS5wcm90b3R5cGUuZ2V0U3RhdGUuY2FsbCh0aGlzKTtcblxuICAgICAgICAvLyBDb252ZXJ0IGJ1ZmZlciB0byBhIHN0cmluZ1xuICAgICAgICBzdGF0ZS5idWZmID0gYXJyYXlCdWZmZXIyVXRmOFN0cihzdGF0ZS5idWZmKTtcblxuICAgICAgICByZXR1cm4gc3RhdGU7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGludGVybmFsIHN0YXRlIG9mIHRoZSBjb21wdXRhdGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBzdGF0ZSBUaGUgc3RhdGVcbiAgICAgKlxuICAgICAqIEByZXR1cm4ge1NwYXJrTUQ1LkFycmF5QnVmZmVyfSBUaGUgaW5zdGFuY2UgaXRzZWxmXG4gICAgICovXG4gICAgU3BhcmtNRDUuQXJyYXlCdWZmZXIucHJvdG90eXBlLnNldFN0YXRlID0gZnVuY3Rpb24gKHN0YXRlKSB7XG4gICAgICAgIC8vIENvbnZlcnQgc3RyaW5nIHRvIGJ1ZmZlclxuICAgICAgICBzdGF0ZS5idWZmID0gdXRmOFN0cjJBcnJheUJ1ZmZlcihzdGF0ZS5idWZmLCB0cnVlKTtcblxuICAgICAgICByZXR1cm4gU3BhcmtNRDUucHJvdG90eXBlLnNldFN0YXRlLmNhbGwodGhpcywgc3RhdGUpO1xuICAgIH07XG5cbiAgICBTcGFya01ENS5BcnJheUJ1ZmZlci5wcm90b3R5cGUuZGVzdHJveSA9IFNwYXJrTUQ1LnByb3RvdHlwZS5kZXN0cm95O1xuXG4gICAgU3BhcmtNRDUuQXJyYXlCdWZmZXIucHJvdG90eXBlLl9maW5pc2ggPSBTcGFya01ENS5wcm90b3R5cGUuX2ZpbmlzaDtcblxuICAgIC8qKlxuICAgICAqIFBlcmZvcm1zIHRoZSBtZDUgaGFzaCBvbiBhbiBhcnJheSBidWZmZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FycmF5QnVmZmVyfSBhcnIgVGhlIGFycmF5IGJ1ZmZlclxuICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gICAgIHJhdyBUcnVlIHRvIGdldCB0aGUgcmF3IHN0cmluZywgZmFsc2UgdG8gZ2V0IHRoZSBoZXggb25lXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtTdHJpbmd9IFRoZSByZXN1bHRcbiAgICAgKi9cbiAgICBTcGFya01ENS5BcnJheUJ1ZmZlci5oYXNoID0gZnVuY3Rpb24gKGFyciwgcmF3KSB7XG4gICAgICAgIHZhciBoYXNoID0gbWQ1MV9hcnJheShuZXcgVWludDhBcnJheShhcnIpKSxcbiAgICAgICAgICAgIHJldCA9IGhleChoYXNoKTtcblxuICAgICAgICByZXR1cm4gcmF3ID8gaGV4VG9CaW5hcnlTdHJpbmcocmV0KSA6IHJldDtcbiAgICB9O1xuXG4gICAgcmV0dXJuIFNwYXJrTUQ1O1xufSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9+L3NwYXJrLW1kNS9zcGFyay1tZDUuanNcbi8vIG1vZHVsZSBpZCA9IDk5XG4vLyBtb2R1bGUgY2h1bmtzID0gMCJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 100 */
- /***/ function(module, exports) {
- eval("'use strict';\n\n/**\n * Stringify/parse functions that don't operate\n * recursively, so they avoid call stack exceeded\n * errors.\n */\nexports.stringify = function stringify(input) {\n var queue = [];\n queue.push({obj: input});\n\n var res = '';\n var next, obj, prefix, val, i, arrayPrefix, keys, k, key, value, objPrefix;\n while ((next = queue.pop())) {\n obj = next.obj;\n prefix = next.prefix || '';\n val = next.val || '';\n res += prefix;\n if (val) {\n res += val;\n } else if (typeof obj !== 'object') {\n res += typeof obj === 'undefined' ? null : JSON.stringify(obj);\n } else if (obj === null) {\n res += 'null';\n } else if (Array.isArray(obj)) {\n queue.push({val: ']'});\n for (i = obj.length - 1; i >= 0; i--) {\n arrayPrefix = i === 0 ? '' : ',';\n queue.push({obj: obj[i], prefix: arrayPrefix});\n }\n queue.push({val: '['});\n } else { // object\n keys = [];\n for (k in obj) {\n if (obj.hasOwnProperty(k)) {\n keys.push(k);\n }\n }\n queue.push({val: '}'});\n for (i = keys.length - 1; i >= 0; i--) {\n key = keys[i];\n value = obj[key];\n objPrefix = (i > 0 ? ',' : '');\n objPrefix += JSON.stringify(key) + ':';\n queue.push({obj: value, prefix: objPrefix});\n }\n queue.push({val: '{'});\n }\n }\n return res;\n};\n\n// Convenience function for the parse function.\n// This pop function is basically copied from\n// pouchCollate.parseIndexableString\nfunction pop(obj, stack, metaStack) {\n var lastMetaElement = metaStack[metaStack.length - 1];\n if (obj === lastMetaElement.element) {\n // popping a meta-element, e.g. an object whose value is another object\n metaStack.pop();\n lastMetaElement = metaStack[metaStack.length - 1];\n }\n var element = lastMetaElement.element;\n var lastElementIndex = lastMetaElement.index;\n if (Array.isArray(element)) {\n element.push(obj);\n } else if (lastElementIndex === stack.length - 2) { // obj with key+value\n var key = stack.pop();\n element[key] = obj;\n } else {\n stack.push(obj); // obj with key only\n }\n}\n\nexports.parse = function (str) {\n var stack = [];\n var metaStack = []; // stack for arrays and objects\n var i = 0;\n var collationIndex,parsedNum,numChar;\n var parsedString,lastCh,numConsecutiveSlashes,ch;\n var arrayElement, objElement;\n while (true) {\n collationIndex = str[i++];\n if (collationIndex === '}' ||\n collationIndex === ']' ||\n typeof collationIndex === 'undefined') {\n if (stack.length === 1) {\n return stack.pop();\n } else {\n pop(stack.pop(), stack, metaStack);\n continue;\n }\n }\n switch (collationIndex) {\n case ' ':\n case '\\t':\n case '\\n':\n case ':':\n case ',':\n break;\n case 'n':\n i += 3; // 'ull'\n pop(null, stack, metaStack);\n break;\n case 't':\n i += 3; // 'rue'\n pop(true, stack, metaStack);\n break;\n case 'f':\n i += 4; // 'alse'\n pop(false, stack, metaStack);\n break;\n case '0':\n case '1':\n case '2':\n case '3':\n case '4':\n case '5':\n case '6':\n case '7':\n case '8':\n case '9':\n case '-':\n parsedNum = '';\n i--;\n while (true) {\n numChar = str[i++];\n if (/[\\d\\.\\-e\\+]/.test(numChar)) {\n parsedNum += numChar;\n } else {\n i--;\n break;\n }\n }\n pop(parseFloat(parsedNum), stack, metaStack);\n break;\n case '\"':\n parsedString = '';\n lastCh = void 0;\n numConsecutiveSlashes = 0;\n while (true) {\n ch = str[i++];\n if (ch !== '\"' || (lastCh === '\\\\' &&\n numConsecutiveSlashes % 2 === 1)) {\n parsedString += ch;\n lastCh = ch;\n if (lastCh === '\\\\') {\n numConsecutiveSlashes++;\n } else {\n numConsecutiveSlashes = 0;\n }\n } else {\n break;\n }\n }\n pop(JSON.parse('\"' + parsedString + '\"'), stack, metaStack);\n break;\n case '[':\n arrayElement = { element: [], index: stack.length };\n stack.push(arrayElement.element);\n metaStack.push(arrayElement);\n break;\n case '{':\n objElement = { element: {}, index: stack.length };\n stack.push(objElement.element);\n metaStack.push(objElement);\n break;\n default:\n throw new Error(\n 'unexpectedly reached end of input: ' + collationIndex);\n }\n }\n};\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTAwLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vfi92dXZ1emVsYS9pbmRleC5qcz84N2ViIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBTdHJpbmdpZnkvcGFyc2UgZnVuY3Rpb25zIHRoYXQgZG9uJ3Qgb3BlcmF0ZVxuICogcmVjdXJzaXZlbHksIHNvIHRoZXkgYXZvaWQgY2FsbCBzdGFjayBleGNlZWRlZFxuICogZXJyb3JzLlxuICovXG5leHBvcnRzLnN0cmluZ2lmeSA9IGZ1bmN0aW9uIHN0cmluZ2lmeShpbnB1dCkge1xuICB2YXIgcXVldWUgPSBbXTtcbiAgcXVldWUucHVzaCh7b2JqOiBpbnB1dH0pO1xuXG4gIHZhciByZXMgPSAnJztcbiAgdmFyIG5leHQsIG9iaiwgcHJlZml4LCB2YWwsIGksIGFycmF5UHJlZml4LCBrZXlzLCBrLCBrZXksIHZhbHVlLCBvYmpQcmVmaXg7XG4gIHdoaWxlICgobmV4dCA9IHF1ZXVlLnBvcCgpKSkge1xuICAgIG9iaiA9IG5leHQub2JqO1xuICAgIHByZWZpeCA9IG5leHQucHJlZml4IHx8ICcnO1xuICAgIHZhbCA9IG5leHQudmFsIHx8ICcnO1xuICAgIHJlcyArPSBwcmVmaXg7XG4gICAgaWYgKHZhbCkge1xuICAgICAgcmVzICs9IHZhbDtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBvYmogIT09ICdvYmplY3QnKSB7XG4gICAgICByZXMgKz0gdHlwZW9mIG9iaiA9PT0gJ3VuZGVmaW5lZCcgPyBudWxsIDogSlNPTi5zdHJpbmdpZnkob2JqKTtcbiAgICB9IGVsc2UgaWYgKG9iaiA9PT0gbnVsbCkge1xuICAgICAgcmVzICs9ICdudWxsJztcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkge1xuICAgICAgcXVldWUucHVzaCh7dmFsOiAnXSd9KTtcbiAgICAgIGZvciAoaSA9IG9iai5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBhcnJheVByZWZpeCA9IGkgPT09IDAgPyAnJyA6ICcsJztcbiAgICAgICAgcXVldWUucHVzaCh7b2JqOiBvYmpbaV0sIHByZWZpeDogYXJyYXlQcmVmaXh9KTtcbiAgICAgIH1cbiAgICAgIHF1ZXVlLnB1c2goe3ZhbDogJ1snfSk7XG4gICAgfSBlbHNlIHsgLy8gb2JqZWN0XG4gICAgICBrZXlzID0gW107XG4gICAgICBmb3IgKGsgaW4gb2JqKSB7XG4gICAgICAgIGlmIChvYmouaGFzT3duUHJvcGVydHkoaykpIHtcbiAgICAgICAgICBrZXlzLnB1c2goayk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHF1ZXVlLnB1c2goe3ZhbDogJ30nfSk7XG4gICAgICBmb3IgKGkgPSBrZXlzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGtleSA9IGtleXNbaV07XG4gICAgICAgIHZhbHVlID0gb2JqW2tleV07XG4gICAgICAgIG9ialByZWZpeCA9IChpID4gMCA/ICcsJyA6ICcnKTtcbiAgICAgICAgb2JqUHJlZml4ICs9IEpTT04uc3RyaW5naWZ5KGtleSkgKyAnOic7XG4gICAgICAgIHF1ZXVlLnB1c2goe29iajogdmFsdWUsIHByZWZpeDogb2JqUHJlZml4fSk7XG4gICAgICB9XG4gICAgICBxdWV1ZS5wdXNoKHt2YWw6ICd7J30pO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzO1xufTtcblxuLy8gQ29udmVuaWVuY2UgZnVuY3Rpb24gZm9yIHRoZSBwYXJzZSBmdW5jdGlvbi5cbi8vIFRoaXMgcG9wIGZ1bmN0aW9uIGlzIGJhc2ljYWxseSBjb3BpZWQgZnJvbVxuLy8gcG91Y2hDb2xsYXRlLnBhcnNlSW5kZXhhYmxlU3RyaW5nXG5mdW5jdGlvbiBwb3Aob2JqLCBzdGFjaywgbWV0YVN0YWNrKSB7XG4gIHZhciBsYXN0TWV0YUVsZW1lbnQgPSBtZXRhU3RhY2tbbWV0YVN0YWNrLmxlbmd0aCAtIDFdO1xuICBpZiAob2JqID09PSBsYXN0TWV0YUVsZW1lbnQuZWxlbWVudCkge1xuICAgIC8vIHBvcHBpbmcgYSBtZXRhLWVsZW1lbnQsIGUuZy4gYW4gb2JqZWN0IHdob3NlIHZhbHVlIGlzIGFub3RoZXIgb2JqZWN0XG4gICAgbWV0YVN0YWNrLnBvcCgpO1xuICAgIGxhc3RNZXRhRWxlbWVudCA9IG1ldGFTdGFja1ttZXRhU3RhY2subGVuZ3RoIC0gMV07XG4gIH1cbiAgdmFyIGVsZW1lbnQgPSBsYXN0TWV0YUVsZW1lbnQuZWxlbWVudDtcbiAgdmFyIGxhc3RFbGVtZW50SW5kZXggPSBsYXN0TWV0YUVsZW1lbnQuaW5kZXg7XG4gIGlmIChBcnJheS5pc0FycmF5KGVsZW1lbnQpKSB7XG4gICAgZWxlbWVudC5wdXNoKG9iaik7XG4gIH0gZWxzZSBpZiAobGFzdEVsZW1lbnRJbmRleCA9PT0gc3RhY2subGVuZ3RoIC0gMikgeyAvLyBvYmogd2l0aCBrZXkrdmFsdWVcbiAgICB2YXIga2V5ID0gc3RhY2sucG9wKCk7XG4gICAgZWxlbWVudFtrZXldID0gb2JqO1xuICB9IGVsc2Uge1xuICAgIHN0YWNrLnB1c2gob2JqKTsgLy8gb2JqIHdpdGgga2V5IG9ubHlcbiAgfVxufVxuXG5leHBvcnRzLnBhcnNlID0gZnVuY3Rpb24gKHN0cikge1xuICB2YXIgc3RhY2sgPSBbXTtcbiAgdmFyIG1ldGFTdGFjayA9IFtdOyAvLyBzdGFjayBmb3IgYXJyYXlzIGFuZCBvYmplY3RzXG4gIHZhciBpID0gMDtcbiAgdmFyIGNvbGxhdGlvbkluZGV4LHBhcnNlZE51bSxudW1DaGFyO1xuICB2YXIgcGFyc2VkU3RyaW5nLGxhc3RDaCxudW1Db25zZWN1dGl2ZVNsYXNoZXMsY2g7XG4gIHZhciBhcnJheUVsZW1lbnQsIG9iakVsZW1lbnQ7XG4gIHdoaWxlICh0cnVlKSB7XG4gICAgY29sbGF0aW9uSW5kZXggPSBzdHJbaSsrXTtcbiAgICBpZiAoY29sbGF0aW9uSW5kZXggPT09ICd9JyB8fFxuICAgICAgICBjb2xsYXRpb25JbmRleCA9PT0gJ10nIHx8XG4gICAgICAgIHR5cGVvZiBjb2xsYXRpb25JbmRleCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGlmIChzdGFjay5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgcmV0dXJuIHN0YWNrLnBvcCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcG9wKHN0YWNrLnBvcCgpLCBzdGFjaywgbWV0YVN0YWNrKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgfVxuICAgIHN3aXRjaCAoY29sbGF0aW9uSW5kZXgpIHtcbiAgICAgIGNhc2UgJyAnOlxuICAgICAgY2FzZSAnXFx0JzpcbiAgICAgIGNhc2UgJ1xcbic6XG4gICAgICBjYXNlICc6JzpcbiAgICAgIGNhc2UgJywnOlxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ24nOlxuICAgICAgICBpICs9IDM7IC8vICd1bGwnXG4gICAgICAgIHBvcChudWxsLCBzdGFjaywgbWV0YVN0YWNrKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd0JzpcbiAgICAgICAgaSArPSAzOyAvLyAncnVlJ1xuICAgICAgICBwb3AodHJ1ZSwgc3RhY2ssIG1ldGFTdGFjayk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnZic6XG4gICAgICAgIGkgKz0gNDsgLy8gJ2Fsc2UnXG4gICAgICAgIHBvcChmYWxzZSwgc3RhY2ssIG1ldGFTdGFjayk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnMCc6XG4gICAgICBjYXNlICcxJzpcbiAgICAgIGNhc2UgJzInOlxuICAgICAgY2FzZSAnMyc6XG4gICAgICBjYXNlICc0JzpcbiAgICAgIGNhc2UgJzUnOlxuICAgICAgY2FzZSAnNic6XG4gICAgICBjYXNlICc3JzpcbiAgICAgIGNhc2UgJzgnOlxuICAgICAgY2FzZSAnOSc6XG4gICAgICBjYXNlICctJzpcbiAgICAgICAgcGFyc2VkTnVtID0gJyc7XG4gICAgICAgIGktLTtcbiAgICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICBudW1DaGFyID0gc3RyW2krK107XG4gICAgICAgICAgaWYgKC9bXFxkXFwuXFwtZVxcK10vLnRlc3QobnVtQ2hhcikpIHtcbiAgICAgICAgICAgIHBhcnNlZE51bSArPSBudW1DaGFyO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpLS07XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcG9wKHBhcnNlRmxvYXQocGFyc2VkTnVtKSwgc3RhY2ssIG1ldGFTdGFjayk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnXCInOlxuICAgICAgICBwYXJzZWRTdHJpbmcgPSAnJztcbiAgICAgICAgbGFzdENoID0gdm9pZCAwO1xuICAgICAgICBudW1Db25zZWN1dGl2ZVNsYXNoZXMgPSAwO1xuICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgIGNoID0gc3RyW2krK107XG4gICAgICAgICAgaWYgKGNoICE9PSAnXCInIHx8IChsYXN0Q2ggPT09ICdcXFxcJyAmJlxuICAgICAgICAgICAgICBudW1Db25zZWN1dGl2ZVNsYXNoZXMgJSAyID09PSAxKSkge1xuICAgICAgICAgICAgcGFyc2VkU3RyaW5nICs9IGNoO1xuICAgICAgICAgICAgbGFzdENoID0gY2g7XG4gICAgICAgICAgICBpZiAobGFzdENoID09PSAnXFxcXCcpIHtcbiAgICAgICAgICAgICAgbnVtQ29uc2VjdXRpdmVTbGFzaGVzKys7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBudW1Db25zZWN1dGl2ZVNsYXNoZXMgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcG9wKEpTT04ucGFyc2UoJ1wiJyArIHBhcnNlZFN0cmluZyArICdcIicpLCBzdGFjaywgbWV0YVN0YWNrKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdbJzpcbiAgICAgICAgYXJyYXlFbGVtZW50ID0geyBlbGVtZW50OiBbXSwgaW5kZXg6IHN0YWNrLmxlbmd0aCB9O1xuICAgICAgICBzdGFjay5wdXNoKGFycmF5RWxlbWVudC5lbGVtZW50KTtcbiAgICAgICAgbWV0YVN0YWNrLnB1c2goYXJyYXlFbGVtZW50KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd7JzpcbiAgICAgICAgb2JqRWxlbWVudCA9IHsgZWxlbWVudDoge30sIGluZGV4OiBzdGFjay5sZW5ndGggfTtcbiAgICAgICAgc3RhY2sucHVzaChvYmpFbGVtZW50LmVsZW1lbnQpO1xuICAgICAgICBtZXRhU3RhY2sucHVzaChvYmpFbGVtZW50KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgJ3VuZXhwZWN0ZWRseSByZWFjaGVkIGVuZCBvZiBpbnB1dDogJyArIGNvbGxhdGlvbkluZGV4KTtcbiAgICB9XG4gIH1cbn07XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL34vdnV2dXplbGEvaW5kZXguanNcbi8vIG1vZHVsZSBpZCA9IDEwMFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 101 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar core_1 = __webpack_require__(4);\nvar BehaviorSubject_1 = __webpack_require__(33);\nvar PouchDB = __webpack_require__(89);\nexports.ARCHIVE_NOTES_TABLES = [];\nvar localDB = new PouchDB('bin_notes_table');\nvar BinNotesTableService = (function () {\n function BinNotesTableService() {\n this.bin_notes_tables_source = new BehaviorSubject_1.BehaviorSubject([]);\n this.bin_notes_tables$ = this.bin_notes_tables_source.asObservable();\n this.localDB = localDB;\n }\n BinNotesTableService.prototype.getNotes = function () {\n var docs = this.localDB.allDocs({\n include_docs: true\n });\n return docs;\n };\n BinNotesTableService.prototype.saveNote = function (note) {\n return this.localDB.put(note);\n };\n BinNotesTableService.prototype.deleteNote = function (note) {\n return this.localDB.remove(note);\n };\n BinNotesTableService.prototype.updateNote = function (note) {\n return this.localDB.put(note);\n };\n BinNotesTableService = __decorate([\n core_1.Injectable(), \n __metadata('design:paramtypes', [])\n ], BinNotesTableService);\n return BinNotesTableService;\n}());\nexports.BinNotesTableService = BinNotesTableService;\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTAxLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vc3JjL2FwcC9zZXJ2aWNlcy9iaW5fdGFibGUuc2VydmljZS50cz84MjY2Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7QmVoYXZpb3JTdWJqZWN0fSBmcm9tICdyeGpzL0JlaGF2aW9yU3ViamVjdCc7XG5pbXBvcnQgKiBhcyBQb3VjaERCIGZyb20gJ3BvdWNoZGInO1xuXG5pbXBvcnQgeyBOb3Rlc1RhYmxlIH0gZnJvbSAnLi9ub3Rlc190YWJsZSc7XG5cbmV4cG9ydCB2YXIgQVJDSElWRV9OT1RFU19UQUJMRVM6IE5vdGVzVGFibGVbXSA9IFtdO1xuXG5sZXQgbG9jYWxEQiA9IG5ldyBQb3VjaERCKCdiaW5fbm90ZXNfdGFibGUnKTtcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIEJpbk5vdGVzVGFibGVTZXJ2aWNlIHtcbiAgcHJpdmF0ZSBiaW5fbm90ZXNfdGFibGVzX3NvdXJjZSA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Tm90ZXNUYWJsZVtdPihbXSk7XG4gIGJpbl9ub3Rlc190YWJsZXMkID0gdGhpcy5iaW5fbm90ZXNfdGFibGVzX3NvdXJjZS5hc09ic2VydmFibGUoKTtcbiAgbG9jYWxEQiA9IGxvY2FsREI7XG5cbiAgY29uc3RydWN0b3IoKSB7fVxuXG4gIGdldE5vdGVzKCkge1xuICAgIHZhciBkb2NzID0gdGhpcy5sb2NhbERCLmFsbERvY3Moe1xuICAgICAgaW5jbHVkZV9kb2NzOiB0cnVlXG4gICAgfSk7XG4gICAgcmV0dXJuIGRvY3M7XG4gIH1cblxuICBzYXZlTm90ZShub3RlOiBhbnkpIHtcbiAgICByZXR1cm4gdGhpcy5sb2NhbERCLnB1dChub3RlKTtcbiAgfVxuXG4gIGRlbGV0ZU5vdGUobm90ZTogYW55KSB7XG4gICAgcmV0dXJuIHRoaXMubG9jYWxEQi5yZW1vdmUobm90ZSk7XG4gIH1cblxuICB1cGRhdGVOb3RlKG5vdGU6IGFueSkge1xuICAgIHJldHVybiB0aGlzLmxvY2FsREIucHV0KG5vdGUpO1xuICB9XG59XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gbm9kZV9tb2R1bGVzL2FuZ3VsYXIyLXRlbXBsYXRlLWxvYWRlciEuL3NyYy9hcHAvc2VydmljZXMvYmluX3RhYmxlLnNlcnZpY2UudHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFJQTtBQUVBO0FBR0E7QUFLQTtBQUpBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBekJBO0FBQUE7O0FBQUE7QUEwQkE7QUFBQTtBQXpCQTsiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ },
- /* 102 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar core_1 = __webpack_require__(4);\nvar BehaviorSubject_1 = __webpack_require__(33);\nvar PouchDB = __webpack_require__(89);\nexports.ARCHIVE_NOTES_TABLES = [];\nvar localDB = new PouchDB('archive_notes_table');\nvar orderDB = new PouchDB('archive_notes_order');\nvar ArchiveNotesTableService = (function () {\n function ArchiveNotesTableService() {\n this.archive_notes_tables_source = new BehaviorSubject_1.BehaviorSubject([]);\n this.archive_notes_tables$ = this.archive_notes_tables_source.asObservable();\n this.localDB = localDB;\n this.order = orderDB;\n }\n ArchiveNotesTableService.prototype.getNotes = function () {\n var docs = this.localDB.allDocs({\n include_docs: true\n });\n return docs;\n };\n ArchiveNotesTableService.prototype.saveNote = function (note) {\n return this.localDB.put(note);\n };\n ArchiveNotesTableService.prototype.deleteNote = function (note) {\n return this.localDB.remove(note);\n };\n ArchiveNotesTableService.prototype.updateNote = function (note) {\n return this.localDB.put(note);\n };\n ArchiveNotesTableService.prototype.getOrder = function (order) {\n var docs = this.order.allDocs({\n include_docs: true\n });\n return docs;\n };\n ArchiveNotesTableService.prototype.saveOrder = function (order) {\n return this.order.put(order);\n };\n ArchiveNotesTableService = __decorate([\n core_1.Injectable(), \n __metadata('design:paramtypes', [])\n ], ArchiveNotesTableService);\n return ArchiveNotesTableService;\n}());\nexports.ArchiveNotesTableService = ArchiveNotesTableService;\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTAyLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vc3JjL2FwcC9zZXJ2aWNlcy9hcmNoaXZlX3RhYmxlLnNlcnZpY2UudHM/MzBlMSJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0JlaGF2aW9yU3ViamVjdH0gZnJvbSAncnhqcy9CZWhhdmlvclN1YmplY3QnO1xuaW1wb3J0ICogYXMgUG91Y2hEQiBmcm9tICdwb3VjaGRiJztcblxuaW1wb3J0IHsgTm90ZXNUYWJsZSB9IGZyb20gJy4vbm90ZXNfdGFibGUnO1xuXG5leHBvcnQgdmFyIEFSQ0hJVkVfTk9URVNfVEFCTEVTOiBOb3Rlc1RhYmxlW10gPSBbXTtcblxubGV0IGxvY2FsREIgPSBuZXcgUG91Y2hEQignYXJjaGl2ZV9ub3Rlc190YWJsZScpO1xubGV0IG9yZGVyREIgPSBuZXcgUG91Y2hEQignYXJjaGl2ZV9ub3Rlc19vcmRlcicpO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgQXJjaGl2ZU5vdGVzVGFibGVTZXJ2aWNlIHtcbiAgcHJpdmF0ZSBhcmNoaXZlX25vdGVzX3RhYmxlc19zb3VyY2UgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PE5vdGVzVGFibGVbXT4oW10pO1xuICBhcmNoaXZlX25vdGVzX3RhYmxlcyQgPSB0aGlzLmFyY2hpdmVfbm90ZXNfdGFibGVzX3NvdXJjZS5hc09ic2VydmFibGUoKTtcbiAgbG9jYWxEQiA9IGxvY2FsREI7XG4gIG9yZGVyID0gb3JkZXJEQjtcbiAgY29uc3RydWN0b3IoKSB7fVxuXG4gIGdldE5vdGVzKCkge1xuICAgIHZhciBkb2NzID0gdGhpcy5sb2NhbERCLmFsbERvY3Moe1xuICAgICAgaW5jbHVkZV9kb2NzOiB0cnVlXG4gICAgfSk7XG4gICAgcmV0dXJuIGRvY3M7XG4gIH1cblxuICBzYXZlTm90ZShub3RlOiBhbnkpIHtcbiAgICByZXR1cm4gdGhpcy5sb2NhbERCLnB1dChub3RlKTtcbiAgfVxuXG4gIGRlbGV0ZU5vdGUobm90ZTogYW55KSB7XG4gICAgcmV0dXJuIHRoaXMubG9jYWxEQi5yZW1vdmUobm90ZSk7XG4gIH1cblxuICB1cGRhdGVOb3RlKG5vdGU6IGFueSkge1xuICAgIHJldHVybiB0aGlzLmxvY2FsREIucHV0KG5vdGUpO1xuICB9XG5cbiAgZ2V0T3JkZXIob3JkZXI6IGFueSkge1xuICAgIHZhciBkb2NzID0gdGhpcy5vcmRlci5hbGxEb2NzKHtcbiAgICAgIGluY2x1ZGVfZG9jczogdHJ1ZVxuICAgIH0pO1xuICAgIHJldHVybiBkb2NzO1xuICB9XG5cbiAgc2F2ZU9yZGVyKG9yZGVyOiBhbnkpIHtcbiAgICByZXR1cm4gdGhpcy5vcmRlci5wdXQob3JkZXIpO1xuICB9XG59XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gbm9kZV9tb2R1bGVzL2FuZ3VsYXIyLXRlbXBsYXRlLWxvYWRlciEuL3NyYy9hcHAvc2VydmljZXMvYXJjaGl2ZV90YWJsZS5zZXJ2aWNlLnRzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBSUE7QUFFQTtBQUNBO0FBR0E7QUFLQTtBQUpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFwQ0E7QUFBQTs7QUFBQTtBQXFDQTtBQUFBO0FBcENBOyIsInNvdXJjZVJvb3QiOiIifQ==");
- /***/ },
- /* 103 */
- /***/ function(module, exports) {
- eval("module.exports = \"<div class=\\\"\\\">\\n <div class=\\\"navbar navbar-default\\\">\\n <div class=\\\"container-fluid\\\">\\n <div class=\\\"navbar-header\\\">\\n <ul class=\\\"navbar-toggle\\\">\\n <li class=\\\"dropdown\\\">\\n <a href=\\\"#\\\" class=\\\"dropdown-toggle\\\" data-toggle=\\\"dropdown\\\" role=\\\"button\\\" aria-haspopup=\\\"true\\\" aria-expanded=\\\"false\\\"> <i class=\\\"glyphicon glyphicon-option-vertical\\\"></i></a>\\n <ul class=\\\"dropdown-menu\\\">\\n\\n <li class=\\\"dropdown-header\\\">Preferences</li>\\n <li><a [routerLink]=\\\"['/notes']\\\">My Notes</a></li>\\n <li><a [routerLink]=\\\"['/archive-notes']\\\">Archive Notes</a></li> \\n <li><a href=\\\"javascript:void(0)\\\" [routerLink]=\\\"['/recycle-bin']\\\">Recycle Bin</a></li> \\n <li role=\\\"separator\\\" class=\\\"divider\\\"></li>\\n <li>\\n <a href=\\\"javascript:void(0)\\\" (click)=\\\"displayTypeChange()\\\">\\n {{displayList ? 'Grid View' : 'List View'}}\\n </a>\\n </li>\\n <li><a href=\\\"javascript:void(0)\\\">Settings</a></li>\\n <li><a href=\\\"javascript:void(0)\\\" [routerLink]=\\\"['/about']\\\">About</a></li> \\n </ul>\\n </li>\\n </ul>\\n <a href=\\\"javascript:void(0)\\\" class=\\\"navbar-brand\\\" [routerLink]=\\\"['/notes']\\\">Preserver </a>\\n <span class=\\\"navbar-brand\\\"><i class=\\\"fa fa-angle-right\\\" aria-hidden=\\\"true\\\"></i> Notes</span>\\n </div>\\n <div id=\\\"navbar\\\" class=\\\"collapse navbar-collapse\\\">\\n <ul class=\\\"nav navbar-nav navbar-right\\\">\\n <li>\\n <a href=\\\"javascript:void(0)\\\" (click)=\\\"displayTypeChange()\\\">\\n <i class=\\\"{{displayList ? 'fa fa-bars' : 'fa fa-th'}}\\\"></i>\\n </a>\\n </li>\\n <li class=\\\"dropdown\\\">\\n <a href=\\\"javascript:void(0)\\\" data-target=\\\"#\\\" class=\\\"dropdown-toggle\\\" data-toggle=\\\"dropdown\\\">\\n <i class=\\\"glyphicon glyphicon-option-vertical\\\"></i>\\n </a>\\n <ul class=\\\"dropdown-menu\\\">\\n <li class=\\\"dropdown-header\\\">Preferences</li>\\n <li><a href=\\\"javascript:void(0)\\\" [routerLink]=\\\"['/notes']\\\">My Notes</a></li>\\n <li><a href=\\\"javascript:void(0)\\\" [routerLink]=\\\"['/archive-notes']\\\">Archive Notes</a></li>\\n <li><a href=\\\"javascript:void(0)\\\" [routerLink]=\\\"['/recycle-bin']\\\">Recycle Bin</a></li> \\n <li class=\\\"divider\\\"></li>\\n <li><a href=\\\"javascript:void(0)\\\">Settings</a></li>\\n <li><a href=\\\"javascript:void(0)\\\" [routerLink]=\\\"['/about']\\\">About</a></li>\\n </ul>\\n </li>\\n </ul>\\n </div>\\n </div>\\n </div>\\n <div class=\\\"container\\\">\\n <div class=\\\"panel panel-default note-editor animated bounceInDown\\\">\\n <div class=\\\"panel-body\\\">\\n <div class=\\\"form-group label-floating\\\" *ngIf=\\\"inputFocusClass\\\">\\n <input type=\\\"text\\\" class=\\\"form-control\\\" placeholder=\\\"Title\\\" [(ngModel)]=\\\"draft.title\\\" >\\n </div> \\n <div class=\\\"form-group label-floating\\\">\\n <textarea class=\\\"form-control\\\" #textarea autosize placeholder=\\\"Write a note\\\" [(ngModel)]=\\\"draft.note\\\" (focus)=\\\"_setInputFocus(true)\\\"></textarea>\\n </div>\\n <div class=\\\"form-group\\\" *ngIf=\\\"inputFocusClass\\\">\\n <button class=\\\"btn btn-primary btn-sm pull-right\\\" (click)=\\\"saveNote($event, textarea)\\\">Save</button>\\n </div>\\n </div>\\n </div>\\n </div>\\n <spinner *ngIf=\\\"spinner\\\"></spinner>\\n <div class=\\\"{{ displayList ? 'container note animate' : 'container note grid-container animate'}}\\\" [dragula]='\\\"another-bag\\\"' [dragulaModel]='notes'>\\n <div *ngFor='let text of notes' class=\\\"{{ displayList ? 'panel panel-default ' + text.doc.color : 'panel panel-default grid-item ' + text.doc.color}}\\\" #noteRow [attr.id]=\\\"text.doc._id\\\">\\n <div data-toggle=\\\"modal\\\" [attr.data-target]=\\\"'#note' + text.doc._id\\\" (click)=\\\"editModalNoteClick(text)\\\">\\n <div class=\\\"panel-body my-note module line-clamp\\\">\\n <p><strong>{{text.doc.title}}</strong></p>\\n <p> {{text.doc.note}} </p>\\n </div>\\n </div>\\n <div class=\\\"{{ 'panel-footer ' + text.doc.color}}\\\">\\n <ul class=\\\"note-footer\\\">\\n <li><a href=\\\"javascript:void(0)\\\" class=\\\"btn btn-link btn-raised\\\"\\n title=\\\"Archive\\\" (click)=\\\"makeArchive(text, noteRow)\\\">\\n <i class=\\\"fa fa-download\\\"></i> \\n </a></li>\\n <li class=\\\"dropup\\\">\\n <a data-target=\\\"#\\\" class=\\\"btn btn-link btn-raised dropup\\\"\\n title=\\\"Color\\\" data-toggle=\\\"dropdown\\\">\\n <i class=\\\"fa fa-th-large\\\"></i>\\n </a>\\n <ul class=\\\"dropdown-menu\\\">\\n <li><a href=\\\"javascript:void(0)\\\" (click)=\\\"setNoteColor('label-default', text)\\\" class=\\\"btn btn-default btn-fab-mini\\\"><i class=\\\"\\\"></i></a></li>\\n <li><a href=\\\"javascript:void(0)\\\" (click)=\\\"setNoteColor('label-primary', text)\\\" class=\\\"btn btn-primary btn-fab-mini\\\"><i class=\\\"\\\"></i></a></li>\\n <li><a href=\\\"javascript:void(0)\\\" (click)=\\\"setNoteColor('label-success', text)\\\" class=\\\"btn btn-success btn-fab-mini\\\"><i class=\\\"\\\"></i></a></li>\\n <li><a href=\\\"javascript:void(0)\\\" (click)=\\\"setNoteColor('label-info', text)\\\" class=\\\"btn btn-info btn-fab-mini\\\"><i class=\\\"\\\"></i></a></li>\\n <li><a href=\\\"javascript:void(0)\\\" (click)=\\\"setNoteColor('label-warning', text)\\\" class=\\\"btn btn-warning btn-fab-mini\\\"><i class=\\\"\\\"></i></a></li>\\n <li><a href=\\\"javascript:void(0)\\\" (click)=\\\"setNoteColor('label-danger', text)\\\" class=\\\"btn btn-danger btn-fab-mini\\\"><i class=\\\"\\\"></i></a></li>\\n <li><a href=\\\"javascript:void(0)\\\" (click)=\\\"setNoteColor('label-darkgray', text)\\\" class=\\\"btn btn-darkgray btn-fab-mini\\\"><i class=\\\"\\\"></i></a></li>\\n <li><a href=\\\"javascript:void(0)\\\" (click)=\\\"setNoteColor('label-primary-old', text)\\\" class=\\\"btn btn-primary-old btn-fab-mini\\\"><i class=\\\"\\\"></i></a></li> \\n </ul>\\n </li>\\n <li><a href=\\\"javascript:void(0)\\\" class=\\\"btn btn-link btn-raised\\\"\\n title=\\\"Delete\\\" (click)=\\\"deleteNote(text, noteRow)\\\">\\n <i class=\\\"fa fa-trash\\\"></i> \\n </a></li>\\n </ul>\\n </div>\\n <div class=\\\"modal fade\\\" id=\\\"{{'note' + text.doc._id}}\\\" tabindex=\\\"-1\\\" role=\\\"dialog\\\" aria-hidden=\\\"true\\\">\\n <div class=\\\"modal-dialog\\\">\\n <div class=\\\"{{'modal-content edit-saved ' + text.doc.color}}\\\">\\n <div class=\\\"modal-header\\\">\\n <h4 class=\\\"modal-title\\\">\\n <div class=\\\"form-group label-floating\\\">\\n <input type=\\\"text\\\" class=\\\"form-control edit-saved-input\\\" placeholder=\\\"Title\\\" [(ngModel)]=\\\"editNoteDraft.title\\\" [value]=\\\"text.doc.title ? text.doc.title : ''\\\" >\\n </div> \\n </h4>\\n </div>\\n <div class=\\\"modal-body\\\">\\n <textarea class=\\\"form-control edit-saved-textera\\\" #editSavedTextarea modaleditorautosize placeholder=\\\"Write a note\\\" [(ngModel)]=\\\"editNoteDraft.note\\\" [value]=\\\"text.doc?.note\\\"></textarea> \\n </div>\\n <div class=\\\"modal-footer\\\">\\n <button type=\\\"button\\\" class=\\\"btn btn-primary btn-sm\\\" data-dismiss=\\\"modal\\\" (click)=\\\"updateModalNote(text)\\\">Done</button>\\n </div>\\n </div>\\n </div>\\n </div>\\n </div>\\n </div>\\n <simple-notifications [options]=\\\"notificationOptions\\\"></simple-notifications>\\n <div class=\\\"container empty-notes-container\\\" *ngIf=\\\"emptyHtmlMsg\\\">\\n <h3 class=\\\"empty-notes-icon empty-notes-main\\\"><i class=\\\"fa fa-file-text-o fa-5x\\\"></i></h3>\\n <div class=\\\"empty-notes\\\">Notes that you add appear here</div>\\n </div>\\n</div>\\n\";//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTAzLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vc3JjL2FwcC9jb21wb25lbnRzL2hvbWUvaG9tZS5jb21wb25lbnQuaHRtbD8wODgwIl0sInNvdXJjZXNDb250ZW50IjpbIm1vZHVsZS5leHBvcnRzID0gXCI8ZGl2IGNsYXNzPVxcXCJcXFwiPlxcbiAgPGRpdiBjbGFzcz1cXFwibmF2YmFyIG5hdmJhci1kZWZhdWx0XFxcIj5cXG4gICAgPGRpdiBjbGFzcz1cXFwiY29udGFpbmVyLWZsdWlkXFxcIj5cXG4gICAgICA8ZGl2IGNsYXNzPVxcXCJuYXZiYXItaGVhZGVyXFxcIj5cXG4gICAgICAgIDx1bCBjbGFzcz1cXFwibmF2YmFyLXRvZ2dsZVxcXCI+XFxuICAgICAgICAgIDxsaSBjbGFzcz1cXFwiZHJvcGRvd25cXFwiPlxcbiAgICAgICAgICAgIDxhIGhyZWY9XFxcIiNcXFwiIGNsYXNzPVxcXCJkcm9wZG93bi10b2dnbGVcXFwiIGRhdGEtdG9nZ2xlPVxcXCJkcm9wZG93blxcXCIgcm9sZT1cXFwiYnV0dG9uXFxcIiBhcmlhLWhhc3BvcHVwPVxcXCJ0cnVlXFxcIiBhcmlhLWV4cGFuZGVkPVxcXCJmYWxzZVxcXCI+IDxpIGNsYXNzPVxcXCJnbHlwaGljb24gZ2x5cGhpY29uLW9wdGlvbi12ZXJ0aWNhbFxcXCI+PC9pPjwvYT5cXG4gICAgICAgICAgICA8dWwgY2xhc3M9XFxcImRyb3Bkb3duLW1lbnVcXFwiPlxcblxcbiAgICAgICAgICAgICAgPGxpIGNsYXNzPVxcXCJkcm9wZG93bi1oZWFkZXJcXFwiPlByZWZlcmVuY2VzPC9saT5cXG4gICAgICAgICAgICAgIDxsaT48YSBbcm91dGVyTGlua109XFxcIlsnL25vdGVzJ11cXFwiPk15IE5vdGVzPC9hPjwvbGk+XFxuICAgICAgICAgICAgICA8bGk+PGEgW3JvdXRlckxpbmtdPVxcXCJbJy9hcmNoaXZlLW5vdGVzJ11cXFwiPkFyY2hpdmUgTm90ZXM8L2E+PC9saT4gICBcXG4gICAgICAgICAgICAgIDxsaT48YSBocmVmPVxcXCJqYXZhc2NyaXB0OnZvaWQoMClcXFwiIFtyb3V0ZXJMaW5rXT1cXFwiWycvcmVjeWNsZS1iaW4nXVxcXCI+UmVjeWNsZSBCaW48L2E+PC9saT4gICAgICAgICAgICAgICAgICAgICAgXFxuICAgICAgICAgICAgICA8bGkgcm9sZT1cXFwic2VwYXJhdG9yXFxcIiBjbGFzcz1cXFwiZGl2aWRlclxcXCI+PC9saT5cXG4gICAgICAgICAgICAgIDxsaT5cXG4gICAgICAgICAgICAgICAgPGEgaHJlZj1cXFwiamF2YXNjcmlwdDp2b2lkKDApXFxcIiAoY2xpY2spPVxcXCJkaXNwbGF5VHlwZUNoYW5nZSgpXFxcIj5cXG4gICAgICAgICAgICAgICAgICB7e2Rpc3BsYXlMaXN0ID8gJ0dyaWQgVmlldycgOiAnTGlzdCBWaWV3J319XFxuICAgICAgICAgICAgICAgIDwvYT5cXG4gICAgICAgICAgICAgIDwvbGk+XFxuICAgICAgICAgICAgICA8bGk+PGEgaHJlZj1cXFwiamF2YXNjcmlwdDp2b2lkKDApXFxcIj5TZXR0aW5nczwvYT48L2xpPlxcbiAgICAgICAgICAgICAgPGxpPjxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCIgW3JvdXRlckxpbmtdPVxcXCJbJy9hYm91dCddXFxcIj5BYm91dDwvYT48L2xpPiAgICAgICAgICAgICAgXFxuICAgICAgICAgICAgPC91bD5cXG4gICAgICAgICAgPC9saT5cXG4gICAgICAgIDwvdWw+XFxuICAgICAgICA8YSBocmVmPVxcXCJqYXZhc2NyaXB0OnZvaWQoMClcXFwiIGNsYXNzPVxcXCJuYXZiYXItYnJhbmRcXFwiIFtyb3V0ZXJMaW5rXT1cXFwiWycvbm90ZXMnXVxcXCI+UHJlc2VydmVyIDwvYT5cXG4gICAgICAgIDxzcGFuIGNsYXNzPVxcXCJuYXZiYXItYnJhbmRcXFwiPjxpIGNsYXNzPVxcXCJmYSBmYS1hbmdsZS1yaWdodFxcXCIgYXJpYS1oaWRkZW49XFxcInRydWVcXFwiPjwvaT4mbmJzcDsmbmJzcDtOb3Rlczwvc3Bhbj5cXG4gICAgICA8L2Rpdj5cXG4gICAgICA8ZGl2IGlkPVxcXCJuYXZiYXJcXFwiIGNsYXNzPVxcXCJjb2xsYXBzZSBuYXZiYXItY29sbGFwc2VcXFwiPlxcbiAgICAgICAgPHVsIGNsYXNzPVxcXCJuYXYgbmF2YmFyLW5hdiBuYXZiYXItcmlnaHRcXFwiPlxcbiAgICAgICAgICA8bGk+XFxuICAgICAgICAgICAgPGEgaHJlZj1cXFwiamF2YXNjcmlwdDp2b2lkKDApXFxcIiAoY2xpY2spPVxcXCJkaXNwbGF5VHlwZUNoYW5nZSgpXFxcIj5cXG4gICAgICAgICAgICAgIDxpIGNsYXNzPVxcXCJ7e2Rpc3BsYXlMaXN0ID8gJ2ZhIGZhLWJhcnMnIDogJ2ZhIGZhLXRoJ319XFxcIj48L2k+XFxuICAgICAgICAgICAgPC9hPlxcbiAgICAgICAgICA8L2xpPlxcbiAgICAgICAgICA8bGkgY2xhc3M9XFxcImRyb3Bkb3duXFxcIj5cXG4gICAgICAgICAgICA8YSBocmVmPVxcXCJqYXZhc2NyaXB0OnZvaWQoMClcXFwiIGRhdGEtdGFyZ2V0PVxcXCIjXFxcIiBjbGFzcz1cXFwiZHJvcGRvd24tdG9nZ2xlXFxcIiBkYXRhLXRvZ2dsZT1cXFwiZHJvcGRvd25cXFwiPlxcbiAgICAgICAgICAgICAgPGkgY2xhc3M9XFxcImdseXBoaWNvbiBnbHlwaGljb24tb3B0aW9uLXZlcnRpY2FsXFxcIj48L2k+XFxuICAgICAgICAgICAgPC9hPlxcbiAgICAgICAgICAgIDx1bCBjbGFzcz1cXFwiZHJvcGRvd24tbWVudVxcXCI+XFxuICAgICAgICAgICAgICA8bGkgY2xhc3M9XFxcImRyb3Bkb3duLWhlYWRlclxcXCI+UHJlZmVyZW5jZXM8L2xpPlxcbiAgICAgICAgICAgICAgPGxpPjxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCIgW3JvdXRlckxpbmtdPVxcXCJbJy9ub3RlcyddXFxcIj5NeSBOb3RlczwvYT48L2xpPlxcbiAgICAgICAgICAgICAgPGxpPjxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCIgW3JvdXRlckxpbmtdPVxcXCJbJy9hcmNoaXZlLW5vdGVzJ11cXFwiPkFyY2hpdmUgTm90ZXM8L2E+PC9saT5cXG4gICAgICAgICAgICAgIDxsaT48YSBocmVmPVxcXCJqYXZhc2NyaXB0OnZvaWQoMClcXFwiIFtyb3V0ZXJMaW5rXT1cXFwiWycvcmVjeWNsZS1iaW4nXVxcXCI+UmVjeWNsZSBCaW48L2E+PC9saT4gICAgICAgICAgICAgIFxcbiAgICAgICAgICAgICAgPGxpIGNsYXNzPVxcXCJkaXZpZGVyXFxcIj48L2xpPlxcbiAgICAgICAgICAgICAgPGxpPjxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCI+U2V0dGluZ3M8L2E+PC9saT5cXG4gICAgICAgICAgICAgIDxsaT48YSBocmVmPVxcXCJqYXZhc2NyaXB0OnZvaWQoMClcXFwiIFtyb3V0ZXJMaW5rXT1cXFwiWycvYWJvdXQnXVxcXCI+QWJvdXQ8L2E+PC9saT5cXG4gICAgICAgICAgICA8L3VsPlxcbiAgICAgICAgICA8L2xpPlxcbiAgICAgICAgPC91bD5cXG4gICAgICA8L2Rpdj5cXG4gICAgPC9kaXY+XFxuICA8L2Rpdj5cXG4gIDxkaXYgY2xhc3M9XFxcImNvbnRhaW5lclxcXCI+XFxuICAgICAgPGRpdiBjbGFzcz1cXFwicGFuZWwgcGFuZWwtZGVmYXVsdCBub3RlLWVkaXRvciBhbmltYXRlZCBib3VuY2VJbkRvd25cXFwiPlxcbiAgICAgICAgPGRpdiBjbGFzcz1cXFwicGFuZWwtYm9keVxcXCI+XFxuICAgICAgICAgIDxkaXYgY2xhc3M9XFxcImZvcm0tZ3JvdXAgbGFiZWwtZmxvYXRpbmdcXFwiICpuZ0lmPVxcXCJpbnB1dEZvY3VzQ2xhc3NcXFwiPlxcbiAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cXFwidGV4dFxcXCIgY2xhc3M9XFxcImZvcm0tY29udHJvbFxcXCIgcGxhY2Vob2xkZXI9XFxcIlRpdGxlXFxcIiBbKG5nTW9kZWwpXT1cXFwiZHJhZnQudGl0bGVcXFwiID5cXG4gICAgICAgICAgPC9kaXY+ICAgICAgICAgIFxcbiAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJmb3JtLWdyb3VwIGxhYmVsLWZsb2F0aW5nXFxcIj5cXG4gICAgICAgICAgICAgPHRleHRhcmVhIGNsYXNzPVxcXCJmb3JtLWNvbnRyb2xcXFwiICN0ZXh0YXJlYSBhdXRvc2l6ZSBwbGFjZWhvbGRlcj1cXFwiV3JpdGUgYSBub3RlXFxcIiBbKG5nTW9kZWwpXT1cXFwiZHJhZnQubm90ZVxcXCIgKGZvY3VzKT1cXFwiX3NldElucHV0Rm9jdXModHJ1ZSlcXFwiPjwvdGV4dGFyZWE+XFxuICAgICAgICAgIDwvZGl2PlxcbiAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJmb3JtLWdyb3VwXFxcIiAqbmdJZj1cXFwiaW5wdXRGb2N1c0NsYXNzXFxcIj5cXG4gICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVxcXCJidG4gYnRuLXByaW1hcnkgYnRuLXNtIHB1bGwtcmlnaHRcXFwiIChjbGljayk9XFxcInNhdmVOb3RlKCRldmVudCwgdGV4dGFyZWEpXFxcIj5TYXZlPC9idXR0b24+XFxuICAgICAgICAgIDwvZGl2PlxcbiAgICAgICAgPC9kaXY+XFxuICAgICAgPC9kaXY+XFxuICA8L2Rpdj5cXG4gIDxzcGlubmVyICpuZ0lmPVxcXCJzcGlubmVyXFxcIj48L3NwaW5uZXI+XFxuICA8ZGl2IGNsYXNzPVxcXCJ7eyBkaXNwbGF5TGlzdCA/ICdjb250YWluZXIgbm90ZSBhbmltYXRlJyA6ICdjb250YWluZXIgbm90ZSBncmlkLWNvbnRhaW5lciBhbmltYXRlJ319XFxcIiBbZHJhZ3VsYV09J1xcXCJhbm90aGVyLWJhZ1xcXCInIFtkcmFndWxhTW9kZWxdPSdub3Rlcyc+XFxuICAgIDxkaXYgKm5nRm9yPSdsZXQgdGV4dCBvZiBub3RlcycgY2xhc3M9XFxcInt7IGRpc3BsYXlMaXN0ID8gJ3BhbmVsIHBhbmVsLWRlZmF1bHQgJyArIHRleHQuZG9jLmNvbG9yIDogJ3BhbmVsIHBhbmVsLWRlZmF1bHQgZ3JpZC1pdGVtICcgKyB0ZXh0LmRvYy5jb2xvcn19XFxcIiAjbm90ZVJvdyBbYXR0ci5pZF09XFxcInRleHQuZG9jLl9pZFxcXCI+XFxuICAgICAgPGRpdiBkYXRhLXRvZ2dsZT1cXFwibW9kYWxcXFwiIFthdHRyLmRhdGEtdGFyZ2V0XT1cXFwiJyNub3RlJyArIHRleHQuZG9jLl9pZFxcXCIgKGNsaWNrKT1cXFwiZWRpdE1vZGFsTm90ZUNsaWNrKHRleHQpXFxcIj5cXG4gICAgICAgIDxkaXYgY2xhc3M9XFxcInBhbmVsLWJvZHkgbXktbm90ZSBtb2R1bGUgbGluZS1jbGFtcFxcXCI+XFxuICAgICAgICAgIDxwPjxzdHJvbmc+e3t0ZXh0LmRvYy50aXRsZX19PC9zdHJvbmc+PC9wPlxcbiAgICAgICAgICA8cD4ge3t0ZXh0LmRvYy5ub3RlfX0gPC9wPlxcbiAgICAgICAgPC9kaXY+XFxuICAgICAgPC9kaXY+XFxuICAgICAgPGRpdiBjbGFzcz1cXFwie3sgJ3BhbmVsLWZvb3RlciAnICsgdGV4dC5kb2MuY29sb3J9fVxcXCI+XFxuICAgICAgICA8dWwgY2xhc3M9XFxcIm5vdGUtZm9vdGVyXFxcIj5cXG4gICAgICAgICAgPGxpPjxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCIgY2xhc3M9XFxcImJ0biBidG4tbGluayBidG4tcmFpc2VkXFxcIlxcbiAgICAgICAgICAgICB0aXRsZT1cXFwiQXJjaGl2ZVxcXCIgKGNsaWNrKT1cXFwibWFrZUFyY2hpdmUodGV4dCwgbm90ZVJvdylcXFwiPlxcbiAgICAgICAgICAgIDxpIGNsYXNzPVxcXCJmYSBmYS1kb3dubG9hZFxcXCI+PC9pPiAgICAgICAgXFxuICAgICAgICAgIDwvYT48L2xpPlxcbiAgICAgICAgICA8bGkgY2xhc3M9XFxcImRyb3B1cFxcXCI+XFxuICAgICAgICAgICAgPGEgZGF0YS10YXJnZXQ9XFxcIiNcXFwiIGNsYXNzPVxcXCJidG4gYnRuLWxpbmsgYnRuLXJhaXNlZCBkcm9wdXBcXFwiXFxuICAgICAgICAgICAgICB0aXRsZT1cXFwiQ29sb3JcXFwiIGRhdGEtdG9nZ2xlPVxcXCJkcm9wZG93blxcXCI+XFxuICAgICAgICAgICAgICA8aSBjbGFzcz1cXFwiZmEgZmEtdGgtbGFyZ2VcXFwiPjwvaT5cXG4gICAgICAgICAgICA8L2E+XFxuICAgICAgICAgICAgPHVsIGNsYXNzPVxcXCJkcm9wZG93bi1tZW51XFxcIj5cXG4gICAgICAgICAgICAgIDxsaT48YSBocmVmPVxcXCJqYXZhc2NyaXB0OnZvaWQoMClcXFwiIChjbGljayk9XFxcInNldE5vdGVDb2xvcignbGFiZWwtZGVmYXVsdCcsIHRleHQpXFxcIiBjbGFzcz1cXFwiYnRuIGJ0bi1kZWZhdWx0IGJ0bi1mYWItbWluaVxcXCI+PGkgY2xhc3M9XFxcIlxcXCI+PC9pPjwvYT48L2xpPlxcbiAgICAgICAgICAgICAgPGxpPjxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCIgKGNsaWNrKT1cXFwic2V0Tm90ZUNvbG9yKCdsYWJlbC1wcmltYXJ5JywgdGV4dClcXFwiIGNsYXNzPVxcXCJidG4gYnRuLXByaW1hcnkgYnRuLWZhYi1taW5pXFxcIj48aSBjbGFzcz1cXFwiXFxcIj48L2k+PC9hPjwvbGk+XFxuICAgICAgICAgICAgICA8bGk+PGEgaHJlZj1cXFwiamF2YXNjcmlwdDp2b2lkKDApXFxcIiAoY2xpY2spPVxcXCJzZXROb3RlQ29sb3IoJ2xhYmVsLXN1Y2Nlc3MnLCB0ZXh0KVxcXCIgY2xhc3M9XFxcImJ0biBidG4tc3VjY2VzcyBidG4tZmFiLW1pbmlcXFwiPjxpIGNsYXNzPVxcXCJcXFwiPjwvaT48L2E+PC9saT5cXG4gICAgICAgICAgICAgIDxsaT48YSBocmVmPVxcXCJqYXZhc2NyaXB0OnZvaWQoMClcXFwiIChjbGljayk9XFxcInNldE5vdGVDb2xvcignbGFiZWwtaW5mbycsIHRleHQpXFxcIiBjbGFzcz1cXFwiYnRuIGJ0bi1pbmZvIGJ0bi1mYWItbWluaVxcXCI+PGkgY2xhc3M9XFxcIlxcXCI+PC9pPjwvYT48L2xpPlxcbiAgICAgICAgICAgICAgPGxpPjxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCIgKGNsaWNrKT1cXFwic2V0Tm90ZUNvbG9yKCdsYWJlbC13YXJuaW5nJywgdGV4dClcXFwiIGNsYXNzPVxcXCJidG4gYnRuLXdhcm5pbmcgYnRuLWZhYi1taW5pXFxcIj48aSBjbGFzcz1cXFwiXFxcIj48L2k+PC9hPjwvbGk+XFxuICAgICAgICAgICAgICA8bGk+PGEgaHJlZj1cXFwiamF2YXNjcmlwdDp2b2lkKDApXFxcIiAoY2xpY2spPVxcXCJzZXROb3RlQ29sb3IoJ2xhYmVsLWRhbmdlcicsIHRleHQpXFxcIiBjbGFzcz1cXFwiYnRuIGJ0bi1kYW5nZXIgYnRuLWZhYi1taW5pXFxcIj48aSBjbGFzcz1cXFwiXFxcIj48L2k+PC9hPjwvbGk+XFxuICAgICAgICAgICAgICA8bGk+PGEgaHJlZj1cXFwiamF2YXNjcmlwdDp2b2lkKDApXFxcIiAoY2xpY2spPVxcXCJzZXROb3RlQ29sb3IoJ2xhYmVsLWRhcmtncmF5JywgdGV4dClcXFwiIGNsYXNzPVxcXCJidG4gYnRuLWRhcmtncmF5IGJ0bi1mYWItbWluaVxcXCI+PGkgY2xhc3M9XFxcIlxcXCI+PC9pPjwvYT48L2xpPlxcbiAgICAgICAgICAgICAgPGxpPjxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCIgKGNsaWNrKT1cXFwic2V0Tm90ZUNvbG9yKCdsYWJlbC1wcmltYXJ5LW9sZCcsIHRleHQpXFxcIiBjbGFzcz1cXFwiYnRuIGJ0bi1wcmltYXJ5LW9sZCBidG4tZmFiLW1pbmlcXFwiPjxpIGNsYXNzPVxcXCJcXFwiPjwvaT48L2E+PC9saT4gICAgICAgICAgICAgIFxcbiAgICAgICAgICAgIDwvdWw+XFxuICAgICAgICAgIDwvbGk+XFxuICAgICAgICAgIDxsaT48YSBocmVmPVxcXCJqYXZhc2NyaXB0OnZvaWQoMClcXFwiIGNsYXNzPVxcXCJidG4gYnRuLWxpbmsgYnRuLXJhaXNlZFxcXCJcXG4gICAgICAgICAgICAgdGl0bGU9XFxcIkRlbGV0ZVxcXCIgKGNsaWNrKT1cXFwiZGVsZXRlTm90ZSh0ZXh0LCBub3RlUm93KVxcXCI+XFxuICAgICAgICAgICAgPGkgY2xhc3M9XFxcImZhIGZhLXRyYXNoXFxcIj48L2k+ICAgICAgICAgIFxcbiAgICAgICAgICA8L2E+PC9saT5cXG4gICAgICAgIDwvdWw+XFxuICAgICAgPC9kaXY+XFxuICAgICAgPGRpdiBjbGFzcz1cXFwibW9kYWwgZmFkZVxcXCIgaWQ9XFxcInt7J25vdGUnICsgdGV4dC5kb2MuX2lkfX1cXFwiIHRhYmluZGV4PVxcXCItMVxcXCIgcm9sZT1cXFwiZGlhbG9nXFxcIiBhcmlhLWhpZGRlbj1cXFwidHJ1ZVxcXCI+XFxuICAgICAgICA8ZGl2IGNsYXNzPVxcXCJtb2RhbC1kaWFsb2dcXFwiPlxcbiAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJ7eydtb2RhbC1jb250ZW50IGVkaXQtc2F2ZWQgJyArIHRleHQuZG9jLmNvbG9yfX1cXFwiPlxcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XFxcIm1vZGFsLWhlYWRlclxcXCI+XFxuICAgICAgICAgICAgICA8aDQgY2xhc3M9XFxcIm1vZGFsLXRpdGxlXFxcIj5cXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwiZm9ybS1ncm91cCBsYWJlbC1mbG9hdGluZ1xcXCI+XFxuICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVxcXCJ0ZXh0XFxcIiBjbGFzcz1cXFwiZm9ybS1jb250cm9sIGVkaXQtc2F2ZWQtaW5wdXRcXFwiIHBsYWNlaG9sZGVyPVxcXCJUaXRsZVxcXCIgWyhuZ01vZGVsKV09XFxcImVkaXROb3RlRHJhZnQudGl0bGVcXFwiIFt2YWx1ZV09XFxcInRleHQuZG9jLnRpdGxlID8gdGV4dC5kb2MudGl0bGUgOiAnJ1xcXCIgPlxcbiAgICAgICAgICAgICAgICA8L2Rpdj4gICAgICAgICAgICAgICAgXFxuICAgICAgICAgICAgICA8L2g0PlxcbiAgICAgICAgICAgIDwvZGl2PlxcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XFxcIm1vZGFsLWJvZHlcXFwiPlxcbiAgICAgICAgICAgICAgPHRleHRhcmVhIGNsYXNzPVxcXCJmb3JtLWNvbnRyb2wgZWRpdC1zYXZlZC10ZXh0ZXJhXFxcIiAjZWRpdFNhdmVkVGV4dGFyZWEgbW9kYWxlZGl0b3JhdXRvc2l6ZSBwbGFjZWhvbGRlcj1cXFwiV3JpdGUgYSBub3RlXFxcIiBbKG5nTW9kZWwpXT1cXFwiZWRpdE5vdGVEcmFmdC5ub3RlXFxcIiBbdmFsdWVdPVxcXCJ0ZXh0LmRvYz8ubm90ZVxcXCI+PC90ZXh0YXJlYT4gICAgICAgICAgICAgIFxcbiAgICAgICAgICAgIDwvZGl2PlxcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XFxcIm1vZGFsLWZvb3RlclxcXCI+XFxuICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9XFxcImJ1dHRvblxcXCIgY2xhc3M9XFxcImJ0biBidG4tcHJpbWFyeSBidG4tc21cXFwiIGRhdGEtZGlzbWlzcz1cXFwibW9kYWxcXFwiIChjbGljayk9XFxcInVwZGF0ZU1vZGFsTm90ZSh0ZXh0KVxcXCI+RG9uZTwvYnV0dG9uPlxcbiAgICAgICAgICAgIDwvZGl2PlxcbiAgICAgICAgICA8L2Rpdj5cXG4gICAgICAgIDwvZGl2PlxcbiAgICAgIDwvZGl2PlxcbiAgICA8L2Rpdj5cXG4gIDwvZGl2PlxcbiAgPHNpbXBsZS1ub3RpZmljYXRpb25zIFtvcHRpb25zXT1cXFwibm90aWZpY2F0aW9uT3B0aW9uc1xcXCI+PC9zaW1wbGUtbm90aWZpY2F0aW9ucz5cXG4gIDxkaXYgY2xhc3M9XFxcImNvbnRhaW5lciBlbXB0eS1ub3Rlcy1jb250YWluZXJcXFwiICpuZ0lmPVxcXCJlbXB0eUh0bWxNc2dcXFwiPlxcbiAgICA8aDMgY2xhc3M9XFxcImVtcHR5LW5vdGVzLWljb24gZW1wdHktbm90ZXMtbWFpblxcXCI+PGkgY2xhc3M9XFxcImZhIGZhLWZpbGUtdGV4dC1vIGZhLTV4XFxcIj48L2k+PC9oMz5cXG4gICAgPGRpdiBjbGFzcz1cXFwiZW1wdHktbm90ZXNcXFwiPk5vdGVzIHRoYXQgeW91IGFkZCBhcHBlYXIgaGVyZTwvZGl2PlxcbiAgPC9kaXY+XFxuPC9kaXY+XFxuXCI7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9zcmMvYXBwL2NvbXBvbmVudHMvaG9tZS9ob21lLmNvbXBvbmVudC5odG1sXG4vLyBtb2R1bGUgaWQgPSAxMDNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIl0sIm1hcHBpbmdzIjoiQUFBQSIsInNvdXJjZVJvb3QiOiIifQ==");
- /***/ },
- /* 104 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar core_1 = __webpack_require__(4);\nvar angular2_notifications_1 = __webpack_require__(63);\nvar _ = __webpack_require__(74);\nvar dragula_1 = __webpack_require__(76);\nvar notes_table_service_1 = __webpack_require__(88);\nvar bin_table_service_1 = __webpack_require__(101);\nvar archive_table_service_1 = __webpack_require__(102);\nvar ArchiveComponent = (function () {\n function ArchiveComponent(dragulaService, _notesService, _archiveNotesService, _binNotesService, _notificationsService) {\n var _this = this;\n this.dragulaService = dragulaService;\n this._notesService = _notesService;\n this._archiveNotesService = _archiveNotesService;\n this._binNotesService = _binNotesService;\n this._notificationsService = _notificationsService;\n this.spinner = true;\n this.displayList = false;\n this.emptyHtmlMsg = false;\n this.notes_table = NOTES_TABLE;\n this.notes = [];\n this.editNoteDraft = {};\n this.order = [];\n this.orderNotes = [];\n this.notificationOptions = {\n timeOut: 3000,\n lastOnBottom: true,\n clickToClose: true,\n showProgressBar: false,\n pauseOnHover: true,\n preventDuplicates: false,\n theClass: \"notes-notifications\",\n rtl: true\n };\n dragulaService.dropModel.subscribe(function (value) {\n _this.onDropModel(value.slice(1));\n });\n dragulaService.drop.subscribe(function (value) {\n _this.onDrop(value);\n });\n dragulaService.removeModel.subscribe(function (value) {\n _this.onRemoveModel(value.slice(1));\n });\n this.displayList = localStorage.getItem(\"displayArchiveTypeList\") == 'true' ? true : false;\n }\n ArchiveComponent.prototype.ngOnInit = function () {\n var _this = this;\n this.subscription = this._archiveNotesService.archive_notes_tables$.subscribe(function (notes_table) { return _this.notes_table = notes_table; });\n this.refreshNotesTables();\n };\n ArchiveComponent.prototype.onDropModel = function (args) {\n var el = args[0], target = args[1], source = args[2];\n var order = [];\n this.notes.forEach(function (row) {\n order.push(row.doc._id);\n });\n localStorage.setItem('archiveOrder', JSON.stringify(order));\n };\n ArchiveComponent.prototype.onRemoveModel = function (args) {\n var el = args[0], source = args[1];\n };\n ArchiveComponent.prototype.onDrop = function (args) {\n var e = args[0], el = args[1];\n };\n ArchiveComponent.prototype.ngOnDestroy = function () {\n this.subscription.unsubscribe();\n };\n ArchiveComponent.prototype.refreshNotesTables = function () {\n var _this = this;\n this._archiveNotesService.getNotes().then(function (alldoc) {\n _this.notes_table = alldoc.rows;\n var testNotes = [];\n testNotes = _this.notes_table;\n if (localStorage.getItem('archiveOrder')) {\n _this.order = JSON.parse(localStorage.getItem('archiveOrder'));\n }\n _this.notes = [];\n _this.order.forEach(function (el) {\n testNotes.forEach(function (row) {\n if (String(row.doc._id) === String(el)) {\n _this.notes.push(row);\n }\n });\n });\n if (_.isEmpty(_this.notes)) {\n _this.emptyHtmlMsg = true;\n }\n else {\n _this.emptyHtmlMsg = false;\n }\n _this.spinner = false;\n }, function (err) {\n _this.spinner = false;\n });\n };\n ArchiveComponent.prototype.deleteNote = function (note, noteRow) {\n var _this = this;\n noteRow.className += this.displayList ? \" animated bounceOutRight\" : \" animated zoomOut\";\n setTimeout(function () {\n _this._archiveNotesService.deleteNote(note.doc)\n .then(function (res) {\n _this._notificationsService.create(\"Done\", \"Note moved to Recycle Bin\", \"success\");\n _this.deleteFromOrder(note);\n _this.refreshNotesTables();\n }, function (err) {\n console.log(\"Error\", err);\n });\n var binNote = note.doc;\n delete binNote._rev;\n _this._binNotesService.saveNote(binNote)\n .then(function (res) {\n }, function (err) {\n console.log(\"Error\", err);\n });\n }, 150);\n };\n ArchiveComponent.prototype.setNoteColor = function (color, note) {\n var _this = this;\n if (note.doc.color != color) {\n note.doc.color = color;\n this._archiveNotesService.updateNote(note.doc)\n .then(function (res) {\n _this.refreshNotesTables();\n }, function (err) {\n console.log(\"Error\", err);\n });\n }\n };\n ArchiveComponent.prototype.updateModalNote = function (note) {\n var _this = this;\n note.doc.note = this.editNoteDraft.note;\n note.doc.title = this.editNoteDraft.title;\n this._archiveNotesService.updateNote(note.doc)\n .then(function (res) {\n _this.editNoteDraft = {};\n _this.refreshNotesTables();\n }, function (err) {\n _this.editNoteDraft = {};\n console.log(\"Error\", err);\n });\n };\n ArchiveComponent.prototype.editModalNoteClick = function (note) {\n this.editNoteDraft.title = note.doc.title;\n this.editNoteDraft.note = note.doc.note;\n };\n ArchiveComponent.prototype.unArchive = function (note, noteRow) {\n var _this = this;\n noteRow.className += this.displayList ? \" animated bounceOutLeft\" : \" animated flipOutY\";\n setTimeout(function () {\n _this._archiveNotesService.deleteNote(note.doc)\n .then(function (res) {\n _this._notificationsService.create(\"Done\", \"Note unarchived\", \"success\");\n _this.deleteFromOrder(note);\n _this.refreshNotesTables();\n }, function (err) {\n console.log(\"Error\", err);\n });\n var archive_note = note;\n delete archive_note.doc._rev;\n archive_note.doc.restore = \"note\";\n _this._notesService.saveNote(archive_note.doc)\n .then(function (res) {\n _this.updateNotesOrder(archive_note.doc);\n }, function (err) { });\n }, 100);\n };\n ArchiveComponent.prototype.displayTypeChange = function () {\n this.displayList = this.displayList ? false : true;\n localStorage.setItem(\"displayArchiveTypeList\", String(this.displayList));\n };\n ArchiveComponent.prototype.deleteFromOrder = function (note) {\n var index = this.order.indexOf(this.order.filter(function (row) {\n return String(row) === String(note.doc._id);\n })[0]);\n if (index !== -1) {\n this.order.splice(index, 1);\n localStorage.setItem('archiveOrder', JSON.stringify(this.order));\n }\n };\n ArchiveComponent.prototype.updateNotesOrder = function (draft) {\n var newOrder = [];\n if (localStorage.getItem('order')) {\n newOrder = JSON.parse(localStorage.getItem('order'));\n newOrder.unshift(draft._id);\n }\n else {\n newOrder.push(draft._id);\n }\n localStorage.setItem(\"order\", JSON.stringify(newOrder));\n };\n ArchiveComponent = __decorate([\n core_1.Component({\n selector: 'archive',\n template: __webpack_require__(105)\n }), \n __metadata('design:paramtypes', [(typeof (_a = typeof dragula_1.DragulaService !== 'undefined' && dragula_1.DragulaService) === 'function' && _a) || Object, (typeof (_b = typeof notes_table_service_1.NotesTableService !== 'undefined' && notes_table_service_1.NotesTableService) === 'function' && _b) || Object, (typeof (_c = typeof archive_table_service_1.ArchiveNotesTableService !== 'undefined' && archive_table_service_1.ArchiveNotesTableService) === 'function' && _c) || Object, (typeof (_d = typeof bin_table_service_1.BinNotesTableService !== 'undefined' && bin_table_service_1.BinNotesTableService) === 'function' && _d) || Object, (typeof (_e = typeof angular2_notifications_1.NotificationsService !== 'undefined' && angular2_notifications_1.NotificationsService) === 'function' && _e) || Object])\n ], ArchiveComponent);\n return ArchiveComponent;\n var _a, _b, _c, _d, _e;\n}());\nexports.ArchiveComponent = ArchiveComponent;\nvar NOTES_TABLE = [];\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTA0LmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vc3JjL2FwcC9jb21wb25lbnRzL2FyY2hpdmUtbm90ZXMvYXJjaGl2ZS5jb21wb25lbnQudHM/ZGRmMSJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTm90aWZpY2F0aW9uc1NlcnZpY2UgfSBmcm9tIFwiYW5ndWxhcjItbm90aWZpY2F0aW9uc1wiO1xuXG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzL1N1YnNjcmlwdGlvbic7XG5pbXBvcnQgKiBhcyBfIGZyb20gJ2xvZGFzaCc7XG5cbmltcG9ydCB7IERyYWd1bGFTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vcHJvdmlkZXJzL2RyYWd1bGEnO1xuXG5pbXBvcnQgeyBOb3Rlc1RhYmxlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvbm90ZXNfdGFibGUnO1xuaW1wb3J0IHsgTm90ZXNUYWJsZVNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9ub3Rlc190YWJsZS5zZXJ2aWNlJztcbmltcG9ydCB7IEJpbk5vdGVzVGFibGVTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvYmluX3RhYmxlLnNlcnZpY2UnO1xuaW1wb3J0IHsgQXJjaGl2ZU5vdGVzVGFibGVTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvYXJjaGl2ZV90YWJsZS5zZXJ2aWNlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXJjaGl2ZScsXG4gIHRlbXBsYXRlOiByZXF1aXJlKCcuL2FyY2hpdmUuY29tcG9uZW50Lmh0bWwnKVxufSlcbmV4cG9ydCBjbGFzcyBBcmNoaXZlQ29tcG9uZW50IHtcbiAgcHVibGljIG5vdGVzOiBhbnk7XG4gIHB1YmxpYyBvcmRlcjphbnk7XG4gIHB1YmxpYyBvcmRlck5vdGVzOiBhbnk7XG4gIHB1YmxpYyBlZGl0Tm90ZURyYWZ0OiBhbnk7XG4gIHB1YmxpYyBub3RpZmljYXRpb25PcHRpb25zOiBhbnk7IFxuICBwdWJsaWMgc3Bpbm5lcjogYm9vbGVhbiA9IHRydWU7XG4gIHB1YmxpYyBkaXNwbGF5TGlzdDogYm9vbGVhbiA9IGZhbHNlOyBcbiAgcHVibGljIGVtcHR5SHRtbE1zZzogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIHB1YmxpYyBub3Rlc190YWJsZSA9IE5PVEVTX1RBQkxFO1xuICBwdWJsaWMgc3Vic2NyaXB0aW9uOlN1YnNjcmlwdGlvbjtcblxuICBjb25zdHJ1Y3RvciAoXG4gICAgICBwcml2YXRlIGRyYWd1bGFTZXJ2aWNlOiBEcmFndWxhU2VydmljZSxcbiAgICAgIHByaXZhdGUgX25vdGVzU2VydmljZTogTm90ZXNUYWJsZVNlcnZpY2UsXG4gICAgICBwcml2YXRlIF9hcmNoaXZlTm90ZXNTZXJ2aWNlOiBBcmNoaXZlTm90ZXNUYWJsZVNlcnZpY2UsXG4gICAgICBwcml2YXRlIF9iaW5Ob3Rlc1NlcnZpY2U6IEJpbk5vdGVzVGFibGVTZXJ2aWNlLFxuICAgICAgcHJpdmF0ZSBfbm90aWZpY2F0aW9uc1NlcnZpY2U6IE5vdGlmaWNhdGlvbnNTZXJ2aWNlXG4gICAgKSB7XG4gICAgdGhpcy5ub3RlcyA9IFtdO1xuICAgIHRoaXMuZWRpdE5vdGVEcmFmdCA9IHt9O1xuICAgIHRoaXMub3JkZXIgPSBbXTtcbiAgICB0aGlzLm9yZGVyTm90ZXMgPSBbXTtcbiAgICB0aGlzLm5vdGlmaWNhdGlvbk9wdGlvbnMgPSB7XG4gICAgICB0aW1lT3V0OiAzMDAwLFxuICAgICAgbGFzdE9uQm90dG9tOiB0cnVlLFxuICAgICAgY2xpY2tUb0Nsb3NlOiB0cnVlLFxuICAgICAgc2hvd1Byb2dyZXNzQmFyOiBmYWxzZSxcbiAgICAgIHBhdXNlT25Ib3ZlcjogdHJ1ZSxcbiAgICAgIHByZXZlbnREdXBsaWNhdGVzOiBmYWxzZSxcbiAgICAgIHRoZUNsYXNzOiBcIm5vdGVzLW5vdGlmaWNhdGlvbnNcIixcbiAgICAgIHJ0bDogdHJ1ZVxuICAgIH07XG5cbiAgICBkcmFndWxhU2VydmljZS5kcm9wTW9kZWwuc3Vic2NyaWJlKCh2YWx1ZSkgPT4ge1xuICAgICAgdGhpcy5vbkRyb3BNb2RlbCh2YWx1ZS5zbGljZSgxKSk7XG4gICAgfSk7XG4gICAgZHJhZ3VsYVNlcnZpY2UuZHJvcC5zdWJzY3JpYmUoKHZhbHVlKSA9PiB7XG4gICAgICB0aGlzLm9uRHJvcCh2YWx1ZSk7XG4gICAgfSk7XG4gICAgZHJhZ3VsYVNlcnZpY2UucmVtb3ZlTW9kZWwuc3Vic2NyaWJlKCh2YWx1ZSkgPT4ge1xuICAgICAgdGhpcy5vblJlbW92ZU1vZGVsKHZhbHVlLnNsaWNlKDEpKTtcbiAgICB9KTtcbiAgICB0aGlzLmRpc3BsYXlMaXN0ID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oXCJkaXNwbGF5QXJjaGl2ZVR5cGVMaXN0XCIpID09ICd0cnVlJyA/IHRydWUgOiBmYWxzZTtcbiAgfVxuICBcbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb24gPSB0aGlzLl9hcmNoaXZlTm90ZXNTZXJ2aWNlLmFyY2hpdmVfbm90ZXNfdGFibGVzJC5zdWJzY3JpYmUoXG4gICAgICBub3Rlc190YWJsZSA9PiB0aGlzLm5vdGVzX3RhYmxlID0gbm90ZXNfdGFibGVcbiAgICApO1xuICAgIHRoaXMucmVmcmVzaE5vdGVzVGFibGVzKCk7XG4gIH1cbiAgXG4gIHByaXZhdGUgb25Ecm9wTW9kZWwoYXJncykge1xuICAgIGxldCBbZWwsIHRhcmdldCwgc291cmNlXSA9IGFyZ3M7XG4gICAgXG4gICAgbGV0IG9yZGVyID0gW107IFxuICAgIHRoaXMubm90ZXMuZm9yRWFjaChyb3cgPT4ge1xuICAgICAgb3JkZXIucHVzaChyb3cuZG9jLl9pZCk7XG4gICAgfSk7XG5cbiAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSgnYXJjaGl2ZU9yZGVyJywgSlNPTi5zdHJpbmdpZnkob3JkZXIpKTtcbiAgfVxuXG4gIHByaXZhdGUgb25SZW1vdmVNb2RlbChhcmdzKSB7XG4gICAgbGV0IFtlbCwgc291cmNlXSA9IGFyZ3M7XG4gIH1cbiAgXG4gIFxuICBwcml2YXRlIG9uRHJvcChhcmdzKSB7XG4gICAgbGV0IFtlLCBlbF0gPSBhcmdzO1xuICB9XG4gIFxuICBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICB9XG5cbiAgcmVmcmVzaE5vdGVzVGFibGVzKCkge1xuICAgIHRoaXMuX2FyY2hpdmVOb3Rlc1NlcnZpY2UuZ2V0Tm90ZXMoKS50aGVuKFxuICAgICAgYWxsZG9jID0+IHtcbiAgICAgICAgdGhpcy5ub3Rlc190YWJsZSA9IGFsbGRvYy5yb3dzO1xuICAgICAgICBsZXQgdGVzdE5vdGVzID0gW107XG4gICAgICAgIHRlc3ROb3RlcyA9IHRoaXMubm90ZXNfdGFibGU7XG4gICAgICAgIGlmIChsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnYXJjaGl2ZU9yZGVyJykpIHtcbiAgICAgICAgICB0aGlzLm9yZGVyID0gSlNPTi5wYXJzZShsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnYXJjaGl2ZU9yZGVyJykpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubm90ZXMgPSBbXTtcbiAgICAgICAgdGhpcy5vcmRlci5mb3JFYWNoKGVsID0+IHtcbiAgICAgICAgICB0ZXN0Tm90ZXMuZm9yRWFjaChyb3cgPT4ge1xuICAgICAgICAgICAgaWYgKFN0cmluZyhyb3cuZG9jLl9pZCkgPT09IFN0cmluZyhlbCkpIHtcbiAgICAgICAgICAgICAgdGhpcy5ub3Rlcy5wdXNoKHJvdyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoXy5pc0VtcHR5KHRoaXMubm90ZXMpKSB7XG4gICAgICAgICAgdGhpcy5lbXB0eUh0bWxNc2cgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuZW1wdHlIdG1sTXNnID0gZmFsc2U7ICAgICAgICAgIFxuICAgICAgICB9XG4gICAgICAgIHRoaXMuc3Bpbm5lciA9IGZhbHNlO1xuICAgICAgfSxcbiAgICAgIGVyciA9PiB7XG4gICAgICAgIHRoaXMuc3Bpbm5lciA9IGZhbHNlOyAgICAgICAgXG4gICAgICB9XG4gICAgKTtcbiAgfVxuICAgIFxuICBkZWxldGVOb3RlKG5vdGUsIG5vdGVSb3cpIHtcbiAgICBub3RlUm93LmNsYXNzTmFtZSArPSB0aGlzLmRpc3BsYXlMaXN0ID8gXCIgYW5pbWF0ZWQgYm91bmNlT3V0UmlnaHRcIiA6IFwiIGFuaW1hdGVkIHpvb21PdXRcIjtcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMuX2FyY2hpdmVOb3Rlc1NlcnZpY2UuZGVsZXRlTm90ZShub3RlLmRvYylcbiAgICAgICAgLnRoZW4ocmVzID0+IHtcbiAgICAgICAgICB0aGlzLl9ub3RpZmljYXRpb25zU2VydmljZS5jcmVhdGUoXCJEb25lXCIsIFwiTm90ZSBtb3ZlZCB0byBSZWN5Y2xlIEJpblwiLCBcInN1Y2Nlc3NcIik7XG4gICAgICAgICAgdGhpcy5kZWxldGVGcm9tT3JkZXIobm90ZSk7XG4gICAgICAgICAgdGhpcy5yZWZyZXNoTm90ZXNUYWJsZXMoKTtcbiAgICAgICAgfSwgZXJyID0+IHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkVycm9yXCIsIGVycik7XG4gICAgICAgIH0pO1xuICAgICAgbGV0IGJpbk5vdGUgPSBub3RlLmRvYztcbiAgICAgIGRlbGV0ZSBiaW5Ob3RlLl9yZXY7XG4gICAgICB0aGlzLl9iaW5Ob3Rlc1NlcnZpY2Uuc2F2ZU5vdGUoYmluTm90ZSlcbiAgICAgICAgLnRoZW4ocmVzID0+IHtcblxuICAgICAgICB9LCBlcnIgPT4ge1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiRXJyb3JcIiwgZXJyKTtcbiAgICAgICAgfSk7XG4gICAgfSwgMTUwKTtcbiAgfVxuICBcbiAgc2V0Tm90ZUNvbG9yKGNvbG9yLCBub3RlKSB7XG4gICAgaWYgKG5vdGUuZG9jLmNvbG9yICE9IGNvbG9yKSB7XG4gICAgICBub3RlLmRvYy5jb2xvciA9IGNvbG9yOyAgICBcbiAgICAgIHRoaXMuX2FyY2hpdmVOb3Rlc1NlcnZpY2UudXBkYXRlTm90ZShub3RlLmRvYylcbiAgICAgICAgLnRoZW4ocmVzID0+IHsgICAgICAgICAgXG4gICAgICAgICAgdGhpcy5yZWZyZXNoTm90ZXNUYWJsZXMoKTtcbiAgICAgICAgfSwgZXJyID0+IHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkVycm9yXCIsIGVycik7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgfVxuICBcbiAgdXBkYXRlTW9kYWxOb3RlKG5vdGUpIHtcbiAgICBub3RlLmRvYy5ub3RlID0gdGhpcy5lZGl0Tm90ZURyYWZ0Lm5vdGU7XG4gICAgbm90ZS5kb2MudGl0bGUgPSB0aGlzLmVkaXROb3RlRHJhZnQudGl0bGU7XG4gICAgdGhpcy5fYXJjaGl2ZU5vdGVzU2VydmljZS51cGRhdGVOb3RlKG5vdGUuZG9jKVxuICAgICAgLnRoZW4ocmVzID0+IHtcbiAgICAgICAgdGhpcy5lZGl0Tm90ZURyYWZ0ID0ge307XG4gICAgICAgIHRoaXMucmVmcmVzaE5vdGVzVGFibGVzKCk7XG4gICAgICB9LCBlcnIgPT4ge1xuICAgICAgICB0aGlzLmVkaXROb3RlRHJhZnQgPSB7fTsgICAgICAgIFxuICAgICAgICBjb25zb2xlLmxvZyhcIkVycm9yXCIsIGVycik7XG4gICAgICB9KTtcbiAgfVxuICBcbiAgZWRpdE1vZGFsTm90ZUNsaWNrKG5vdGUpIHtcbiAgICB0aGlzLmVkaXROb3RlRHJhZnQudGl0bGUgPSBub3RlLmRvYy50aXRsZTtcbiAgICB0aGlzLmVkaXROb3RlRHJhZnQubm90ZSA9IG5vdGUuZG9jLm5vdGU7ICAgICAgICAgXG4gIH1cblxuICB1bkFyY2hpdmUobm90ZSwgbm90ZVJvdykge1xuICAgIG5vdGVSb3cuY2xhc3NOYW1lICs9IHRoaXMuZGlzcGxheUxpc3QgPyBcIiBhbmltYXRlZCBib3VuY2VPdXRMZWZ0XCIgOiBcIiBhbmltYXRlZCBmbGlwT3V0WVwiO1xuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5fYXJjaGl2ZU5vdGVzU2VydmljZS5kZWxldGVOb3RlKG5vdGUuZG9jKVxuICAgICAgICAudGhlbihyZXMgPT4ge1xuICAgICAgICAgIHRoaXMuX25vdGlmaWNhdGlvbnNTZXJ2aWNlLmNyZWF0ZShcIkRvbmVcIiwgXCJOb3RlIHVuYXJjaGl2ZWRcIiwgXCJzdWNjZXNzXCIpOyAgICAgIFxuICAgICAgICAgIHRoaXMuZGVsZXRlRnJvbU9yZGVyKG5vdGUpOyAgICBcbiAgICAgICAgICB0aGlzLnJlZnJlc2hOb3Rlc1RhYmxlcygpO1xuICAgICAgICB9LCBlcnIgPT4ge1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiRXJyb3JcIiwgZXJyKTtcbiAgICAgICAgfSk7XG4gICAgICBsZXQgYXJjaGl2ZV9ub3RlID0gbm90ZTtcbiAgICAgIGRlbGV0ZSBhcmNoaXZlX25vdGUuZG9jLl9yZXY7XG4gICAgICBhcmNoaXZlX25vdGUuZG9jLnJlc3RvcmUgPSBcIm5vdGVcIjtcbiAgICAgIHRoaXMuX25vdGVzU2VydmljZS5zYXZlTm90ZShhcmNoaXZlX25vdGUuZG9jKVxuICAgICAgICAudGhlbihyZXMgPT4ge1xuICAgICAgICAgIHRoaXMudXBkYXRlTm90ZXNPcmRlcihhcmNoaXZlX25vdGUuZG9jKTtcbiAgICAgICAgfSwgZXJyID0+IHt9KTtcbiAgICB9LCAxMDApO1xuICB9XG4gIFxuICBkaXNwbGF5VHlwZUNoYW5nZSgpIHtcbiAgICB0aGlzLmRpc3BsYXlMaXN0ID0gdGhpcy5kaXNwbGF5TGlzdCA/IGZhbHNlIDogdHJ1ZTtcbiAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShcImRpc3BsYXlBcmNoaXZlVHlwZUxpc3RcIiwgU3RyaW5nKHRoaXMuZGlzcGxheUxpc3QpKTtcbiAgfVxuICBcbiAgZGVsZXRlRnJvbU9yZGVyKG5vdGUpIHtcbiAgICBsZXQgaW5kZXggPSB0aGlzLm9yZGVyLmluZGV4T2YodGhpcy5vcmRlci5maWx0ZXIocm93ID0+IHtcbiAgICAgIHJldHVybiBTdHJpbmcocm93KSA9PT0gU3RyaW5nKG5vdGUuZG9jLl9pZCk7XG4gICAgfSlbMF0pO1xuICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgIHRoaXMub3JkZXIuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKCdhcmNoaXZlT3JkZXInLCBKU09OLnN0cmluZ2lmeSh0aGlzLm9yZGVyKSk7XG4gICAgfVxuICB9XG4gIFxuICB1cGRhdGVOb3Rlc09yZGVyKGRyYWZ0KSB7XG4gICAgbGV0IG5ld09yZGVyID0gW107XG4gICAgaWYgKGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdvcmRlcicpKSB7XG4gICAgICBuZXdPcmRlciA9IEpTT04ucGFyc2UobG9jYWxTdG9yYWdlLmdldEl0ZW0oJ29yZGVyJykpO1xuICAgICAgbmV3T3JkZXIudW5zaGlmdChkcmFmdC5faWQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdPcmRlci5wdXNoKGRyYWZ0Ll9pZCk7XG4gICAgfVxuICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKFwib3JkZXJcIiwgSlNPTi5zdHJpbmdpZnkobmV3T3JkZXIpKTtcbiAgfVxufVxuXG5sZXQgTk9URVNfVEFCTEU6IE5vdGVzVGFibGVbXSA9IFtdXG5cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyBub2RlX21vZHVsZXMvYW5ndWxhcjItdGVtcGxhdGUtbG9hZGVyIS4vc3JjL2FwcC9jb21wb25lbnRzL2FyY2hpdmUtbm90ZXMvYXJjaGl2ZS5jb21wb25lbnQudHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBR0E7QUFFQTtBQUdBO0FBQ0E7QUFDQTtBQU1BO0FBYUE7QUFiQTtBQWNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFaQTtBQUNBO0FBQ0E7QUFFQTtBQVVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQUNBO0FBR0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUFBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUVBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFqTkE7QUFBQTtBQUNBO0FBQ0E7QUFDQTs7QUFBQTtBQStNQTs7QUFBQTtBQTlNQTtBQWdOQTsiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ },
- /* 105 */
- /***/ function(module, exports) {
- eval("module.exports = \"<div class=\\\"\\\">\\n <div class=\\\"navbar navbar-info\\\">\\n <div class=\\\"container-fluid\\\">\\n <div class=\\\"navbar-header\\\">\\n <ul class=\\\"navbar-toggle\\\">\\n <li class=\\\"dropdown\\\">\\n <a href=\\\"#\\\" class=\\\"dropdown-toggle\\\" data-toggle=\\\"dropdown\\\" role=\\\"button\\\" aria-haspopup=\\\"true\\\" aria-expanded=\\\"false\\\"> <i class=\\\"glyphicon glyphicon-option-vertical\\\"></i></a>\\n <ul class=\\\"dropdown-menu\\\">\\n\\n <li class=\\\"dropdown-header\\\">Preferences</li>\\n <li><a [routerLink]=\\\"['/notes']\\\">My Notes</a></li>\\n <li><a [routerLink]=\\\"['/archive-notes']\\\">Archive Notes</a></li> \\n <li><a href=\\\"javascript:void(0)\\\" [routerLink]=\\\"['/recycle-bin']\\\">Recycle Bin</a></li> \\n <li role=\\\"separator\\\" class=\\\"divider\\\"></li>\\n <li>\\n <a href=\\\"javascript:void(0)\\\" (click)=\\\"displayTypeChange()\\\">\\n {{displayList ? 'Grid View' : 'List View'}}\\n </a>\\n </li>\\n <li><a href=\\\"javascript:void(0)\\\">Settings</a></li>\\n <li><a href=\\\"javascript:void(0)\\\" [routerLink]=\\\"['/About']\\\">About</a></li>\\n </ul>\\n </li>\\n </ul>\\n <a href=\\\"javascript:void(0)\\\" class=\\\"navbar-brand\\\" [routerLink]=\\\"['/notes']\\\">Preserver </a>\\n <span class=\\\"navbar-brand\\\"><i class=\\\"fa fa-angle-right\\\" aria-hidden=\\\"true\\\"></i> Archive</span>\\n </div>\\n <div id=\\\"navbar\\\" class=\\\"collapse navbar-collapse\\\">\\n <ul class=\\\"nav navbar-nav navbar-right\\\">\\n <li>\\n <a href=\\\"javascript:void(0)\\\" (click)=\\\"displayTypeChange()\\\">\\n <i class=\\\"{{displayList ? 'fa fa-bars' : 'fa fa-th'}}\\\"></i>\\n </a>\\n </li>\\n <li class=\\\"dropdown\\\">\\n <a href=\\\"javascript:void(0)\\\" data-target=\\\"#\\\" class=\\\"dropdown-toggle\\\" data-toggle=\\\"dropdown\\\">\\n <i class=\\\"glyphicon glyphicon-option-vertical\\\"></i>\\n </a>\\n <ul class=\\\"dropdown-menu\\\">\\n <li class=\\\"dropdown-header\\\">Preferences</li>\\n <li><a href=\\\"javascript:void(0)\\\" [routerLink]=\\\"['/notes']\\\">My Notes</a></li>\\n <li><a href=\\\"javascript:void(0)\\\" [routerLink]=\\\"['/archive-notes']\\\">Archive Notes</a></li>\\n <li><a href=\\\"javascript:void(0)\\\" [routerLink]=\\\"['/recycle-bin']\\\">Recycle Bin</a></li> \\n <li class=\\\"divider\\\"></li>\\n <li><a href=\\\"javascript:void(0)\\\">Settings</a></li>\\n <li><a href=\\\"javascript:void(0)\\\" [routerLink]=\\\"['/About']\\\">About</a></li>\\n </ul>\\n </li>\\n </ul>\\n </div>\\n </div>\\n </div>\\n <spinner *ngIf=\\\"spinner\\\"></spinner>\\n <div class=\\\"{{ displayList ? 'container note animate' : 'container note grid-container animate'}}\\\" [dragula]='\\\"another-bag\\\"' [dragulaModel]='notes'>\\n <div *ngFor='let text of notes' class=\\\"{{ displayList ? 'panel panel-default ' + text.doc.color : 'panel panel-default grid-item ' + text.doc.color}}\\\" #noteRow [attr.id]=\\\"text.doc._id\\\">\\n <div data-toggle=\\\"modal\\\" [attr.data-target]=\\\"'#note' + text.doc._id\\\" (click)=\\\"editModalNoteClick(text)\\\">\\n <div class=\\\"panel-body my-note module line-clamp\\\">\\n <p><strong>{{text.doc.title}}</strong></p>\\n <p> {{text.doc.note}} </p>\\n </div>\\n </div>\\n <div class=\\\"{{ 'panel-footer ' + text.doc.color}}\\\">\\n <ul class=\\\"note-footer\\\">\\n <li><a href=\\\"javascript:void(0)\\\" class=\\\"btn btn-link btn-raised\\\"\\n title=\\\"Unarchive\\\" (click)=\\\"unArchive(text, noteRow)\\\">\\n <i class=\\\"fa fa-upload\\\"></i> \\n </a></li>\\n <li class=\\\"dropup\\\">\\n <a data-target=\\\"#\\\" class=\\\"btn btn-link btn-raised dropup\\\"\\n title=\\\"Color\\\" data-toggle=\\\"dropdown\\\">\\n <i class=\\\"fa fa-th-large\\\"></i>\\n </a>\\n <ul class=\\\"dropdown-menu\\\">\\n <li><a href=\\\"javascript:void(0)\\\" (click)=\\\"setNoteColor('label-default', text)\\\" class=\\\"btn btn-default btn-fab-mini\\\"><i class=\\\"\\\"></i></a></li>\\n <li><a href=\\\"javascript:void(0)\\\" (click)=\\\"setNoteColor('label-primary', text)\\\" class=\\\"btn btn-primary btn-fab-mini\\\"><i class=\\\"\\\"></i></a></li>\\n <li><a href=\\\"javascript:void(0)\\\" (click)=\\\"setNoteColor('label-success', text)\\\" class=\\\"btn btn-success btn-fab-mini\\\"><i class=\\\"\\\"></i></a></li>\\n <li><a href=\\\"javascript:void(0)\\\" (click)=\\\"setNoteColor('label-info', text)\\\" class=\\\"btn btn-info btn-fab-mini\\\"><i class=\\\"\\\"></i></a></li>\\n <li><a href=\\\"javascript:void(0)\\\" (click)=\\\"setNoteColor('label-warning', text)\\\" class=\\\"btn btn-warning btn-fab-mini\\\"><i class=\\\"\\\"></i></a></li>\\n <li><a href=\\\"javascript:void(0)\\\" (click)=\\\"setNoteColor('label-danger', text)\\\" class=\\\"btn btn-danger btn-fab-mini\\\"><i class=\\\"\\\"></i></a></li>\\n <li><a href=\\\"javascript:void(0)\\\" (click)=\\\"setNoteColor('label-darkgray', text)\\\" class=\\\"btn btn-darkgray btn-fab-mini\\\"><i class=\\\"\\\"></i></a></li>\\n <li><a href=\\\"javascript:void(0)\\\" (click)=\\\"setNoteColor('label-primary-old', text)\\\" class=\\\"btn btn-primary-old btn-fab-mini\\\"><i class=\\\"\\\"></i></a></li> \\n </ul>\\n </li>\\n <li><a href=\\\"javascript:void(0)\\\" class=\\\"btn btn-link btn-raised\\\"\\n title=\\\"Delete\\\" (click)=\\\"deleteNote(text, noteRow)\\\">\\n <i class=\\\"fa fa-trash\\\"></i> \\n </a></li>\\n </ul>\\n </div>\\n <div class=\\\"modal fade\\\" id=\\\"{{'note' + text.doc._id}}\\\" tabindex=\\\"-1\\\" role=\\\"dialog\\\" aria-hidden=\\\"true\\\">\\n <div class=\\\"modal-dialog\\\">\\n <div class=\\\"{{'modal-content edit-saved ' + text.doc.color}}\\\">\\n <div class=\\\"modal-header\\\">\\n <h4 class=\\\"modal-title\\\">\\n <div class=\\\"form-group label-floating\\\">\\n <input type=\\\"text\\\" class=\\\"form-control edit-saved-input\\\" placeholder=\\\"Title\\\" [(ngModel)]=\\\"editNoteDraft.title\\\" [value]=\\\"text.doc.title ? text.doc.title : ''\\\" >\\n </div> \\n </h4>\\n </div>\\n <div class=\\\"modal-body\\\">\\n <textarea class=\\\"form-control edit-saved-textera\\\" #editSavedTextarea modaleditorautosize placeholder=\\\"Write a note\\\" [(ngModel)]=\\\"editNoteDraft.note\\\" [value]=\\\"text.doc?.note\\\"></textarea> \\n </div>\\n <div class=\\\"modal-footer\\\">\\n <button type=\\\"button\\\" class=\\\"btn btn-primary btn-sm\\\" data-dismiss=\\\"modal\\\" (click)=\\\"updateModalNote(text)\\\">Done</button>\\n </div>\\n </div>\\n </div>\\n </div>\\n </div>\\n </div>\\n <simple-notifications [options]=\\\"notificationOptions\\\"></simple-notifications>\\n <div class=\\\"container empty-notes-container\\\" *ngIf=\\\"emptyHtmlMsg\\\">\\n <div class=\\\"empty-notes-icon empty-archive\\\"></div>\\n <div class=\\\"empty-notes\\\">Your archived notes appear here</div>\\n </div>\\n</div>\";//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTA1LmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vc3JjL2FwcC9jb21wb25lbnRzL2FyY2hpdmUtbm90ZXMvYXJjaGl2ZS5jb21wb25lbnQuaHRtbD8zZWU0Il0sInNvdXJjZXNDb250ZW50IjpbIm1vZHVsZS5leHBvcnRzID0gXCI8ZGl2IGNsYXNzPVxcXCJcXFwiPlxcbiAgPGRpdiBjbGFzcz1cXFwibmF2YmFyIG5hdmJhci1pbmZvXFxcIj5cXG4gICAgPGRpdiBjbGFzcz1cXFwiY29udGFpbmVyLWZsdWlkXFxcIj5cXG4gICAgICA8ZGl2IGNsYXNzPVxcXCJuYXZiYXItaGVhZGVyXFxcIj5cXG4gICAgICAgIDx1bCBjbGFzcz1cXFwibmF2YmFyLXRvZ2dsZVxcXCI+XFxuICAgICAgICAgIDxsaSBjbGFzcz1cXFwiZHJvcGRvd25cXFwiPlxcbiAgICAgICAgICAgIDxhIGhyZWY9XFxcIiNcXFwiIGNsYXNzPVxcXCJkcm9wZG93bi10b2dnbGVcXFwiIGRhdGEtdG9nZ2xlPVxcXCJkcm9wZG93blxcXCIgcm9sZT1cXFwiYnV0dG9uXFxcIiBhcmlhLWhhc3BvcHVwPVxcXCJ0cnVlXFxcIiBhcmlhLWV4cGFuZGVkPVxcXCJmYWxzZVxcXCI+IDxpIGNsYXNzPVxcXCJnbHlwaGljb24gZ2x5cGhpY29uLW9wdGlvbi12ZXJ0aWNhbFxcXCI+PC9pPjwvYT5cXG4gICAgICAgICAgICA8dWwgY2xhc3M9XFxcImRyb3Bkb3duLW1lbnVcXFwiPlxcblxcbiAgICAgICAgICAgICAgPGxpIGNsYXNzPVxcXCJkcm9wZG93bi1oZWFkZXJcXFwiPlByZWZlcmVuY2VzPC9saT5cXG4gICAgICAgICAgICAgIDxsaT48YSBbcm91dGVyTGlua109XFxcIlsnL25vdGVzJ11cXFwiPk15IE5vdGVzPC9hPjwvbGk+XFxuICAgICAgICAgICAgICA8bGk+PGEgW3JvdXRlckxpbmtdPVxcXCJbJy9hcmNoaXZlLW5vdGVzJ11cXFwiPkFyY2hpdmUgTm90ZXM8L2E+PC9saT4gICBcXG4gICAgICAgICAgICAgIDxsaT48YSBocmVmPVxcXCJqYXZhc2NyaXB0OnZvaWQoMClcXFwiIFtyb3V0ZXJMaW5rXT1cXFwiWycvcmVjeWNsZS1iaW4nXVxcXCI+UmVjeWNsZSBCaW48L2E+PC9saT4gICAgICAgICAgICAgICAgICAgICAgIFxcbiAgICAgICAgICAgICAgPGxpIHJvbGU9XFxcInNlcGFyYXRvclxcXCIgY2xhc3M9XFxcImRpdmlkZXJcXFwiPjwvbGk+XFxuICAgICAgICAgICAgICA8bGk+XFxuICAgICAgICAgICAgICAgIDxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCIgKGNsaWNrKT1cXFwiZGlzcGxheVR5cGVDaGFuZ2UoKVxcXCI+XFxuICAgICAgICAgICAgICAgICAge3tkaXNwbGF5TGlzdCA/ICdHcmlkIFZpZXcnIDogJ0xpc3QgVmlldyd9fVxcbiAgICAgICAgICAgICAgICA8L2E+XFxuICAgICAgICAgICAgICA8L2xpPlxcbiAgICAgICAgICAgICAgPGxpPjxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCI+U2V0dGluZ3M8L2E+PC9saT5cXG4gICAgICAgICAgICAgIDxsaT48YSBocmVmPVxcXCJqYXZhc2NyaXB0OnZvaWQoMClcXFwiIFtyb3V0ZXJMaW5rXT1cXFwiWycvQWJvdXQnXVxcXCI+QWJvdXQ8L2E+PC9saT5cXG4gICAgICAgICAgICA8L3VsPlxcbiAgICAgICAgICA8L2xpPlxcbiAgICAgICAgPC91bD5cXG4gICAgICAgIDxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCIgY2xhc3M9XFxcIm5hdmJhci1icmFuZFxcXCIgW3JvdXRlckxpbmtdPVxcXCJbJy9ub3RlcyddXFxcIj5QcmVzZXJ2ZXIgPC9hPlxcbiAgICAgICAgPHNwYW4gY2xhc3M9XFxcIm5hdmJhci1icmFuZFxcXCI+PGkgY2xhc3M9XFxcImZhIGZhLWFuZ2xlLXJpZ2h0XFxcIiBhcmlhLWhpZGRlbj1cXFwidHJ1ZVxcXCI+PC9pPiZuYnNwOyZuYnNwO0FyY2hpdmU8L3NwYW4+XFxuICAgICAgPC9kaXY+XFxuICAgICAgPGRpdiBpZD1cXFwibmF2YmFyXFxcIiBjbGFzcz1cXFwiY29sbGFwc2UgbmF2YmFyLWNvbGxhcHNlXFxcIj5cXG4gICAgICAgIDx1bCBjbGFzcz1cXFwibmF2IG5hdmJhci1uYXYgbmF2YmFyLXJpZ2h0XFxcIj5cXG4gICAgICAgICAgPGxpPlxcbiAgICAgICAgICAgIDxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCIgKGNsaWNrKT1cXFwiZGlzcGxheVR5cGVDaGFuZ2UoKVxcXCI+XFxuICAgICAgICAgICAgICA8aSBjbGFzcz1cXFwie3tkaXNwbGF5TGlzdCA/ICdmYSBmYS1iYXJzJyA6ICdmYSBmYS10aCd9fVxcXCI+PC9pPlxcbiAgICAgICAgICAgIDwvYT5cXG4gICAgICAgICAgPC9saT5cXG4gICAgICAgICAgPGxpIGNsYXNzPVxcXCJkcm9wZG93blxcXCI+XFxuICAgICAgICAgICAgPGEgaHJlZj1cXFwiamF2YXNjcmlwdDp2b2lkKDApXFxcIiBkYXRhLXRhcmdldD1cXFwiI1xcXCIgY2xhc3M9XFxcImRyb3Bkb3duLXRvZ2dsZVxcXCIgZGF0YS10b2dnbGU9XFxcImRyb3Bkb3duXFxcIj5cXG4gICAgICAgICAgICAgIDxpIGNsYXNzPVxcXCJnbHlwaGljb24gZ2x5cGhpY29uLW9wdGlvbi12ZXJ0aWNhbFxcXCI+PC9pPlxcbiAgICAgICAgICAgIDwvYT5cXG4gICAgICAgICAgICA8dWwgY2xhc3M9XFxcImRyb3Bkb3duLW1lbnVcXFwiPlxcbiAgICAgICAgICAgICAgPGxpIGNsYXNzPVxcXCJkcm9wZG93bi1oZWFkZXJcXFwiPlByZWZlcmVuY2VzPC9saT5cXG4gICAgICAgICAgICAgIDxsaT48YSBocmVmPVxcXCJqYXZhc2NyaXB0OnZvaWQoMClcXFwiIFtyb3V0ZXJMaW5rXT1cXFwiWycvbm90ZXMnXVxcXCI+TXkgTm90ZXM8L2E+PC9saT5cXG4gICAgICAgICAgICAgIDxsaT48YSBocmVmPVxcXCJqYXZhc2NyaXB0OnZvaWQoMClcXFwiIFtyb3V0ZXJMaW5rXT1cXFwiWycvYXJjaGl2ZS1ub3RlcyddXFxcIj5BcmNoaXZlIE5vdGVzPC9hPjwvbGk+XFxuICAgICAgICAgICAgICA8bGk+PGEgaHJlZj1cXFwiamF2YXNjcmlwdDp2b2lkKDApXFxcIiBbcm91dGVyTGlua109XFxcIlsnL3JlY3ljbGUtYmluJ11cXFwiPlJlY3ljbGUgQmluPC9hPjwvbGk+ICAgICAgICAgICAgICBcXG4gICAgICAgICAgICAgIDxsaSBjbGFzcz1cXFwiZGl2aWRlclxcXCI+PC9saT5cXG4gICAgICAgICAgICAgIDxsaT48YSBocmVmPVxcXCJqYXZhc2NyaXB0OnZvaWQoMClcXFwiPlNldHRpbmdzPC9hPjwvbGk+XFxuICAgICAgICAgICAgICA8bGk+PGEgaHJlZj1cXFwiamF2YXNjcmlwdDp2b2lkKDApXFxcIiBbcm91dGVyTGlua109XFxcIlsnL0Fib3V0J11cXFwiPkFib3V0PC9hPjwvbGk+XFxuICAgICAgICAgICAgPC91bD5cXG4gICAgICAgICAgPC9saT5cXG4gICAgICAgIDwvdWw+XFxuICAgICAgPC9kaXY+XFxuICAgIDwvZGl2PlxcbiAgPC9kaXY+XFxuICA8c3Bpbm5lciAqbmdJZj1cXFwic3Bpbm5lclxcXCI+PC9zcGlubmVyPlxcbiAgPGRpdiBjbGFzcz1cXFwie3sgZGlzcGxheUxpc3QgPyAnY29udGFpbmVyIG5vdGUgYW5pbWF0ZScgOiAnY29udGFpbmVyIG5vdGUgZ3JpZC1jb250YWluZXIgYW5pbWF0ZSd9fVxcXCIgW2RyYWd1bGFdPSdcXFwiYW5vdGhlci1iYWdcXFwiJyBbZHJhZ3VsYU1vZGVsXT0nbm90ZXMnPlxcbiAgICA8ZGl2ICpuZ0Zvcj0nbGV0IHRleHQgb2Ygbm90ZXMnIGNsYXNzPVxcXCJ7eyBkaXNwbGF5TGlzdCA/ICdwYW5lbCBwYW5lbC1kZWZhdWx0ICcgKyB0ZXh0LmRvYy5jb2xvciA6ICdwYW5lbCBwYW5lbC1kZWZhdWx0IGdyaWQtaXRlbSAnICsgdGV4dC5kb2MuY29sb3J9fVxcXCIgI25vdGVSb3cgW2F0dHIuaWRdPVxcXCJ0ZXh0LmRvYy5faWRcXFwiPlxcbiAgICAgIDxkaXYgZGF0YS10b2dnbGU9XFxcIm1vZGFsXFxcIiBbYXR0ci5kYXRhLXRhcmdldF09XFxcIicjbm90ZScgKyB0ZXh0LmRvYy5faWRcXFwiIChjbGljayk9XFxcImVkaXRNb2RhbE5vdGVDbGljayh0ZXh0KVxcXCI+XFxuICAgICAgICA8ZGl2IGNsYXNzPVxcXCJwYW5lbC1ib2R5IG15LW5vdGUgbW9kdWxlIGxpbmUtY2xhbXBcXFwiPlxcbiAgICAgICAgICA8cD48c3Ryb25nPnt7dGV4dC5kb2MudGl0bGV9fTwvc3Ryb25nPjwvcD5cXG4gICAgICAgICAgPHA+IHt7dGV4dC5kb2Mubm90ZX19IDwvcD5cXG4gICAgICAgIDwvZGl2PlxcbiAgICAgIDwvZGl2PlxcbiAgICAgIDxkaXYgY2xhc3M9XFxcInt7ICdwYW5lbC1mb290ZXIgJyArIHRleHQuZG9jLmNvbG9yfX1cXFwiPlxcbiAgICAgICAgPHVsIGNsYXNzPVxcXCJub3RlLWZvb3RlclxcXCI+XFxuICAgICAgICAgIDxsaT48YSBocmVmPVxcXCJqYXZhc2NyaXB0OnZvaWQoMClcXFwiIGNsYXNzPVxcXCJidG4gYnRuLWxpbmsgYnRuLXJhaXNlZFxcXCJcXG4gICAgICAgICAgICAgdGl0bGU9XFxcIlVuYXJjaGl2ZVxcXCIgKGNsaWNrKT1cXFwidW5BcmNoaXZlKHRleHQsIG5vdGVSb3cpXFxcIj5cXG4gICAgICAgICAgICA8aSBjbGFzcz1cXFwiZmEgZmEtdXBsb2FkXFxcIj48L2k+ICAgICAgICBcXG4gICAgICAgICAgPC9hPjwvbGk+XFxuICAgICAgICAgIDxsaSBjbGFzcz1cXFwiZHJvcHVwXFxcIj5cXG4gICAgICAgICAgICA8YSBkYXRhLXRhcmdldD1cXFwiI1xcXCIgY2xhc3M9XFxcImJ0biBidG4tbGluayBidG4tcmFpc2VkIGRyb3B1cFxcXCJcXG4gICAgICAgICAgICAgIHRpdGxlPVxcXCJDb2xvclxcXCIgZGF0YS10b2dnbGU9XFxcImRyb3Bkb3duXFxcIj5cXG4gICAgICAgICAgICAgIDxpIGNsYXNzPVxcXCJmYSBmYS10aC1sYXJnZVxcXCI+PC9pPlxcbiAgICAgICAgICAgIDwvYT5cXG4gICAgICAgICAgICA8dWwgY2xhc3M9XFxcImRyb3Bkb3duLW1lbnVcXFwiPlxcbiAgICAgICAgICAgICAgPGxpPjxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCIgKGNsaWNrKT1cXFwic2V0Tm90ZUNvbG9yKCdsYWJlbC1kZWZhdWx0JywgdGV4dClcXFwiIGNsYXNzPVxcXCJidG4gYnRuLWRlZmF1bHQgYnRuLWZhYi1taW5pXFxcIj48aSBjbGFzcz1cXFwiXFxcIj48L2k+PC9hPjwvbGk+XFxuICAgICAgICAgICAgICA8bGk+PGEgaHJlZj1cXFwiamF2YXNjcmlwdDp2b2lkKDApXFxcIiAoY2xpY2spPVxcXCJzZXROb3RlQ29sb3IoJ2xhYmVsLXByaW1hcnknLCB0ZXh0KVxcXCIgY2xhc3M9XFxcImJ0biBidG4tcHJpbWFyeSBidG4tZmFiLW1pbmlcXFwiPjxpIGNsYXNzPVxcXCJcXFwiPjwvaT48L2E+PC9saT5cXG4gICAgICAgICAgICAgIDxsaT48YSBocmVmPVxcXCJqYXZhc2NyaXB0OnZvaWQoMClcXFwiIChjbGljayk9XFxcInNldE5vdGVDb2xvcignbGFiZWwtc3VjY2VzcycsIHRleHQpXFxcIiBjbGFzcz1cXFwiYnRuIGJ0bi1zdWNjZXNzIGJ0bi1mYWItbWluaVxcXCI+PGkgY2xhc3M9XFxcIlxcXCI+PC9pPjwvYT48L2xpPlxcbiAgICAgICAgICAgICAgPGxpPjxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCIgKGNsaWNrKT1cXFwic2V0Tm90ZUNvbG9yKCdsYWJlbC1pbmZvJywgdGV4dClcXFwiIGNsYXNzPVxcXCJidG4gYnRuLWluZm8gYnRuLWZhYi1taW5pXFxcIj48aSBjbGFzcz1cXFwiXFxcIj48L2k+PC9hPjwvbGk+XFxuICAgICAgICAgICAgICA8bGk+PGEgaHJlZj1cXFwiamF2YXNjcmlwdDp2b2lkKDApXFxcIiAoY2xpY2spPVxcXCJzZXROb3RlQ29sb3IoJ2xhYmVsLXdhcm5pbmcnLCB0ZXh0KVxcXCIgY2xhc3M9XFxcImJ0biBidG4td2FybmluZyBidG4tZmFiLW1pbmlcXFwiPjxpIGNsYXNzPVxcXCJcXFwiPjwvaT48L2E+PC9saT5cXG4gICAgICAgICAgICAgIDxsaT48YSBocmVmPVxcXCJqYXZhc2NyaXB0OnZvaWQoMClcXFwiIChjbGljayk9XFxcInNldE5vdGVDb2xvcignbGFiZWwtZGFuZ2VyJywgdGV4dClcXFwiIGNsYXNzPVxcXCJidG4gYnRuLWRhbmdlciBidG4tZmFiLW1pbmlcXFwiPjxpIGNsYXNzPVxcXCJcXFwiPjwvaT48L2E+PC9saT5cXG4gICAgICAgICAgICAgIDxsaT48YSBocmVmPVxcXCJqYXZhc2NyaXB0OnZvaWQoMClcXFwiIChjbGljayk9XFxcInNldE5vdGVDb2xvcignbGFiZWwtZGFya2dyYXknLCB0ZXh0KVxcXCIgY2xhc3M9XFxcImJ0biBidG4tZGFya2dyYXkgYnRuLWZhYi1taW5pXFxcIj48aSBjbGFzcz1cXFwiXFxcIj48L2k+PC9hPjwvbGk+XFxuICAgICAgICAgICAgICA8bGk+PGEgaHJlZj1cXFwiamF2YXNjcmlwdDp2b2lkKDApXFxcIiAoY2xpY2spPVxcXCJzZXROb3RlQ29sb3IoJ2xhYmVsLXByaW1hcnktb2xkJywgdGV4dClcXFwiIGNsYXNzPVxcXCJidG4gYnRuLXByaW1hcnktb2xkIGJ0bi1mYWItbWluaVxcXCI+PGkgY2xhc3M9XFxcIlxcXCI+PC9pPjwvYT48L2xpPiAgICAgICAgICAgICAgXFxuICAgICAgICAgICAgPC91bD5cXG4gICAgICAgICAgPC9saT5cXG4gICAgICAgICAgPGxpPjxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCIgY2xhc3M9XFxcImJ0biBidG4tbGluayBidG4tcmFpc2VkXFxcIlxcbiAgICAgICAgICAgICB0aXRsZT1cXFwiRGVsZXRlXFxcIiAoY2xpY2spPVxcXCJkZWxldGVOb3RlKHRleHQsIG5vdGVSb3cpXFxcIj5cXG4gICAgICAgICAgICA8aSBjbGFzcz1cXFwiZmEgZmEtdHJhc2hcXFwiPjwvaT4gICAgICAgICAgXFxuICAgICAgICAgIDwvYT48L2xpPlxcbiAgICAgICAgPC91bD5cXG4gICAgICA8L2Rpdj5cXG4gICAgICA8ZGl2IGNsYXNzPVxcXCJtb2RhbCBmYWRlXFxcIiBpZD1cXFwie3snbm90ZScgKyB0ZXh0LmRvYy5faWR9fVxcXCIgdGFiaW5kZXg9XFxcIi0xXFxcIiByb2xlPVxcXCJkaWFsb2dcXFwiIGFyaWEtaGlkZGVuPVxcXCJ0cnVlXFxcIj5cXG4gICAgICAgIDxkaXYgY2xhc3M9XFxcIm1vZGFsLWRpYWxvZ1xcXCI+XFxuICAgICAgICAgIDxkaXYgY2xhc3M9XFxcInt7J21vZGFsLWNvbnRlbnQgZWRpdC1zYXZlZCAnICsgdGV4dC5kb2MuY29sb3J9fVxcXCI+XFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwibW9kYWwtaGVhZGVyXFxcIj5cXG4gICAgICAgICAgICAgIDxoNCBjbGFzcz1cXFwibW9kYWwtdGl0bGVcXFwiPlxcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJmb3JtLWdyb3VwIGxhYmVsLWZsb2F0aW5nXFxcIj5cXG4gICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XFxcInRleHRcXFwiIGNsYXNzPVxcXCJmb3JtLWNvbnRyb2wgZWRpdC1zYXZlZC1pbnB1dFxcXCIgcGxhY2Vob2xkZXI9XFxcIlRpdGxlXFxcIiBbKG5nTW9kZWwpXT1cXFwiZWRpdE5vdGVEcmFmdC50aXRsZVxcXCIgW3ZhbHVlXT1cXFwidGV4dC5kb2MudGl0bGUgPyB0ZXh0LmRvYy50aXRsZSA6ICcnXFxcIiA+XFxuICAgICAgICAgICAgICAgIDwvZGl2PiAgICAgICAgICAgICAgICBcXG4gICAgICAgICAgICAgIDwvaDQ+XFxuICAgICAgICAgICAgPC9kaXY+XFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwibW9kYWwtYm9keVxcXCI+XFxuICAgICAgICAgICAgICA8dGV4dGFyZWEgY2xhc3M9XFxcImZvcm0tY29udHJvbCBlZGl0LXNhdmVkLXRleHRlcmFcXFwiICNlZGl0U2F2ZWRUZXh0YXJlYSBtb2RhbGVkaXRvcmF1dG9zaXplIHBsYWNlaG9sZGVyPVxcXCJXcml0ZSBhIG5vdGVcXFwiIFsobmdNb2RlbCldPVxcXCJlZGl0Tm90ZURyYWZ0Lm5vdGVcXFwiIFt2YWx1ZV09XFxcInRleHQuZG9jPy5ub3RlXFxcIj48L3RleHRhcmVhPiAgICAgICAgICAgICAgXFxuICAgICAgICAgICAgPC9kaXY+XFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwibW9kYWwtZm9vdGVyXFxcIj5cXG4gICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cXFwiYnV0dG9uXFxcIiBjbGFzcz1cXFwiYnRuIGJ0bi1wcmltYXJ5IGJ0bi1zbVxcXCIgZGF0YS1kaXNtaXNzPVxcXCJtb2RhbFxcXCIgKGNsaWNrKT1cXFwidXBkYXRlTW9kYWxOb3RlKHRleHQpXFxcIj5Eb25lPC9idXR0b24+XFxuICAgICAgICAgICAgPC9kaXY+XFxuICAgICAgICAgIDwvZGl2PlxcbiAgICAgICAgPC9kaXY+XFxuICAgICAgPC9kaXY+XFxuICAgIDwvZGl2PlxcbiAgPC9kaXY+XFxuICA8c2ltcGxlLW5vdGlmaWNhdGlvbnMgW29wdGlvbnNdPVxcXCJub3RpZmljYXRpb25PcHRpb25zXFxcIj48L3NpbXBsZS1ub3RpZmljYXRpb25zPlxcbiAgPGRpdiBjbGFzcz1cXFwiY29udGFpbmVyIGVtcHR5LW5vdGVzLWNvbnRhaW5lclxcXCIgKm5nSWY9XFxcImVtcHR5SHRtbE1zZ1xcXCI+XFxuICAgIDxkaXYgY2xhc3M9XFxcImVtcHR5LW5vdGVzLWljb24gZW1wdHktYXJjaGl2ZVxcXCI+PC9kaXY+XFxuICAgIDxkaXYgY2xhc3M9XFxcImVtcHR5LW5vdGVzXFxcIj5Zb3VyIGFyY2hpdmVkIG5vdGVzIGFwcGVhciBoZXJlPC9kaXY+XFxuICA8L2Rpdj5cXG48L2Rpdj5cIjtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL3NyYy9hcHAvY29tcG9uZW50cy9hcmNoaXZlLW5vdGVzL2FyY2hpdmUuY29tcG9uZW50Lmh0bWxcbi8vIG1vZHVsZSBpZCA9IDEwNVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiXSwibWFwcGluZ3MiOiJBQUFBIiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 106 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar core_1 = __webpack_require__(4);\nvar angular2_notifications_1 = __webpack_require__(63);\nvar _ = __webpack_require__(74);\nvar notes_table_service_1 = __webpack_require__(88);\nvar bin_table_service_1 = __webpack_require__(101);\nvar archive_table_service_1 = __webpack_require__(102);\nvar BinComponent = (function () {\n function BinComponent(_notesService, _archiveNotesService, _binNotesService, _notificationsService) {\n this._notesService = _notesService;\n this._archiveNotesService = _archiveNotesService;\n this._binNotesService = _binNotesService;\n this._notificationsService = _notificationsService;\n this.spinner = true;\n this.displayList = false;\n this.notes_table = NOTES_TABLE;\n this.emptyHtmlMsg = false;\n this.notes = [];\n this.toDeleteNote = {};\n this.notificationOptions = {\n timeOut: 3000,\n lastOnBottom: true,\n clickToClose: true,\n showProgressBar: false,\n pauseOnHover: true,\n preventDuplicates: false,\n theClass: \"notes-notifications\",\n rtl: true\n };\n this.displayList = localStorage.getItem(\"displayBinTypeList\") == 'true' ? true : false;\n }\n BinComponent.prototype.ngOnInit = function () {\n var _this = this;\n this.subscription = this._binNotesService.bin_notes_tables$.subscribe(function (notes_table) { return _this.notes_table = notes_table; });\n this.refreshNotesTables();\n };\n BinComponent.prototype.refreshNotesTables = function () {\n var _this = this;\n this._binNotesService.getNotes().then(function (alldoc) {\n _this.notes_table = alldoc.rows;\n _this.notes = _this.notes_table;\n if (_.isEmpty(_this.notes)) {\n _this.emptyHtmlMsg = true;\n }\n else {\n _this.emptyHtmlMsg = false;\n }\n _this.spinner = false;\n }, function (err) {\n _this.spinner = false;\n });\n };\n BinComponent.prototype.deleteNote = function () {\n var _this = this;\n if (this.toDeleteNote) {\n this.toDeleteNoteRow.className += this.displayList ? \" animated bounceOutRight\" : \" animated zoomOut\";\n setTimeout(function () {\n _this._binNotesService.deleteNote(_this.toDeleteNote.doc)\n .then(function (res) {\n _this.refreshNotesTables();\n _this.toDeleteNote = {};\n }, function (err) {\n console.log(\"Error\", err);\n });\n }, 200);\n }\n };\n BinComponent.prototype.setDeleteNote = function (note, noteRow) {\n this.toDeleteNote = note;\n this.toDeleteNoteRow = noteRow;\n };\n BinComponent.prototype.restoreNote = function (note, noteRow) {\n var _this = this;\n noteRow.className += this.displayList ? \" animated bounceOutLeft\" : \" animated flipOutY\";\n setTimeout(function () {\n _this._binNotesService.deleteNote(note.doc)\n .then(function (res) {\n _this._notificationsService.create(\"Done\", \"Note restored\", \"success\");\n _this.refreshNotesTables();\n }, function (err) {\n console.log(\"Error\", err);\n });\n var restore_note = note;\n delete restore_note.doc._rev;\n if (restore_note.doc.restore === \"archive\") {\n _this._archiveNotesService.saveNote(restore_note.doc)\n .then(function (res) {\n _this.updateArchiveNotesOrder(restore_note.doc);\n }, function (err) { });\n }\n else if (restore_note.doc.restore === \"note\") {\n _this._notesService.saveNote(restore_note.doc)\n .then(function (res) {\n _this.updateNotesOrder(restore_note.doc);\n }, function (err) { });\n }\n }, 300);\n };\n BinComponent.prototype.displayTypeChange = function () {\n this.displayList = this.displayList ? false : true;\n localStorage.setItem(\"displayBinTypeList\", String(this.displayList));\n };\n BinComponent.prototype.updateArchiveNotesOrder = function (note) {\n var newOrder = [];\n if (localStorage.getItem('archiveOrder')) {\n newOrder = JSON.parse(localStorage.getItem('archiveOrder'));\n newOrder.unshift(note._id);\n }\n else {\n newOrder.push(note._id);\n }\n localStorage.setItem(\"archiveOrder\", JSON.stringify(newOrder));\n };\n BinComponent.prototype.updateNotesOrder = function (draft) {\n var newOrder = [];\n if (localStorage.getItem('order')) {\n newOrder = JSON.parse(localStorage.getItem('order'));\n newOrder.unshift(draft._id);\n }\n else {\n newOrder.push(draft._id);\n }\n localStorage.setItem(\"order\", JSON.stringify(newOrder));\n };\n BinComponent = __decorate([\n core_1.Component({\n selector: 'bin',\n template: __webpack_require__(107),\n }), \n __metadata('design:paramtypes', [(typeof (_a = typeof notes_table_service_1.NotesTableService !== 'undefined' && notes_table_service_1.NotesTableService) === 'function' && _a) || Object, (typeof (_b = typeof archive_table_service_1.ArchiveNotesTableService !== 'undefined' && archive_table_service_1.ArchiveNotesTableService) === 'function' && _b) || Object, (typeof (_c = typeof bin_table_service_1.BinNotesTableService !== 'undefined' && bin_table_service_1.BinNotesTableService) === 'function' && _c) || Object, (typeof (_d = typeof angular2_notifications_1.NotificationsService !== 'undefined' && angular2_notifications_1.NotificationsService) === 'function' && _d) || Object])\n ], BinComponent);\n return BinComponent;\n var _a, _b, _c, _d;\n}());\nexports.BinComponent = BinComponent;\nvar NOTES_TABLE = [];\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTA2LmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vc3JjL2FwcC9jb21wb25lbnRzL2Jpbi9iaW4uY29tcG9uZW50LnRzP2IwNTMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE5vdGlmaWNhdGlvbnNTZXJ2aWNlIH0gZnJvbSBcImFuZ3VsYXIyLW5vdGlmaWNhdGlvbnNcIjtcblxuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcy9TdWJzY3JpcHRpb24nO1xuaW1wb3J0ICogYXMgXyBmcm9tICdsb2Rhc2gnO1xuXG5pbXBvcnQgeyBEcmFndWxhU2VydmljZSB9IGZyb20gJy4uLy4uL3Byb3ZpZGVycy9kcmFndWxhJztcblxuaW1wb3J0IHsgTm90ZXNUYWJsZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL25vdGVzX3RhYmxlJztcbmltcG9ydCB7IE5vdGVzVGFibGVTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvbm90ZXNfdGFibGUuc2VydmljZSc7XG5pbXBvcnQgeyBCaW5Ob3Rlc1RhYmxlU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2Jpbl90YWJsZS5zZXJ2aWNlJztcbmltcG9ydCB7IEFyY2hpdmVOb3Rlc1RhYmxlU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2FyY2hpdmVfdGFibGUuc2VydmljZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2JpbicsXG4gIHRlbXBsYXRlOiByZXF1aXJlKCcuL2Jpbi5jb21wb25lbnQuaHRtbCcpLFxufSlcbmV4cG9ydCBjbGFzcyBCaW5Db21wb25lbnQge1xuICBwdWJsaWMgbm90ZXM6IGFueTtcbiAgcHVibGljIG9yZGVyTm90ZXM6IGFueTtcbiAgcHVibGljIGVkaXROb3RlRHJhZnQ6IGFueTtcbiAgcHVibGljIG5vdGlmaWNhdGlvbk9wdGlvbnM6IGFueTsgXG4gIHB1YmxpYyBzcGlubmVyOiBib29sZWFuID0gdHJ1ZTtcbiAgcHVibGljIGRpc3BsYXlMaXN0OiBib29sZWFuID0gZmFsc2U7IFxuICBwdWJsaWMgdG9EZWxldGVOb3RlOiBhbnk7XG4gIHB1YmxpYyB0b0RlbGV0ZU5vdGVSb3c6IGFueTtcblxuICBwdWJsaWMgbm90ZXNfdGFibGUgPSBOT1RFU19UQUJMRTtcbiAgcHVibGljIHN1YnNjcmlwdGlvbjpTdWJzY3JpcHRpb247XG4gIHB1YmxpYyBvcmRlcjphbnk7XG4gIHB1YmxpYyBlbXB0eUh0bWxNc2c6IGJvb2xlYW4gPSBmYWxzZTtcbiAgY29uc3RydWN0b3IoXG4gICAgICBwcml2YXRlIF9ub3Rlc1NlcnZpY2U6IE5vdGVzVGFibGVTZXJ2aWNlLFxuICAgICAgcHJpdmF0ZSBfYXJjaGl2ZU5vdGVzU2VydmljZTogQXJjaGl2ZU5vdGVzVGFibGVTZXJ2aWNlLFxuICAgICAgcHJpdmF0ZSBfYmluTm90ZXNTZXJ2aWNlOiBCaW5Ob3Rlc1RhYmxlU2VydmljZSxcbiAgICAgIHByaXZhdGUgX25vdGlmaWNhdGlvbnNTZXJ2aWNlOiBOb3RpZmljYXRpb25zU2VydmljZVxuICAgICkge1xuICAgIHRoaXMubm90ZXMgPSBbXTtcbiAgICB0aGlzLnRvRGVsZXRlTm90ZSA9IHt9O1xuICAgIHRoaXMubm90aWZpY2F0aW9uT3B0aW9ucyA9IHtcbiAgICAgIHRpbWVPdXQ6IDMwMDAsXG4gICAgICBsYXN0T25Cb3R0b206IHRydWUsXG4gICAgICBjbGlja1RvQ2xvc2U6IHRydWUsXG4gICAgICBzaG93UHJvZ3Jlc3NCYXI6IGZhbHNlLFxuICAgICAgcGF1c2VPbkhvdmVyOiB0cnVlLFxuICAgICAgcHJldmVudER1cGxpY2F0ZXM6IGZhbHNlLFxuICAgICAgdGhlQ2xhc3M6IFwibm90ZXMtbm90aWZpY2F0aW9uc1wiLFxuICAgICAgcnRsOiB0cnVlXG4gICAgfTtcbiAgICB0aGlzLmRpc3BsYXlMaXN0ID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oXCJkaXNwbGF5QmluVHlwZUxpc3RcIikgPT0gJ3RydWUnID8gdHJ1ZSA6IGZhbHNlO1xuICB9XG4gIFxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbiA9IHRoaXMuX2Jpbk5vdGVzU2VydmljZS5iaW5fbm90ZXNfdGFibGVzJC5zdWJzY3JpYmUoXG4gICAgICBub3Rlc190YWJsZSA9PiB0aGlzLm5vdGVzX3RhYmxlID0gbm90ZXNfdGFibGVcbiAgICApO1xuICAgIHRoaXMucmVmcmVzaE5vdGVzVGFibGVzKCk7XG4gIH1cblxuICByZWZyZXNoTm90ZXNUYWJsZXMoKSB7XG4gICAgdGhpcy5fYmluTm90ZXNTZXJ2aWNlLmdldE5vdGVzKCkudGhlbihcbiAgICAgIGFsbGRvYyA9PiB7XG4gICAgICAgIHRoaXMubm90ZXNfdGFibGUgPSBhbGxkb2Mucm93cztcbiAgICAgICAgdGhpcy5ub3RlcyA9IHRoaXMubm90ZXNfdGFibGU7XG4gICAgICAgIGlmIChfLmlzRW1wdHkodGhpcy5ub3RlcykpIHtcbiAgICAgICAgICB0aGlzLmVtcHR5SHRtbE1zZyA9IHRydWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5lbXB0eUh0bWxNc2cgPSBmYWxzZTsgICAgICAgICAgXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zcGlubmVyID0gZmFsc2U7XG4gICAgICB9LFxuICAgICAgZXJyID0+IHtcbiAgICAgICAgdGhpcy5zcGlubmVyID0gZmFsc2U7ICAgICAgICBcbiAgICAgIH1cbiAgICApO1xuICB9XG4gICAgXG4gIGRlbGV0ZU5vdGUoKSB7XG4gICAgaWYgKHRoaXMudG9EZWxldGVOb3RlKSB7XG4gICAgICB0aGlzLnRvRGVsZXRlTm90ZVJvdy5jbGFzc05hbWUgKz0gdGhpcy5kaXNwbGF5TGlzdCA/IFwiIGFuaW1hdGVkIGJvdW5jZU91dFJpZ2h0XCIgOiBcIiBhbmltYXRlZCB6b29tT3V0XCI7XG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgdGhpcy5fYmluTm90ZXNTZXJ2aWNlLmRlbGV0ZU5vdGUodGhpcy50b0RlbGV0ZU5vdGUuZG9jKVxuICAgICAgICAgIC50aGVuKHJlcyA9PiB7XG4gICAgICAgICAgICB0aGlzLnJlZnJlc2hOb3Rlc1RhYmxlcygpO1xuICAgICAgICAgICAgdGhpcy50b0RlbGV0ZU5vdGUgPSB7fTtcbiAgICAgICAgICB9LCBlcnIgPT4ge1xuICAgICAgICAgICAgY29uc29sZS5sb2coXCJFcnJvclwiLCBlcnIpO1xuICAgICAgICAgIH0pO1xuICAgICAgfSwgMjAwKTtcbiAgICB9XG4gIH1cbiAgXG4gIHNldERlbGV0ZU5vdGUobm90ZSwgbm90ZVJvdykge1xuICAgIHRoaXMudG9EZWxldGVOb3RlID0gbm90ZTtcbiAgICB0aGlzLnRvRGVsZXRlTm90ZVJvdyA9IG5vdGVSb3c7XG4gIH1cbiAgXG4gIHJlc3RvcmVOb3RlKG5vdGUsIG5vdGVSb3cpIHtcbiAgICBub3RlUm93LmNsYXNzTmFtZSArPSB0aGlzLmRpc3BsYXlMaXN0ID8gXCIgYW5pbWF0ZWQgYm91bmNlT3V0TGVmdFwiIDogXCIgYW5pbWF0ZWQgZmxpcE91dFlcIjtcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMuX2Jpbk5vdGVzU2VydmljZS5kZWxldGVOb3RlKG5vdGUuZG9jKVxuICAgICAgICAudGhlbihyZXMgPT4geyAgICAgIFxuICAgICAgICAgIHRoaXMuX25vdGlmaWNhdGlvbnNTZXJ2aWNlLmNyZWF0ZShcIkRvbmVcIiwgXCJOb3RlIHJlc3RvcmVkXCIsIFwic3VjY2Vzc1wiKTtcbiAgICAgICAgICB0aGlzLnJlZnJlc2hOb3Rlc1RhYmxlcygpO1xuICAgICAgICB9LCBlcnIgPT4ge1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiRXJyb3JcIiwgZXJyKTtcbiAgICAgICAgfSk7XG4gICAgICBsZXQgcmVzdG9yZV9ub3RlID0gbm90ZTtcbiAgICAgIGRlbGV0ZSByZXN0b3JlX25vdGUuZG9jLl9yZXY7XG4gICAgICBpZiAocmVzdG9yZV9ub3RlLmRvYy5yZXN0b3JlID09PSBcImFyY2hpdmVcIiApIHtcbiAgICAgICAgdGhpcy5fYXJjaGl2ZU5vdGVzU2VydmljZS5zYXZlTm90ZShyZXN0b3JlX25vdGUuZG9jKVxuICAgICAgICAgIC50aGVuKHJlcyA9PiB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUFyY2hpdmVOb3Rlc09yZGVyKHJlc3RvcmVfbm90ZS5kb2MpO1xuICAgICAgICAgIH0sIGVyciA9PiB7fSk7XG4gICAgICB9IGVsc2UgaWYgKHJlc3RvcmVfbm90ZS5kb2MucmVzdG9yZSA9PT0gXCJub3RlXCIpIHtcbiAgICAgICAgdGhpcy5fbm90ZXNTZXJ2aWNlLnNhdmVOb3RlKHJlc3RvcmVfbm90ZS5kb2MpXG4gICAgICAgICAgLnRoZW4ocmVzID0+IHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlTm90ZXNPcmRlcihyZXN0b3JlX25vdGUuZG9jKTtcbiAgICAgICAgICB9LCBlcnIgPT4ge30pO1xuICAgICAgfVxuICAgIH0sIDMwMCk7XG4gIH1cbiAgXG4gIGRpc3BsYXlUeXBlQ2hhbmdlKCkge1xuICAgIHRoaXMuZGlzcGxheUxpc3QgPSB0aGlzLmRpc3BsYXlMaXN0ID8gZmFsc2UgOiB0cnVlO1xuICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKFwiZGlzcGxheUJpblR5cGVMaXN0XCIsIFN0cmluZyh0aGlzLmRpc3BsYXlMaXN0KSk7XG4gIH1cbiAgXG4gIHVwZGF0ZUFyY2hpdmVOb3Rlc09yZGVyKG5vdGUpIHtcbiAgICBsZXQgbmV3T3JkZXIgPSBbXTtcbiAgICBpZiAobG9jYWxTdG9yYWdlLmdldEl0ZW0oJ2FyY2hpdmVPcmRlcicpKSB7XG4gICAgICBuZXdPcmRlciA9IEpTT04ucGFyc2UobG9jYWxTdG9yYWdlLmdldEl0ZW0oJ2FyY2hpdmVPcmRlcicpKTtcbiAgICAgIG5ld09yZGVyLnVuc2hpZnQobm90ZS5faWQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdPcmRlci5wdXNoKG5vdGUuX2lkKTtcbiAgICB9XG4gICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oXCJhcmNoaXZlT3JkZXJcIiwgSlNPTi5zdHJpbmdpZnkobmV3T3JkZXIpKTtcbiAgfVxuICBcbiAgdXBkYXRlTm90ZXNPcmRlcihkcmFmdCkge1xuICAgIGxldCBuZXdPcmRlciA9IFtdO1xuICAgIGlmIChsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgnb3JkZXInKSkge1xuICAgICAgbmV3T3JkZXIgPSBKU09OLnBhcnNlKGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdvcmRlcicpKTtcbiAgICAgIG5ld09yZGVyLnVuc2hpZnQoZHJhZnQuX2lkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3T3JkZXIucHVzaChkcmFmdC5faWQpO1xuICAgIH1cbiAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShcIm9yZGVyXCIsIEpTT04uc3RyaW5naWZ5KG5ld09yZGVyKSk7XG4gIH1cbn1cblxubGV0IE5PVEVTX1RBQkxFOiBOb3Rlc1RhYmxlW10gPSBbXVxuXG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gbm9kZV9tb2R1bGVzL2FuZ3VsYXIyLXRlbXBsYXRlLWxvYWRlciEuL3NyYy9hcHAvY29tcG9uZW50cy9iaW4vYmluLmNvbXBvbmVudC50cyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQUFBO0FBQ0E7QUFHQTtBQUtBO0FBQ0E7QUFDQTtBQU1BO0FBY0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQWJBO0FBQ0E7QUFJQTtBQUdBO0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQUE7QUFDQTtBQUdBO0FBQ0E7QUFFQTtBQUFBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUVBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQXZJQTtBQUFBO0FBQ0E7QUFDQTtBQUNBOztBQUFBO0FBcUlBOztBQUFBO0FBcElBO0FBc0lBOyIsInNvdXJjZVJvb3QiOiIifQ==");
- /***/ },
- /* 107 */
- /***/ function(module, exports) {
- eval("module.exports = \"<div class=\\\"\\\">\\n <div class=\\\"navbar navbar-danger\\\">\\n <div class=\\\"container-fluid\\\">\\n <div class=\\\"navbar-header\\\">\\n <ul class=\\\"navbar-toggle\\\">\\n <li class=\\\"dropdown\\\">\\n <a href=\\\"#\\\" class=\\\"dropdown-toggle\\\" data-toggle=\\\"dropdown\\\" role=\\\"button\\\" aria-haspopup=\\\"true\\\" aria-expanded=\\\"false\\\"> <i class=\\\"glyphicon glyphicon-option-vertical\\\"></i></a>\\n <ul class=\\\"dropdown-menu\\\">\\n\\n <li class=\\\"dropdown-header\\\">Preferences</li>\\n <li><a [routerLink]=\\\"['/notes']\\\">My Notes</a></li>\\n <li><a [routerLink]=\\\"['/archive-notes']\\\">Archive Notes</a></li> \\n <li><a href=\\\"javascript:void(0)\\\" [routerLink]=\\\"['/recycle-bin']\\\">Recycle Bin</a></li> \\n <li role=\\\"separator\\\" class=\\\"divider\\\"></li>\\n <li>\\n <a href=\\\"javascript:void(0)\\\" (click)=\\\"displayTypeChange()\\\">\\n {{displayList ? 'Grid View' : 'List View'}}\\n </a>\\n </li>\\n <li><a href=\\\"javascript:void(0)\\\">Settings</a></li>\\n <li><a href=\\\"javascript:void(0)\\\" [routerLink]=\\\"['/about']\\\">About</a></li>\\n </ul>\\n </li>\\n </ul>\\n <a href=\\\"javascript:void(0)\\\" class=\\\"navbar-brand\\\" [routerLink]=\\\"['/notes']\\\">Preserver </a>\\n <span class=\\\"navbar-brand\\\"><i class=\\\"fa fa-angle-right\\\" aria-hidden=\\\"true\\\"></i> Recycle Bin</span>\\n </div>\\n <div id=\\\"navbar\\\" class=\\\"collapse navbar-collapse\\\">\\n <ul class=\\\"nav navbar-nav navbar-right\\\">\\n <li>\\n <a href=\\\"javascript:void(0)\\\" (click)=\\\"displayTypeChange()\\\">\\n <i class=\\\"{{displayList ? 'fa fa-bars' : 'fa fa-th'}}\\\"></i>\\n </a>\\n </li>\\n <li class=\\\"dropdown\\\">\\n <a href=\\\"javascript:void(0)\\\" data-target=\\\"#\\\" class=\\\"dropdown-toggle\\\" data-toggle=\\\"dropdown\\\">\\n <i class=\\\"glyphicon glyphicon-option-vertical\\\"></i>\\n </a>\\n <ul class=\\\"dropdown-menu\\\">\\n <li class=\\\"dropdown-header\\\">Preferences</li>\\n <li><a href=\\\"javascript:void(0)\\\" [routerLink]=\\\"['/notes']\\\">My Notes</a></li>\\n <li><a href=\\\"javascript:void(0)\\\" [routerLink]=\\\"['/archive-notes']\\\">Archive Notes</a></li>\\n <li><a href=\\\"javascript:void(0)\\\" [routerLink]=\\\"['/recycle-bin']\\\">Recycle Bin</a></li> \\n <li class=\\\"divider\\\"></li>\\n <li><a href=\\\"javascript:void(0)\\\">Settings</a></li>\\n <li><a href=\\\"javascript:void(0)\\\" [routerLink]=\\\"['/about']\\\">About</a></li>\\n </ul>\\n </li>\\n </ul>\\n </div>\\n </div>\\n </div>\\n <spinner *ngIf=\\\"spinner\\\"></spinner>\\n <div class=\\\"{{ displayList ? 'container note animate' : 'container note grid-container animate'}}\\\">\\n <div *ngFor='let text of notes' class=\\\"{{ displayList ? 'panel panel-default ' + text.doc.color : 'panel panel-default grid-item ' + text.doc.color}}\\\" #noteRow [attr.id]=\\\"text.doc._id\\\">\\n <div class=\\\"panel-body my-note module line-clamp\\\">\\n <p><strong>{{text.doc?.title}}</strong></p>\\n <p> {{text.doc?.note}} </p>\\n </div>\\n <div class=\\\"{{ 'panel-footer ' + text.doc.color}}\\\">\\n <ul class=\\\"note-footer\\\">\\n <li class=\\\"dropup\\\">\\n <a class=\\\"btn btn-link btn-raised\\\"\\n title=\\\"Delete forever\\\" data-target=\\\"#deleteNote\\\" data-toggle=\\\"modal\\\" (click)=\\\"setDeleteNote(text, noteRow)\\\">\\n <i class=\\\"fa fa-trash\\\"></i>\\n </a>\\n </li>\\n <li>\\n <a class=\\\"btn btn-link btn-raised\\\"\\n title=\\\"Restore\\\" (click)=\\\"restoreNote(text, noteRow)\\\">\\n <i class=\\\"fa fa-undo\\\"></i>\\n </a>\\n </li>\\n </ul>\\n </div>\\n <div class=\\\"modal fade\\\" id=\\\"{{'note' + text.doc._id}}\\\" tabindex=\\\"-1\\\" role=\\\"dialog\\\" aria-hidden=\\\"true\\\">\\n <div class=\\\"modal-dialog\\\">\\n <div class=\\\"{{'modal-content ' + text.doc.color}}\\\">\\n <div class=\\\"modal-header\\\">\\n <h4 class=\\\"modal-title\\\">\\n <p class=\\\"\\\"><strong>{{text.doc.title}}</strong></p>\\n </h4>\\n </div>\\n <div class=\\\"modal-body\\\">\\n <p class=\\\"edit-saved-textera\\\">{{text.doc.note}}</p>\\n </div>\\n </div>\\n </div>\\n </div>\\n </div>\\n </div>\\n <div class=\\\"modal fade\\\" id=\\\"deleteNote\\\">\\n <div class=\\\"modal-dialog\\\">\\n <div class=\\\"modal-content\\\">\\n <div class=\\\"modal-header\\\">\\n <button type=\\\"button\\\" class=\\\"close\\\" data-dismiss=\\\"modal\\\" aria-hidden=\\\"true\\\">×</button>\\n <h4 class=\\\"modal-title\\\">Delete note forever?</h4>\\n </div>\\n <div class=\\\"modal-body\\\">\\n <p></p>\\n </div>\\n <div class=\\\"modal-footer\\\">\\n <button type=\\\"button\\\" class=\\\"btn btn-default btn-sm\\\" data-dismiss=\\\"modal\\\">CANCEL</button>\\n <button type=\\\"button\\\" class=\\\"btn btn-primary btn-sm\\\" data-dismiss=\\\"modal\\\" (click)=\\\"deleteNote()\\\">DELETE</button>\\n </div>\\n </div>\\n </div>\\n </div>\\n <simple-notifications [options]=\\\"notificationOptions\\\"></simple-notifications>\\n <div class=\\\"container empty-notes-container\\\" *ngIf=\\\"emptyHtmlMsg\\\">\\n <div class=\\\"empty-notes-icon empty-bin\\\"></div>\\n <div class=\\\"empty-notes\\\">No notes in Recycle Bin</div>\\n </div>\\n</div>\";//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTA3LmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vc3JjL2FwcC9jb21wb25lbnRzL2Jpbi9iaW4uY29tcG9uZW50Lmh0bWw/YTZkMyJdLCJzb3VyY2VzQ29udGVudCI6WyJtb2R1bGUuZXhwb3J0cyA9IFwiPGRpdiBjbGFzcz1cXFwiXFxcIj5cXG4gIDxkaXYgY2xhc3M9XFxcIm5hdmJhciBuYXZiYXItZGFuZ2VyXFxcIj5cXG4gICAgPGRpdiBjbGFzcz1cXFwiY29udGFpbmVyLWZsdWlkXFxcIj5cXG4gICAgICA8ZGl2IGNsYXNzPVxcXCJuYXZiYXItaGVhZGVyXFxcIj5cXG4gICAgICAgIDx1bCBjbGFzcz1cXFwibmF2YmFyLXRvZ2dsZVxcXCI+XFxuICAgICAgICAgIDxsaSBjbGFzcz1cXFwiZHJvcGRvd25cXFwiPlxcbiAgICAgICAgICAgIDxhIGhyZWY9XFxcIiNcXFwiIGNsYXNzPVxcXCJkcm9wZG93bi10b2dnbGVcXFwiIGRhdGEtdG9nZ2xlPVxcXCJkcm9wZG93blxcXCIgcm9sZT1cXFwiYnV0dG9uXFxcIiBhcmlhLWhhc3BvcHVwPVxcXCJ0cnVlXFxcIiBhcmlhLWV4cGFuZGVkPVxcXCJmYWxzZVxcXCI+IDxpIGNsYXNzPVxcXCJnbHlwaGljb24gZ2x5cGhpY29uLW9wdGlvbi12ZXJ0aWNhbFxcXCI+PC9pPjwvYT5cXG4gICAgICAgICAgICA8dWwgY2xhc3M9XFxcImRyb3Bkb3duLW1lbnVcXFwiPlxcblxcbiAgICAgICAgICAgICAgPGxpIGNsYXNzPVxcXCJkcm9wZG93bi1oZWFkZXJcXFwiPlByZWZlcmVuY2VzPC9saT5cXG4gICAgICAgICAgICAgIDxsaT48YSBbcm91dGVyTGlua109XFxcIlsnL25vdGVzJ11cXFwiPk15IE5vdGVzPC9hPjwvbGk+XFxuICAgICAgICAgICAgICA8bGk+PGEgW3JvdXRlckxpbmtdPVxcXCJbJy9hcmNoaXZlLW5vdGVzJ11cXFwiPkFyY2hpdmUgTm90ZXM8L2E+PC9saT4gICBcXG4gICAgICAgICAgICAgIDxsaT48YSBocmVmPVxcXCJqYXZhc2NyaXB0OnZvaWQoMClcXFwiIFtyb3V0ZXJMaW5rXT1cXFwiWycvcmVjeWNsZS1iaW4nXVxcXCI+UmVjeWNsZSBCaW48L2E+PC9saT4gICAgICAgICAgICAgICAgICAgICAgIFxcbiAgICAgICAgICAgICAgPGxpIHJvbGU9XFxcInNlcGFyYXRvclxcXCIgY2xhc3M9XFxcImRpdmlkZXJcXFwiPjwvbGk+XFxuICAgICAgICAgICAgICA8bGk+XFxuICAgICAgICAgICAgICAgIDxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCIgKGNsaWNrKT1cXFwiZGlzcGxheVR5cGVDaGFuZ2UoKVxcXCI+XFxuICAgICAgICAgICAgICAgICAge3tkaXNwbGF5TGlzdCA/ICdHcmlkIFZpZXcnIDogJ0xpc3QgVmlldyd9fVxcbiAgICAgICAgICAgICAgICA8L2E+XFxuICAgICAgICAgICAgICA8L2xpPlxcbiAgICAgICAgICAgICAgPGxpPjxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCI+U2V0dGluZ3M8L2E+PC9saT5cXG4gICAgICAgICAgICAgIDxsaT48YSBocmVmPVxcXCJqYXZhc2NyaXB0OnZvaWQoMClcXFwiIFtyb3V0ZXJMaW5rXT1cXFwiWycvYWJvdXQnXVxcXCI+QWJvdXQ8L2E+PC9saT5cXG4gICAgICAgICAgICA8L3VsPlxcbiAgICAgICAgICA8L2xpPlxcbiAgICAgICAgPC91bD5cXG4gICAgICAgIDxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCIgY2xhc3M9XFxcIm5hdmJhci1icmFuZFxcXCIgW3JvdXRlckxpbmtdPVxcXCJbJy9ub3RlcyddXFxcIj5QcmVzZXJ2ZXIgPC9hPlxcbiAgICAgICAgPHNwYW4gY2xhc3M9XFxcIm5hdmJhci1icmFuZFxcXCI+PGkgY2xhc3M9XFxcImZhIGZhLWFuZ2xlLXJpZ2h0XFxcIiBhcmlhLWhpZGRlbj1cXFwidHJ1ZVxcXCI+PC9pPiZuYnNwOyZuYnNwO1JlY3ljbGUgQmluPC9zcGFuPlxcbiAgICAgIDwvZGl2PlxcbiAgICAgIDxkaXYgaWQ9XFxcIm5hdmJhclxcXCIgY2xhc3M9XFxcImNvbGxhcHNlIG5hdmJhci1jb2xsYXBzZVxcXCI+XFxuICAgICAgICA8dWwgY2xhc3M9XFxcIm5hdiBuYXZiYXItbmF2IG5hdmJhci1yaWdodFxcXCI+XFxuICAgICAgICAgIDxsaT5cXG4gICAgICAgICAgICA8YSBocmVmPVxcXCJqYXZhc2NyaXB0OnZvaWQoMClcXFwiIChjbGljayk9XFxcImRpc3BsYXlUeXBlQ2hhbmdlKClcXFwiPlxcbiAgICAgICAgICAgICAgPGkgY2xhc3M9XFxcInt7ZGlzcGxheUxpc3QgPyAnZmEgZmEtYmFycycgOiAnZmEgZmEtdGgnfX1cXFwiPjwvaT5cXG4gICAgICAgICAgICA8L2E+XFxuICAgICAgICAgIDwvbGk+XFxuICAgICAgICAgIDxsaSBjbGFzcz1cXFwiZHJvcGRvd25cXFwiPlxcbiAgICAgICAgICAgIDxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCIgZGF0YS10YXJnZXQ9XFxcIiNcXFwiIGNsYXNzPVxcXCJkcm9wZG93bi10b2dnbGVcXFwiIGRhdGEtdG9nZ2xlPVxcXCJkcm9wZG93blxcXCI+XFxuICAgICAgICAgICAgICA8aSBjbGFzcz1cXFwiZ2x5cGhpY29uIGdseXBoaWNvbi1vcHRpb24tdmVydGljYWxcXFwiPjwvaT5cXG4gICAgICAgICAgICA8L2E+XFxuICAgICAgICAgICAgPHVsIGNsYXNzPVxcXCJkcm9wZG93bi1tZW51XFxcIj5cXG4gICAgICAgICAgICAgIDxsaSBjbGFzcz1cXFwiZHJvcGRvd24taGVhZGVyXFxcIj5QcmVmZXJlbmNlczwvbGk+XFxuICAgICAgICAgICAgICA8bGk+PGEgaHJlZj1cXFwiamF2YXNjcmlwdDp2b2lkKDApXFxcIiBbcm91dGVyTGlua109XFxcIlsnL25vdGVzJ11cXFwiPk15IE5vdGVzPC9hPjwvbGk+XFxuICAgICAgICAgICAgICA8bGk+PGEgaHJlZj1cXFwiamF2YXNjcmlwdDp2b2lkKDApXFxcIiBbcm91dGVyTGlua109XFxcIlsnL2FyY2hpdmUtbm90ZXMnXVxcXCI+QXJjaGl2ZSBOb3RlczwvYT48L2xpPlxcbiAgICAgICAgICAgICAgPGxpPjxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCIgW3JvdXRlckxpbmtdPVxcXCJbJy9yZWN5Y2xlLWJpbiddXFxcIj5SZWN5Y2xlIEJpbjwvYT48L2xpPiAgICAgICAgICAgICAgXFxuICAgICAgICAgICAgICA8bGkgY2xhc3M9XFxcImRpdmlkZXJcXFwiPjwvbGk+XFxuICAgICAgICAgICAgICA8bGk+PGEgaHJlZj1cXFwiamF2YXNjcmlwdDp2b2lkKDApXFxcIj5TZXR0aW5nczwvYT48L2xpPlxcbiAgICAgICAgICAgICAgPGxpPjxhIGhyZWY9XFxcImphdmFzY3JpcHQ6dm9pZCgwKVxcXCIgW3JvdXRlckxpbmtdPVxcXCJbJy9hYm91dCddXFxcIj5BYm91dDwvYT48L2xpPlxcbiAgICAgICAgICAgIDwvdWw+XFxuICAgICAgICAgIDwvbGk+XFxuICAgICAgICA8L3VsPlxcbiAgICAgIDwvZGl2PlxcbiAgICA8L2Rpdj5cXG4gIDwvZGl2PlxcbiAgPHNwaW5uZXIgKm5nSWY9XFxcInNwaW5uZXJcXFwiPjwvc3Bpbm5lcj5cXG4gIDxkaXYgY2xhc3M9XFxcInt7IGRpc3BsYXlMaXN0ID8gJ2NvbnRhaW5lciBub3RlIGFuaW1hdGUnIDogJ2NvbnRhaW5lciBub3RlIGdyaWQtY29udGFpbmVyIGFuaW1hdGUnfX1cXFwiPlxcbiAgICA8ZGl2ICpuZ0Zvcj0nbGV0IHRleHQgb2Ygbm90ZXMnIGNsYXNzPVxcXCJ7eyBkaXNwbGF5TGlzdCA/ICdwYW5lbCBwYW5lbC1kZWZhdWx0ICcgKyB0ZXh0LmRvYy5jb2xvciA6ICdwYW5lbCBwYW5lbC1kZWZhdWx0IGdyaWQtaXRlbSAnICsgdGV4dC5kb2MuY29sb3J9fVxcXCIgI25vdGVSb3cgW2F0dHIuaWRdPVxcXCJ0ZXh0LmRvYy5faWRcXFwiPlxcbiAgICAgIDxkaXYgY2xhc3M9XFxcInBhbmVsLWJvZHkgbXktbm90ZSBtb2R1bGUgbGluZS1jbGFtcFxcXCI+XFxuICAgICAgICA8cD48c3Ryb25nPnt7dGV4dC5kb2M/LnRpdGxlfX08L3N0cm9uZz48L3A+XFxuICAgICAgICA8cD4ge3t0ZXh0LmRvYz8ubm90ZX19IDwvcD5cXG4gICAgICA8L2Rpdj5cXG4gICAgICA8ZGl2IGNsYXNzPVxcXCJ7eyAncGFuZWwtZm9vdGVyICcgKyB0ZXh0LmRvYy5jb2xvcn19XFxcIj5cXG4gICAgICAgIDx1bCBjbGFzcz1cXFwibm90ZS1mb290ZXJcXFwiPlxcbiAgICAgICAgICA8bGkgY2xhc3M9XFxcImRyb3B1cFxcXCI+XFxuICAgICAgICAgICAgPGEgY2xhc3M9XFxcImJ0biBidG4tbGluayBidG4tcmFpc2VkXFxcIlxcbiAgICAgICAgICAgICAgdGl0bGU9XFxcIkRlbGV0ZSBmb3JldmVyXFxcIiBkYXRhLXRhcmdldD1cXFwiI2RlbGV0ZU5vdGVcXFwiIGRhdGEtdG9nZ2xlPVxcXCJtb2RhbFxcXCIgKGNsaWNrKT1cXFwic2V0RGVsZXRlTm90ZSh0ZXh0LCBub3RlUm93KVxcXCI+XFxuICAgICAgICAgICAgICA8aSBjbGFzcz1cXFwiZmEgZmEtdHJhc2hcXFwiPjwvaT5cXG4gICAgICAgICAgICA8L2E+XFxuICAgICAgICAgIDwvbGk+XFxuICAgICAgICAgIDxsaT5cXG4gICAgICAgICAgICA8YSBjbGFzcz1cXFwiYnRuIGJ0bi1saW5rIGJ0bi1yYWlzZWRcXFwiXFxuICAgICAgICAgICAgICB0aXRsZT1cXFwiUmVzdG9yZVxcXCIgKGNsaWNrKT1cXFwicmVzdG9yZU5vdGUodGV4dCwgbm90ZVJvdylcXFwiPlxcbiAgICAgICAgICAgICAgPGkgY2xhc3M9XFxcImZhIGZhLXVuZG9cXFwiPjwvaT5cXG4gICAgICAgICAgICA8L2E+XFxuICAgICAgICAgIDwvbGk+XFxuICAgICAgICA8L3VsPlxcbiAgICAgIDwvZGl2PlxcbiAgICAgIDxkaXYgY2xhc3M9XFxcIm1vZGFsIGZhZGVcXFwiIGlkPVxcXCJ7eydub3RlJyArIHRleHQuZG9jLl9pZH19XFxcIiB0YWJpbmRleD1cXFwiLTFcXFwiIHJvbGU9XFxcImRpYWxvZ1xcXCIgYXJpYS1oaWRkZW49XFxcInRydWVcXFwiPlxcbiAgICAgICAgPGRpdiBjbGFzcz1cXFwibW9kYWwtZGlhbG9nXFxcIj5cXG4gICAgICAgICAgPGRpdiBjbGFzcz1cXFwie3snbW9kYWwtY29udGVudCAnICsgdGV4dC5kb2MuY29sb3J9fVxcXCI+XFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwibW9kYWwtaGVhZGVyXFxcIj5cXG4gICAgICAgICAgICAgIDxoNCBjbGFzcz1cXFwibW9kYWwtdGl0bGVcXFwiPlxcbiAgICAgICAgICAgICAgICA8cCBjbGFzcz1cXFwiXFxcIj48c3Ryb25nPnt7dGV4dC5kb2MudGl0bGV9fTwvc3Ryb25nPjwvcD5cXG4gICAgICAgICAgICAgIDwvaDQ+XFxuICAgICAgICAgICAgPC9kaXY+XFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwibW9kYWwtYm9keVxcXCI+XFxuICAgICAgICAgICAgICA8cCBjbGFzcz1cXFwiZWRpdC1zYXZlZC10ZXh0ZXJhXFxcIj57e3RleHQuZG9jLm5vdGV9fTwvcD5cXG4gICAgICAgICAgICA8L2Rpdj5cXG4gICAgICAgICAgPC9kaXY+XFxuICAgICAgICA8L2Rpdj5cXG4gICAgICA8L2Rpdj5cXG4gICAgPC9kaXY+XFxuICA8L2Rpdj5cXG4gIDxkaXYgY2xhc3M9XFxcIm1vZGFsIGZhZGVcXFwiIGlkPVxcXCJkZWxldGVOb3RlXFxcIj5cXG4gICAgPGRpdiBjbGFzcz1cXFwibW9kYWwtZGlhbG9nXFxcIj5cXG4gICAgICA8ZGl2IGNsYXNzPVxcXCJtb2RhbC1jb250ZW50XFxcIj5cXG4gICAgICAgIDxkaXYgY2xhc3M9XFxcIm1vZGFsLWhlYWRlclxcXCI+XFxuICAgICAgICAgIDxidXR0b24gdHlwZT1cXFwiYnV0dG9uXFxcIiBjbGFzcz1cXFwiY2xvc2VcXFwiIGRhdGEtZGlzbWlzcz1cXFwibW9kYWxcXFwiIGFyaWEtaGlkZGVuPVxcXCJ0cnVlXFxcIj7DlzwvYnV0dG9uPlxcbiAgICAgICAgICA8aDQgY2xhc3M9XFxcIm1vZGFsLXRpdGxlXFxcIj5EZWxldGUgbm90ZSBmb3JldmVyPzwvaDQ+XFxuICAgICAgICA8L2Rpdj5cXG4gICAgICAgIDxkaXYgY2xhc3M9XFxcIm1vZGFsLWJvZHlcXFwiPlxcbiAgICAgICAgICA8cD48L3A+XFxuICAgICAgICA8L2Rpdj5cXG4gICAgICAgIDxkaXYgY2xhc3M9XFxcIm1vZGFsLWZvb3RlclxcXCI+XFxuICAgICAgICAgIDxidXR0b24gdHlwZT1cXFwiYnV0dG9uXFxcIiBjbGFzcz1cXFwiYnRuIGJ0bi1kZWZhdWx0IGJ0bi1zbVxcXCIgZGF0YS1kaXNtaXNzPVxcXCJtb2RhbFxcXCI+Q0FOQ0VMPC9idXR0b24+XFxuICAgICAgICAgIDxidXR0b24gdHlwZT1cXFwiYnV0dG9uXFxcIiBjbGFzcz1cXFwiYnRuIGJ0bi1wcmltYXJ5IGJ0bi1zbVxcXCIgZGF0YS1kaXNtaXNzPVxcXCJtb2RhbFxcXCIgKGNsaWNrKT1cXFwiZGVsZXRlTm90ZSgpXFxcIj5ERUxFVEU8L2J1dHRvbj5cXG4gICAgICAgIDwvZGl2PlxcbiAgICAgIDwvZGl2PlxcbiAgICA8L2Rpdj5cXG4gIDwvZGl2PlxcbiAgPHNpbXBsZS1ub3RpZmljYXRpb25zIFtvcHRpb25zXT1cXFwibm90aWZpY2F0aW9uT3B0aW9uc1xcXCI+PC9zaW1wbGUtbm90aWZpY2F0aW9ucz5cXG4gIDxkaXYgY2xhc3M9XFxcImNvbnRhaW5lciBlbXB0eS1ub3Rlcy1jb250YWluZXJcXFwiICpuZ0lmPVxcXCJlbXB0eUh0bWxNc2dcXFwiPlxcbiAgICA8ZGl2IGNsYXNzPVxcXCJlbXB0eS1ub3Rlcy1pY29uIGVtcHR5LWJpblxcXCI+PC9kaXY+XFxuICAgIDxkaXYgY2xhc3M9XFxcImVtcHR5LW5vdGVzXFxcIj5ObyBub3RlcyBpbiBSZWN5Y2xlIEJpbjwvZGl2PlxcbiAgPC9kaXY+XFxuPC9kaXY+XCI7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9zcmMvYXBwL2NvbXBvbmVudHMvYmluL2Jpbi5jb21wb25lbnQuaHRtbFxuLy8gbW9kdWxlIGlkID0gMTA3XG4vLyBtb2R1bGUgY2h1bmtzID0gMCJdLCJtYXBwaW5ncyI6IkFBQUEiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ },
- /* 108 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar core_1 = __webpack_require__(4);\nvar AboutComponent = (function () {\n function AboutComponent() {\n }\n AboutComponent = __decorate([\n core_1.Component({\n selector: 'about',\n template: __webpack_require__(109),\n styles: [__webpack_require__(110)]\n }), \n __metadata('design:paramtypes', [])\n ], AboutComponent);\n return AboutComponent;\n}());\nexports.AboutComponent = AboutComponent;\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTA4LmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vc3JjL2FwcC9jb21wb25lbnRzL2Fib3V0L2Fib3V0LmNvbXBvbmVudC50cz9mYWY3Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYWJvdXQnLFxuICB0ZW1wbGF0ZTogcmVxdWlyZSgnLi9hYm91dC5jb21wb25lbnQuaHRtbCcpLFxuICBzdHlsZXM6IFsgcmVxdWlyZSgnLi9hYm91dC5jb21wb25lbnQuY3NzJykgXVxufSlcbmV4cG9ydCBjbGFzcyBBYm91dENvbXBvbmVudCB7IH1cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyBub2RlX21vZHVsZXMvYW5ndWxhcjItdGVtcGxhdGUtbG9hZGVyIS4vc3JjL2FwcC9jb21wb25lbnRzL2Fib3V0L2Fib3V0LmNvbXBvbmVudC50cyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQUFBO0FBTUE7QUFBQTtBQUFBO0FBTEE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUFBO0FBQ0E7QUFBQTtBQUFBOyIsInNvdXJjZVJvb3QiOiIifQ==");
- /***/ },
- /* 109 */
- /***/ function(module, exports) {
- eval("module.exports = \"<div class=\\\"about\\\">\\n\\n <div class=\\\"profile-card\\\">\\n\\n <div class=\\\"header\\\">\\n\\n <a href=\\\"#\\\" [routerLink]=\\\"['/notes']\\\">\\n <img src=\\\"/public/images/logo.png\\\" />\\n </a>\\n\\n <h1>Preserver</h1>\\n\\n <h2>Preserver is an notes organizer desktop app based on Electron. developed by Hitesh Balar</h2>\\n\\n </div>\\n\\n <div class=\\\"profile-bio\\\">\\n\\n <p>Organize your life with preserver application for keeping track of notes, tasks, and to-do lists.</p>\\n\\n </div>\\n\\n <ul class=\\\"profile-social-links\\\">\\n\\n <li>\\n <a href=\\\"#\\\" [routerLink]=\\\"['/notes']\\\">\\n <i class=\\\"fa fa-arrow-left\\\"></i>\\n </a>\\n </li>\\n\\n <li>\\n <a href=\\\"https://github.com/hsbalar/Preserver\\\" target=\\\"_blank\\\">\\n <i class=\\\"fa fa-github\\\"></i>\\n </a>\\n </li>\\n\\n <li>\\n <a href=\\\"https://twitter.com/Hsbalar\\\" target=\\\"_blank\\\">\\n <i class=\\\"fa fa-twitter\\\"></i>\\n </a>\\n </li>\\n\\n </ul>\\n </div>\\n</div>\\n\";//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTA5LmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vc3JjL2FwcC9jb21wb25lbnRzL2Fib3V0L2Fib3V0LmNvbXBvbmVudC5odG1sP2FjMjIiXSwic291cmNlc0NvbnRlbnQiOlsibW9kdWxlLmV4cG9ydHMgPSBcIjxkaXYgY2xhc3M9XFxcImFib3V0XFxcIj5cXG5cXG4gIDxkaXYgY2xhc3M9XFxcInByb2ZpbGUtY2FyZFxcXCI+XFxuXFxuICAgIDxkaXYgY2xhc3M9XFxcImhlYWRlclxcXCI+XFxuXFxuICAgICAgPGEgaHJlZj1cXFwiI1xcXCIgW3JvdXRlckxpbmtdPVxcXCJbJy9ub3RlcyddXFxcIj5cXG4gICAgICAgIDxpbWcgc3JjPVxcXCIvcHVibGljL2ltYWdlcy9sb2dvLnBuZ1xcXCIgLz5cXG4gICAgICA8L2E+XFxuXFxuICAgICAgPGgxPlByZXNlcnZlcjwvaDE+XFxuXFxuICAgICAgPGgyPlByZXNlcnZlciBpcyBhbiBub3RlcyBvcmdhbml6ZXIgZGVza3RvcCBhcHAgYmFzZWQgb24gRWxlY3Ryb24uIGRldmVsb3BlZCBieSBIaXRlc2ggQmFsYXI8L2gyPlxcblxcbiAgICA8L2Rpdj5cXG5cXG4gICAgPGRpdiBjbGFzcz1cXFwicHJvZmlsZS1iaW9cXFwiPlxcblxcbiAgICAgIDxwPk9yZ2FuaXplIHlvdXIgbGlmZSB3aXRoIHByZXNlcnZlciBhcHBsaWNhdGlvbiBmb3Iga2VlcGluZyB0cmFjayBvZiBub3RlcywgdGFza3MsIGFuZCB0by1kbyBsaXN0cy48L3A+XFxuXFxuICAgIDwvZGl2PlxcblxcbiAgICA8dWwgY2xhc3M9XFxcInByb2ZpbGUtc29jaWFsLWxpbmtzXFxcIj5cXG5cXG4gICAgICA8bGk+XFxuICAgICAgICA8YSBocmVmPVxcXCIjXFxcIiBbcm91dGVyTGlua109XFxcIlsnL25vdGVzJ11cXFwiPlxcbiAgICAgICAgICA8aSBjbGFzcz1cXFwiZmEgZmEtYXJyb3ctbGVmdFxcXCI+PC9pPlxcbiAgICAgICAgPC9hPlxcbiAgICAgIDwvbGk+XFxuXFxuICAgICAgPGxpPlxcbiAgICAgICAgPGEgaHJlZj1cXFwiaHR0cHM6Ly9naXRodWIuY29tL2hzYmFsYXIvUHJlc2VydmVyXFxcIiB0YXJnZXQ9XFxcIl9ibGFua1xcXCI+XFxuICAgICAgICAgIDxpIGNsYXNzPVxcXCJmYSBmYS1naXRodWJcXFwiPjwvaT5cXG4gICAgICAgIDwvYT5cXG4gICAgICA8L2xpPlxcblxcbiAgICAgIDxsaT5cXG4gICAgICAgIDxhIGhyZWY9XFxcImh0dHBzOi8vdHdpdHRlci5jb20vSHNiYWxhclxcXCIgdGFyZ2V0PVxcXCJfYmxhbmtcXFwiPlxcbiAgICAgICAgICA8aSBjbGFzcz1cXFwiZmEgZmEtdHdpdHRlclxcXCI+PC9pPlxcbiAgICAgICAgPC9hPlxcbiAgICAgIDwvbGk+XFxuXFxuICAgIDwvdWw+XFxuICA8L2Rpdj5cXG48L2Rpdj5cXG5cIjtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL3NyYy9hcHAvY29tcG9uZW50cy9hYm91dC9hYm91dC5jb21wb25lbnQuaHRtbFxuLy8gbW9kdWxlIGlkID0gMTA5XG4vLyBtb2R1bGUgY2h1bmtzID0gMCJdLCJtYXBwaW5ncyI6IkFBQUEiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ },
- /* 110 */
- /***/ function(module, exports) {
- eval("module.exports = \".about {\\n\\tbackground: #bcdee7 url(\\\"/public/images/bg.png\\\") no-repeat center center fixed;\\n background-size: 120% auto;\\n position: fixed;\\n\\tpadding: 0px;\\n\\tmargin: 0px;\\n\\twidth: 100%;\\n\\theight: 100%;\\n\\tfont: normal 14px/1.618em \\\"Hind\\\", sans-serif;\\n\\t-webkit-font-smoothing: antialiased;\\n}\\n\\nh1, h2 {\\n font-weight: 400;\\n margin: 0px 0px 5px 0px;\\n}\\nh1 {\\n font-size: 24px;\\n}\\nh2 {\\n font-size: 16px;\\n}\\np {\\n margin: 0px;\\n}\\n\\n.back {\\n bottom: 0;\\n padding: 40px 0px 0px 20px;\\n}\\n\\n.profile-card {\\n\\tbackground: #FFB300;\\n\\twidth: 56px;\\n\\theight: 56px;\\n\\tposition: absolute;\\n\\tleft: 50%;\\n\\ttop: 50%;\\n z-index: 2;\\n\\toverflow: hidden;\\n opacity: 0;\\n margin-top: 70px;\\n\\t-webkit-transform: translate(-50%, -50%);\\n\\ttransform: translate(-50%, -50%);\\n\\t-webkit-border-radius: 50%;\\n\\tborder-radius: 50%;\\n\\t-webkit-box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16), 0px 3px 6px rgba(0, 0, 0, 0.23);\\n\\tbox-shadow: 0px 3px 6px rgba(0 ,0, 0, 0.16), 0px 3px 6px rgba(0, 0, 0, 0.23);\\n -webkit-animation: init 0.1s 0.2s cubic-bezier(0.55, 0.055, 0.675, 0.19) forwards, moveDown 0.3s 0.8s cubic-bezier(0.6, -0.28, 0.735, 0.045) forwards, moveUp 0.5s 1.8s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards, materia_landscape 0.5s 1.2s cubic-bezier(0.86, 0, 0.07, 1) forwards;\\n animation: init 0.1s 0.2s cubic-bezier(0.55, 0.055, 0.675, 0.19) forwards, moveDown 0.3s 0.8s cubic-bezier(0.6, -0.28, 0.735, 0.045) forwards, moveUp 0.5s 1.8s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards, materia_landscape 0.5s 1.2s cubic-bezier(0.86, 0, 0.07, 1) forwards;\\n}\\n.profile-card .header {\\n padding: 40px 20px 30px 20px;\\n display: inline-block;\\n\\tbackground: #FFFFFF;\\n color: #000000;\\n margin-top: 50px;\\n opacity: 0;\\n text-align: center;\\n -webkit-animation: moveIn 1s 1.1s ease forwards;\\n animation: moveIn 1s 1.1s ease forwards;\\n}\\n.profile-card .header h1 {\\n color: #FF5722;\\n}\\n.profile-card .header a {\\n display: inline-block;\\n text-align: center;\\n position: relative;\\n margin: 25px 30px;\\n}\\n\\n.profile-card .header a > img {\\n width: 120px;\\n max-width: 100%;\\n -webkit-border-radius: 50%;\\n border-radius: 50%;\\n -webkit-transition: -webkit-box-shadow 0.3s ease;\\n transition: box-shadow 0.3s ease;\\n}\\n.profile-card .header a:hover > img {\\n -webkit-box-shadow: 0px 0px 0px 12px rgba(0, 0, 0, 0.1);\\n box-shadow: 0px 0px 0px 12px rgba(0, 0, 0, 0.1);\\n}\\n.profile-card .profile-bio {\\n width: 175px;\\n height: 180px;\\n display: inline-block;\\n padding: 50px 20px 30px 20px;\\n\\tbackground: #FFFFFF;\\n color: #333333;\\n margin-top: 50px;\\n text-align: center;\\n opacity: 0;\\n -webkit-animation: moveIn 1s 1s ease forwards;\\n animation: moveIn 1s 1s ease forwards;\\n}\\n.profile-social-links {\\n width: 218px;\\n display: inline-block;\\n margin: 0px;\\n padding: 15px 20px;\\n\\tbackground: #FFFFFF;\\n margin-top: 50px;\\n text-align: center;\\n opacity: 0;\\n -webkit-box-sizing: border-box;\\n box-sizing: border-box;\\n -webkit-animation: moveIn 1s 1.1s ease forwards;\\n animation: moveIn 1s 1.1s ease forwards;\\n}\\n.profile-social-links li {\\n list-style: none;\\n margin: -5px 0px 0px 0px;\\n padding: 0px;\\n float: left;\\n width: 33.3%;\\n text-align: center;\\n}\\n.profile-social-links li a {\\n display: inline-block;\\n width: 24px;\\n height: 24px;\\n padding: 6px;\\n position: relative;\\n overflow: hidden!important;\\n -webkit-border-radius: 50%;\\n border-radius: 50%;\\n}\\n.profile-social-links li a {\\n position: relative;\\n z-index: 1;\\n}\\n.profile-social-links li a:before {\\n display: block;\\n content: \\\"\\\";\\n background: rgba(0, 0, 0, 0.3);\\n position: absolute;\\n left: 0px;\\n top: 0px;\\n width: 36px;\\n height: 36px;\\n opacity: 1;\\n -webkit-transition: transform 0.4s ease, opacity 1s ease-out;\\n transition: transform 0.4s ease, opacity 1s ease-out;\\n -webkit-transform: scale3d(0, 0, 1);\\n transform: scale3d(0, 0, 1);\\n -webkit-border-radius: 50%;\\n border-radius: 50%;\\n}\\n.profile-social-links li a:hover:before {\\n -webkit-animation: ripple 1s ease forwards;\\n animation: ripple 1s ease forwards;\\n}\\n.profile-social-links li a,\\n.profile-social-links li a {\\n width: 24px;\\n}\\n\\n\\n@media screen and (min-aspect-ratio: 4/3) {\\n body {\\n background-size: 100% auto;\\n }\\n body:before {\\n width: 0px;\\n }\\n @-webkit-keyframes puff {\\n 0% {\\n top: 100%;\\n width: 0px;\\n padding-bottom: 0px;\\n }\\n \\t100% {\\n top: 50%;\\n width: 100%;\\n padding-bottom: 100%;\\n }\\n }\\n @keyframes puff {\\n 0% {\\n top: 100%;\\n width: 0px;\\n padding-bottom: 0px;\\n }\\n \\t100% {\\n top: 50%;\\n width: 100%;\\n padding-bottom: 100%;\\n }\\n }\\n}\\n@media screen and (min-height: 480px) {\\n\\t.profile-card {\\n\\t\\t-webkit-animation: init 0.1s 0.2s cubic-bezier(0.55, 0.055, 0.675, 0.19) forwards, moveDown 0.3s 0.8s cubic-bezier(0.6, -0.28, 0.735, 0.045) forwards, moveUp 0.5s 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards, materia_portrait 0.5s 1s cubic-bezier(0.86, 0, 0.07, 1) forwards;\\n\\t\\tanimation: init 0.1s 0.2s cubic-bezier(0.55, 0.055, 0.675, 0.19) forwards, moveDown 0.3s 0.8s cubic-bezier(0.6, -0.28, 0.735, 0.045) forwards, moveUp 0.5s 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards, materia_portrait 0.5s 1s cubic-bezier(0.86, 0, 0.07, 1) forwards;\\n\\t}\\n\\t.profile-card header {\\n width: auto;\\n height: auto;\\n padding: 30px 20px;\\n display: block;\\n float: none;\\n border-right: none;\\n }\\n .profile-card .profile-bio {\\n width: auto;\\n height: auto;\\n padding: 15px 20px 30px 20px;\\n display: block;\\n float: none;\\n }\\n .profile-social-links {\\n width: 100%;\\n display: block;\\n float: none;\\n }\\n}\\n@media screen and (min-aspect-ratio: 4/3) {\\n body {\\n background-size: 100% auto;\\n }\\n body:before {\\n width: 0px;\\n\\t\\t-webkit-animation: init 0.1s 0.2s cubic-bezier(0.55, 0.055, 0.675, 0.19) forwards, moveDown 0.3s 0.8s cubic-bezier(0.6, -0.28, 0.735, 0.045) forwards, moveUp 0.5s 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards, materia_portrait 0.5s 2.7s cubic-bezier(0.86, 0, 0.07, 1) forwards;\\n\\t\\tanimation: init 0.1s 0.2s cubic-bezier(0.55, 0.055, 0.675, 0.19) forwards, moveDown 0.3s 0.8s cubic-bezier(0.6, -0.28, 0.735, 0.045) forwards, moveUp 0.5s 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards, materia_portrait 0.5s 2.7s cubic-bezier(0.86, 0, 0.07, 1) forwards;\\n\\t}\\n}\\n@-webkit-keyframes init {\\n 0% {\\n \\twidth: 0px;\\n \\theight: 0px;\\n }\\n\\t100% {\\n width: 56px;\\n height: 56px;\\n margin-top: 0px;\\n opacity: 1;\\n }\\n}\\n@keyframes init {\\n 0% {\\n \\twidth: 0px;\\n \\theight: 0px;\\n }\\n\\t100% {\\n width: 56px;\\n height: 56px;\\n margin-top: 0px;\\n opacity: 1;\\n }\\n}\\n@-webkit-keyframes puff_portrait {\\n 0% {\\n top: 100%;\\n height: 0px;\\n padding: 0px;\\n }\\n\\t100% {\\n top: 50%;\\n height: 100%;\\n padding: 0px 100%;\\n }\\n}\\n@keyframes puff_portrait {\\n 0% {\\n top: 100%;\\n height: 0px;\\n padding: 0px;\\n }\\n\\t100% {\\n top: 50%;\\n height: 100%;\\n padding: 0px 100%;\\n }\\n}\\n@-webkit-keyframes puff_landscape {\\n\\t0% {\\n\\t\\ttop: 100%;\\n\\t\\twidth: 0px;\\n\\t\\tpadding-bottom: 0px;\\n\\t}\\n\\t100% {\\n\\t\\ttop: 50%;\\n\\t\\twidth: 100%;\\n\\t\\tpadding-bottom: 100%;\\n\\t}\\n}\\n@keyframes puff_landscape {\\n\\t0% {\\n\\t\\ttop: 100%;\\n\\t\\twidth: 0px;\\n\\t\\tpadding-bottom: 0px;\\n\\t}\\n\\t100% {\\n\\t\\ttop: 50%;\\n\\t\\twidth: 100%;\\n\\t\\tpadding-bottom: 100%;\\n\\t}\\n}\\n@-webkit-keyframes borderRadius {\\n 0% {\\n -webkit-border-radius: 50%;\\n }\\n\\t100% {\\n -webkit-border-radius: 0px;\\n }\\n}\\n@keyframes borderRadius {\\n 0% {\\n -webkit-border-radius: 50%;\\n }\\n\\t100% {\\n border-radius: 0px;\\n }\\n}\\n@-webkit-keyframes moveDown {\\n 0% {\\n \\t top: 50%;\\n }\\n\\t50% {\\n\\t top: 40%;\\n }\\n 100% {\\n top: 100%;\\n }\\n}\\n@keyframes moveDown {\\n 0% {\\n \\t top: 50%;\\n }\\n\\t50% {\\n\\t top: 40%;\\n }\\n 100% {\\n top: 100%;\\n }\\n}\\n@-webkit-keyframes moveUp {\\n 0% {\\n background: #FFB300;\\n top: 100%;\\n }\\n\\t50% {\\n\\t top: 40%;\\n }\\n 100% {\\n top: 50%;\\n background: #E0E0E0;\\n }\\n}\\n@keyframes moveUp {\\n 0% {\\n background: #FFB300;\\n top: 100%;\\n }\\n\\t50% {\\n\\t top: 40%;\\n }\\n 100% {\\n top: 50%;\\n background: #E0E0E0;\\n }\\n}\\n@-webkit-keyframes materia_landscape {\\n 0% {\\n background: #E0E0E0;\\n }\\n 50% {\\n -webkit-border-radius: 4px;\\n }\\n 100% {\\n width: 440px;\\n height: 280px;\\n background: #FFFFFF;\\n -webkit-border-radius: 4px;\\n }\\n}\\n@keyframes materia_landscape {\\n 0% {\\n background: #E0E0E0;\\n }\\n 50% {\\n border-radius: 4px;\\n }\\n 100% {\\n width: 440px;\\n height: 280px;\\n background: #FFFFFF;\\n border-radius: 4px;\\n }\\n}\\n@-webkit-keyframes materia_portrait {\\n\\t0% {\\n\\t\\tbackground: #E0E0E0;\\n\\t}\\n\\t50% {\\n\\t\\t-webkit-border-radius: 4px;\\n\\t}\\n\\t100% {\\n\\t\\twidth: 280px;\\n\\t\\theight: 440px;\\n\\t\\tbackground: #FFFFFF;\\n\\t\\t-webkit-border-radius: 4px;\\n\\t}\\n}\\n@keyframes materia_portrait {\\n\\t0% {\\n\\t\\tbackground: #E0E0E0;\\n\\t}\\n\\t50% {\\n\\t\\tborder-radius: 4px;\\n\\t}\\n\\t100% {\\n\\t\\twidth: 280px;\\n\\t\\theight: 440px;\\n\\t\\tbackground: #FFFFFF;\\n\\t\\tborder-radius: 4px;\\n\\t}\\n}\\n@-webkit-keyframes moveIn {\\n 0% {\\n margin-top: 50px;\\n opacity: 0;\\n }\\n\\t100% {\\n opacity: 1;\\n margin-top: -20px;\\n }\\n}\\n@keyframes moveIn {\\n 0% {\\n margin-top: 50px;\\n opacity: 0;\\n }\\n\\t100% {\\n opacity: 1;\\n margin-top: -20px;\\n }\\n}\\n@-webkit-keyframes scaleIn {\\n 0% {\\n -webkit-transform: scale(0);\\n }\\n\\t100% {\\n -webkit-transform: scale(1);\\n }\\n}\\n@keyframes scaleIn {\\n 0% {\\n transform: scale(0);\\n }\\n\\t100% {\\n transform: scale(1);\\n }\\n}\\n@-webkit-keyframes ripple {\\n 0% {\\n transform: scale3d(0, 0, 0);\\n }\\n 50%, 100% {\\n -webkit-transform: scale3d(1, 1, 1);\\n }\\n 100% {\\n opacity: 0;\\n }\\n}\\n@keyframes ripple {\\n 0% {\\n transform: scale3d(0, 0, 0);\\n }\\n 50%, 100% {\\n transform: scale3d(1, 1, 1);\\n }\\n 100% {\\n opacity: 0;\\n }\\n}\\n\"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTEwLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vc3JjL2FwcC9jb21wb25lbnRzL2Fib3V0L2Fib3V0LmNvbXBvbmVudC5jc3M/OTIyMSJdLCJzb3VyY2VzQ29udGVudCI6WyJtb2R1bGUuZXhwb3J0cyA9IFwiLmFib3V0IHtcXG5cXHRiYWNrZ3JvdW5kOiAjYmNkZWU3IHVybChcXFwiL3B1YmxpYy9pbWFnZXMvYmcucG5nXFxcIikgbm8tcmVwZWF0IGNlbnRlciBjZW50ZXIgZml4ZWQ7XFxuICAgIGJhY2tncm91bmQtc2l6ZTogMTIwJSBhdXRvO1xcbiAgICBwb3NpdGlvbjogZml4ZWQ7XFxuXFx0cGFkZGluZzogMHB4O1xcblxcdG1hcmdpbjogMHB4O1xcblxcdHdpZHRoOiAxMDAlO1xcblxcdGhlaWdodDogMTAwJTtcXG5cXHRmb250OiBub3JtYWwgMTRweC8xLjYxOGVtIFxcXCJIaW5kXFxcIiwgc2Fucy1zZXJpZjtcXG5cXHQtd2Via2l0LWZvbnQtc21vb3RoaW5nOiBhbnRpYWxpYXNlZDtcXG59XFxuXFxuaDEsIGgyIHtcXG4gICAgZm9udC13ZWlnaHQ6IDQwMDtcXG4gICAgbWFyZ2luOiAwcHggMHB4IDVweCAwcHg7XFxufVxcbmgxIHtcXG4gICAgZm9udC1zaXplOiAyNHB4O1xcbn1cXG5oMiB7XFxuICAgIGZvbnQtc2l6ZTogMTZweDtcXG59XFxucCB7XFxuICAgIG1hcmdpbjogMHB4O1xcbn1cXG5cXG4uYmFjayB7XFxuICAgIGJvdHRvbTogMDtcXG4gICAgcGFkZGluZzogNDBweCAwcHggMHB4IDIwcHg7XFxufVxcblxcbi5wcm9maWxlLWNhcmQge1xcblxcdGJhY2tncm91bmQ6ICNGRkIzMDA7XFxuXFx0d2lkdGg6IDU2cHg7XFxuXFx0aGVpZ2h0OiA1NnB4O1xcblxcdHBvc2l0aW9uOiBhYnNvbHV0ZTtcXG5cXHRsZWZ0OiA1MCU7XFxuXFx0dG9wOiA1MCU7XFxuICAgIHotaW5kZXg6IDI7XFxuXFx0b3ZlcmZsb3c6IGhpZGRlbjtcXG4gICAgb3BhY2l0eTogMDtcXG4gICAgbWFyZ2luLXRvcDogNzBweDtcXG5cXHQtd2Via2l0LXRyYW5zZm9ybTogdHJhbnNsYXRlKC01MCUsIC01MCUpO1xcblxcdHRyYW5zZm9ybTogdHJhbnNsYXRlKC01MCUsIC01MCUpO1xcblxcdC13ZWJraXQtYm9yZGVyLXJhZGl1czogNTAlO1xcblxcdGJvcmRlci1yYWRpdXM6IDUwJTtcXG5cXHQtd2Via2l0LWJveC1zaGFkb3c6IDBweCAzcHggNnB4IHJnYmEoMCwgMCwgMCwgMC4xNiksIDBweCAzcHggNnB4IHJnYmEoMCwgMCwgMCwgMC4yMyk7XFxuXFx0Ym94LXNoYWRvdzogMHB4IDNweCA2cHggcmdiYSgwICwwLCAwLCAwLjE2KSwgMHB4IDNweCA2cHggcmdiYSgwLCAwLCAwLCAwLjIzKTtcXG4gICAgLXdlYmtpdC1hbmltYXRpb246IGluaXQgMC4xcyAwLjJzIGN1YmljLWJlemllcigwLjU1LCAwLjA1NSwgMC42NzUsIDAuMTkpIGZvcndhcmRzLCBtb3ZlRG93biAwLjNzIDAuOHMgY3ViaWMtYmV6aWVyKDAuNiwgLTAuMjgsIDAuNzM1LCAwLjA0NSkgZm9yd2FyZHMsIG1vdmVVcCAwLjVzIDEuOHMgY3ViaWMtYmV6aWVyKDAuMTc1LCAwLjg4NSwgMC4zMiwgMS4yNzUpIGZvcndhcmRzLCBtYXRlcmlhX2xhbmRzY2FwZSAwLjVzIDEuMnMgY3ViaWMtYmV6aWVyKDAuODYsIDAsIDAuMDcsIDEpIGZvcndhcmRzO1xcbiAgICBhbmltYXRpb246IGluaXQgMC4xcyAwLjJzIGN1YmljLWJlemllcigwLjU1LCAwLjA1NSwgMC42NzUsIDAuMTkpIGZvcndhcmRzLCBtb3ZlRG93biAwLjNzIDAuOHMgY3ViaWMtYmV6aWVyKDAuNiwgLTAuMjgsIDAuNzM1LCAwLjA0NSkgZm9yd2FyZHMsIG1vdmVVcCAwLjVzIDEuOHMgY3ViaWMtYmV6aWVyKDAuMTc1LCAwLjg4NSwgMC4zMiwgMS4yNzUpIGZvcndhcmRzLCBtYXRlcmlhX2xhbmRzY2FwZSAwLjVzIDEuMnMgY3ViaWMtYmV6aWVyKDAuODYsIDAsIDAuMDcsIDEpIGZvcndhcmRzO1xcbn1cXG4ucHJvZmlsZS1jYXJkIC5oZWFkZXIge1xcbiAgICBwYWRkaW5nOiA0MHB4IDIwcHggMzBweCAyMHB4O1xcbiAgICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XFxuXFx0YmFja2dyb3VuZDogI0ZGRkZGRjtcXG4gICAgY29sb3I6ICMwMDAwMDA7XFxuICAgIG1hcmdpbi10b3A6IDUwcHg7XFxuICAgIG9wYWNpdHk6IDA7XFxuICAgIHRleHQtYWxpZ246IGNlbnRlcjtcXG4gICAgLXdlYmtpdC1hbmltYXRpb246IG1vdmVJbiAxcyAxLjFzIGVhc2UgZm9yd2FyZHM7XFxuICAgIGFuaW1hdGlvbjogbW92ZUluIDFzIDEuMXMgZWFzZSBmb3J3YXJkcztcXG59XFxuLnByb2ZpbGUtY2FyZCAuaGVhZGVyIGgxIHtcXG4gICAgY29sb3I6ICNGRjU3MjI7XFxufVxcbi5wcm9maWxlLWNhcmQgLmhlYWRlciBhIHtcXG4gICAgZGlzcGxheTogaW5saW5lLWJsb2NrO1xcbiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7XFxuICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcXG4gICAgbWFyZ2luOiAyNXB4IDMwcHg7XFxufVxcblxcbi5wcm9maWxlLWNhcmQgLmhlYWRlciBhID4gaW1nIHtcXG4gICAgd2lkdGg6IDEyMHB4O1xcbiAgICBtYXgtd2lkdGg6IDEwMCU7XFxuICAgIC13ZWJraXQtYm9yZGVyLXJhZGl1czogNTAlO1xcbiAgICBib3JkZXItcmFkaXVzOiA1MCU7XFxuICAgIC13ZWJraXQtdHJhbnNpdGlvbjogLXdlYmtpdC1ib3gtc2hhZG93IDAuM3MgZWFzZTtcXG4gICAgdHJhbnNpdGlvbjogYm94LXNoYWRvdyAwLjNzIGVhc2U7XFxufVxcbi5wcm9maWxlLWNhcmQgLmhlYWRlciBhOmhvdmVyID4gaW1nIHtcXG4gICAgLXdlYmtpdC1ib3gtc2hhZG93OiAwcHggMHB4IDBweCAxMnB4IHJnYmEoMCwgMCwgMCwgMC4xKTtcXG4gICAgYm94LXNoYWRvdzogMHB4IDBweCAwcHggMTJweCByZ2JhKDAsIDAsIDAsIDAuMSk7XFxufVxcbi5wcm9maWxlLWNhcmQgLnByb2ZpbGUtYmlvIHtcXG4gICAgd2lkdGg6IDE3NXB4O1xcbiAgICBoZWlnaHQ6IDE4MHB4O1xcbiAgICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XFxuICAgIHBhZGRpbmc6IDUwcHggMjBweCAzMHB4IDIwcHg7XFxuXFx0YmFja2dyb3VuZDogI0ZGRkZGRjtcXG4gICAgY29sb3I6ICMzMzMzMzM7XFxuICAgIG1hcmdpbi10b3A6IDUwcHg7XFxuICAgIHRleHQtYWxpZ246IGNlbnRlcjtcXG4gICAgb3BhY2l0eTogMDtcXG4gICAgLXdlYmtpdC1hbmltYXRpb246IG1vdmVJbiAxcyAxcyBlYXNlIGZvcndhcmRzO1xcbiAgICBhbmltYXRpb246IG1vdmVJbiAxcyAxcyBlYXNlIGZvcndhcmRzO1xcbn1cXG4ucHJvZmlsZS1zb2NpYWwtbGlua3Mge1xcbiAgICB3aWR0aDogMjE4cHg7XFxuICAgIGRpc3BsYXk6IGlubGluZS1ibG9jaztcXG4gICAgbWFyZ2luOiAwcHg7XFxuICAgIHBhZGRpbmc6IDE1cHggMjBweDtcXG5cXHRiYWNrZ3JvdW5kOiAjRkZGRkZGO1xcbiAgICBtYXJnaW4tdG9wOiA1MHB4O1xcbiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7XFxuICAgIG9wYWNpdHk6IDA7XFxuICAgIC13ZWJraXQtYm94LXNpemluZzogYm9yZGVyLWJveDtcXG4gICAgYm94LXNpemluZzogYm9yZGVyLWJveDtcXG4gICAgLXdlYmtpdC1hbmltYXRpb246IG1vdmVJbiAxcyAxLjFzIGVhc2UgZm9yd2FyZHM7XFxuICAgIGFuaW1hdGlvbjogbW92ZUluIDFzIDEuMXMgZWFzZSBmb3J3YXJkcztcXG59XFxuLnByb2ZpbGUtc29jaWFsLWxpbmtzIGxpIHtcXG4gICAgbGlzdC1zdHlsZTogbm9uZTtcXG4gICAgbWFyZ2luOiAtNXB4IDBweCAwcHggMHB4O1xcbiAgICBwYWRkaW5nOiAwcHg7XFxuICAgIGZsb2F0OiBsZWZ0O1xcbiAgICB3aWR0aDogMzMuMyU7XFxuICAgIHRleHQtYWxpZ246IGNlbnRlcjtcXG59XFxuLnByb2ZpbGUtc29jaWFsLWxpbmtzIGxpIGEge1xcbiAgICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XFxuICAgIHdpZHRoOiAyNHB4O1xcbiAgICBoZWlnaHQ6IDI0cHg7XFxuICAgIHBhZGRpbmc6IDZweDtcXG4gICAgcG9zaXRpb246IHJlbGF0aXZlO1xcbiAgICBvdmVyZmxvdzogaGlkZGVuIWltcG9ydGFudDtcXG4gICAgLXdlYmtpdC1ib3JkZXItcmFkaXVzOiA1MCU7XFxuICAgIGJvcmRlci1yYWRpdXM6IDUwJTtcXG59XFxuLnByb2ZpbGUtc29jaWFsLWxpbmtzIGxpIGEge1xcbiAgICBwb3NpdGlvbjogcmVsYXRpdmU7XFxuICAgIHotaW5kZXg6IDE7XFxufVxcbi5wcm9maWxlLXNvY2lhbC1saW5rcyBsaSBhOmJlZm9yZSB7XFxuICAgIGRpc3BsYXk6IGJsb2NrO1xcbiAgICBjb250ZW50OiBcXFwiXFxcIjtcXG4gICAgYmFja2dyb3VuZDogcmdiYSgwLCAwLCAwLCAwLjMpO1xcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XFxuICAgIGxlZnQ6IDBweDtcXG4gICAgdG9wOiAwcHg7XFxuICAgIHdpZHRoOiAzNnB4O1xcbiAgICBoZWlnaHQ6IDM2cHg7XFxuICAgIG9wYWNpdHk6IDE7XFxuICAgIC13ZWJraXQtdHJhbnNpdGlvbjogdHJhbnNmb3JtIDAuNHMgZWFzZSwgb3BhY2l0eSAxcyBlYXNlLW91dDtcXG4gICAgdHJhbnNpdGlvbjogdHJhbnNmb3JtIDAuNHMgZWFzZSwgb3BhY2l0eSAxcyBlYXNlLW91dDtcXG4gICAgLXdlYmtpdC10cmFuc2Zvcm06IHNjYWxlM2QoMCwgMCwgMSk7XFxuICAgIHRyYW5zZm9ybTogc2NhbGUzZCgwLCAwLCAxKTtcXG4gICAgLXdlYmtpdC1ib3JkZXItcmFkaXVzOiA1MCU7XFxuICAgIGJvcmRlci1yYWRpdXM6IDUwJTtcXG59XFxuLnByb2ZpbGUtc29jaWFsLWxpbmtzIGxpIGE6aG92ZXI6YmVmb3JlIHtcXG4gICAgLXdlYmtpdC1hbmltYXRpb246IHJpcHBsZSAxcyBlYXNlIGZvcndhcmRzO1xcbiAgICBhbmltYXRpb246IHJpcHBsZSAxcyBlYXNlIGZvcndhcmRzO1xcbn1cXG4ucHJvZmlsZS1zb2NpYWwtbGlua3MgbGkgYSxcXG4ucHJvZmlsZS1zb2NpYWwtbGlua3MgbGkgYSB7XFxuICAgIHdpZHRoOiAyNHB4O1xcbn1cXG5cXG5cXG5AbWVkaWEgc2NyZWVuIGFuZCAobWluLWFzcGVjdC1yYXRpbzogNC8zKSB7XFxuICAgIGJvZHkge1xcbiAgICAgICAgYmFja2dyb3VuZC1zaXplOiAxMDAlIGF1dG87XFxuICAgIH1cXG4gICAgYm9keTpiZWZvcmUge1xcbiAgICAgICAgd2lkdGg6IDBweDtcXG4gICAgfVxcbiAgICBALXdlYmtpdC1rZXlmcmFtZXMgcHVmZiB7XFxuICAgICAgICAwJSB7XFxuICAgICAgICAgICAgdG9wOiAxMDAlO1xcbiAgICAgICAgICAgIHdpZHRoOiAwcHg7XFxuICAgICAgICAgICAgcGFkZGluZy1ib3R0b206IDBweDtcXG4gICAgICAgIH1cXG4gICAgXFx0MTAwJSB7XFxuICAgICAgICAgICAgdG9wOiA1MCU7XFxuICAgICAgICAgICAgd2lkdGg6IDEwMCU7XFxuICAgICAgICAgICAgcGFkZGluZy1ib3R0b206IDEwMCU7XFxuICAgICAgICB9XFxuICAgIH1cXG4gICAgQGtleWZyYW1lcyBwdWZmIHtcXG4gICAgICAgIDAlIHtcXG4gICAgICAgICAgICB0b3A6IDEwMCU7XFxuICAgICAgICAgICAgd2lkdGg6IDBweDtcXG4gICAgICAgICAgICBwYWRkaW5nLWJvdHRvbTogMHB4O1xcbiAgICAgICAgfVxcbiAgICBcXHQxMDAlIHtcXG4gICAgICAgICAgICB0b3A6IDUwJTtcXG4gICAgICAgICAgICB3aWR0aDogMTAwJTtcXG4gICAgICAgICAgICBwYWRkaW5nLWJvdHRvbTogMTAwJTtcXG4gICAgICAgIH1cXG4gICAgfVxcbn1cXG5AbWVkaWEgc2NyZWVuIGFuZCAobWluLWhlaWdodDogNDgwcHgpIHtcXG5cXHQucHJvZmlsZS1jYXJkIHtcXG5cXHRcXHQtd2Via2l0LWFuaW1hdGlvbjogaW5pdCAwLjFzIDAuMnMgY3ViaWMtYmV6aWVyKDAuNTUsIDAuMDU1LCAwLjY3NSwgMC4xOSkgZm9yd2FyZHMsIG1vdmVEb3duIDAuM3MgMC44cyBjdWJpYy1iZXppZXIoMC42LCAtMC4yOCwgMC43MzUsIDAuMDQ1KSBmb3J3YXJkcywgbW92ZVVwIDAuNXMgMC44cyBjdWJpYy1iZXppZXIoMC4xNzUsIDAuODg1LCAwLjMyLCAxLjI3NSkgZm9yd2FyZHMsIG1hdGVyaWFfcG9ydHJhaXQgMC41cyAxcyBjdWJpYy1iZXppZXIoMC44NiwgMCwgMC4wNywgMSkgZm9yd2FyZHM7XFxuXFx0XFx0YW5pbWF0aW9uOiBpbml0IDAuMXMgMC4ycyBjdWJpYy1iZXppZXIoMC41NSwgMC4wNTUsIDAuNjc1LCAwLjE5KSBmb3J3YXJkcywgbW92ZURvd24gMC4zcyAwLjhzIGN1YmljLWJlemllcigwLjYsIC0wLjI4LCAwLjczNSwgMC4wNDUpIGZvcndhcmRzLCBtb3ZlVXAgMC41cyAwLjhzIGN1YmljLWJlemllcigwLjE3NSwgMC44ODUsIDAuMzIsIDEuMjc1KSBmb3J3YXJkcywgbWF0ZXJpYV9wb3J0cmFpdCAwLjVzIDFzIGN1YmljLWJlemllcigwLjg2LCAwLCAwLjA3LCAxKSBmb3J3YXJkcztcXG5cXHR9XFxuXFx0LnByb2ZpbGUtY2FyZCBoZWFkZXIge1xcbiAgICAgICAgd2lkdGg6IGF1dG87XFxuICAgICAgICBoZWlnaHQ6IGF1dG87XFxuICAgICAgICBwYWRkaW5nOiAzMHB4IDIwcHg7XFxuICAgICAgICBkaXNwbGF5OiBibG9jaztcXG4gICAgICAgIGZsb2F0OiBub25lO1xcbiAgICAgICAgYm9yZGVyLXJpZ2h0OiBub25lO1xcbiAgICB9XFxuICAgIC5wcm9maWxlLWNhcmQgLnByb2ZpbGUtYmlvIHtcXG4gICAgICAgIHdpZHRoOiBhdXRvO1xcbiAgICAgICAgaGVpZ2h0OiBhdXRvO1xcbiAgICAgICAgcGFkZGluZzogMTVweCAyMHB4IDMwcHggMjBweDtcXG4gICAgICAgIGRpc3BsYXk6IGJsb2NrO1xcbiAgICAgICAgZmxvYXQ6IG5vbmU7XFxuICAgIH1cXG4gICAgLnByb2ZpbGUtc29jaWFsLWxpbmtzIHtcXG4gICAgICAgIHdpZHRoOiAxMDAlO1xcbiAgICAgICAgZGlzcGxheTogYmxvY2s7XFxuICAgICAgICBmbG9hdDogbm9uZTtcXG4gICAgfVxcbn1cXG5AbWVkaWEgc2NyZWVuIGFuZCAobWluLWFzcGVjdC1yYXRpbzogNC8zKSB7XFxuICAgIGJvZHkge1xcbiAgICAgICAgYmFja2dyb3VuZC1zaXplOiAxMDAlIGF1dG87XFxuICAgIH1cXG4gICAgYm9keTpiZWZvcmUge1xcbiAgICAgICAgd2lkdGg6IDBweDtcXG5cXHRcXHQtd2Via2l0LWFuaW1hdGlvbjogaW5pdCAwLjFzIDAuMnMgY3ViaWMtYmV6aWVyKDAuNTUsIDAuMDU1LCAwLjY3NSwgMC4xOSkgZm9yd2FyZHMsIG1vdmVEb3duIDAuM3MgMC44cyBjdWJpYy1iZXppZXIoMC42LCAtMC4yOCwgMC43MzUsIDAuMDQ1KSBmb3J3YXJkcywgbW92ZVVwIDAuNXMgMC44cyBjdWJpYy1iZXppZXIoMC4xNzUsIDAuODg1LCAwLjMyLCAxLjI3NSkgZm9yd2FyZHMsIG1hdGVyaWFfcG9ydHJhaXQgMC41cyAyLjdzIGN1YmljLWJlemllcigwLjg2LCAwLCAwLjA3LCAxKSBmb3J3YXJkcztcXG5cXHRcXHRhbmltYXRpb246IGluaXQgMC4xcyAwLjJzIGN1YmljLWJlemllcigwLjU1LCAwLjA1NSwgMC42NzUsIDAuMTkpIGZvcndhcmRzLCBtb3ZlRG93biAwLjNzIDAuOHMgY3ViaWMtYmV6aWVyKDAuNiwgLTAuMjgsIDAuNzM1LCAwLjA0NSkgZm9yd2FyZHMsIG1vdmVVcCAwLjVzIDAuOHMgY3ViaWMtYmV6aWVyKDAuMTc1LCAwLjg4NSwgMC4zMiwgMS4yNzUpIGZvcndhcmRzLCBtYXRlcmlhX3BvcnRyYWl0IDAuNXMgMi43cyBjdWJpYy1iZXppZXIoMC44NiwgMCwgMC4wNywgMSkgZm9yd2FyZHM7XFxuXFx0fVxcbn1cXG5ALXdlYmtpdC1rZXlmcmFtZXMgaW5pdCB7XFxuICAgIDAlIHtcXG4gICAgXFx0d2lkdGg6IDBweDtcXG4gICAgXFx0aGVpZ2h0OiAwcHg7XFxuICAgIH1cXG5cXHQxMDAlIHtcXG4gICAgICAgIHdpZHRoOiA1NnB4O1xcbiAgICAgICAgaGVpZ2h0OiA1NnB4O1xcbiAgICAgICAgbWFyZ2luLXRvcDogMHB4O1xcbiAgICAgICAgb3BhY2l0eTogMTtcXG4gICAgfVxcbn1cXG5Aa2V5ZnJhbWVzIGluaXQge1xcbiAgICAwJSB7XFxuICAgIFxcdHdpZHRoOiAwcHg7XFxuICAgIFxcdGhlaWdodDogMHB4O1xcbiAgICB9XFxuXFx0MTAwJSB7XFxuICAgICAgICB3aWR0aDogNTZweDtcXG4gICAgICAgIGhlaWdodDogNTZweDtcXG4gICAgICAgIG1hcmdpbi10b3A6IDBweDtcXG4gICAgICAgIG9wYWNpdHk6IDE7XFxuICAgIH1cXG59XFxuQC13ZWJraXQta2V5ZnJhbWVzIHB1ZmZfcG9ydHJhaXQge1xcbiAgICAwJSB7XFxuICAgICAgICB0b3A6IDEwMCU7XFxuICAgICAgICBoZWlnaHQ6IDBweDtcXG4gICAgICAgIHBhZGRpbmc6IDBweDtcXG4gICAgfVxcblxcdDEwMCUge1xcbiAgICAgICAgdG9wOiA1MCU7XFxuICAgICAgICBoZWlnaHQ6IDEwMCU7XFxuICAgICAgICBwYWRkaW5nOiAwcHggMTAwJTtcXG4gICAgfVxcbn1cXG5Aa2V5ZnJhbWVzIHB1ZmZfcG9ydHJhaXQge1xcbiAgICAwJSB7XFxuICAgICAgICB0b3A6IDEwMCU7XFxuICAgICAgICBoZWlnaHQ6IDBweDtcXG4gICAgICAgIHBhZGRpbmc6IDBweDtcXG4gICAgfVxcblxcdDEwMCUge1xcbiAgICAgICAgdG9wOiA1MCU7XFxuICAgICAgICBoZWlnaHQ6IDEwMCU7XFxuICAgICAgICBwYWRkaW5nOiAwcHggMTAwJTtcXG4gICAgfVxcbn1cXG5ALXdlYmtpdC1rZXlmcmFtZXMgcHVmZl9sYW5kc2NhcGUge1xcblxcdDAlIHtcXG5cXHRcXHR0b3A6IDEwMCU7XFxuXFx0XFx0d2lkdGg6IDBweDtcXG5cXHRcXHRwYWRkaW5nLWJvdHRvbTogMHB4O1xcblxcdH1cXG5cXHQxMDAlIHtcXG5cXHRcXHR0b3A6IDUwJTtcXG5cXHRcXHR3aWR0aDogMTAwJTtcXG5cXHRcXHRwYWRkaW5nLWJvdHRvbTogMTAwJTtcXG5cXHR9XFxufVxcbkBrZXlmcmFtZXMgcHVmZl9sYW5kc2NhcGUge1xcblxcdDAlIHtcXG5cXHRcXHR0b3A6IDEwMCU7XFxuXFx0XFx0d2lkdGg6IDBweDtcXG5cXHRcXHRwYWRkaW5nLWJvdHRvbTogMHB4O1xcblxcdH1cXG5cXHQxMDAlIHtcXG5cXHRcXHR0b3A6IDUwJTtcXG5cXHRcXHR3aWR0aDogMTAwJTtcXG5cXHRcXHRwYWRkaW5nLWJvdHRvbTogMTAwJTtcXG5cXHR9XFxufVxcbkAtd2Via2l0LWtleWZyYW1lcyBib3JkZXJSYWRpdXMge1xcbiAgICAwJSB7XFxuICAgICAgICAtd2Via2l0LWJvcmRlci1yYWRpdXM6IDUwJTtcXG4gICAgfVxcblxcdDEwMCUge1xcbiAgICAgICAgLXdlYmtpdC1ib3JkZXItcmFkaXVzOiAwcHg7XFxuICAgIH1cXG59XFxuQGtleWZyYW1lcyBib3JkZXJSYWRpdXMge1xcbiAgICAwJSB7XFxuICAgICAgICAtd2Via2l0LWJvcmRlci1yYWRpdXM6IDUwJTtcXG4gICAgfVxcblxcdDEwMCUge1xcbiAgICAgICAgYm9yZGVyLXJhZGl1czogMHB4O1xcbiAgICB9XFxufVxcbkAtd2Via2l0LWtleWZyYW1lcyBtb3ZlRG93biB7XFxuICAgIDAlIHtcXG4gICBcXHQgICAgdG9wOiA1MCU7XFxuICAgIH1cXG5cXHQ1MCUge1xcblxcdCAgIHRvcDogNDAlO1xcbiAgICB9XFxuICAgIDEwMCUge1xcbiAgICAgICB0b3A6IDEwMCU7XFxuICAgIH1cXG59XFxuQGtleWZyYW1lcyBtb3ZlRG93biB7XFxuICAgIDAlIHtcXG4gICBcXHQgICAgdG9wOiA1MCU7XFxuICAgIH1cXG5cXHQ1MCUge1xcblxcdCAgIHRvcDogNDAlO1xcbiAgICB9XFxuICAgIDEwMCUge1xcbiAgICAgICB0b3A6IDEwMCU7XFxuICAgIH1cXG59XFxuQC13ZWJraXQta2V5ZnJhbWVzIG1vdmVVcCB7XFxuICAgIDAlIHtcXG4gICAgICAgIGJhY2tncm91bmQ6ICNGRkIzMDA7XFxuICAgICAgICB0b3A6IDEwMCU7XFxuICAgIH1cXG5cXHQ1MCUge1xcblxcdCAgIHRvcDogNDAlO1xcbiAgICB9XFxuICAgIDEwMCUge1xcbiAgICAgICB0b3A6IDUwJTtcXG4gICAgICAgYmFja2dyb3VuZDogI0UwRTBFMDtcXG4gICAgfVxcbn1cXG5Aa2V5ZnJhbWVzIG1vdmVVcCB7XFxuICAgIDAlIHtcXG4gICAgICAgIGJhY2tncm91bmQ6ICNGRkIzMDA7XFxuICAgICAgICB0b3A6IDEwMCU7XFxuICAgIH1cXG5cXHQ1MCUge1xcblxcdCAgIHRvcDogNDAlO1xcbiAgICB9XFxuICAgIDEwMCUge1xcbiAgICAgICB0b3A6IDUwJTtcXG4gICAgICAgYmFja2dyb3VuZDogI0UwRTBFMDtcXG4gICAgfVxcbn1cXG5ALXdlYmtpdC1rZXlmcmFtZXMgbWF0ZXJpYV9sYW5kc2NhcGUge1xcbiAgICAwJSB7XFxuICAgICAgICBiYWNrZ3JvdW5kOiAjRTBFMEUwO1xcbiAgICB9XFxuICAgIDUwJSB7XFxuICAgICAgICAtd2Via2l0LWJvcmRlci1yYWRpdXM6IDRweDtcXG4gICAgfVxcbiAgICAxMDAlIHtcXG4gICAgICAgIHdpZHRoOiA0NDBweDtcXG4gICAgICAgIGhlaWdodDogMjgwcHg7XFxuICAgICAgICBiYWNrZ3JvdW5kOiAjRkZGRkZGO1xcbiAgICAgICAgLXdlYmtpdC1ib3JkZXItcmFkaXVzOiA0cHg7XFxuICAgIH1cXG59XFxuQGtleWZyYW1lcyBtYXRlcmlhX2xhbmRzY2FwZSB7XFxuICAgIDAlIHtcXG4gICAgICAgIGJhY2tncm91bmQ6ICNFMEUwRTA7XFxuICAgIH1cXG4gICAgNTAlIHtcXG4gICAgICAgIGJvcmRlci1yYWRpdXM6IDRweDtcXG4gICAgfVxcbiAgICAxMDAlIHtcXG4gICAgICAgIHdpZHRoOiA0NDBweDtcXG4gICAgICAgIGhlaWdodDogMjgwcHg7XFxuICAgICAgICBiYWNrZ3JvdW5kOiAjRkZGRkZGO1xcbiAgICAgICAgYm9yZGVyLXJhZGl1czogNHB4O1xcbiAgICB9XFxufVxcbkAtd2Via2l0LWtleWZyYW1lcyBtYXRlcmlhX3BvcnRyYWl0IHtcXG5cXHQwJSB7XFxuXFx0XFx0YmFja2dyb3VuZDogI0UwRTBFMDtcXG5cXHR9XFxuXFx0NTAlIHtcXG5cXHRcXHQtd2Via2l0LWJvcmRlci1yYWRpdXM6IDRweDtcXG5cXHR9XFxuXFx0MTAwJSB7XFxuXFx0XFx0d2lkdGg6IDI4MHB4O1xcblxcdFxcdGhlaWdodDogNDQwcHg7XFxuXFx0XFx0YmFja2dyb3VuZDogI0ZGRkZGRjtcXG5cXHRcXHQtd2Via2l0LWJvcmRlci1yYWRpdXM6IDRweDtcXG5cXHR9XFxufVxcbkBrZXlmcmFtZXMgbWF0ZXJpYV9wb3J0cmFpdCB7XFxuXFx0MCUge1xcblxcdFxcdGJhY2tncm91bmQ6ICNFMEUwRTA7XFxuXFx0fVxcblxcdDUwJSB7XFxuXFx0XFx0Ym9yZGVyLXJhZGl1czogNHB4O1xcblxcdH1cXG5cXHQxMDAlIHtcXG5cXHRcXHR3aWR0aDogMjgwcHg7XFxuXFx0XFx0aGVpZ2h0OiA0NDBweDtcXG5cXHRcXHRiYWNrZ3JvdW5kOiAjRkZGRkZGO1xcblxcdFxcdGJvcmRlci1yYWRpdXM6IDRweDtcXG5cXHR9XFxufVxcbkAtd2Via2l0LWtleWZyYW1lcyBtb3ZlSW4ge1xcbiAgICAwJSB7XFxuICAgICAgICBtYXJnaW4tdG9wOiA1MHB4O1xcbiAgICAgICAgb3BhY2l0eTogMDtcXG4gICAgfVxcblxcdDEwMCUge1xcbiAgICAgICAgb3BhY2l0eTogMTtcXG4gICAgICAgIG1hcmdpbi10b3A6IC0yMHB4O1xcbiAgICB9XFxufVxcbkBrZXlmcmFtZXMgbW92ZUluIHtcXG4gICAgMCUge1xcbiAgICAgICAgbWFyZ2luLXRvcDogNTBweDtcXG4gICAgICAgIG9wYWNpdHk6IDA7XFxuICAgIH1cXG5cXHQxMDAlIHtcXG4gICAgICAgIG9wYWNpdHk6IDE7XFxuICAgICAgICBtYXJnaW4tdG9wOiAtMjBweDtcXG4gICAgfVxcbn1cXG5ALXdlYmtpdC1rZXlmcmFtZXMgc2NhbGVJbiB7XFxuICAgIDAlIHtcXG4gICAgICAgIC13ZWJraXQtdHJhbnNmb3JtOiBzY2FsZSgwKTtcXG4gICAgfVxcblxcdDEwMCUge1xcbiAgICAgICAgLXdlYmtpdC10cmFuc2Zvcm06IHNjYWxlKDEpO1xcbiAgICB9XFxufVxcbkBrZXlmcmFtZXMgc2NhbGVJbiB7XFxuICAgIDAlIHtcXG4gICAgICAgIHRyYW5zZm9ybTogc2NhbGUoMCk7XFxuICAgIH1cXG5cXHQxMDAlIHtcXG4gICAgICAgIHRyYW5zZm9ybTogc2NhbGUoMSk7XFxuICAgIH1cXG59XFxuQC13ZWJraXQta2V5ZnJhbWVzIHJpcHBsZSB7XFxuICAgIDAlIHtcXG4gICAgICAgIHRyYW5zZm9ybTogc2NhbGUzZCgwLCAwLCAwKTtcXG4gICAgfVxcbiAgICA1MCUsIDEwMCUge1xcbiAgICAgICAgLXdlYmtpdC10cmFuc2Zvcm06IHNjYWxlM2QoMSwgMSwgMSk7XFxuICAgIH1cXG4gICAgMTAwJSB7XFxuICAgICAgICBvcGFjaXR5OiAwO1xcbiAgICB9XFxufVxcbkBrZXlmcmFtZXMgcmlwcGxlIHtcXG4gICAgMCUge1xcbiAgICAgICAgdHJhbnNmb3JtOiBzY2FsZTNkKDAsIDAsIDApO1xcbiAgICB9XFxuICAgIDUwJSwgMTAwJSB7XFxuICAgICAgICB0cmFuc2Zvcm06IHNjYWxlM2QoMSwgMSwgMSk7XFxuICAgIH1cXG4gICAgMTAwJSB7XFxuICAgICAgICBvcGFjaXR5OiAwO1xcbiAgICB9XFxufVxcblwiXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9zcmMvYXBwL2NvbXBvbmVudHMvYWJvdXQvYWJvdXQuY29tcG9uZW50LmNzc1xuLy8gbW9kdWxlIGlkID0gMTEwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCJdLCJtYXBwaW5ncyI6IkFBQUEiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ },
- /* 111 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar core_1 = __webpack_require__(4);\nvar Spinner = (function () {\n function Spinner() {\n }\n Spinner = __decorate([\n core_1.Component({\n selector: 'spinner',\n template: \"\\n <div class=\\\"loaders-container\\\">\\n <div class=\\\"spinner\\\">\\n <div class=\\\"circle\\\"></div>\\n </div>\\n </div>\\n \",\n styles: [\n \".loaders-container {\\n width: 100%;\\n height: 100%;\\n }\\n .loaders-container .spinner {\\n box-sizing: border-box;\\n width: 40px;\\n height: 40px;\\n position: absolute;\\n left: 50%;\\n top: 50%;\\n z-index: 1;\\n margin-top: -20px;\\n margin-left: -20px;\\n }\\n .circle {\\n box-sizing: border-box;\\n width: 40px;\\n height: 40px;\\n border-radius: 100%;\\n border: 3px solid #bdc5c5;\\n border-top-color: #009688;\\n -webkit-animation: spin 1s infinite linear;\\n animation: spin 1s infinite linear;\\n }\\n @-webkit-keyframes spin {\\n 100% {\\n -webkit-transform: rotate(360deg);\\n transform: rotate(360deg);\\n }\\n }\\n @keyframes spin {\\n 100% {\\n -webkit-transform: rotate(360deg);\\n transform: rotate(360deg);\\n }\\n }\"\n ]\n }), \n __metadata('design:paramtypes', [])\n ], Spinner);\n return Spinner;\n}());\nexports.Spinner = Spinner;\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTExLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vc3JjL2FwcC9jb21wb25lbnRzL3NwaW5uZXIvc3Bpbm5lci50cz9jNWViIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7Q29tcG9uZW50fSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnc3Bpbm5lcicsXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cImxvYWRlcnMtY29udGFpbmVyXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwic3Bpbm5lclwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY2lyY2xlXCI+PC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgYCxcbiAgc3R5bGVzOiBbXG4gICAgYC5sb2FkZXJzLWNvbnRhaW5lciB7XG4gICAgICAgIHdpZHRoOiAxMDAlO1xuICAgICAgICBoZWlnaHQ6IDEwMCU7XG4gICAgICB9XG4gICAgICAubG9hZGVycy1jb250YWluZXIgLnNwaW5uZXIge1xuICAgICAgICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xuICAgICAgICB3aWR0aDogNDBweDtcbiAgICAgICAgaGVpZ2h0OiA0MHB4O1xuICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgICAgIGxlZnQ6IDUwJTtcbiAgICAgICAgdG9wOiA1MCU7XG4gICAgICAgIHotaW5kZXg6IDE7XG4gICAgICAgIG1hcmdpbi10b3A6IC0yMHB4O1xuICAgICAgICBtYXJnaW4tbGVmdDogLTIwcHg7XG4gICAgICB9XG4gICAgICAuY2lyY2xlIHtcbiAgICAgICAgYm94LXNpemluZzogYm9yZGVyLWJveDtcbiAgICAgICAgd2lkdGg6IDQwcHg7XG4gICAgICAgIGhlaWdodDogNDBweDtcbiAgICAgICAgYm9yZGVyLXJhZGl1czogMTAwJTtcbiAgICAgICAgYm9yZGVyOiAzcHggc29saWQgI2JkYzVjNTtcbiAgICAgICAgYm9yZGVyLXRvcC1jb2xvcjogIzAwOTY4ODtcbiAgICAgICAgLXdlYmtpdC1hbmltYXRpb246IHNwaW4gMXMgaW5maW5pdGUgbGluZWFyO1xuICAgICAgICBhbmltYXRpb246IHNwaW4gMXMgaW5maW5pdGUgbGluZWFyO1xuICAgICAgfVxuICAgICAgQC13ZWJraXQta2V5ZnJhbWVzIHNwaW4ge1xuICAgICAgICAxMDAlIHtcbiAgICAgICAgICAtd2Via2l0LXRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7XG4gICAgICAgICAgdHJhbnNmb3JtOiByb3RhdGUoMzYwZGVnKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgQGtleWZyYW1lcyBzcGluIHtcbiAgICAgICAgMTAwJSB7XG4gICAgICAgICAgLXdlYmtpdC10cmFuc2Zvcm06IHJvdGF0ZSgzNjBkZWcpO1xuICAgICAgICAgIHRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7XG4gICAgICAgIH1cbiAgICAgIH1gXG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgU3Bpbm5lciB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyBub2RlX21vZHVsZXMvYW5ndWxhcjItdGVtcGxhdGUtbG9hZGVyIS4vc3JjL2FwcC9jb21wb25lbnRzL3NwaW5uZXIvc3Bpbm5lci50cyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQUFBO0FBbURBO0FBQ0E7QUFBQTtBQWxEQTtBQUFBO0FBQ0E7QUFDQTtBQU9BO0FBQ0E7QUFxQ0E7QUFDQTs7QUFBQTtBQUdBO0FBQUE7QUFGQTsiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ },
- /* 112 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar core_1 = __webpack_require__(4);\nvar dragula_1 = __webpack_require__(76);\nvar dragula = __webpack_require__(77);\nvar Dragula = (function () {\n function Dragula(el, dragulaService) {\n this.el = el;\n this.dragulaService = dragulaService;\n this.container = el.nativeElement;\n }\n Dragula.prototype.ngOnInit = function () {\n var _this = this;\n // console.log(this.bag);\n var bag = this.dragulaService.find(this.bag);\n var checkModel = function () {\n if (_this.dragulaModel) {\n if (_this.drake.models) {\n _this.drake.models.push(_this.dragulaModel);\n }\n else {\n _this.drake.models = [_this.dragulaModel];\n }\n }\n };\n if (bag) {\n this.drake = bag.drake;\n checkModel();\n this.drake.containers.push(this.container);\n }\n else {\n this.drake = dragula({\n containers: [this.container]\n });\n checkModel();\n this.dragulaService.add(this.bag, this.drake);\n }\n };\n Dragula.prototype.ngOnChanges = function (changes) {\n // console.log('dragula.directive: ngOnChanges');\n // console.log(changes);\n if (changes && changes['dragulaModel']) {\n if (this.drake) {\n if (this.drake.models) {\n var modelIndex = this.drake.models.indexOf(changes['dragulaModel'].previousValue);\n this.drake.models.splice(modelIndex, 1, changes['dragulaModel'].currentValue);\n }\n else {\n this.drake.models = [changes['dragulaModel'].currentValue];\n }\n }\n }\n };\n __decorate([\n core_1.Input('dragula'), \n __metadata('design:type', String)\n ], Dragula.prototype, \"bag\", void 0);\n __decorate([\n core_1.Input(), \n __metadata('design:type', Object)\n ], Dragula.prototype, \"dragulaModel\", void 0);\n Dragula = __decorate([\n core_1.Directive({\n selector: '[dragula]'\n }), \n __metadata('design:paramtypes', [(typeof (_a = typeof core_1.ElementRef !== 'undefined' && core_1.ElementRef) === 'function' && _a) || Object, (typeof (_b = typeof dragula_1.DragulaService !== 'undefined' && dragula_1.DragulaService) === 'function' && _b) || Object])\n ], Dragula);\n return Dragula;\n var _a, _b;\n}());\nexports.Dragula = Dragula;\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTEyLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vc3JjL2FwcC9kaXJlY3RpdmVzL2RyYWd1bGEudHM/NTFjYSJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBEaXJlY3RpdmUsXG4gIElucHV0LFxuICBFbGVtZW50UmVmLFxuICBPbkluaXQsXG4gIE9uQ2hhbmdlcyxcbiAgU2ltcGxlQ2hhbmdlXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtEcmFndWxhU2VydmljZX0gZnJvbSAnLi4vcHJvdmlkZXJzL2RyYWd1bGEnO1xuaW1wb3J0ICogYXMgZHJhZ3VsYSBmcm9tICdkcmFndWxhJztcblxuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnW2RyYWd1bGFdJ1xufSlcbmV4cG9ydCBjbGFzcyBEcmFndWxhIGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMge1xuICBASW5wdXQoJ2RyYWd1bGEnKSBiYWc6IHN0cmluZztcbiAgQElucHV0KCkgZHJhZ3VsYU1vZGVsOiBhbnk7XG4gIHByaXZhdGUgY29udGFpbmVyOiBhbnk7XG4gIHByaXZhdGUgZHJha2U6IGFueTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGVsOiBFbGVtZW50UmVmLCBwcml2YXRlIGRyYWd1bGFTZXJ2aWNlOiBEcmFndWxhU2VydmljZSkge1xuICAgIHRoaXMuY29udGFpbmVyID0gZWwubmF0aXZlRWxlbWVudDtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIC8vIGNvbnNvbGUubG9nKHRoaXMuYmFnKTtcbiAgICBsZXQgYmFnID0gdGhpcy5kcmFndWxhU2VydmljZS5maW5kKHRoaXMuYmFnKTtcbiAgICBsZXQgY2hlY2tNb2RlbCA9ICgpID0+IHtcbiAgICAgIGlmICh0aGlzLmRyYWd1bGFNb2RlbCkge1xuICAgICAgICBpZiAodGhpcy5kcmFrZS5tb2RlbHMpIHtcbiAgICAgICAgICB0aGlzLmRyYWtlLm1vZGVscy5wdXNoKHRoaXMuZHJhZ3VsYU1vZGVsKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmRyYWtlLm1vZGVscyA9IFt0aGlzLmRyYWd1bGFNb2RlbF07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuICAgIGlmIChiYWcpIHtcbiAgICAgIHRoaXMuZHJha2UgPSBiYWcuZHJha2U7XG4gICAgICBjaGVja01vZGVsKCk7XG4gICAgICB0aGlzLmRyYWtlLmNvbnRhaW5lcnMucHVzaCh0aGlzLmNvbnRhaW5lcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZHJha2UgPSBkcmFndWxhKHtcbiAgICAgICAgY29udGFpbmVyczogW3RoaXMuY29udGFpbmVyXVxuICAgICAgfSk7XG4gICAgICBjaGVja01vZGVsKCk7XG4gICAgICB0aGlzLmRyYWd1bGFTZXJ2aWNlLmFkZCh0aGlzLmJhZywgdGhpcy5kcmFrZSk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczoge1twcm9wTmFtZTogc3RyaW5nXTogU2ltcGxlQ2hhbmdlfSkge1xuICAgIC8vIGNvbnNvbGUubG9nKCdkcmFndWxhLmRpcmVjdGl2ZTogbmdPbkNoYW5nZXMnKTtcbiAgICAvLyBjb25zb2xlLmxvZyhjaGFuZ2VzKTtcbiAgICBpZiAoY2hhbmdlcyAmJiBjaGFuZ2VzWydkcmFndWxhTW9kZWwnXSkge1xuICAgICAgaWYgKHRoaXMuZHJha2UpIHtcbiAgICAgICAgaWYgKHRoaXMuZHJha2UubW9kZWxzKSB7XG4gICAgICAgICAgbGV0IG1vZGVsSW5kZXggPSB0aGlzLmRyYWtlLm1vZGVscy5pbmRleE9mKGNoYW5nZXNbJ2RyYWd1bGFNb2RlbCddLnByZXZpb3VzVmFsdWUpO1xuICAgICAgICAgIHRoaXMuZHJha2UubW9kZWxzLnNwbGljZShtb2RlbEluZGV4LCAxLCBjaGFuZ2VzWydkcmFndWxhTW9kZWwnXS5jdXJyZW50VmFsdWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuZHJha2UubW9kZWxzID0gW2NoYW5nZXNbJ2RyYWd1bGFNb2RlbCddLmN1cnJlbnRWYWx1ZV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gbm9kZV9tb2R1bGVzL2FuZ3VsYXIyLXRlbXBsYXRlLWxvYWRlciEuL3NyYy9hcHAvZGlyZWN0aXZlcy9kcmFndWxhLnRzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUE7QUFRQTtBQUNBO0FBS0E7QUFNQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBL0NBO0FBQUE7O0FBQUE7QUFDQTtBQUFBOztBQUFBO0FBTEE7QUFBQTtBQUNBO0FBQ0E7O0FBQUE7QUFrREE7O0FBQUE7QUFqREE7Iiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 113 */
- /***/ function(module, exports, __webpack_require__) {
- eval("\"use strict\";\nvar __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\nvar __metadata = (this && this.__metadata) || function (k, v) {\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\nvar core_1 = __webpack_require__(4);\nvar FluidHeightDirective = (function () {\n function FluidHeightDirective(element) {\n this.element = element;\n }\n FluidHeightDirective.prototype.onInput = function (textArea) {\n this.adjust();\n };\n FluidHeightDirective.prototype.ngOnInit = function () {\n this.adjust();\n };\n FluidHeightDirective.prototype.adjust = function () {\n this.element.nativeElement.style.overflow = 'hidden';\n this.element.nativeElement.style.height = 'auto';\n this.element.nativeElement.style.height = this.element.nativeElement.scrollHeight + \"px\";\n };\n __decorate([\n core_1.HostListener('input', ['$event.target']), \n __metadata('design:type', Function), \n __metadata('design:paramtypes', [Object]), \n __metadata('design:returntype', void 0)\n ], FluidHeightDirective.prototype, \"onInput\", null);\n FluidHeightDirective = __decorate([\n core_1.Directive({\n selector: 'textarea[autosize]'\n }), \n __metadata('design:paramtypes', [(typeof (_a = typeof core_1.ElementRef !== 'undefined' && core_1.ElementRef) === 'function' && _a) || Object])\n ], FluidHeightDirective);\n return FluidHeightDirective;\n var _a;\n}());\nexports.FluidHeightDirective = FluidHeightDirective;\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTEzLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vc3JjL2FwcC9kaXJlY3RpdmVzL2ZsdWlkLWhlaWdodC50cz80NDc1Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEVsZW1lbnRSZWYsIEhvc3RMaXN0ZW5lciwgRGlyZWN0aXZlfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuQERpcmVjdGl2ZSh7XG4gICAgc2VsZWN0b3I6ICd0ZXh0YXJlYVthdXRvc2l6ZV0nXG59KVxuXG5leHBvcnQgY2xhc3MgRmx1aWRIZWlnaHREaXJlY3RpdmUge1xuIEBIb3N0TGlzdGVuZXIoJ2lucHV0JyxbJyRldmVudC50YXJnZXQnXSlcbiAgb25JbnB1dCh0ZXh0QXJlYTogSFRNTFRleHRBcmVhRWxlbWVudCk6IHZvaWQge1xuICAgIHRoaXMuYWRqdXN0KCk7XG4gIH1cbiAgY29uc3RydWN0b3IocHVibGljIGVsZW1lbnQ6IEVsZW1lbnRSZWYpe1xuICB9XG4gIG5nT25Jbml0KCk6IHZvaWR7XG4gICAgdGhpcy5hZGp1c3QoKTtcbiAgfVxuICBhZGp1c3QoKTogdm9pZHtcbiAgICB0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS5vdmVyZmxvdyA9ICdoaWRkZW4nO1xuICAgIHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LnN0eWxlLmhlaWdodCA9ICdhdXRvJztcbiAgICB0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zdHlsZS5oZWlnaHQgPSB0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudC5zY3JvbGxIZWlnaHQgKyBcInB4XCI7XG4gIH1cbn1cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gbm9kZV9tb2R1bGVzL2FuZ3VsYXIyLXRlbXBsYXRlLWxvYWRlciEuL3NyYy9hcHAvZGlyZWN0aXZlcy9mbHVpZC1oZWlnaHQudHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQTtBQU1BO0FBS0E7QUFBQTtBQUNBO0FBSkE7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQWJBO0FBQUE7Ozs7QUFBQTtBQUxBO0FBQUE7QUFDQTtBQUNBOztBQUFBO0FBaUJBOztBQUFBO0FBZkE7Iiwic291cmNlUm9vdCI6IiJ9");
- /***/ },
- /* 114 */
- /***/ function(module, exports) {
- eval("\"use strict\";\nvar NotesTable = (function () {\n function NotesTable() {\n }\n return NotesTable;\n}());\nexports.NotesTable = NotesTable;\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTE0LmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vLy4vc3JjL2FwcC9zZXJ2aWNlcy9ub3Rlc190YWJsZS50cz8zZDQ2Il0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjbGFzcyBOb3Rlc1RhYmxlIHtcbiAgaWQ6IHN0cmluZztcbiAgdGl0bGU6IHN0cmluZztcbiAgbm90ZTogc3RyaW5nO1xuICBsYWJlbDogc3RyaW5nO1xuICBjb2xvcjogc3RyaW5nO1xuICB0aW1lOiBzdHJpbmc7XG4gIHJlc3RvcmU6IHN0cmluZztcbn1cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyBub2RlX21vZHVsZXMvYW5ndWxhcjItdGVtcGxhdGUtbG9hZGVyIS4vc3JjL2FwcC9zZXJ2aWNlcy9ub3Rlc190YWJsZS50cyJdLCJtYXBwaW5ncyI6IjtBQUFBO0FBQUE7QUFRQTtBQUFBO0FBQUE7QUFSQTsiLCJzb3VyY2VSb290IjoiIn0=");
- /***/ }
- ]);
|